Beispiel #1
0
    def modifyConfig():
        log.info("Config modification requested")
        data = request.get_json()
        temp_config = 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.debug("Config written")
        log.info('Restarting...')
        try:
            p = psutil.Process(os.getpid())
            for handler in p.open_files() + p.connections():
                os.close(handler.fd)
        except:
            pass

        python = sys.executable
        os.execl(python, python, *sys.argv)
        return resp()
Beispiel #2
0
def deleteInvite():
    code = request.get_json()["code"]
    invites = dict(data_store.invites)
    if code in invites:
        del data_store.invites[code]
    log.info(f"Invite deleted: {code}")
    return resp()
Beispiel #3
0
def inviteProxy(path):
    if checkInvite(path):
        log.info(f"Invite {path} used to request form")
        try:
            email = data_store.invites[path]["email"]
        except KeyError:
            email = ""
        return render_template(
            "form.html",
            bs5=config.getboolean("ui", "bs5"),
            css_file=css_file,
            contactMessage=config["ui"]["contact_message"],
            helpMessage=config["ui"]["help_message"],
            successMessage=config["ui"]["success_message"],
            jfLink=config["jellyfin"]["public_server"],
            validate=config.getboolean("password_validation", "enabled"),
            requirements=validator().getCriteria(),
            email=email,
            username=(not config.getboolean("email", "no_username")),
        )
    elif "admin.html" not in path and "admin.html" not in path:
        return app.send_static_file(path)
    else:
        log.debug("Attempted use of invalid invite")
        return render_template(
            "invalidCode.html",
            bs5=config.getboolean("ui", "bs5"),
            css_file=css_file,
            contactMessage=config["ui"]["contact_message"],
        )
Beispiel #4
0
def switchToIds():
    try:
        with open(config["files"]["emails"], "r") as f:
            emails = json.load(f)
    except (FileNotFoundError, json.decoder.JSONDecodeError):
        emails = {}
    users = jf.getUsers(public=False)
    new_emails = {}
    match = False
    for key in emails:
        for user in users:
            if user["Name"] == key:
                match = True
                new_emails[user["Id"]] = emails[key]
            elif user["Id"] == key:
                new_emails[user["Id"]] = emails[key]
    if match:
        from pathlib import Path

        email_file = Path(config["files"]["emails"]).name
        log.info((f"{email_file} modified to use userID instead of " +
                  "usernames. These will be used in future."))
        emails = new_emails
        with open(config["files"]["emails"], "w") as f:
            f.write(json.dumps(emails, indent=4))
Beispiel #5
0
def generateInvite():
    current_time = datetime.datetime.now()
    data = request.get_json()
    delta = datetime.timedelta(days=int(data["days"]),
                               hours=int(data["hours"]),
                               minutes=int(data["minutes"]))
    invite_code = secrets.token_urlsafe(16)
    invite = {}
    invite["created"] = format_datetime(current_time)
    if data["multiple-uses"]:
        if data["no-limit"]:
            invite["no-limit"] = True
        else:
            invite["remaining-uses"] = int(data["remaining-uses"])
    else:
        invite["remaining-uses"] = 1
    log.debug(f"Creating new invite: {invite_code}")
    valid_till = current_time + delta
    invite["valid_till"] = valid_till.strftime("%Y-%m-%dT%H:%M:%S.%f")
    if "email" in data and config.getboolean("invite_emails", "enabled"):
        address = data["email"]
        invite["email"] = address
        log.info(f"Sending invite to {address}")
        method = config["email"]["method"]
        if method == "mailgun":
            from jellyfin_accounts.email import Mailgun

            email = Mailgun(address)
        elif method == "smtp":
            from jellyfin_accounts.email import Smtp

            email = Smtp(address)
        email.construct_invite({"expiry": valid_till, "code": invite_code})
        response = email.send()
        if response is False or type(response) != bool:
            invite["email"] = f"Failed to send to {address}"
    if config.getboolean("notifications", "enabled"):
        if "notify-creation" in data:
            invite["notify-creation"] = data["notify-creation"]
        if "notify-expiry" in data:
            invite["notify-expiry"] = data["notify-expiry"]
    data_store.invites[invite_code] = invite
    log.info(f"New invite created: {invite_code}")
    return resp()
