mirror of
https://github.com/spl0k/supysonic.git
synced 2024-11-09 19:52:16 +00:00
Apply changes
This commit is contained in:
parent
8e2adf8fc8
commit
b2f0c99f79
@ -33,6 +33,9 @@ log_level = WARNING
|
|||||||
; for testing purposes. Default: on
|
; for testing purposes. Default: on
|
||||||
;mount_api = on
|
;mount_api = on
|
||||||
|
|
||||||
|
; Require API key for authentication. Default: yes
|
||||||
|
require_api_key = yes
|
||||||
|
|
||||||
; Enable the administrative web interface. Default: on
|
; Enable the administrative web interface. Default: on
|
||||||
;mount_webui = on
|
;mount_webui = on
|
||||||
|
|
||||||
@ -87,3 +90,21 @@ default_transcode_target = mp3
|
|||||||
;mp3 = audio/mpeg
|
;mp3 = audio/mpeg
|
||||||
;ogg = audio/vorbis
|
;ogg = audio/vorbis
|
||||||
|
|
||||||
|
[ldap]
|
||||||
|
; Server URL. Default: none
|
||||||
|
;url = ldapi://%2Frun%2Fslapd%2Fldapi
|
||||||
|
;url = ldap://127.0.0.1:389
|
||||||
|
|
||||||
|
; Bind credentials. Default: none
|
||||||
|
;bind_dn = cn=username,dc=example,dc=org
|
||||||
|
;bind_pw = password
|
||||||
|
|
||||||
|
; Base DN. Default: none
|
||||||
|
;base_dn = ou=Users,dc=example,dc=org
|
||||||
|
|
||||||
|
; User filter. The variable '{username}' is used for filtering. Default: none
|
||||||
|
;user_filter = (&(objectClass=inetOrgperson)(uid={username}))
|
||||||
|
|
||||||
|
; Mail attribute. Default: mail
|
||||||
|
;mail_attr = mail
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import binascii
|
|||||||
import uuid
|
import uuid
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
|
from flask import current_app
|
||||||
from peewee import IntegrityError
|
from peewee import IntegrityError
|
||||||
|
|
||||||
from ..db import ClientPrefs, Folder
|
from ..db import ClientPrefs, Folder
|
||||||
@ -56,10 +57,16 @@ def decode_password(password):
|
|||||||
|
|
||||||
@api.before_request
|
@api.before_request
|
||||||
def authorize():
|
def authorize():
|
||||||
|
require_api_key = current_app.config["WEBAPP"]["require_api_key"]
|
||||||
|
|
||||||
if request.authorization:
|
if request.authorization:
|
||||||
user = UserManager.try_auth(
|
user = UserManager.try_auth_api(
|
||||||
request.authorization.username, request.authorization.password
|
request.authorization.username, request.authorization.password
|
||||||
)
|
)
|
||||||
|
if user is None and not require_api_key:
|
||||||
|
user = UserManager.try_auth(
|
||||||
|
request.authorization.username, request.authorization.password
|
||||||
|
)
|
||||||
if user is not None:
|
if user is not None:
|
||||||
request.user = user
|
request.user = user
|
||||||
return
|
return
|
||||||
@ -69,7 +76,11 @@ def authorize():
|
|||||||
password = request.values["p"]
|
password = request.values["p"]
|
||||||
password = decode_password(password)
|
password = decode_password(password)
|
||||||
|
|
||||||
user = UserManager.try_auth(username, password)
|
user = UserManager.try_auth_api(username, password)
|
||||||
|
if user is None and not require_api_key:
|
||||||
|
user = UserManager.try_auth(
|
||||||
|
request.authorization.username, request.authorization.password
|
||||||
|
)
|
||||||
if user is None:
|
if user is None:
|
||||||
raise Unauthorized()
|
raise Unauthorized()
|
||||||
|
|
||||||
|
125
supysonic/cli.py
125
supysonic/cli.py
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
import click
|
import click
|
||||||
import time
|
import time
|
||||||
|
import uuid
|
||||||
|
|
||||||
from click.exceptions import ClickException
|
from click.exceptions import ClickException
|
||||||
|
|
||||||
@ -236,12 +237,12 @@ def user():
|
|||||||
def user_list():
|
def user_list():
|
||||||
"""Lists users."""
|
"""Lists users."""
|
||||||
|
|
||||||
click.echo("Name\t\tAdmin\tJukebox\tEmail")
|
click.echo("Name\t\tLDAP\tAdmin\tJukebox\tEmail")
|
||||||
click.echo("----\t\t-----\t-------\t-----")
|
click.echo("----\t\t-----\t-----\t-------\t-----")
|
||||||
for u in User.select():
|
for u in User.select():
|
||||||
click.echo(
|
click.echo(
|
||||||
"{: <16}{}\t{}\t{}".format(
|
"{: <16}{}\t{}\t{}\t{}".format(
|
||||||
u.name, "*" if u.admin else "", "*" if u.jukebox else "", u.mail
|
u.name, "*" if u.ldap else "", "*" if u.admin else "", "*" if u.jukebox else "", u.mail
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -249,7 +250,7 @@ def user_list():
|
|||||||
@user.command("add")
|
@user.command("add")
|
||||||
@click.argument("name")
|
@click.argument("name")
|
||||||
@click.password_option("-p", "--password", help="Specifies the user's password")
|
@click.password_option("-p", "--password", help="Specifies the user's password")
|
||||||
@click.option("-e", "--email", default="", help="Sets the user's email address")
|
@click.option("-e", "--email", default=None, help="Sets the user's email address")
|
||||||
def user_add(name, password, email):
|
def user_add(name, password, email):
|
||||||
"""Adds a new user.
|
"""Adds a new user.
|
||||||
|
|
||||||
@ -262,10 +263,42 @@ def user_add(name, password, email):
|
|||||||
raise ClickException(str(e)) from e
|
raise ClickException(str(e)) from e
|
||||||
|
|
||||||
|
|
||||||
|
@user.group("edit")
|
||||||
|
def user_edit():
|
||||||
|
"""User edit commands"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@user_edit.command("email")
|
||||||
|
@click.argument("name")
|
||||||
|
@click.option("-e", "--email", prompt=True, default="", help="Sets the user's email address")
|
||||||
|
def user_edit_email(name, email):
|
||||||
|
"""Changes an user's email.
|
||||||
|
|
||||||
|
|
||||||
|
NAME is the name (or login) of the user to edit.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = User.get(name=name)
|
||||||
|
if user is None:
|
||||||
|
raise ClickException("No such user")
|
||||||
|
|
||||||
|
if user.ldap:
|
||||||
|
raise ClickException("Unavailable for LDAP users")
|
||||||
|
|
||||||
|
if email == "":
|
||||||
|
email = None
|
||||||
|
|
||||||
|
if user.mail != email:
|
||||||
|
user.mail = email
|
||||||
|
user.save()
|
||||||
|
click.echo(f"Updated user '{name}'")
|
||||||
|
|
||||||
|
|
||||||
@user.command("delete")
|
@user.command("delete")
|
||||||
@click.argument("name")
|
@click.argument("name")
|
||||||
def user_delete(name):
|
def user_delete(name):
|
||||||
"""Deletes a user.
|
"""Deletes an user.
|
||||||
|
|
||||||
NAME is the name of the user to delete.
|
NAME is the name of the user to delete.
|
||||||
"""
|
"""
|
||||||
@ -295,7 +328,7 @@ def _echo_role_change(username, name, value):
|
|||||||
help="Grant or revoke jukebox rights",
|
help="Grant or revoke jukebox rights",
|
||||||
)
|
)
|
||||||
def user_roles(name, admin, jukebox):
|
def user_roles(name, admin, jukebox):
|
||||||
"""Enable/disable rights for a user.
|
"""Enable/disable rights for an user.
|
||||||
|
|
||||||
NAME is the login of the user to which grant or revoke rights.
|
NAME is the login of the user to which grant or revoke rights.
|
||||||
"""
|
"""
|
||||||
@ -314,27 +347,31 @@ def user_roles(name, admin, jukebox):
|
|||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
|
|
||||||
@user.command("changepass")
|
@user_edit.command("password")
|
||||||
@click.argument("name")
|
@click.argument("name")
|
||||||
@click.password_option("-p", "--password", help="New password")
|
@click.password_option("-p", "--password", help="New password")
|
||||||
def user_changepass(name, password):
|
def user_changepass(name, password):
|
||||||
"""Changes a user's password.
|
"""Changes an user's password.
|
||||||
|
|
||||||
NAME is the login of the user to which change the password.
|
NAME is the login of the user to which change the password.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
user = User.get(name=name)
|
||||||
UserManager.change_password2(name, password)
|
if user is None:
|
||||||
click.echo(f"Successfully changed '{name}' password")
|
raise ClickException(f"User '{name}' does not exist.")
|
||||||
except User.DoesNotExist as e:
|
|
||||||
raise ClickException(f"User '{name}' does not exist.") from e
|
if user.ldap:
|
||||||
|
raise ClickException("Unavailable for LDAP users")
|
||||||
|
|
||||||
|
UserManager.change_password2(name, password)
|
||||||
|
click.echo(f"Successfully changed '{name}' password")
|
||||||
|
|
||||||
|
|
||||||
@user.command("rename")
|
@user_edit.command("username")
|
||||||
@click.argument("name")
|
@click.argument("name")
|
||||||
@click.argument("newname")
|
@click.argument("newname")
|
||||||
def user_rename(name, newname):
|
def user_rename(name, newname):
|
||||||
"""Renames a user.
|
"""Renames an user.
|
||||||
|
|
||||||
User NAME will then be known as NEWNAME.
|
User NAME will then be known as NEWNAME.
|
||||||
"""
|
"""
|
||||||
@ -361,6 +398,62 @@ def user_rename(name, newname):
|
|||||||
click.echo(f"User '{name}' renamed to '{newname}'")
|
click.echo(f"User '{name}' renamed to '{newname}'")
|
||||||
|
|
||||||
|
|
||||||
|
@user.group("apikey")
|
||||||
|
def user_apikey():
|
||||||
|
"""User API key commands"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@user_apikey.command("show")
|
||||||
|
@click.argument("name")
|
||||||
|
def user_apikey_show(name):
|
||||||
|
"""Shows the API key of an user.
|
||||||
|
|
||||||
|
NAME is the name (or login) of the user to show the API key.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = User.get(name=name)
|
||||||
|
if user is None:
|
||||||
|
raise ClickException(f"User '{name}' does not exist.")
|
||||||
|
|
||||||
|
click.echo(f"'{name}' API key: {user.api_key}")
|
||||||
|
|
||||||
|
|
||||||
|
@user_apikey.command("new")
|
||||||
|
@click.argument("name")
|
||||||
|
def user_apikey_new(name):
|
||||||
|
"""Generates a new API key for an user.
|
||||||
|
|
||||||
|
NAME is the name (or login) of the user to generate the API key for.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = User.get(name=name)
|
||||||
|
if user is None:
|
||||||
|
raise ClickException(f"User '{name}' does not exist.")
|
||||||
|
|
||||||
|
user.api_key = str(uuid.uuid4()).replace("-", "")
|
||||||
|
user.save()
|
||||||
|
click.echo(f"Updated '{name}' API key")
|
||||||
|
|
||||||
|
|
||||||
|
@user_apikey.command("delete")
|
||||||
|
@click.argument("name")
|
||||||
|
def user_apikey_delete(name):
|
||||||
|
"""Deletes the API key of an user.
|
||||||
|
|
||||||
|
NAME is the name (or login) of the user to delete the API key.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = User.get(name=name)
|
||||||
|
if user is None:
|
||||||
|
raise ClickException(f"User '{name}' does not exist.")
|
||||||
|
|
||||||
|
if user.api_key is not None:
|
||||||
|
user.api_key = None
|
||||||
|
user.save()
|
||||||
|
click.echo(f"Deleted '{name}' API key")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
config = IniConfig.from_common_locations()
|
config = IniConfig.from_common_locations()
|
||||||
init_database(config.BASE["database_uri"])
|
init_database(config.BASE["database_uri"])
|
||||||
|
@ -36,6 +36,7 @@ class DefaultConfig:
|
|||||||
"log_level": "WARNING",
|
"log_level": "WARNING",
|
||||||
"mount_webui": True,
|
"mount_webui": True,
|
||||||
"mount_api": True,
|
"mount_api": True,
|
||||||
|
"require_api_key": True,
|
||||||
"index_ignored_prefixes": "El La Le Las Les Los The",
|
"index_ignored_prefixes": "El La Le Las Les Los The",
|
||||||
}
|
}
|
||||||
DAEMON = {
|
DAEMON = {
|
||||||
@ -51,6 +52,14 @@ class DefaultConfig:
|
|||||||
LASTFM = {"api_key": None, "secret": None}
|
LASTFM = {"api_key": None, "secret": None}
|
||||||
TRANSCODING = {}
|
TRANSCODING = {}
|
||||||
MIMETYPES = {}
|
MIMETYPES = {}
|
||||||
|
LDAP = {
|
||||||
|
"url": None,
|
||||||
|
"bind_dn": None,
|
||||||
|
"bind_pw": None,
|
||||||
|
"base_dn": None,
|
||||||
|
"user_filter": None,
|
||||||
|
"mail_attr": "mail"
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
current_config = self
|
current_config = self
|
||||||
|
@ -428,12 +428,15 @@ class User(_Model):
|
|||||||
id = PrimaryKeyField()
|
id = PrimaryKeyField()
|
||||||
name = CharField(64, unique=True)
|
name = CharField(64, unique=True)
|
||||||
mail = CharField(null=True)
|
mail = CharField(null=True)
|
||||||
password = FixedCharField(40)
|
password = FixedCharField(40, null=True)
|
||||||
salt = FixedCharField(6)
|
salt = FixedCharField(6, null=True)
|
||||||
|
|
||||||
|
ldap = BooleanField(default=False)
|
||||||
admin = BooleanField(default=False)
|
admin = BooleanField(default=False)
|
||||||
jukebox = BooleanField(default=False)
|
jukebox = BooleanField(default=False)
|
||||||
|
|
||||||
|
api_key = CharField(32, null=True)
|
||||||
|
|
||||||
lastfm_session = FixedCharField(32, null=True)
|
lastfm_session = FixedCharField(32, null=True)
|
||||||
lastfm_status = BooleanField(
|
lastfm_status = BooleanField(
|
||||||
default=True
|
default=True
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
# Distributed under terms of the GNU AGPLv3 license.
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import uuid
|
||||||
|
|
||||||
from flask import flash, redirect, render_template, request, session, url_for
|
from flask import flash, redirect, render_template, request, session, url_for
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
@ -172,22 +173,37 @@ def change_username_post(uid):
|
|||||||
@frontend.route("/user/<uid>/changemail")
|
@frontend.route("/user/<uid>/changemail")
|
||||||
@me_or_uuid
|
@me_or_uuid
|
||||||
def change_mail_form(uid, user):
|
def change_mail_form(uid, user):
|
||||||
return render_template("change_mail.html", user=user)
|
if user.ldap:
|
||||||
|
flash("Unavailable for LDAP users")
|
||||||
|
return redirect(url_for("frontend.user_profile", uid=uid))
|
||||||
|
else:
|
||||||
|
return render_template("change_mail.html", user=user)
|
||||||
|
|
||||||
|
|
||||||
@frontend.route("/user/<uid>/changemail", methods=["POST"])
|
@frontend.route("/user/<uid>/changemail", methods=["POST"])
|
||||||
@me_or_uuid
|
@me_or_uuid
|
||||||
def change_mail_post(uid, user):
|
def change_mail_post(uid, user):
|
||||||
mail = request.form.get("mail", "")
|
mail = request.form.get("mail", "")
|
||||||
# No validation, lol.
|
if mail == "":
|
||||||
user.mail = mail
|
mail = None
|
||||||
|
if user.mail == mail:
|
||||||
|
flash("No changes made")
|
||||||
|
else:
|
||||||
|
# No validation, lol.
|
||||||
|
user.mail = mail
|
||||||
|
user.save()
|
||||||
|
flash("Email changed")
|
||||||
return redirect(url_for("frontend.user_profile", uid=uid))
|
return redirect(url_for("frontend.user_profile", uid=uid))
|
||||||
|
|
||||||
|
|
||||||
@frontend.route("/user/<uid>/changepass")
|
@frontend.route("/user/<uid>/changepass")
|
||||||
@me_or_uuid
|
@me_or_uuid
|
||||||
def change_password_form(uid, user):
|
def change_password_form(uid, user):
|
||||||
return render_template("change_pass.html", user=user)
|
if user.ldap:
|
||||||
|
flash("Unavailable for LDAP users")
|
||||||
|
return redirect(url_for("frontend.user_profile", uid=uid))
|
||||||
|
else:
|
||||||
|
return render_template("change_pass.html", user=user)
|
||||||
|
|
||||||
|
|
||||||
@frontend.route("/user/<uid>/changepass", methods=["POST"])
|
@frontend.route("/user/<uid>/changepass", methods=["POST"])
|
||||||
@ -235,8 +251,8 @@ def add_user_form():
|
|||||||
def add_user_post():
|
def add_user_post():
|
||||||
error = False
|
error = False
|
||||||
args = request.form.copy()
|
args = request.form.copy()
|
||||||
(name, passwd, passwd_confirm) = map(
|
(name, passwd, passwd_confirm, mail) = map(
|
||||||
args.pop, ("user", "passwd", "passwd_confirm"), (None,) * 3
|
args.pop, ("user", "passwd", "passwd_confirm", "mail"), (None,) * 4
|
||||||
)
|
)
|
||||||
if not name:
|
if not name:
|
||||||
flash("The name is required.")
|
flash("The name is required.")
|
||||||
@ -248,9 +264,12 @@ def add_user_post():
|
|||||||
flash("The passwords don't match.")
|
flash("The passwords don't match.")
|
||||||
error = True
|
error = True
|
||||||
|
|
||||||
|
if mail == "":
|
||||||
|
mail = None
|
||||||
|
|
||||||
if not error:
|
if not error:
|
||||||
try:
|
try:
|
||||||
UserManager.add(name, passwd, **args)
|
UserManager.add(name, passwd, mail=mail, **args)
|
||||||
flash(f"User '{name}' successfully added")
|
flash(f"User '{name}' successfully added")
|
||||||
return redirect(url_for("frontend.user_index"))
|
return redirect(url_for("frontend.user_index"))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
@ -333,3 +352,24 @@ def logout():
|
|||||||
session.clear()
|
session.clear()
|
||||||
flash("Logged out!")
|
flash("Logged out!")
|
||||||
return redirect(url_for("frontend.login"))
|
return redirect(url_for("frontend.login"))
|
||||||
|
|
||||||
|
|
||||||
|
@frontend.route("/user/<uid>/new_api_key")
|
||||||
|
@me_or_uuid
|
||||||
|
def new_api_key(uid, user):
|
||||||
|
user.api_key = str(uuid.uuid4()).replace("-", "")
|
||||||
|
user.save()
|
||||||
|
flash("API key updated")
|
||||||
|
return redirect(url_for("frontend.user_profile", uid=uid))
|
||||||
|
|
||||||
|
|
||||||
|
@frontend.route("/user/<uid>/del_api_key")
|
||||||
|
@me_or_uuid
|
||||||
|
def del_api_key(uid, user):
|
||||||
|
if user.api_key is None:
|
||||||
|
flash("No changes made")
|
||||||
|
else:
|
||||||
|
user.api_key = None
|
||||||
|
user.save()
|
||||||
|
flash("API key deleted")
|
||||||
|
return redirect(url_for("frontend.user_profile", uid=uid))
|
||||||
|
47
supysonic/ldap.py
Normal file
47
supysonic/ldap.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# This file is part of Supysonic.
|
||||||
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013-2018 Alban 'spl0k' Féron
|
||||||
|
#
|
||||||
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ldap3
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
ldap3 = None
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Ldap:
|
||||||
|
@staticmethod
|
||||||
|
def try_auth(username, password):
|
||||||
|
config = current_app.config["LDAP"]
|
||||||
|
if None in config.values():
|
||||||
|
return
|
||||||
|
elif not ldap3:
|
||||||
|
logger.warning("Module 'ldap3' is not installed.")
|
||||||
|
return
|
||||||
|
|
||||||
|
server = ldap3.Server(config["url"], get_info=None)
|
||||||
|
|
||||||
|
with ldap3.Connection(server, config["bind_dn"], config["bind_pw"], read_only=True) as conn:
|
||||||
|
conn.search(
|
||||||
|
config["base_dn"],
|
||||||
|
config["user_filter"].format(username=username),
|
||||||
|
search_scope=ldap3.LEVEL,
|
||||||
|
attributes=[config["mail_attr"]],
|
||||||
|
size_limit=1
|
||||||
|
)
|
||||||
|
entries = conn.entries
|
||||||
|
|
||||||
|
if entries:
|
||||||
|
try:
|
||||||
|
with ldap3.Connection(server, entries[0].entry_dn, password, read_only=True):
|
||||||
|
return {"mail": entries[0][config["mail_attr"]].value}
|
||||||
|
except ldap3.core.exceptions.LDAPBindError:
|
||||||
|
return False
|
@ -12,6 +12,7 @@ import string
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from ..db import User
|
from ..db import User
|
||||||
|
from ..ldap import Ldap
|
||||||
|
|
||||||
|
|
||||||
class UserManager:
|
class UserManager:
|
||||||
@ -45,15 +46,42 @@ class UserManager:
|
|||||||
user.delete_instance(recursive=True)
|
user.delete_instance(recursive=True)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def try_auth(name, password):
|
def try_auth_api(name, password):
|
||||||
user = User.get_or_none(name=name)
|
user = User.get_or_none(name=name)
|
||||||
if user is None:
|
if user is None:
|
||||||
return None
|
return None
|
||||||
elif UserManager.__encrypt_password(password, user.salt)[0] != user.password:
|
if user.api_key is None:
|
||||||
|
return None
|
||||||
|
elif password != user.api_key:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def try_auth(name, password):
|
||||||
|
ldap_user = Ldap.try_auth(name, password)
|
||||||
|
user = User.get_or_none(name=name)
|
||||||
|
|
||||||
|
if ldap_user is None:
|
||||||
|
if user is None:
|
||||||
|
return None
|
||||||
|
elif UserManager.__encrypt_password(password, user.salt)[0] != user.password:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return user
|
||||||
|
elif ldap_user:
|
||||||
|
if user is None:
|
||||||
|
user = User.create(name=name, mail=ldap_user["mail"], ldap=True)
|
||||||
|
return user
|
||||||
|
elif not user.ldap:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
if user.mail != ldap_user["mail"]:
|
||||||
|
user.mail = ldap_user["mail"]
|
||||||
|
return user
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def change_password(uid, old_pass, new_pass):
|
def change_password(uid, old_pass, new_pass):
|
||||||
user = UserManager.get(uid)
|
user = UserManager.get(uid)
|
||||||
|
@ -53,10 +53,12 @@ CREATE TABLE IF NOT EXISTS user (
|
|||||||
id CHAR(32) PRIMARY KEY,
|
id CHAR(32) PRIMARY KEY,
|
||||||
name VARCHAR(64) NOT NULL,
|
name VARCHAR(64) NOT NULL,
|
||||||
mail VARCHAR(256),
|
mail VARCHAR(256),
|
||||||
password CHAR(40) NOT NULL,
|
password CHAR(40),
|
||||||
salt CHAR(6) NOT NULL,
|
salt CHAR(6),
|
||||||
|
ldap BOOLEAN NOT NULL,
|
||||||
admin BOOLEAN NOT NULL,
|
admin BOOLEAN NOT NULL,
|
||||||
jukebox BOOLEAN NOT NULL,
|
jukebox BOOLEAN NOT NULL,
|
||||||
|
api_key CHAR(32),
|
||||||
lastfm_session CHAR(32),
|
lastfm_session CHAR(32),
|
||||||
lastfm_status BOOLEAN NOT NULL,
|
lastfm_status BOOLEAN NOT NULL,
|
||||||
last_play_id CHAR(32) REFERENCES track(id),
|
last_play_id CHAR(32) REFERENCES track(id),
|
||||||
|
@ -53,10 +53,12 @@ CREATE TABLE IF NOT EXISTS "user" (
|
|||||||
id UUID PRIMARY KEY,
|
id UUID PRIMARY KEY,
|
||||||
name VARCHAR(64) NOT NULL,
|
name VARCHAR(64) NOT NULL,
|
||||||
mail VARCHAR(256),
|
mail VARCHAR(256),
|
||||||
password CHAR(40) NOT NULL,
|
password CHAR(40),
|
||||||
salt CHAR(6) NOT NULL,
|
salt CHAR(6),
|
||||||
|
ldap BOOLEAN NOT NULL,
|
||||||
admin BOOLEAN NOT NULL,
|
admin BOOLEAN NOT NULL,
|
||||||
jukebox BOOLEAN NOT NULL,
|
jukebox BOOLEAN NOT NULL,
|
||||||
|
api_key CHAR(32),
|
||||||
lastfm_session CHAR(32),
|
lastfm_session CHAR(32),
|
||||||
lastfm_status BOOLEAN NOT NULL,
|
lastfm_status BOOLEAN NOT NULL,
|
||||||
last_play_id UUID REFERENCES track,
|
last_play_id UUID REFERENCES track,
|
||||||
|
@ -55,10 +55,12 @@ CREATE TABLE IF NOT EXISTS user (
|
|||||||
id CHAR(36) PRIMARY KEY,
|
id CHAR(36) PRIMARY KEY,
|
||||||
name VARCHAR(64) NOT NULL,
|
name VARCHAR(64) NOT NULL,
|
||||||
mail VARCHAR(256),
|
mail VARCHAR(256),
|
||||||
password CHAR(40) NOT NULL,
|
password CHAR(40),
|
||||||
salt CHAR(6) NOT NULL,
|
salt CHAR(6),
|
||||||
|
ldap BOOLEAN NOT NULL,
|
||||||
admin BOOLEAN NOT NULL,
|
admin BOOLEAN NOT NULL,
|
||||||
jukebox BOOLEAN NOT NULL,
|
jukebox BOOLEAN NOT NULL,
|
||||||
|
api_key CHAR(32),
|
||||||
lastfm_session CHAR(32),
|
lastfm_session CHAR(32),
|
||||||
lastfm_status BOOLEAN NOT NULL,
|
lastfm_status BOOLEAN NOT NULL,
|
||||||
last_play_id CHAR(36) REFERENCES track,
|
last_play_id CHAR(36) REFERENCES track,
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
<label class="sr-only" for="mail">eMail</label>
|
<label class="sr-only" for="mail">eMail</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-addon"><span class="glyphicon glyphicon-envelope"></span></div>
|
<div class="input-group-addon"><span class="glyphicon glyphicon-envelope"></span></div>
|
||||||
<input type="text" class="form-control" id="mail" name="mail" value="{{ request.form.mail or user.mail }}" placeholder="eMail" />
|
<input type="text" class="form-control" id="mail" name="mail" value="{{ user.mail or "" }}" placeholder="eMail" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" class="btn btn-default" />
|
<input type="submit" class="btn btn-default" />
|
||||||
|
@ -25,7 +25,9 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="page-header first-header">
|
<div class="page-header first-header">
|
||||||
<h2>{{ user.name }}{% if user.admin %} <small><span class="glyphicon
|
<h2>{{ user.name }}{% if user.ldap %} <small><span class="glyphicon
|
||||||
|
glyphicon-cloud" data-toggle="tooltip" data-placement="right" title="LDAP"></span></small>{% endif %}
|
||||||
|
{% if user.admin %} <small><span class="glyphicon
|
||||||
glyphicon-certificate" data-toggle="tooltip" data-placement="right"
|
glyphicon-certificate" data-toggle="tooltip" data-placement="right"
|
||||||
title="{% if request.user.id == user.id %}You're an admin!{% else %}The user is an admin!{% endif %}"></span></small>{% endif %}</h2>
|
title="{% if request.user.id == user.id %}You're an admin!{% else %}The user is an admin!{% endif %}"></span></small>{% endif %}</h2>
|
||||||
</div>
|
</div>
|
||||||
@ -37,6 +39,7 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-addon">User eMail</div>
|
<div class="input-group-addon">User eMail</div>
|
||||||
<input type="text" class="form-control" id="email" placeholder="{{ user.mail }}" readonly>
|
<input type="text" class="form-control" id="email" placeholder="{{ user.mail }}" readonly>
|
||||||
|
{% if not user.ldap %}
|
||||||
<div class="input-group-btn">
|
<div class="input-group-btn">
|
||||||
{% if request.user.id == user.id %}
|
{% if request.user.id == user.id %}
|
||||||
<a href="{{ url_for('frontend.change_mail_form', uid = 'me') }}" class="btn btn-default">Change eMail</a>
|
<a href="{{ url_for('frontend.change_mail_form', uid = 'me') }}" class="btn btn-default">Change eMail</a>
|
||||||
@ -44,6 +47,24 @@
|
|||||||
<a href="{{ url_for('frontend.change_mail_form', uid = user.id) }}" class="btn btn-default">Change eMail</a>
|
<a href="{{ url_for('frontend.change_mail_form', uid = user.id) }}" class="btn btn-default">Change eMail</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<form>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="sr-only" for="apikey">API key</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-addon">API key</div>
|
||||||
|
<input type="text" class="form-control" id="apikey" {% if user.api_key %}value{% else %}placeholder{% endif %}="{{ user.api_key }}" readonly>
|
||||||
|
<div class="input-group-btn">
|
||||||
|
<a href="{{ url_for('frontend.new_api_key', uid = 'me') if request.user.id == user.id else url_for('frontend.new_api_key', uid = user.id) }}" class="btn btn-default">
|
||||||
|
<span class="glyphicon glyphicon-refresh" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Generate key"></span></a>
|
||||||
|
<a href="{{ url_for('frontend.del_api_key', uid = 'me') if request.user.id == user.id else url_for('frontend.del_api_key', uid = user.id) }}" class="btn btn-default{% if not user.api_key %} disabled{% endif %}">
|
||||||
|
<span class="glyphicon glyphicon-remove-circle" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Delete key"></span></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -83,11 +104,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if request.user.id == user.id %}
|
{% if request.user.id == user.id %}
|
||||||
|
{% if not user.ldap %}
|
||||||
<a href="{{ url_for('frontend.change_password_form', uid = 'me') }}" class="btn btn-default">Change password</a></li>
|
<a href="{{ url_for('frontend.change_password_form', uid = 'me') }}" class="btn btn-default">Change password</a></li>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ url_for('frontend.change_username_form', uid = user.id) }}" class="btn btn-default">Change username or admin status</a></li>
|
<a href="{{ url_for('frontend.change_username_form', uid = user.id) }}" class="btn btn-default">Change username or admin status</a></li>
|
||||||
|
{% if not user.ldap %}
|
||||||
<a href="{{ url_for('frontend.change_password_form', uid = user.id) }}" class="btn btn-default">Change password</a></li>
|
<a href="{{ url_for('frontend.change_password_form', uid = user.id) }}" class="btn btn-default">Change password</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
{% if clients.count() %}
|
{% if clients.count() %}
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2>Clients</h2>
|
<h2>Clients</h2>
|
||||||
|
@ -18,14 +18,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<table class="table table-striped table-hover">
|
<table class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th>Name</th><th>EMail</th><th>Admin</th><th>Last play date</th><th></th></tr>
|
<tr><th>Name</th><th>EMail</th><th>LDAP</th><th>Admin</th><th>Last play date</th><th></th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for user in users %}
|
{% for user in users %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% if request.user.id == user.id %}{{ user.name }}{% else %}
|
<td>{% if request.user.id == user.id %}{{ user.name }}{% else %}
|
||||||
<a href="{{ url_for('frontend.user_profile', uid = user.id) }}">{{ user.name }}</a>{% endif %}</td>
|
<a href="{{ url_for('frontend.user_profile', uid = user.id) }}">{{ user.name }}</a>{% endif %}</td>
|
||||||
<td>{{ user.mail }}</td><td>{{ user.admin }}</td><td>{{ user.last_play_date }}</td><td>
|
<td>{{ user.mail }}</td><td>{{ user.ldap }}</td><td>{{ user.admin }}</td><td>{{ user.last_play_date }}</td><td>
|
||||||
{% if request.user.id != user.id %}<button class="btn btn-danger btn-xs" data-href="{{ url_for('frontend.del_user', uid = user.id) }}" data-toggle="modal" data-target="#confirm-delete" aria-label="Delete user">
|
{% if request.user.id != user.id %}<button class="btn btn-danger btn-xs" data-href="{{ url_for('frontend.del_user', uid = user.id) }}" data-toggle="modal" data-target="#confirm-delete" aria-label="Delete user">
|
||||||
<span class="glyphicon glyphicon-remove-circle" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Delete user"></span></button>{% endif %}</td></tr>
|
<span class="glyphicon glyphicon-remove-circle" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Delete user"></span></button>{% endif %}</td></tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
Loading…
Reference in New Issue
Block a user