mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-15 01:32:57 -07:00
Generate a unique token for each mobile device
This commit is contained in:
parent
5029b19d37
commit
08619244f0
6 changed files with 139 additions and 94 deletions
|
@ -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,41 +3042,52 @@ $(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;
|
||||
$('#api_qr_string').html(encoded_string);
|
||||
$('#api_qr_code').empty().qrcode({
|
||||
text: encoded_string
|
||||
});
|
||||
$.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
|
||||
});
|
||||
|
||||
(function poll(){
|
||||
verifiedDevice = false;
|
||||
setTimeout(function() {
|
||||
$.ajax({
|
||||
url: 'verify_mobile_device',
|
||||
type: 'GET',
|
||||
data: { device_token: token },
|
||||
success: function(data) {
|
||||
if (data.result === 'success') {
|
||||
verifiedDevice = true;
|
||||
getMobileDevicesTable();
|
||||
$('#api-qr-modal').modal('hide');
|
||||
showMsg('<i class="fa fa-check"></i> ' + data.message, false, true, 5000, false);
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
if (!(verifiedDevice)) {
|
||||
poll();
|
||||
}
|
||||
},
|
||||
timeout: 1000
|
||||
});
|
||||
}, 1000);
|
||||
})();
|
||||
(function poll(){
|
||||
verifiedDevice = false;
|
||||
setTimeout(function() {
|
||||
$.ajax({
|
||||
url: 'verify_mobile_device',
|
||||
type: 'GET',
|
||||
data: { device_token: token },
|
||||
success: function(data) {
|
||||
if (data.result === 'success') {
|
||||
verifiedDevice = true;
|
||||
getMobileDevicesTable();
|
||||
$('#api-qr-modal').modal('hide');
|
||||
showMsg('<i class="fa fa-check"></i> ' + data.message, false, true, 5000, false);
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
if (!(verifiedDevice)) {
|
||||
poll();
|
||||
}
|
||||
},
|
||||
timeout: 1000
|
||||
});
|
||||
}, 1000);
|
||||
})();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$('#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;
|
||||
})
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
self._api_msg = 'Device registration successful.'
|
||||
self._api_result_type = 'success'
|
||||
return
|
||||
|
||||
def _api_make_md(self):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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])
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue