mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-15 01:32:57 -07:00
Add automatic Android app QR scan verification
This commit is contained in:
parent
ddf671abd1
commit
40060255ee
4 changed files with 103 additions and 13 deletions
|
@ -3032,6 +3032,7 @@ $(document).ready(function() {
|
||||||
return deferred;
|
return deferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var verifiedDevice = false;
|
||||||
$('#generate_qr').click(function () {
|
$('#generate_qr').click(function () {
|
||||||
getPlexPyURL().then(function (url) {
|
getPlexPyURL().then(function (url) {
|
||||||
var parser = document.createElement('a');
|
var parser = document.createElement('a');
|
||||||
|
@ -3040,14 +3041,44 @@ $(document).ready(function() {
|
||||||
$('#api_qr_private').toggle((valid !== 'n/a'));
|
$('#api_qr_private').toggle((valid !== 'n/a'));
|
||||||
});
|
});
|
||||||
|
|
||||||
var encoded_string = url + '|' + $('#api_key').val();
|
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_string').html(encoded_string);
|
||||||
$('#api_qr_code').empty().qrcode({
|
$('#api_qr_code').empty().qrcode({
|
||||||
text: encoded_string
|
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);
|
||||||
|
})();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#api-qr-modal').on('hidden.bs.modal', function () {
|
||||||
|
verifiedDevice = true;
|
||||||
|
})
|
||||||
|
|
||||||
$('body').on('click', 'a[data-tab-destination]', function () {
|
$('body').on('click', 'a[data-tab-destination]', function () {
|
||||||
var tab = $(this).data('tab-destination');
|
var tab = $(this).data('tab-destination');
|
||||||
$("a[href=#" + tab + "]").click();
|
$("a[href=#" + tab + "]").click();
|
||||||
|
|
|
@ -341,7 +341,7 @@ class API2:
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def register_device(self, device_name='', device_id='', **kwargs):
|
def register_device(self, device_id='', device_name='', device_token='' **kwargs):
|
||||||
""" Registers the PlexPy Android App for notifications.
|
""" Registers the PlexPy Android App for notifications.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -350,26 +350,28 @@ class API2:
|
||||||
device_id (str): The OneSignal device id of the PlexPy Android App
|
device_id (str): The OneSignal device id of the PlexPy Android App
|
||||||
|
|
||||||
Optional parameters:
|
Optional parameters:
|
||||||
None
|
device_token (str): The device token to verify QR code scan
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
if not device_name:
|
if not device_id:
|
||||||
|
self._api_msg = 'Device registartion failed: no device id provided.'
|
||||||
|
self._api_result_type = 'error'
|
||||||
|
return
|
||||||
|
|
||||||
|
elif not device_name:
|
||||||
self._api_msg = 'Device registartion failed: no device name provided.'
|
self._api_msg = 'Device registartion failed: no device name provided.'
|
||||||
self._api_result_type = 'error'
|
self._api_result_type = 'error'
|
||||||
return
|
return
|
||||||
|
|
||||||
elif not device_id:
|
|
||||||
self._api_msg = 'Device registartion failed: no device token provided.'
|
|
||||||
self._api_result_type = 'error'
|
|
||||||
return
|
|
||||||
|
|
||||||
db = database.MonitorDatabase()
|
db = database.MonitorDatabase()
|
||||||
|
|
||||||
keys = {'device_id': device_id}
|
keys = {'device_id': device_id}
|
||||||
values = {'device_name': device_name}
|
values = {'device_name': device_name,
|
||||||
|
'device_token': device_token}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = db.upsert(table_name='mobile_devices', key_dict=keys, value_dict=values)
|
result = db.upsert(table_name='mobile_devices', key_dict=keys, value_dict=values)
|
||||||
|
|
47
plexpy/mobile_app.py
Normal file
47
plexpy/mobile_app.py
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# This file is part of PlexPy.
|
||||||
|
#
|
||||||
|
# PlexPy is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# PlexPy is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import plexpy
|
||||||
|
import database
|
||||||
|
import helpers
|
||||||
|
import logger
|
||||||
|
|
||||||
|
|
||||||
|
def get_mobile_devices(device_id=None, device_token=None):
|
||||||
|
where = where_id = where_token = ''
|
||||||
|
if device_id or device_token:
|
||||||
|
where = 'WHERE '
|
||||||
|
if device_id:
|
||||||
|
where_id += 'device_id = "%s"' % device_id
|
||||||
|
if device_token:
|
||||||
|
where_token = 'device_token = "%s"' % 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)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -39,6 +39,7 @@ import http_handler
|
||||||
import libraries
|
import libraries
|
||||||
import log_reader
|
import log_reader
|
||||||
import logger
|
import logger
|
||||||
|
import mobile_app
|
||||||
import notification_handler
|
import notification_handler
|
||||||
import notifiers
|
import notifiers
|
||||||
import plextv
|
import plextv
|
||||||
|
@ -3197,9 +3198,18 @@ class WebInterface(object):
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@requireAuth(member_of("admin"))
|
@requireAuth(member_of("admin"))
|
||||||
def get_mobile_devices_table(self, **kwargs):
|
def get_mobile_devices_table(self, **kwargs):
|
||||||
result = notifiers.ANDROIDAPP().get_devices()
|
result = mobile_app.get_mobile_devices()
|
||||||
devices_list = [{'device_id': id, 'device_name': name} for id, name in result.iteritems()]
|
return serve_template(templatename="mobile_devices_table.html", devices_list=result)
|
||||||
return serve_template(templatename="mobile_devices_table.html", devices_list=devices_list)
|
|
||||||
|
@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)
|
||||||
|
if result:
|
||||||
|
return {'result': 'success', 'message': 'Device registered successfully.', 'data': result}
|
||||||
|
else:
|
||||||
|
return {'result': 'error', 'message': 'Device not registered.'}
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@cherrypy.tools.json_out()
|
@cherrypy.tools.json_out()
|
||||||
|
@ -3219,7 +3229,7 @@ class WebInterface(object):
|
||||||
None
|
None
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
result = notifiers.delete_mobile_device(device_id=device_id)
|
result = mobile_app.delete_mobile_device(device_id=device_id)
|
||||||
if result:
|
if result:
|
||||||
return {'result': 'success', 'message': 'Device deleted successfully.'}
|
return {'result': 'success', 'message': 'Device deleted successfully.'}
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue