1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06:17 +00:00

Ability to grant jukebox right when creating an user from the API

This commit is contained in:
Alban Féron 2020-11-10 15:38:24 +01:00
parent c2f5ec43b9
commit debb396b0e
No known key found for this signature in database
GPG Key ID: 8CE0313646D16165
8 changed files with 55 additions and 46 deletions

View File

@ -691,7 +691,7 @@ No parameter
| `adminRole` | | ✔️ | | `adminRole` | | ✔️ |
| `settingsRole` | | | | `settingsRole` | | |
| `streamRole` | | | | `streamRole` | | |
| `jukeboxRole` | | 📅 | | `jukeboxRole` | | ✔️ |
| `downloadRole` | | | | `downloadRole` | | |
| `uploadRole` | | | | `uploadRole` | | |
| `playlistRole` | | | | `playlistRole` | | |

View File

@ -1,9 +1,7 @@
# coding: utf-8
#
# This file is part of Supysonic. # This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
# #
# Copyright (C) 2013-2018 Alban 'spl0k' Féron # Copyright (C) 2013-2020 Alban 'spl0k' Féron
# #
# Distributed under terms of the GNU AGPLv3 license. # Distributed under terms of the GNU AGPLv3 license.
@ -49,17 +47,26 @@ def users_info():
) )
def get_roles_dict():
roles = {}
for role in ("admin", "jukebox"):
value = request.values.get(role + "Role")
value = value in (True, "True", "true", 1, "1")
roles[role] = value
return roles
@api.route("/createUser.view", methods=["GET", "POST"]) @api.route("/createUser.view", methods=["GET", "POST"])
@admin_only @admin_only
def user_add(): def user_add():
username = request.values["username"] username = request.values["username"]
password = request.values["password"] password = request.values["password"]
email = request.values["email"] email = request.values["email"]
admin = request.values.get("adminRole") roles = get_roles_dict()
admin = True if admin in (True, "True", "true", 1, "1") else False
password = decode_password(password) password = decode_password(password)
UserManager.add(username, password, email, admin) UserManager.add(username, password, mail=email, **roles)
return request.formatter.empty return request.formatter.empty

View File

@ -1,5 +1,3 @@
# coding: utf-8
#
# This file is part of Supysonic. # This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
# #
@ -375,7 +373,7 @@ class SupysonicCLI(cmd.Cmd):
try: try:
if not password: if not password:
password = self._ask_password() # pragma: nocover password = self._ask_password() # pragma: nocover
UserManager.add(name, password, email, False) UserManager.add(name, password, mail=email)
except ValueError as e: except ValueError as e:
self.write_error_line(str(e)) self.write_error_line(str(e))

View File

@ -1,5 +1,3 @@
# coding: utf-8
#
# This file is part of Supysonic. # This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
# #
@ -231,8 +229,9 @@ def add_user_form():
@admin_only @admin_only
def add_user_post(): def add_user_post():
error = False error = False
(name, passwd, passwd_confirm, mail, admin) = map( args = request.form.copy()
request.form.get, ["user", "passwd", "passwd_confirm", "mail", "admin"] (name, passwd, passwd_confirm) = map(
args.pop, ["user", "passwd", "passwd_confirm"], [None] * 3
) )
if not name: if not name:
flash("The name is required.") flash("The name is required.")
@ -244,13 +243,9 @@ def add_user_post():
flash("The passwords don't match.") flash("The passwords don't match.")
error = True error = True
admin = admin is not None
if mail is None:
mail = ""
if not error: if not error:
try: try:
UserManager.add(name, passwd, mail, admin) UserManager.add(name, passwd, **args)
flash("User '%s' successfully added" % name) flash("User '%s' successfully added" % name)
return redirect(url_for("frontend.user_index")) return redirect(url_for("frontend.user_index"))
except ValueError as e: except ValueError as e:

View File

@ -1,9 +1,7 @@
# coding: utf-8
#
# This file is part of Supysonic. # This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
# #
# Copyright (C) 2013-2018 Alban 'spl0k' Féron # Copyright (C) 2013-2020 Alban 'spl0k' Féron
# 2017 Óscar García Amor # 2017 Óscar García Amor
# #
# Distributed under terms of the GNU AGPLv3 license. # Distributed under terms of the GNU AGPLv3 license.
@ -31,15 +29,12 @@ class UserManager:
return User[uid] return User[uid]
@staticmethod @staticmethod
def add(name, password, mail, admin): def add(name, password, **kwargs):
if User.exists(name=name): if User.exists(name=name):
raise ValueError("User '{}' exists".format(name)) raise ValueError("User '{}' exists".format(name))
crypt, salt = UserManager.__encrypt_password(password) crypt, salt = UserManager.__encrypt_password(password)
return User(name=name, password=crypt, salt=salt, **kwargs)
user = User(name=name, mail=mail, password=crypt, salt=salt, admin=admin)
return user
@staticmethod @staticmethod
def delete(uid): def delete(uid):

View File

@ -1,10 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
# coding: utf-8
# #
# This file is part of Supysonic. # This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
# #
# Copyright (C) 2017-2018 Alban 'spl0k' Féron # Copyright (C) 2017-2020 Alban 'spl0k' Féron
# 2017 Óscar García Amor # 2017 Óscar García Amor
# #
# Distributed under terms of the GNU AGPLv3 license. # Distributed under terms of the GNU AGPLv3 license.
@ -98,19 +97,37 @@ class UserTestCase(ApiTestBase):
self.assertEqual(child.get("username"), "charlie") self.assertEqual(child.get("username"), "charlie")
self.assertEqual(child.get("email"), "unicorn@example.com") self.assertEqual(child.get("email"), "unicorn@example.com")
self.assertEqual(child.get("adminRole"), "true") self.assertEqual(child.get("adminRole"), "true")
self.assertEqual(child.get("jukeboxRole"), "true") # admin gives full control
self._make_request( self._make_request(
"createUser", "createUser",
{"username": "dave", "password": "Dav3", "email": "dave@example.com"}, {
"username": "dave",
"password": "Dav3",
"email": "dave@example.com",
"jukeboxRole": True,
},
skip_post=True, skip_post=True,
) )
rv, child = self._make_request("getUser", {"username": "dave"}, tag="user") rv, child = self._make_request("getUser", {"username": "dave"}, tag="user")
self.assertEqual(child.get("username"), "dave") self.assertEqual(child.get("username"), "dave")
self.assertEqual(child.get("email"), "dave@example.com") self.assertEqual(child.get("email"), "dave@example.com")
self.assertEqual(child.get("adminRole"), "false") self.assertEqual(child.get("adminRole"), "false")
self.assertEqual(child.get("jukeboxRole"), "true")
self._make_request(
"createUser",
{"username": "eve", "password": "3ve", "email": "eve@example.com"},
skip_post=True,
)
rv, child = self._make_request("getUser", {"username": "eve"}, tag="user")
self.assertEqual(child.get("username"), "eve")
self.assertEqual(child.get("email"), "eve@example.com")
self.assertEqual(child.get("adminRole"), "false")
self.assertEqual(child.get("jukeboxRole"), "false")
rv, child = self._make_request("getUsers", tag="users") rv, child = self._make_request("getUsers", tag="users")
self.assertEqual(len(child), 4) self.assertEqual(len(child), 5)
def test_delete_user(self): def test_delete_user(self):
# non admin # non admin

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python
# coding: utf-8
# #
# This file is part of Supysonic. # This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
@ -31,15 +30,15 @@ class UserManagerTestCase(unittest.TestCase):
@db_session @db_session
def create_data(self): def create_data(self):
# Create some users # Create some users
self.assertIsInstance( alice = UserManager.add("alice", "ALICE", admin=True)
UserManager.add("alice", "ALICE", "test@example.com", True), db.User self.assertIsInstance(alice, db.User)
) self.assertTrue(alice.admin)
self.assertIsInstance(
UserManager.add("bob", "BOB", "bob@example.com", False), db.User bob = UserManager.add("bob", "BOB")
) self.assertIsInstance(bob, db.User)
self.assertIsInstance( self.assertFalse(bob.admin)
UserManager.add("charlie", "CHARLIE", "charlie@example.com", False), db.User
) self.assertIsInstance(UserManager.add("charlie", "CHARLIE"), db.User)
folder = db.Folder(name="Root", path="tests/assets", root=True) folder = db.Folder(name="Root", path="tests/assets", root=True)
artist = db.Artist(name="Artist") artist = db.Artist(name="Artist")
@ -97,9 +96,7 @@ class UserManagerTestCase(unittest.TestCase):
self.assertEqual(db.User.select().count(), 3) self.assertEqual(db.User.select().count(), 3)
# Create duplicate # Create duplicate
self.assertRaises( self.assertRaises(ValueError, UserManager.add, "alice", "Alic3", admin=True)
ValueError, UserManager.add, "alice", "Alic3", "alice@example.com", True
)
@db_session @db_session
def test_delete_user(self): def test_delete_user(self):

View File

@ -93,8 +93,8 @@ class TestBase(unittest.TestCase):
self.client = self.__app.test_client() self.client = self.__app.test_client()
with db_session: with db_session:
UserManager.add("alice", "Alic3", "test@example.com", True) UserManager.add("alice", "Alic3", admin=True)
UserManager.add("bob", "B0b", "bob@example.com", False) UserManager.add("bob", "B0b")
def _patch_client(self): def _patch_client(self):
self.client.get = patch_method(self.client.get) self.client.get = patch_method(self.client.get)