This commit is contained in:
Harvey Tindall 2020-06-21 20:21:33 +01:00
parent b943bd1f27
commit 079dff8d9f
5 changed files with 31 additions and 39 deletions

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
__version__ = "0.2" __version__ = "0.2.1"
import secrets import secrets
import configparser import configparser
@ -102,13 +102,13 @@ for key in ['user_configuration', 'user_displayprefs']:
with open(config['files']['invites'], 'r') as f: with open(config['files']['invites'], 'r') as f:
temp_invites = json.load(f) temp_invites = json.load(f)
if 'invites' in temp_invites: if 'invites' in temp_invites:
new_invites = {} new_invites = {}
log.info('Converting invites.json to new format, temporary.') log.info('Converting invites.json to new format, temporary.')
for el in temp_invites['invites']: for el in temp_invites['invites']:
i = {'valid_till': el['valid_till']} i = {'valid_till': el['valid_till']}
if 'email' in el: if 'email' in el:
i['email'] = el['email'] i['email'] = el['email']
new_invites[el['code']] = i new_invites[el['code']] = i
with open(config['files']['invites'], 'w') as f: with open(config['files']['invites'], 'w') as f:
f.write(json.dumps(new_invites, indent=4, default=str)) f.write(json.dumps(new_invites, indent=4, default=str))
@ -178,17 +178,17 @@ def main():
config['jellyfin']['device'], config['jellyfin']['device'],
config['jellyfin']['device_id']) config['jellyfin']['device_id'])
print("NOTE: This can now be done through the web ui.") print("NOTE: This can now be done through the web ui.")
print(""" print("""
This tool lets you grab various settings from a user, This tool lets you grab various settings from a user,
so that they can be applied every time a new account is so that they can be applied every time a new account is
created. """) created. """)
print("Step 1: User Policy.") print("Step 1: User Policy.")
print(""" print("""
A user policy stores a users permissions (e.g access rights and A user policy stores a users permissions (e.g access rights and
most of the other settings in the 'Profile' and 'Access' tabs most of the other settings in the 'Profile' and 'Access' tabs
of a user). """) of a user). """)
success = False success = False
msg = "Get public users only or all users? (requires auth) [public/all]: " msg = "Get public users only or all users? (requires auth) [public/all]: "
public = False public = False
while not success: while not success:
choice = input(msg) choice = input(msg)

View File

@ -2,6 +2,10 @@ import json
import datetime import datetime
class JSONFile(dict): class JSONFile(dict):
"""
Behaves like a dictionary, but automatically
reads and writes to a JSON file (most of the time).
"""
@staticmethod @staticmethod
def readJSON(path): def readJSON(path):
try: try:

View File

@ -66,13 +66,15 @@ class Jellyfin:
"User-Agent": self.useragent, "User-Agent": self.useragent,
"X-Emby-Authorization": self.auth "X-Emby-Authorization": self.auth
} }
def getUsers(self, username="all", id="all", public=True): def getUsers(self, username: str = "all",
userId: str = "all",
public: bool = True):
""" """
Returns details on user(s), such as ID, Name, Policy. Returns details on user(s), such as ID, Name, Policy.
:param username: (optional) Username to get info about. :param username: (optional) Username to get info about.
Leave blank to get all users. Leave blank to get all users.
:param id: (optional) User ID to get info about. :param userId: (optional) User ID to get info about.
Leave blank to get all users. Leave blank to get all users.
:param public: True = Get publicly visible users only (no auth required), :param public: True = Get publicly visible users only (no auth required),
False = Get all users (auth required). False = Get all users (auth required).
@ -124,7 +126,8 @@ class Jellyfin:
return user return user
if not match: if not match:
raise self.UserNotFoundError raise self.UserNotFoundError
def authenticate(self, username, password):
def authenticate(self, username: str, password: str):
""" """
Authenticates by name with Jellyfin. Authenticates by name with Jellyfin.
@ -151,7 +154,7 @@ class Jellyfin:
return True return True
else: else:
raise self.AuthenticationError raise self.AuthenticationError
def setPolicy(self, userId, policy): def setPolicy(self, userId: str, policy: dict):
""" """
Sets a user's policy (Admin rights, Library Access, etc.) by user ID. Sets a user's policy (Admin rights, Library Access, etc.) by user ID.
@ -161,7 +164,7 @@ class Jellyfin:
return requests.post(self.server+"/Users/"+userId+"/Policy", return requests.post(self.server+"/Users/"+userId+"/Policy",
headers=self.header, headers=self.header,
params=policy) params=policy)
def newUser(self, username, password): def newUser(self, username: str, password: str):
for user in self.getUsers(): for user in self.getUsers():
if user['Name'] == username: if user['Name'] == username:
raise self.UserExistsError raise self.UserExistsError
@ -176,7 +179,7 @@ class Jellyfin:
else: else:
raise self.AuthenticationRequiredError raise self.AuthenticationRequiredError
return response return response
def getViewOrder(self, userId, public=True): def getViewOrder(self, userId: str, public: bool = True):
if not public: if not public:
param = '?IncludeHidden=true' param = '?IncludeHidden=true'
else: else:
@ -187,7 +190,7 @@ class Jellyfin:
for library in views: for library in views:
orderedViews.append(library['Id']) orderedViews.append(library['Id'])
return orderedViews return orderedViews
def setConfiguration(self, userId, configuration): def setConfiguration(self, userId: str, configuration: dict):
""" """
Sets a user's configuration (Settings the user can change themselves). Sets a user's configuration (Settings the user can change themselves).
:param userId: ID of the user to modify. :param userId: ID of the user to modify.
@ -207,17 +210,17 @@ class Jellyfin:
raise self.AuthenticationRequiredError raise self.AuthenticationRequiredError
else: else:
raise self.UnknownError raise self.UnknownError
def getConfiguration(self, username="all", id="all"): def getConfiguration(self, username: str = "all", userId: str = "all"):
""" """
Gets a user's Configuration. This can also be found in getUsers if Gets a user's Configuration. This can also be found in getUsers if
public is set to False. public is set to False.
:param username: The user's username. :param username: The user's username.
:param id: The user's ID. :param userId: The user's ID.
""" """
return self.getUsers(username=username, return self.getUsers(username=username,
id=id, userId=userId,
public=False)['Configuration'] public=False)['Configuration']
def getDisplayPreferences(self, userId): def getDisplayPreferences(self, userId: str):
""" """
Gets a user's Display Preferences (Home layout). Gets a user's Display Preferences (Home layout).
:param userId: The user's ID. :param userId: The user's ID.
@ -235,7 +238,7 @@ class Jellyfin:
raise self.AuthenticationRequiredError raise self.AuthenticationRequiredError
else: else:
raise self.UnknownError raise self.UnknownError
def setDisplayPreferences(self, userId, preferences): def setDisplayPreferences(self, userId: str, preferences: dict):
""" """
Sets a user's Display Preferences (Home layout). Sets a user's Display Preferences (Home layout).
:param userId: The user's ID. :param userId: The user's ID.

