diff --git a/data/config-default.ini b/data/config-default.ini
index 453d511..2650138 100644
--- a/data/config-default.ini
+++ b/data/config-default.ini
@@ -103,5 +103,7 @@ invites =
; Path to store emails addresses in JSON
emails =
; Path to the user policy template. Can be acquired with get-template.
-user_template =
+user_template =
+; Path to custom bootstrap.css
+custom_css =
diff --git a/data/templates/404.html b/data/templates/404.html
index 1bbd935..7a83bd5 100644
--- a/data/templates/404.html
+++ b/data/templates/404.html
@@ -12,8 +12,8 @@
-
Create Jellyfin Account
-
+404
+
diff --git a/data/templates/admin.html b/data/templates/admin.html
index 5e42ea9..aa7e642 100644
--- a/data/templates/admin.html
+++ b/data/templates/admin.html
@@ -14,7 +14,7 @@
-
+
diff --git a/data/templates/form.html b/data/templates/form.html
index d90d3c7..ce6e1ca 100644
--- a/data/templates/form.html
+++ b/data/templates/form.html
@@ -12,7 +12,7 @@
-
+
diff --git a/data/templates/invalidCode.html b/data/templates/invalidCode.html
index 118a60b..f5cc409 100644
--- a/data/templates/invalidCode.html
+++ b/data/templates/invalidCode.html
@@ -3,8 +3,8 @@
-Create Jellyfin Account
-
+Invalid Code
+
diff --git a/images/jellyfin-accounts-social.png b/images/jellyfin-accounts-social.png
new file mode 100644
index 0000000..e653ace
Binary files /dev/null and b/images/jellyfin-accounts-social.png differ
diff --git a/images/jellyfin-accounts-social.svg b/images/jellyfin-accounts-social.svg
new file mode 100644
index 0000000..201db6f
--- /dev/null
+++ b/images/jellyfin-accounts-social.svg
@@ -0,0 +1,197 @@
+
+
diff --git a/jellyfin_accounts/web.py b/jellyfin_accounts/web.py
index 7fc82f1..44dced6 100644
--- a/jellyfin_accounts/web.py
+++ b/jellyfin_accounts/web.py
@@ -1,7 +1,7 @@
import json
from pathlib import Path
from flask import Flask, send_from_directory, render_template
-from __main__ import config, app, g
+from __main__ import config, app, g, css
from __main__ import web_log as log
from jellyfin_accounts.web_api import checkInvite, validator
@@ -9,6 +9,9 @@ from jellyfin_accounts.web_api import checkInvite, validator
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html',
+ css_href=css['href'],
+ css_integrity=css['integrity'],
+ css_crossorigin=css['crossorigin'],
contactMessage=config['ui']['contact_message']), 404
@@ -16,6 +19,9 @@ def page_not_found(e):
def admin():
# return app.send_static_file('admin.html')
return render_template('admin.html',
+ css_href=css['href'],
+ css_integrity=css['integrity'],
+ css_crossorigin=css['crossorigin'],
contactMessage='',
email_enabled=config.getboolean(
'invite_emails', 'enabled'))
@@ -26,6 +32,9 @@ def static_proxy(path):
if 'html' not in path:
return app.send_static_file(path)
return render_template('404.html',
+ css_href=css['href'],
+ css_integrity=css['integrity'],
+ css_crossorigin=css['crossorigin'],
contactMessage=config['ui']['contact_message']), 404
@@ -45,6 +54,9 @@ def inviteProxy(path):
except KeyError:
email = ""
return render_template('form.html',
+ css_href=css['href'],
+ css_integrity=css['integrity'],
+ css_crossorigin=css['crossorigin'],
contactMessage=config['ui']['contact_message'],
helpMessage=config['ui']['help_message'],
successMessage=config['ui']['success_message'],
@@ -59,4 +71,7 @@ def inviteProxy(path):
else:
log.debug('Attempted use of invalid invite')
return render_template('invalidCode.html',
+ css_href=css['href'],
+ css_integrity=css['integrity'],
+ css_crossorigin=css['crossorigin'],
contactMessage=config['ui']['contact_message'])
diff --git a/jf-accounts b/jf-accounts
index cfc0e61..c0657af 100755
--- a/jf-accounts
+++ b/jf-accounts
@@ -87,9 +87,34 @@ if args.port is not None:
for key in config['files']:
if config['files'][key] == '':
- log.debug(f'Using default {key}')
- config['files'][key] = str(data_dir / (key + '.json'))
+ if key != 'custom_css':
+ log.debug(f'Using default {key}')
+ config['files'][key] = str(data_dir / (key + '.json'))
+
+def default_css():
+ css = {}
+ css['href'] = "https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
+ css['integrity'] = "sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
+ css['crossorigin'] = "anonymous"
+ return css
+
+
+css = {}
+css = default_css()
+if 'custom_css' in config['files']:
+ if config['files']['custom_css'] != '':
+ try:
+ shutil.copy(config['files']['custom_css'],
+ (local_dir / 'static' / 'bootstrap.css'))
+ log.debug('Loaded custom CSS')
+ css['href'] = '/bootstrap.css'
+ css['integrity'] = ''
+ css['crossorigin'] = ''
+ except FileNotFoundError:
+ log.error(f'Custom CSS {config["files"]["custom_css"]} not found, using default.')
+
+
if ('email_html' not in config['password_resets'] or
config['password_resets']['email_html'] == ''):
log.debug('Using default password reset email HTML template')
@@ -110,7 +135,6 @@ if ('email_text' not in config['invite_emails'] or
config['invite_emails']['email_text'] = str(local_dir /
'invite-email.txt')
-
if args.get_policy:
import json
from jellyfin_accounts.jf_api import Jellyfin