Generate a unique token for each mobile device

This commit is contained in:
JonnyWong16 2017-03-31 21:02:09 -07:00
parent 5029b19d37
commit 08619244f0
6 changed files with 139 additions and 94 deletions

View file

@ -2652,13 +2652,9 @@ $(document).ready(function() {
$('#api_key').click(function(){ $('#api_key').select() });
$("#generate_api").click(function() {
$.get('generateAPI',
function(data){
if (data.error != undefined) {
alert(data.error);
return;
}
$('#api_key').val(data);
$.get('generate_api_key',
function (apikey) {
$('#api_key').val(apikey);
});
});
@ -3046,8 +3042,8 @@ $(document).ready(function() {
});
$('#api_qr_https').toggle(!(url.startsWith('https')));
var token = Math.random().toString(36).substr(2, 20);
var encoded_string = url + '|' + $('#api_key').val() + '|' + token;
$.get('generate_api_key', { device: true }).then(function (token) {
var encoded_string = url + '|' + token;
$('#api_qr_string').html(encoded_string);
$('#api_qr_code').empty().qrcode({
text: encoded_string
@ -3079,8 +3075,19 @@ $(document).ready(function() {
})();
});
});
});
$('#api-qr-modal').on('hidden.bs.modal', function () {
if (!(verifiedDevice)) {
$.ajax({
url: 'verify_mobile_device',
type: 'GET',
data: { cancel: true },
success: function(data) {
showMsg('<i class="fa fa-times"></i> ' + data.message, false, true, 5000, false);
}
});
}
verifiedDevice = true;
})

View file

@ -36,6 +36,7 @@ import activity_pinger
import config
import database
import logger
import mobile_app
import notification_handler
import notifiers
import plextv
@ -165,6 +166,7 @@ def initialize(config_file):
# Add notifier configs to logger blacklist
notifiers.blacklist_logger()
mobile_app.blacklist_logger()
# Check if PlexPy has a uuid
if CONFIG.PMS_UUID == '' or not CONFIG.PMS_UUID:

View file

@ -33,6 +33,7 @@ import plexpy
import config
import database
import logger
import mobile_app
import plextv
import pmsconnect
@ -88,7 +89,9 @@ class API2:
elif 'apikey' not in kwargs:
self._api_msg = 'Parameter apikey is required'
elif kwargs.get('apikey', '') != plexpy.CONFIG.API_KEY:
elif (kwargs.get('apikey', '') != plexpy.CONFIG.API_KEY and
kwargs.get('apikey', '') != mobile_app.TEMP_DEVICE_TOKEN and
not mobile_app.get_mobile_device_by_token(kwargs.get('apikey', ''))):
self._api_msg = 'Invalid apikey'
elif 'cmd' not in kwargs:
@ -105,7 +108,9 @@ class API2:
# Allow override for the api.
self._api_out_type = kwargs.pop('out_type', 'json')
if self._api_apikey == plexpy.CONFIG.API_KEY and plexpy.CONFIG.API_ENABLED and self._api_cmd in self._api_valid_methods:
if ((self._api_apikey == plexpy.CONFIG.API_KEY or
mobile_app.get_mobile_device_by_token(self._api_apikey)) and
plexpy.CONFIG.API_ENABLED and self._api_cmd in self._api_valid_methods):
self._api_authenticated = True
self._api_msg = None
self._api_kwargs = kwargs
@ -341,7 +346,7 @@ class API2:
return data
def register_device(self, device_id='', device_name='', device_token='', **kwargs):
def register_device(self, device_id='', device_name='', **kwargs):
""" Registers the PlexPy Android App for notifications.
```
@ -350,7 +355,7 @@ class API2:
device_id (str): The OneSignal device id of the PlexPy Android App
Optional parameters:
device_token (str): The device token to verify QR code scan
None
Returns:
None
@ -366,28 +371,18 @@ class API2:
self._api_result_type = 'error'
return
result = mobile_app.add_mobile_device(device_id=device_id,
device_name=device_name,
device_token=self._api_apikey)
db = database.MonitorDatabase()
keys = {'device_id': device_id}
values = {'device_name': device_name,
'device_token': device_token}
try:
result = db.upsert(table_name='mobile_devices', key_dict=keys, value_dict=values)
except Exception as e:
logger.warn(u"PlexPy APIv2 :: Failed to register mobile device in the database: %s." % e)
self._api_msg = 'Device registartion failed: database error.'
self._api_result_type = 'error'
return
if result == 'insert':
logger.info(u"PlexPy APIv2 :: Registered mobile device in the database: %s." % device_name)
else:
logger.debug(u"PlexPy APIv2 :: Re-registered mobile device in the database: %s." % device_name)
if result:
self._api_msg = 'Device registration successful.'
self._api_result_type = 'success'
mobile_app.TEMP_DEVICE_TOKEN = None
else:
self._api_msg = 'Device registartion failed: database error.'
self._api_result_type = 'error'
return
def _api_make_md(self):

View file

@ -19,6 +19,9 @@ import helpers
import logger
TEMP_DEVICE_TOKEN = None
def get_mobile_devices(device_id=None, device_token=None):
where = where_id = where_token = ''
args = []
@ -33,19 +36,57 @@ def get_mobile_devices(device_id=None, device_token=None):
args.append(device_token)
where += ' AND '.join([w for w in [where_id, where_token] if w])
monitor_db = database.MonitorDatabase()
result = monitor_db.select('SELECT * FROM mobile_devices %s' % where, args=args)
db = database.MonitorDatabase()
result = db.select('SELECT * FROM mobile_devices %s' % where, args=args)
return result
def get_mobile_device_by_token(device_token=None):
if not device_token:
return None
return get_mobile_devices(device_token=device_token)
def add_mobile_device(device_id=None, device_name=None, device_token=None):
db = database.MonitorDatabase()
keys = {'device_id': device_id}
values = {'device_name': device_name,
'device_token': device_token}
try:
result = db.upsert(table_name='mobile_devices', key_dict=keys, value_dict=values)
except Exception as e:
logger.warn(u"PlexPy MobileApp :: Failed to register mobile device in the database: %s." % e)
return
if result == 'insert':
logger.info(u"PlexPy MobileApp :: Registered mobile device '%s' in the database." % device_name)
else:
logger.debug(u"PlexPy MobileApp :: Re-registered mobile device '%s' in the database." % device_name)
return True
def delete_mobile_device(device_id=None):
monitor_db = database.MonitorDatabase()
db = database.MonitorDatabase()
if device_id:
logger.debug(u"PlexPy Notifiers :: Deleting device_id %s from the database." % device_id)
result = monitor_db.action('DELETE FROM mobile_devices WHERE device_id = ?', args=[device_id])
logger.debug(u"PlexPy MobileApp :: Deleting device_id %s from the database." % device_id)
result = db.action('DELETE FROM mobile_devices WHERE device_id = ?', args=[device_id])
return True
else:
return False
def blacklist_logger():
devices = get_mobile_devices()
blacklist = []
for d in devices:
blacklist.append(d['device_token'])
logger._BLACKLIST_WORDS.extend(blacklist)

View file

@ -375,8 +375,8 @@ def get_notifiers(notifier_id=None, notify_action=None):
args.append(1)
where += ' AND '.join([w for w in [where_id, where_action] if w])
monitor_db = database.MonitorDatabase()
result = monitor_db.select('SELECT id, agent_id, agent_name, agent_label, friendly_name, %s FROM notifiers %s'
db = database.MonitorDatabase()
result = db.select('SELECT id, agent_id, agent_name, agent_label, friendly_name, %s FROM notifiers %s'
% (', '.join(notify_actions), where), args=args)
for item in result:
@ -386,11 +386,11 @@ def get_notifiers(notifier_id=None, notify_action=None):
def delete_notifier(notifier_id=None):
monitor_db = database.MonitorDatabase()
db = database.MonitorDatabase()
if str(notifier_id).isdigit():
logger.debug(u"PlexPy Notifiers :: Deleting notifier_id %s from the database." % notifier_id)
result = monitor_db.action('DELETE FROM notifiers WHERE id = ?',
result = db.action('DELETE FROM notifiers WHERE id = ?',
args=[notifier_id])
return True
else:
@ -404,8 +404,8 @@ def get_notifier_config(notifier_id=None):
logger.error(u"PlexPy Notifiers :: Unable to retrieve notifier config: invalid notifier_id %s." % notifier_id)
return None
monitor_db = database.MonitorDatabase()
result = monitor_db.select_single('SELECT * FROM notifiers WHERE id = ?',
db = database.MonitorDatabase()
result = db.select_single('SELECT * FROM notifiers WHERE id = ?',
args=[notifier_id])
if not result:
@ -466,10 +466,10 @@ def add_notifier_config(agent_id=None, **kwargs):
values[a['name'] + '_subject'] = a['subject']
values[a['name'] + '_body'] = a['body']
monitor_db = database.MonitorDatabase()
db = database.MonitorDatabase()
try:
monitor_db.upsert(table_name='notifiers', key_dict=keys, value_dict=values)
notifier_id = monitor_db.last_insert_id()
db.upsert(table_name='notifiers', key_dict=keys, value_dict=values)
notifier_id = db.last_insert_id()
logger.info(u"PlexPy Notifiers :: Added new notification agent: %s (notifier_id %s)." % (agent['label'], notifier_id))
return notifier_id
except Exception as e:
@ -514,9 +514,9 @@ def set_notifier_config(notifier_id=None, agent_id=None, **kwargs):
values.update(subject_text)
values.update(body_text)
monitor_db = database.MonitorDatabase()
db = database.MonitorDatabase()
try:
monitor_db.upsert(table_name='notifiers', key_dict=keys, value_dict=values)
db.upsert(table_name='notifiers', key_dict=keys, value_dict=values)
logger.info(u"PlexPy Notifiers :: Updated notification agent: %s (notifier_id %s)." % (agent['label'], notifier_id))
return True
except Exception as e:
@ -538,8 +538,8 @@ def send_notification(notifier_id=None, subject='', body='', notify_action='', *
def blacklist_logger():
monitor_db = database.MonitorDatabase()
notifiers = monitor_db.select('SELECT notifier_config FROM notifiers')
db = database.MonitorDatabase()
notifiers = db.select('SELECT notifier_config FROM notifiers')
blacklist = []
blacklist_keys = [w.lstrip('_') for w in _BLACKLIST_KEYS]
@ -554,17 +554,6 @@ def blacklist_logger():
logger._BLACKLIST_WORDS.extend(blacklist)
def delete_mobile_device(device_id=None):
monitor_db = database.MonitorDatabase()
if device_id:
logger.debug(u"PlexPy Notifiers :: Deleting device_id %s from the database." % device_id)
result = monitor_db.action('DELETE FROM mobile_devices WHERE device_id = ?', [device_id])
return True
else:
return False
class PrettyMetadata(object):
def __init__(self, parameters):
self.parameters = parameters
@ -692,7 +681,7 @@ class ANDROIDAPP(Notifier):
return
# Check mobile device is still registered
if self.config['device_id'] and not mobile_app.get_mobile_devices(device_id=self.config['device_id']):
if not mobile_app.get_mobile_devices(device_id=self.config['device_id']):
logger.warn(u"PlexPy Notifiers :: Unable to send Android app notification: device not registered.")
return
@ -867,8 +856,8 @@ class BROWSER(Notifier):
if not self.config['enabled']:
return
monitor_db = database.MonitorDatabase()
result = monitor_db.select('SELECT subject_text, body_text FROM notify_log '
db = database.MonitorDatabase()
result = db.select('SELECT subject_text, body_text FROM notify_log '
'WHERE agent_id = 17 AND timestamp >= ? ',
args=[time.time() - 3])

View file

@ -3204,9 +3204,14 @@ class WebInterface(object):
@cherrypy.expose
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
def verify_mobile_device(self, device_token='', **kwargs):
result = mobile_app.get_mobile_devices(device_token=device_token)
def verify_mobile_device(self, device_token='', cancel=False, **kwargs):
if cancel == 'true':
mobile_app.TEMP_DEVICE_TOKEN = None
return {'result': 'error', 'message': 'Device registration cancelled.'}
result = mobile_app.get_mobile_device_by_token(device_token)
if result:
mobile_app.TEMP_DEVICE_TOKEN = None
return {'result': 'success', 'message': 'Device registered successfully.', 'data': result}
else:
return {'result': 'error', 'message': 'Device not registered.'}
@ -3421,10 +3426,16 @@ class WebInterface(object):
logger.warn(u"Unable to retrieve data for get_server_pref.")
@cherrypy.expose
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
def generateAPI(self, **kwargs):
def generate_api_key(self, device=None, **kwargs):
apikey = hashlib.sha224(str(random.getrandbits(256))).hexdigest()[0:32]
logger.info(u"New API key generated.")
logger._BLACKLIST_WORDS.append(apikey)
if device == 'true':
mobile_app.TEMP_DEVICE_TOKEN = apikey
return apikey
@cherrypy.expose