View File

@ -3,18 +3,10 @@ from configparser import RawConfigParser
from jellyfin_accounts.jf_api import Jellyfin from jellyfin_accounts.jf_api import Jellyfin
from jellyfin_accounts import config, config_path, app, first_run from jellyfin_accounts import config, config_path, app, first_run
from jellyfin_accounts import web_log as log from jellyfin_accounts import web_log as log
from jellyfin_accounts.web_api import resp
import os import os
if first_run: if first_run:
def resp(success=True, code=500):
if success:
r = jsonify({'success': True})
r.status_code = 200
else:
r = jsonify({'success': False})
r.status_code = code
return r
def tempJF(server): def tempJF(server):
return Jellyfin(server, return Jellyfin(server,
config['jellyfin']['client'], config['jellyfin']['client'],
@ -30,7 +22,6 @@ if first_run:
def setup(): def setup():
return render_template('setup.html') return render_template('setup.html')
@app.route('/<path:path>') @app.route('/<path:path>')
def static_proxy(path): def static_proxy(path):
if 'html' not in path: if 'html' not in path:
@ -38,7 +29,6 @@ if first_run:
else: else:
return render_template('404.html'), 404 return render_template('404.html'), 404
@app.route('/modifyConfig', methods=['POST']) @app.route('/modifyConfig', methods=['POST'])
def modifyConfig(): def modifyConfig():
log.info('Config modification requested') log.info('Config modification requested')
@ -59,10 +49,10 @@ if first_run:
with open(config_path, 'w') as config_file: with open(config_path, 'w') as config_file:
temp_config.write(config_file) temp_config.write(config_file)
log.debug('Config written') log.debug('Config written')
# ugly exit, sorry
os._exit(1) os._exit(1)
return resp() return resp()
@app.route('/testJF', methods=['GET', 'POST']) @app.route('/testJF', methods=['GET', 'POST'])
def testJF(): def testJF():
data = request.get_json() data = request.get_json()

View File

@ -42,8 +42,3 @@ class PasswordValidator:
text += criterion text += criterion
lines[criterion] = text lines[criterion] = text
return lines return lines