mirror of
				https://github.com/hrfee/jellyfin-accounts.git
				synced 2025-11-04 03:59:35 +00:00 
			
		
		
		
	added config-base file and config.ini generator
This commit is contained in:
		
							parent
							
								
									00ba11940a
								
							
						
					
					
						commit
						4606415a38
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -12,3 +12,5 @@ colors.txt
 | 
			
		||||
theme.css
 | 
			
		||||
data/static/bootstrap-jf.css
 | 
			
		||||
old/
 | 
			
		||||
.jf-accounts/
 | 
			
		||||
tools/__pycache__/
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ import signal
 | 
			
		||||
import sys
 | 
			
		||||
import json
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from flask import Flask, g
 | 
			
		||||
from flask import Flask, jsonify, g
 | 
			
		||||
from jellyfin_accounts.data_store import JSONStorage
 | 
			
		||||
 | 
			
		||||
parser = argparse.ArgumentParser(description="jellyfin-accounts")
 | 
			
		||||
@ -110,18 +110,21 @@ if "no_username" not in config["email"]:
 | 
			
		||||
    config["email"]["no_username"] = "false"
 | 
			
		||||
    log.debug("Set no_username to false")
 | 
			
		||||
 | 
			
		||||
with open(config["files"]["invites"], "r") as f:
 | 
			
		||||
    temp_invites = json.load(f)
 | 
			
		||||
if "invites" in temp_invites:
 | 
			
		||||
    new_invites = {}
 | 
			
		||||
    log.info("Converting invites.json to new format, temporary.")
 | 
			
		||||
    for el in temp_invites["invites"]:
 | 
			
		||||
        i = {"valid_till": el["valid_till"]}
 | 
			
		||||
        if "email" in el:
 | 
			
		||||
            i["email"] = el["email"]
 | 
			
		||||
        new_invites[el["code"]] = i
 | 
			
		||||
    with open(config["files"]["invites"], "w") as f:
 | 
			
		||||
        f.write(json.dumps(new_invites, indent=4, default=str))
 | 
			
		||||
try:
 | 
			
		||||
    with open(config["files"]["invites"], "r") as f:
 | 
			
		||||
        temp_invites = json.load(f)
 | 
			
		||||
    if "invites" in temp_invites:
 | 
			
		||||
        new_invites = {}
 | 
			
		||||
        log.info("Converting invites.json to new format, temporary.")
 | 
			
		||||
        for el in temp_invites["invites"]:
 | 
			
		||||
            i = {"valid_till": el["valid_till"]}
 | 
			
		||||
            if "email" in el:
 | 
			
		||||
                i["email"] = el["email"]
 | 
			
		||||
            new_invites[el["code"]] = i
 | 
			
		||||
        with open(config["files"]["invites"], "w") as f:
 | 
			
		||||
            f.write(json.dumps(new_invites, indent=4, default=str))
 | 
			
		||||
except FileNotFoundError:
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
data_store = JSONStorage(
 | 
			
		||||
@ -195,6 +198,18 @@ if (
 | 
			
		||||
    config["jellyfin"]["public_server"] = config["jellyfin"]["server"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def resp(success=True, code=500):
 | 
			
		||||
    if success:
 | 
			
		||||
        r = jsonify({"success": True})
 | 
			
		||||
        if code == 500:
 | 
			
		||||
            r.status_code = 200
 | 
			
		||||
        else:
 | 
			
		||||
            r.status_code = code
 | 
			
		||||
    else:
 | 
			
		||||
        r = jsonify({"success": False})
 | 
			
		||||
        r.status_code = code
 | 
			
		||||
    return r
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    if args.get_defaults:
 | 
			
		||||
        import json
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,10 @@ class Jellyfin:
 | 
			
		||||
            "User-Agent": self.useragent,
 | 
			
		||||
            "X-Emby-Authorization": self.auth,
 | 
			
		||||
        }
 | 
			
		||||
        self.info = requests.get(self.server + "/System/Info/Public").json()
 | 
			
		||||
        try:
 | 
			
		||||
            self.info = requests.get(self.server + "/System/Info/Public").json()
 | 
			
		||||
        except:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    def getUsers(self, username: str = "all", userId: str = "all", public: bool = True):
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,8 @@
 | 
			
		||||
from flask import request, jsonify, render_template
 | 
			
		||||
from configparser import RawConfigParser
 | 
			
		||||
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, resp
 | 
			
		||||
from jellyfin_accounts import web_log as log
 | 
			
		||||
from jellyfin_accounts.web_api import resp
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
if first_run:
 | 
			
		||||
 | 
			
		||||
@ -4,24 +4,11 @@ import json
 | 
			
		||||
import datetime
 | 
			
		||||
import secrets
 | 
			
		||||
import time
 | 
			
		||||
from jellyfin_accounts import config, config_path, app, g, data_store
 | 
			
		||||
from jellyfin_accounts import config, config_path, app, g, data_store, resp, configparser
 | 
			
		||||
from jellyfin_accounts import web_log as log
 | 
			
		||||
from jellyfin_accounts.validate_password import PasswordValidator
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def resp(success=True, code=500):
 | 
			
		||||
    if success:
 | 
			
		||||
        r = jsonify({"success": True})
 | 
			
		||||
        if code == 500:
 | 
			
		||||
            r.status_code = 200
 | 
			
		||||
        else:
 | 
			
		||||
            r.status_code = code
 | 
			
		||||
    else:
 | 
			
		||||
        r = jsonify({"success": False})
 | 
			
		||||
        r.status_code = code
 | 
			
		||||
    return r
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def checkInvite(code, delete=False):
 | 
			
		||||
    current_time = datetime.datetime.now()
 | 
			
		||||
    invites = dict(data_store.invites)
 | 
			
		||||
@ -327,4 +314,34 @@ def setDefaults():
 | 
			
		||||
    return resp()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import jellyfin_accounts.setup
 | 
			
		||||
 | 
			
		||||
@app.route("/modifyConfig", methods=["POST"])
 | 
			
		||||
@auth.login_required
 | 
			
		||||
def modifyConfig():
 | 
			
		||||
    log.info("Config modification requested")
 | 
			
		||||
    data = request.get_json()
 | 
			
		||||
    temp_config = configparser.RawConfigParser(comment_prefixes="/", allow_no_value=True)
 | 
			
		||||
    temp_config.read(config_path)
 | 
			
		||||
    for section in data:
 | 
			
		||||
        if section in temp_config:
 | 
			
		||||
            for item in data[section]:
 | 
			
		||||
                if item in temp_config[section]:
 | 
			
		||||
                    temp_config[section][item] = data[section][item]
 | 
			
		||||
                    data[section][item] = True
 | 
			
		||||
                    log.debug(f"{section}/{item} modified")
 | 
			
		||||
                else:
 | 
			
		||||
                    data[section][item] = False
 | 
			
		||||
                    log.debug(f"{section}/{item} does not exist in config")
 | 
			
		||||
    with open(config_path, "w") as config_file:
 | 
			
		||||
        temp_config.write(config_file)
 | 
			
		||||
    log.info("Config written, reloading")
 | 
			
		||||
    config.read(config_path)
 | 
			
		||||
    log.info("Config reloaded.")
 | 
			
		||||
    return resp()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@app.route('/getConfig', methods=["GET"])
 | 
			
		||||
@auth.login_required
 | 
			
		||||
def getConfig():
 | 
			
		||||
    log.debug('Config requested')
 | 
			
		||||
    return jsonify(config._sections), 200
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										486
									
								
								tools/config-base.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										486
									
								
								tools/config-base.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,486 @@
 | 
			
		||||
{
 | 
			
		||||
    "jellyfin": {
 | 
			
		||||
        "meta": {
 | 
			
		||||
            "name": "Jellyfin",
 | 
			
		||||
            "description": "Settings for connecting to Jellyfin"
 | 
			
		||||
        },
 | 
			
		||||
        "username": {
 | 
			
		||||
            "name": "Jellyfin Username",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "username",
 | 
			
		||||
            "description": "It is recommended to create a limited admin account for this program."
 | 
			
		||||
        },
 | 
			
		||||
        "password": {
 | 
			
		||||
            "name": "Jellyfin Password",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "password",
 | 
			
		||||
            "value": "password"
 | 
			
		||||
        },
 | 
			
		||||
        "server": {
 | 
			
		||||
            "name": "Server address",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "http://jellyfin.local:8096",
 | 
			
		||||
            "description": "Jellyfin server address. Can be public, or local for security purposes."
 | 
			
		||||
        },
 | 
			
		||||
        "public_server": {
 | 
			
		||||
            "name": "Public address",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "https://jellyf.in:443",
 | 
			
		||||
            "description": "Publicly accessible Jellyfin address for invite form. Leave blank to reuse the above address."
 | 
			
		||||
        },
 | 
			
		||||
        "client": {
 | 
			
		||||
            "name": "Client Name",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "jf-accounts",
 | 
			
		||||
            "description": "This and below settings will show on the Jellyfin dashboard when the program connects. You may as well leave them alone."
 | 
			
		||||
        },
 | 
			
		||||
        "version": {
 | 
			
		||||
            "name": "Version Number",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "0.2.4"
 | 
			
		||||
        },
 | 
			
		||||
        "device": {
 | 
			
		||||
            "name": "Device Name",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "jf-accounts"
 | 
			
		||||
        },
 | 
			
		||||
        "device_id": {
 | 
			
		||||
            "name": "Device ID",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "jf-accounts-0.2.4"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "ui": {
 | 
			
		||||
        "meta": {
 | 
			
		||||
            "name": "General",
 | 
			
		||||
            "description": "Settings related to the UI and program functionality."
 | 
			
		||||
        },
 | 
			
		||||
        "host": {
 | 
			
		||||
            "name": "Address",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "0.0.0.0",
 | 
			
		||||
            "description": "Set 0.0.0.0 to run on localhost"
 | 
			
		||||
        },
 | 
			
		||||
        "port": {
 | 
			
		||||
            "name": "Port",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "int",
 | 
			
		||||
            "value": 8056
 | 
			
		||||
        },
 | 
			
		||||
        "jellyfin_login": {
 | 
			
		||||
            "name": "Use Jellyfin for authentication",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "bool",
 | 
			
		||||
            "value": true,
 | 
			
		||||
            "description": "Enable this to use Jellyfin users instead of the below username and pw."
 | 
			
		||||
        },
 | 
			
		||||
        "admin_only": {
 | 
			
		||||
            "name": "Allow admin users only",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "depends_true": "jellyfin_login",
 | 
			
		||||
            "type": "bool",
 | 
			
		||||
            "value": true,
 | 
			
		||||
            "description": "Allows only admin users on Jellyfin to access the admin page."
 | 
			
		||||
        },
 | 
			
		||||
        "username": {
 | 
			
		||||
            "name": "Web Username",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "depends_false": "jellyfin_login",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "your username",
 | 
			
		||||
            "description": "Username for admin page (Leave blank if using jellyfin_login)"
 | 
			
		||||
        },
 | 
			
		||||
        "password": {
 | 
			
		||||
            "name": "Web Password",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "depends_false": "jellyfin_login",
 | 
			
		||||
            "type": "password",
 | 
			
		||||
            "value": "your password",
 | 
			
		||||
            "description": "Password for admin page (Leave blank if using jellyfin_login)"
 | 
			
		||||
        },
 | 
			
		||||
        "debug": {
 | 
			
		||||
            "name": "Debug logging",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "bool",
 | 
			
		||||
            "value": false
 | 
			
		||||
        },
 | 
			
		||||
        "contact_message": {
 | 
			
		||||
            "name": "Contact message",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "Need help? contact me.",
 | 
			
		||||
            "description": "Displayed at bottom of all pages except admin"
 | 
			
		||||
        },
 | 
			
		||||
        "help_message": {
 | 
			
		||||
            "name": "Help message",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "Enter your details to create an account.",
 | 
			
		||||
            "description": "Display at top of invite form."
 | 
			
		||||
        },
 | 
			
		||||
        "success_message": {
 | 
			
		||||
            "name": "Success message",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "Your account has been created. Click below to continue to Jellyfin.",
 | 
			
		||||
            "description": "Displayed when a user creates an account"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "password_validation": {
 | 
			
		||||
        "meta": {
 | 
			
		||||
            "name": "Password Validation",
 | 
			
		||||
            "description": "Password validation (minimum length, etc.)"
 | 
			
		||||
        },
 | 
			
		||||
        "enabled": {
 | 
			
		||||
            "name": "Enabled",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "bool",
 | 
			
		||||
            "value": true
 | 
			
		||||
        },
 | 
			
		||||
        "min_length": {
 | 
			
		||||
            "name": "Minimum Length",
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "8"
 | 
			
		||||
        },
 | 
			
		||||
        "upper": {
 | 
			
		||||
            "name": "Minimum uppercase characters",
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "1"
 | 
			
		||||
        },
 | 
			
		||||
        "lower": {
 | 
			
		||||
            "name": "Minimum lowercase characters",
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "0"
 | 
			
		||||
        },
 | 
			
		||||
        "number": {
 | 
			
		||||
            "name": "Minimum number count",
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "1"
 | 
			
		||||
        },
 | 
			
		||||
        "special": {
 | 
			
		||||
            "name": "Minimum number of special characters",
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "0"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "email": {
 | 
			
		||||
        "meta": {
 | 
			
		||||
            "name": "Email",
 | 
			
		||||
            "description": "General email settings. Ignore if not using email features."
 | 
			
		||||
        },
 | 
			
		||||
        "no_username": {
 | 
			
		||||
            "name": "Use email addresses as username",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "method",
 | 
			
		||||
            "type": "bool",
 | 
			
		||||
            "value": false,
 | 
			
		||||
            "description": "Use email address from invite form as username on Jellyfin."
 | 
			
		||||
        },
 | 
			
		||||
        "use_24h": {
 | 
			
		||||
            "name": "Use 24h time",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "method",
 | 
			
		||||
            "type": "bool",
 | 
			
		||||
            "value": true
 | 
			
		||||
        },
 | 
			
		||||
        "date_format": {
 | 
			
		||||
            "name": "Date format",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "method",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "%d/%m/%y",
 | 
			
		||||
            "description": "Date format used in emails. Follows datetime.strftime format."
 | 
			
		||||
        },
 | 
			
		||||
        "message": {
 | 
			
		||||
            "name": "Help message",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "method",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "Need help? contact me.",
 | 
			
		||||
            "description": "Message displayed at bottom of emails."
 | 
			
		||||
        },
 | 
			
		||||
        "method": {
 | 
			
		||||
            "name": "Email method",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "select",
 | 
			
		||||
            "options": [
 | 
			
		||||
                "smtp",
 | 
			
		||||
                "mailgun"
 | 
			
		||||
            ],
 | 
			
		||||
            "value": "smtp",
 | 
			
		||||
            "description": "Method of sending email to use."
 | 
			
		||||
        },
 | 
			
		||||
        "address": {
 | 
			
		||||
            "name": "Sent from (address)",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "method",
 | 
			
		||||
            "type": "email",
 | 
			
		||||
            "value": "jellyfin@jellyf.in",
 | 
			
		||||
            "description": "Address to send emails from"
 | 
			
		||||
        },
 | 
			
		||||
        "from": {
 | 
			
		||||
            "Name": "Sent from (name)",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "method",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "Jellyfin",
 | 
			
		||||
            "description": "The name of the sender"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "password_resets": {
 | 
			
		||||
        "meta": {
 | 
			
		||||
            "name": "Password Resets",
 | 
			
		||||
            "description": "Settings for the password reset handler."
 | 
			
		||||
        },
 | 
			
		||||
        "enabled": {
 | 
			
		||||
            "name": "Enabled",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "bool",
 | 
			
		||||
            "value": true,
 | 
			
		||||
            "description": "Enable to store provided email addresses, monitor Jellyfin directory for pw-resets, and send reset pins"
 | 
			
		||||
        },
 | 
			
		||||
        "watch_directory": {
 | 
			
		||||
            "name": "Jellyfin directory",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "/path/to/jellyfin",
 | 
			
		||||
            "description": "Path to the folder Jellyfin puts password-reset files."
 | 
			
		||||
        },
 | 
			
		||||
        "email_html": {
 | 
			
		||||
            "name": "Custom email (HTML)",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Path to custom email html"
 | 
			
		||||
        },
 | 
			
		||||
        "email_text": {
 | 
			
		||||
            "name": "Custom email (plaintext)",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Path to custom email in plain text"
 | 
			
		||||
        },
 | 
			
		||||
        "subject": {
 | 
			
		||||
            "name": "Email subject",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "Password Reset - Jellyfin",
 | 
			
		||||
            "description": "Subject of password reset emails."
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "invite_emails": {
 | 
			
		||||
        "meta": {
 | 
			
		||||
            "name": "Invite emails",
 | 
			
		||||
            "description": "Settings for sending invites directly to users."
 | 
			
		||||
        },
 | 
			
		||||
        "enabled": {
 | 
			
		||||
            "name": "Enabled",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "bool",
 | 
			
		||||
            "value": true
 | 
			
		||||
        },
 | 
			
		||||
        "email_html": {
 | 
			
		||||
            "name": "Custom email (HTML)",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Path to custom email HTML"
 | 
			
		||||
        },
 | 
			
		||||
        "email_text": {
 | 
			
		||||
            "name": "Custom email (plaintext)",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Path to custom email in plain text"
 | 
			
		||||
        },
 | 
			
		||||
        "subject": {
 | 
			
		||||
            "name": "Email subject",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "Invite - Jellyfin",
 | 
			
		||||
            "description": "Subject of invite emails."
 | 
			
		||||
        },
 | 
			
		||||
        "url_base": {
 | 
			
		||||
            "name": "URL Base",
 | 
			
		||||
            "required": true,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "depends_true": "enabled",
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "http://accounts.jellyf.in:8056/invite",
 | 
			
		||||
            "description": "Base URL for jf-accounts. This is necessary because using a reverse proxy means the program has no way of knowing the URL itself."
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "mailgun": {
 | 
			
		||||
        "meta": {
 | 
			
		||||
            "name": "Mailgun (Email)",
 | 
			
		||||
            "description": "Mailgun API connection settings"
 | 
			
		||||
        },
 | 
			
		||||
        "api_url": {
 | 
			
		||||
            "name": "API URL",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "https://api.mailgun.net..."
 | 
			
		||||
        },
 | 
			
		||||
        "api_key": {
 | 
			
		||||
            "name": "API Key",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "your api key"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "smtp": {
 | 
			
		||||
        "meta": {
 | 
			
		||||
            "name": "SMTP (Email)",
 | 
			
		||||
            "description": "SMTP Server connection settings."
 | 
			
		||||
        },
 | 
			
		||||
        "encryption": {
 | 
			
		||||
            "name": "Encryption Method",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "select",
 | 
			
		||||
            "options": [
 | 
			
		||||
                "ssl_tls",
 | 
			
		||||
                "starttls"
 | 
			
		||||
            ],
 | 
			
		||||
            "value": "starttls",
 | 
			
		||||
            "description": "Your email provider should provide different ports for each encryption method. Generally 465 for ssl_tls, 587 for starttls."
 | 
			
		||||
        },
 | 
			
		||||
        "server": {
 | 
			
		||||
            "name": "Server address",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "smtp.jellyf.in",
 | 
			
		||||
            "description": "SMTP Server address."
 | 
			
		||||
        },
 | 
			
		||||
        "port": {
 | 
			
		||||
            "name": "Port",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "int",
 | 
			
		||||
            "value": 465
 | 
			
		||||
        },
 | 
			
		||||
        "password": {
 | 
			
		||||
            "name": "Password",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": false,
 | 
			
		||||
            "type": "password",
 | 
			
		||||
            "value": "smtp password"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "files": {
 | 
			
		||||
        "meta": {
 | 
			
		||||
            "name": "File Storage",
 | 
			
		||||
            "description": "Optional settings for changing storage locations."
 | 
			
		||||
        },
 | 
			
		||||
        "invites": {
 | 
			
		||||
            "name": "Invite Storage",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Location of stored invites (json)."
 | 
			
		||||
        },
 | 
			
		||||
        "emails": {
 | 
			
		||||
            "name": "Email Addresses",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Location of stored email addresses (json)."
 | 
			
		||||
        },
 | 
			
		||||
        "user_template": {
 | 
			
		||||
            "name": "User Template",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Location of stored user policy template (json)."
 | 
			
		||||
        },
 | 
			
		||||
        "user_configuration": {
 | 
			
		||||
            "name": "userConfiguration",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Location of stored user configuration template (used for setting homescreen layout) (json)"
 | 
			
		||||
        },
 | 
			
		||||
        "user_displayprefs": {
 | 
			
		||||
            "name": "displayPreferences",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Location of stored displayPreferences template (also used for homescreen layout) (json)"
 | 
			
		||||
        },
 | 
			
		||||
        "custom_css": {
 | 
			
		||||
            "name": "Custom CSS",
 | 
			
		||||
            "required": false,
 | 
			
		||||
            "requires_restart": true,
 | 
			
		||||
            "type": "text",
 | 
			
		||||
            "value": "",
 | 
			
		||||
            "description": "Location of custom bootstrap CSS."
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										115
									
								
								tools/config.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								tools/config.ini
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,115 @@
 | 
			
		||||
[jellyfin]
 | 
			
		||||
; settings for connecting to jellyfin
 | 
			
		||||
; it is recommended to create a limited admin account for this program.
 | 
			
		||||
username = username
 | 
			
		||||
password = password
 | 
			
		||||
; jellyfin server address. can be public, or local for security purposes.
 | 
			
		||||
server = http://jellyfin.local:8096
 | 
			
		||||
; publicly accessible jellyfin address for invite form. leave blank to reuse the above address.
 | 
			
		||||
public_server = https://jellyf.in:443
 | 
			
		||||
; this and below settings will show on the jellyfin dashboard when the program connects. you may as well leave them alone.
 | 
			
		||||
client = jf-accounts
 | 
			
		||||
version = 0.2.4
 | 
			
		||||
device = jf-accounts
 | 
			
		||||
device_id = jf-accounts-0.2.4
 | 
			
		||||
 | 
			
		||||
[ui]
 | 
			
		||||
; settings related to the ui and program functionality.
 | 
			
		||||
; set 0.0.0.0 to run on localhost
 | 
			
		||||
host = 0.0.0.0
 | 
			
		||||
port = 8056
 | 
			
		||||
; enable this to use jellyfin users instead of the below username and pw.
 | 
			
		||||
jellyfin_login = true
 | 
			
		||||
; allows only admin users on jellyfin to access the admin page.
 | 
			
		||||
admin_only = true
 | 
			
		||||
; username for admin page (leave blank if using jellyfin_login)
 | 
			
		||||
username = your username
 | 
			
		||||
; password for admin page (leave blank if using jellyfin_login)
 | 
			
		||||
password = your password
 | 
			
		||||
debug = false
 | 
			
		||||
; displayed at bottom of all pages except admin
 | 
			
		||||
contact_message = Need help? contact me.
 | 
			
		||||
; display at top of invite form.
 | 
			
		||||
help_message = Enter your details to create an account.
 | 
			
		||||
; displayed when a user creates an account
 | 
			
		||||
success_message = Your account has been created. Click below to continue to Jellyfin.
 | 
			
		||||
 | 
			
		||||
[password_validation]
 | 
			
		||||
; password validation (minimum length, etc.)
 | 
			
		||||
enabled = true
 | 
			
		||||
min_length = 8
 | 
			
		||||
upper = 1
 | 
			
		||||
lower = 0
 | 
			
		||||
number = 1
 | 
			
		||||
special = 0
 | 
			
		||||
 | 
			
		||||
[email]
 | 
			
		||||
; general email settings. ignore if not using email features.
 | 
			
		||||
; use email address from invite form as username on jellyfin.
 | 
			
		||||
no_username = false
 | 
			
		||||
use_24h = true
 | 
			
		||||
; date format used in emails. follows datetime.strftime format.
 | 
			
		||||
date_format = %d/%m/%y
 | 
			
		||||
; message displayed at bottom of emails.
 | 
			
		||||
message = Need help? contact me.
 | 
			
		||||
; method of sending email to use.
 | 
			
		||||
method = smtp
 | 
			
		||||
; address to send emails from
 | 
			
		||||
address = jellyfin@jellyf.in
 | 
			
		||||
; the name of the sender
 | 
			
		||||
from = Jellyfin
 | 
			
		||||
 | 
			
		||||
[password_resets]
 | 
			
		||||
; settings for the password reset handler.
 | 
			
		||||
; enable to store provided email addresses, monitor jellyfin directory for pw-resets, and send reset pins
 | 
			
		||||
enabled = true
 | 
			
		||||
; path to the folder jellyfin puts password-reset files.
 | 
			
		||||
watch_directory = /path/to/jellyfin
 | 
			
		||||
; path to custom email html
 | 
			
		||||
email_html = 
 | 
			
		||||
; path to custom email in plain text
 | 
			
		||||
email_text = 
 | 
			
		||||
; subject of password reset emails.
 | 
			
		||||
subject = Password Reset - Jellyfin
 | 
			
		||||
 | 
			
		||||
[invite_emails]
 | 
			
		||||
; settings for sending invites directly to users.
 | 
			
		||||
enabled = true
 | 
			
		||||
; path to custom email html
 | 
			
		||||
email_html = 
 | 
			
		||||
; path to custom email in plain text
 | 
			
		||||
email_text = 
 | 
			
		||||
; subject of invite emails.
 | 
			
		||||
subject = Invite - Jellyfin
 | 
			
		||||
; base url for jf-accounts. this is necessary because using a reverse proxy means the program has no way of knowing the url itself.
 | 
			
		||||
url_base = http://accounts.jellyf.in:8056/invite
 | 
			
		||||
 | 
			
		||||
[mailgun]
 | 
			
		||||
; mailgun api connection settings
 | 
			
		||||
api_url = https://api.mailgun.net...
 | 
			
		||||
api_key = your api key
 | 
			
		||||
 | 
			
		||||
[smtp]
 | 
			
		||||
; smtp server connection settings.
 | 
			
		||||
; your email provider should provide different ports for each encryption method. generally 465 for ssl_tls, 587 for starttls.
 | 
			
		||||
encryption = starttls
 | 
			
		||||
; smtp server address.
 | 
			
		||||
server = smtp.jellyf.in
 | 
			
		||||
port = 465
 | 
			
		||||
password = smtp password
 | 
			
		||||
 | 
			
		||||
[files]
 | 
			
		||||
; optional settings for changing storage locations.
 | 
			
		||||
; location of stored invites (json).
 | 
			
		||||
invites = 
 | 
			
		||||
; location of stored email addresses (json).
 | 
			
		||||
emails = 
 | 
			
		||||
; location of stored user policy template (json).
 | 
			
		||||
user_template = 
 | 
			
		||||
; location of stored user configuration template (used for setting homescreen layout) (json)
 | 
			
		||||
user_configuration = 
 | 
			
		||||
; location of stored displaypreferences template (also used for homescreen layout) (json)
 | 
			
		||||
user_displayprefs = 
 | 
			
		||||
; location of custom bootstrap css.
 | 
			
		||||
custom_css = 
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								tools/generate-config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								tools/generate-config.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
import configparser, json
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
print("This tool generates a config.ini from the base JSON config format.")
 | 
			
		||||
 | 
			
		||||
# path = Path(input("Path to config-base.json: "))
 | 
			
		||||
path = 'config-base.json'
 | 
			
		||||
 | 
			
		||||
with open(path, 'r') as f:
 | 
			
		||||
    config_base = json.load(f)
 | 
			
		||||
 | 
			
		||||
ini = configparser.RawConfigParser(allow_no_value=True)
 | 
			
		||||
 | 
			
		||||
for section in config_base:
 | 
			
		||||
    ini.add_section(section)
 | 
			
		||||
    for entry in config_base[section]:
 | 
			
		||||
        if 'description' in config_base[section][entry]:
 | 
			
		||||
            ini.set(section,
 | 
			
		||||
                    '; ' + config_base[section][entry]['description'])
 | 
			
		||||
        if entry != 'meta':
 | 
			
		||||
            value = config_base[section][entry]['value']
 | 
			
		||||
            print(f'{entry} : {type(value)} : should be {config_base[section][entry]["type"]}')
 | 
			
		||||
            if isinstance(value, bool):
 | 
			
		||||
                value = str(value).lower()
 | 
			
		||||
            else:
 | 
			
		||||
                value = str(value)
 | 
			
		||||
            ini.set(section,
 | 
			
		||||
                    entry,
 | 
			
		||||
                    value)
 | 
			
		||||
 | 
			
		||||
with open('config.ini', 'w') as config_file:
 | 
			
		||||
    ini.write(config_file)
 | 
			
		||||
print("written.")
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user