Beispiel #6
0
def modifyConfig():
    global config
    log.info("Config modification requested")
    data = request.get_json()
    temp_config = configparser.RawConfigParser(comment_prefixes="/",
                                               allow_no_value=True)
    temp_config.read(str(config_path.resolve()))
    for section in data:
        if section in temp_config and 'restart-program' not in section:
            for item in data[section]:
                temp_config[section][item] = data[section][item]
                data[section][item] = True
                log.debug(f"{section}/{item} modified")
    with open(config_path, "w") as config_file:
        temp_config.write(config_file)
    config.trigger_reload()
    log.info("Config written.")
    if 'restart-program' in data:
        if data['restart-program']:
            log.info('Restarting...')
            try:
                proc = psutil.Process(os.getpid())
                for handler in proc.open_files() + proc.connections():
                    os.close(handler.fd)
            except Exception as e:
                log.error(f'Failed restart: {type(e).__name__}')
            python = sys.executable
            os.execl(python, python, *sys.argv)
    return resp()
Beispiel #7
0
def newUser():
    data = request.get_json()
    log.debug("Attempted newUser")
    if checkInvite(data["code"]):
        validation = validator().validate(data["password"])
        valid = True
        for criterion in validation:
            if validation[criterion] is False:
                valid = False
        if valid:
            log.debug("User password valid")
            try:
                user = jf.newUser(data["username"], data["password"])
            except Jellyfin.UserExistsError:
                error = f'User already exists named {data["username"]}'
                log.debug(error)
                return jsonify({"error": error})
            except:
                return jsonify({"error": "Unknown error"})
            invites = dict(data_store.invites)
            checkInvite(data["code"], used=True, username=data["username"])
            if (config.getboolean("notifications", "enabled")
                    and "notify" in invites[data["code"]]):
                for address in invites[data["code"]]["notify"]:
                    if "notify-creation" in invites[
                            data["code"]]["notify"][address]:
                        if invites[data["code"]]["notify"][address][
                                "notify-creation"]:
                            method = config["email"]["method"]
                            if method == "mailgun":
                                email = Mailgun(address)
                            elif method == "smtp":
                                email = Smtp(address)
                            if email.construct_created({
                                    "code":
                                    data["code"],
                                    "username":
                                    data["username"],
                                    "created":
                                    datetime.datetime.now(),
                            }):
                                threading.Thread(target=email.send).start()
            if user.status_code == 200:
                try:
                    policy = data_store.user_template
                    if policy != {}:
                        jf.setPolicy(user.json()["Id"], policy)
                    else:
                        log.debug("user policy was blank")
                except:
                    log.error("Failed to set new user policy")
                try:
                    configuration = data_store.user_configuration
                    displayprefs = data_store.user_displayprefs
                    if configuration != {} and displayprefs != {}:
                        if jf.setConfiguration(user.json()["Id"],
                                               configuration):
                            jf.setDisplayPreferences(user.json()["Id"],
                                                     displayprefs)
                            log.debug("Set homescreen layout.")
                    else:
                        log.debug(
                            "user configuration and/or displayprefs were blank"
                        )
                except:
                    log.error("Failed to set new user homescreen layout")
                if config.getboolean("password_resets", "enabled"):
                    data_store.emails[user.json()["Id"]] = data["email"]
                    log.debug("Email address stored")
                log.info("New user created")
            else:
                log.error(f"New user creation failed: {user.status_code}")
                return resp(False)
        else:
            log.debug("User password invalid")
        return jsonify(validation)
    else:
        log.debug("Attempted newUser unauthorized")
        return resp(False, code=401)
Beispiel #8
0
    config["jellyfin"]["client"],
    config["jellyfin"]["version"],
    config["jellyfin"]["device"],
    config["jellyfin"]["device_id"],
)

from jellyfin_accounts.login import auth

jf_address = config["jellyfin"]["server"]
success = False
for i in range(3):
    try:
        jf.authenticate(config["jellyfin"]["username"],
                        config["jellyfin"]["password"])
        success = True
        log.info(f"Successfully authenticated with {jf_address}")
        break
    except Jellyfin.AuthenticationError:
        log.error(f"Failed to authenticate with {jf_address}, Retrying...")
        time.sleep(5)

if not success:
    log.error("Could not authenticate after 3 tries.")
    exit()

# Temporary fixes below.


def switchToIds():
    try:
        with open(config["files"]["emails"], "r") as f: