mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-13 08:42:59 -07:00
Allow Plex admin to login as Tautulli admin
This commit is contained in:
parent
3f90037db3
commit
896a37bea9
8 changed files with 113 additions and 54 deletions
|
@ -472,6 +472,13 @@
|
|||
</div>
|
||||
<input type="text" id="http_hashed_password" name="http_hashed_password" value="${config['http_hashed_password']}" style="display: none;" data-parsley-trigger="change" data-parsley-type="integer" data-parsley-range="[0, 1]"
|
||||
data-parsley-errors-container="#http_hash_password_error" data-parsley-error-message="Cannot un-hash password, please set a new password." data-parsley-no-focus required>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" class="auth-settings" name="http_plex_admin" id="http_plex_admin" value="1" ${config['http_plex_admin']} data-parsley-trigger="change"> Allow Plex Admin
|
||||
</label>
|
||||
<span id="allowPlexCheck" style="color: #eb8600; padding-left: 10px;"></span>
|
||||
<p class="help-block">Allow the Plex server admin to login as a Tautulli admin using their Plex.tv account.</p>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" class="auth-settings" name="http_basic_auth" id="http_basic_auth" value="1" ${config['http_basic_auth']} data-parsley-trigger="change"> Use Basic Authentication
|
||||
|
@ -479,6 +486,7 @@
|
|||
<p class="help-block">Use basic HTTP authentication instead of the HTML login form.</p>
|
||||
</div>
|
||||
|
||||
<input type="checkbox" name="auth_changed" id="auth_changed" value="1" style="display: none;">
|
||||
|
||||
<div class="padded-header">
|
||||
<h3>Guest Access</h3>
|
||||
|
@ -1777,6 +1785,7 @@ $(document).ready(function() {
|
|||
|
||||
$( ".auth-settings" ).change(function() {
|
||||
authChanged = true;
|
||||
$("#auth_changed").prop('checked', true);
|
||||
});
|
||||
|
||||
$( ".directory-settings" ).change(function() {
|
||||
|
@ -2016,6 +2025,26 @@ $(document).ready(function() {
|
|||
}
|
||||
});
|
||||
|
||||
function allowPlexAdminCheck () {
|
||||
if ($("#http_basic_auth").is(":checked")) {
|
||||
$("#http_plex_admin").attr("disabled", true);
|
||||
$("#http_plex_admin").attr("checked", false);
|
||||
$("#allowPlexCheck").html("Plex admin login cannot be enabled with basic authentication.");
|
||||
} else if ($('#http_username').val() == '' || $('#http_password').val() == '') {
|
||||
$("#http_plex_admin").attr("disabled", true);
|
||||
$("#http_plex_admin").attr("checked", false);
|
||||
$("#allowPlexCheck").html("You must set an admin username and password above to allow Plex admin login.");
|
||||
} else {
|
||||
$("#http_plex_admin").attr("disabled", false);
|
||||
$("#allowPlexCheck").html("");
|
||||
}
|
||||
}
|
||||
allowPlexAdminCheck();
|
||||
|
||||
$('#http_username, #http_password, #http_basic_auth').change(function () {
|
||||
allowPlexAdminCheck();
|
||||
});
|
||||
|
||||
function allowGuestAccessCheck () {
|
||||
if ($("#http_basic_auth").is(":checked")) {
|
||||
$("#allow_guest_access").attr("disabled", true);
|
||||
|
@ -2024,7 +2053,7 @@ $(document).ready(function() {
|
|||
} else if ($('#http_username').val() == '' || $('#http_password').val() == '') {
|
||||
$("#allow_guest_access").attr("disabled", true);
|
||||
$("#allow_guest_access").attr("checked", false);
|
||||
$("#allowGuestCheck").html("You must set an admin password above to allow guest access.");
|
||||
$("#allowGuestCheck").html("You must set an admin username and password above to allow guest access.");
|
||||
} else {
|
||||
$("#allow_guest_access").attr("disabled", false);
|
||||
$("#allowGuestCheck").html("");
|
||||
|
|
|
@ -502,7 +502,7 @@ def dbcheck():
|
|||
c_db.execute(
|
||||
'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
'user_id INTEGER DEFAULT NULL UNIQUE, username TEXT NOT NULL, friendly_name TEXT, '
|
||||
'thumb TEXT, custom_avatar_url TEXT, email TEXT, is_home_user INTEGER DEFAULT NULL, '
|
||||
'thumb TEXT, custom_avatar_url TEXT, email TEXT, is_admin INTEGER DEFAULT 0, is_home_user INTEGER DEFAULT NULL, '
|
||||
'is_allow_sync INTEGER DEFAULT NULL, is_restricted INTEGER DEFAULT NULL, do_notify INTEGER DEFAULT 1, '
|
||||
'keep_history INTEGER DEFAULT 1, deleted_user INTEGER DEFAULT 0, allow_guest INTEGER DEFAULT 0, '
|
||||
'user_token TEXT, server_token TEXT, shared_libraries TEXT, filter_all TEXT, filter_movies TEXT, filter_tv TEXT, '
|
||||
|
@ -1289,6 +1289,15 @@ def dbcheck():
|
|||
'ALTER TABLE users ADD COLUMN filter_photos TEXT'
|
||||
)
|
||||
|
||||
# Upgrade users table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT is_admin FROM users')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table users.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE users ADD COLUMN is_admin INTEGER DEFAULT 0'
|
||||
)
|
||||
|
||||
# Upgrade notify_log table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT poster_url FROM notify_log')
|
||||
|
|
|
@ -225,6 +225,7 @@ _CONFIG_DEFINITIONS = {
|
|||
'HTTP_PROXY': (int, 'General', 0),
|
||||
'HTTP_ROOT': (str, 'General', ''),
|
||||
'HTTP_USERNAME': (str, 'General', ''),
|
||||
'HTTP_PLEX_ADMIN': (int, 'General', 0),
|
||||
'HIPCHAT_URL': (str, 'Hipchat', ''),
|
||||
'HIPCHAT_COLOR': (str, 'Hipchat', ''),
|
||||
'HIPCHAT_INCL_SUBJECT': (int, 'Hipchat', 1),
|
||||
|
|
|
@ -335,6 +335,7 @@ class PlexTV(object):
|
|||
"thumb": helpers.get_xml_attr(a, 'thumb'),
|
||||
"email": helpers.get_xml_attr(a, 'email'),
|
||||
"is_home_user": helpers.get_xml_attr(a, 'home'),
|
||||
"is_admin": 1,
|
||||
"is_allow_sync": None,
|
||||
"is_restricted": helpers.get_xml_attr(a, 'restricted'),
|
||||
"filter_all": helpers.get_xml_attr(a, 'filterAll'),
|
||||
|
@ -357,6 +358,7 @@ class PlexTV(object):
|
|||
"username": helpers.get_xml_attr(a, 'title'),
|
||||
"thumb": helpers.get_xml_attr(a, 'thumb'),
|
||||
"email": helpers.get_xml_attr(a, 'email'),
|
||||
"is_admin": 0,
|
||||
"is_home_user": helpers.get_xml_attr(a, 'home'),
|
||||
"is_allow_sync": helpers.get_xml_attr(a, 'allowSync'),
|
||||
"is_restricted": helpers.get_xml_attr(a, 'restricted'),
|
||||
|
|
|
@ -52,6 +52,7 @@ def refresh_users():
|
|||
new_value_dict = {"username": item['username'],
|
||||
"thumb": item['thumb'],
|
||||
"email": item['email'],
|
||||
"is_admin": item['is_admin'],
|
||||
"is_home_user": item['is_home_user'],
|
||||
"is_allow_sync": item['is_allow_sync'],
|
||||
"is_restricted": item['is_restricted'],
|
||||
|
@ -330,6 +331,7 @@ class Users(object):
|
|||
'friendly_name': 'Local',
|
||||
'user_thumb': common.DEFAULT_USER_THUMB,
|
||||
'email': '',
|
||||
'is_admin': '',
|
||||
'is_home_user': 0,
|
||||
'is_allow_sync': 0,
|
||||
'is_restricted': 0,
|
||||
|
@ -349,21 +351,21 @@ class Users(object):
|
|||
try:
|
||||
if str(user_id).isdigit():
|
||||
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
|
||||
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history, deleted_user, ' \
|
||||
'email, is_admin, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history, deleted_user, ' \
|
||||
'allow_guest, shared_libraries ' \
|
||||
'FROM users ' \
|
||||
'WHERE user_id = ? '
|
||||
result = monitor_db.select(query, args=[user_id])
|
||||
elif user:
|
||||
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
|
||||
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history, deleted_user, ' \
|
||||
'email, is_admin, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history, deleted_user, ' \
|
||||
'allow_guest, shared_libraries ' \
|
||||
'FROM users ' \
|
||||
'WHERE username = ? COLLATE NOCASE '
|
||||
result = monitor_db.select(query, args=[user])
|
||||
elif email:
|
||||
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
|
||||
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history, deleted_user, ' \
|
||||
'email, is_admin, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history, deleted_user, ' \
|
||||
'allow_guest, shared_libraries ' \
|
||||
'FROM users ' \
|
||||
'WHERE email = ? COLLATE NOCASE '
|
||||
|
@ -398,6 +400,7 @@ class Users(object):
|
|||
'friendly_name': friendly_name,
|
||||
'user_thumb': user_thumb,
|
||||
'email': item['email'],
|
||||
'is_admin': item['is_admin'],
|
||||
'is_home_user': item['is_home_user'],
|
||||
'is_allow_sync': item['is_allow_sync'],
|
||||
'is_restricted': item['is_restricted'],
|
||||
|
|
|
@ -54,10 +54,17 @@ def user_login(username=None, password=None):
|
|||
if user_id != str(user_details['user_id']):
|
||||
# The user is not in the database.
|
||||
return None
|
||||
elif plexpy.CONFIG.HTTP_PLEX_ADMIN and user_details['is_admin']:
|
||||
# Plex admin login
|
||||
return 'admin'
|
||||
elif not user_details['allow_guest'] or user_details['deleted_user']:
|
||||
# Guest access is disabled or the user is deleted.
|
||||
return None
|
||||
|
||||
# Stop here if guest access is not enabled
|
||||
if not plexpy.CONFIG.ALLOW_GUEST_ACCESS:
|
||||
return None
|
||||
|
||||
# The user is in the database, and guest access is enabled, so try to retrieve a server token.
|
||||
# If a server token is returned, then the user is a valid friend of the server.
|
||||
plex_tv = PlexTV(token=user_token)
|
||||
|
@ -75,7 +82,7 @@ def user_login(username=None, password=None):
|
|||
# Refresh the users list to make sure we have all the correct permissions.
|
||||
refresh_users()
|
||||
# Successful login
|
||||
return True
|
||||
return 'guest'
|
||||
else:
|
||||
logger.warn(u"Tautulli WebAuth :: Unable to register user '%s' in database." % username)
|
||||
return None
|
||||
|
@ -96,15 +103,19 @@ def check_credentials(username, password, admin_login='0'):
|
|||
"""Verifies credentials for username and password.
|
||||
Returns True and the user group on success or False and no user group"""
|
||||
|
||||
if plexpy.CONFIG.HTTP_PASSWORD:
|
||||
if plexpy.CONFIG.HTTP_HASHED_PASSWORD and \
|
||||
username == plexpy.CONFIG.HTTP_USERNAME and check_hash(password, plexpy.CONFIG.HTTP_PASSWORD):
|
||||
return True, u'admin'
|
||||
return True, 'admin'
|
||||
elif not plexpy.CONFIG.HTTP_HASHED_PASSWORD and \
|
||||
username == plexpy.CONFIG.HTTP_USERNAME and password == plexpy.CONFIG.HTTP_PASSWORD:
|
||||
return True, u'admin'
|
||||
elif not admin_login == '1' and plexpy.CONFIG.ALLOW_GUEST_ACCESS and user_login(username, password):
|
||||
return True, u'guest'
|
||||
else:
|
||||
return True, 'admin'
|
||||
|
||||
if plexpy.CONFIG.HTTP_PLEX_ADMIN or (not admin_login == '1' and plexpy.CONFIG.ALLOW_GUEST_ACCESS):
|
||||
plex_login = user_login(username, password)
|
||||
if plex_login is not None:
|
||||
return True, plex_login
|
||||
|
||||
return False, None
|
||||
|
||||
|
||||
|
@ -163,15 +174,12 @@ def requireAuth(*conditions):
|
|||
#
|
||||
# Define those at will however suits the application.
|
||||
|
||||
def member_of(groupname):
|
||||
def check():
|
||||
# replace with actual check if <username> is in <groupname>
|
||||
return cherrypy.request.login['user'] == plexpy.CONFIG.HTTP_USERNAME and groupname == 'admin'
|
||||
return check
|
||||
def member_of(user_group):
|
||||
return cherrypy.request.login['user_group'] == user_group
|
||||
|
||||
|
||||
def name_is(reqd_username):
|
||||
return lambda: reqd_username == cherrypy.request.login['user']
|
||||
def name_is(user_name):
|
||||
return cherrypy.request.login['user'] == user_name
|
||||
|
||||
|
||||
# These might be handy
|
||||
|
|
|
@ -2538,6 +2538,7 @@ class WebInterface(object):
|
|||
"http_password": http_password,
|
||||
"http_root": plexpy.CONFIG.HTTP_ROOT,
|
||||
"http_proxy": checked(plexpy.CONFIG.HTTP_PROXY),
|
||||
"http_plex_admin": checked(plexpy.CONFIG.HTTP_PLEX_ADMIN),
|
||||
"launch_browser": checked(plexpy.CONFIG.LAUNCH_BROWSER),
|
||||
"enable_https": checked(plexpy.CONFIG.ENABLE_HTTPS),
|
||||
"https_create_cert": checked(plexpy.CONFIG.HTTPS_CREATE_CERT),
|
||||
|
@ -2632,7 +2633,7 @@ class WebInterface(object):
|
|||
"monitor_pms_updates", "monitor_remote_access", "get_file_sizes", "log_blacklist", "http_hash_password",
|
||||
"allow_guest_access", "cache_images", "http_proxy", "http_basic_auth", "notify_concurrent_by_ip",
|
||||
"history_table_activity", "plexpy_auto_update",
|
||||
"themoviedb_lookup", "tvmaze_lookup"
|
||||
"themoviedb_lookup", "tvmaze_lookup", "http_plex_admin"
|
||||
]
|
||||
for checked_config in checked_configs:
|
||||
if checked_config not in kwargs:
|
||||
|
@ -2673,8 +2674,7 @@ class WebInterface(object):
|
|||
refresh_users = False
|
||||
|
||||
# First run from the setup wizard
|
||||
if kwargs.get('first_run'):
|
||||
del kwargs['first_run']
|
||||
if kwargs.pop('first_run', None):
|
||||
first_run = True
|
||||
|
||||
# If we change any monitoring settings, make sure we reschedule tasks.
|
||||
|
@ -2728,12 +2728,15 @@ class WebInterface(object):
|
|||
refresh_libraries = True
|
||||
|
||||
# If we change the server, make sure we grab the new url and refresh libraries and users lists.
|
||||
if kwargs.get('server_changed'):
|
||||
del kwargs['server_changed']
|
||||
if kwargs.pop('server_changed', None):
|
||||
server_changed = True
|
||||
refresh_users = True
|
||||
refresh_libraries = True
|
||||
|
||||
# If we change the authentication settings, make sure we refresh the users lists.
|
||||
if kwargs.pop('auth_changed', None):
|
||||
refresh_users = True
|
||||
|
||||
plexpy.CONFIG.process_kwargs(kwargs)
|
||||
|
||||
# Write the config
|
||||
|
|
|
@ -68,8 +68,12 @@ def initialize(options):
|
|||
protocol = "http"
|
||||
|
||||
if options['http_password']:
|
||||
logger.info(u"Tautulli WebStart :: Web server authentication is enabled, username is '%s'",
|
||||
options['http_username'])
|
||||
login_allowed = ["Tautulli admin (username is '%s')" % options['http_username']]
|
||||
if plexpy.CONFIG.HTTP_PLEX_ADMIN:
|
||||
login_allowed.append("Plex admin")
|
||||
|
||||
logger.info(u"Tautulli WebStart :: Web server authentication is enabled: %s allowed", ' and '.join(login_allowed))
|
||||
|
||||
if options['http_basic_auth']:
|
||||
auth_enabled = False
|
||||
basic_auth_enabled = True
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue