diff --git a/docs/api.md b/docs/api.md index d77855a..95603e8 100644 --- a/docs/api.md +++ b/docs/api.md @@ -691,7 +691,7 @@ No parameter | `adminRole` | | ✔️ | | `settingsRole` | | | | `streamRole` | | | -| `jukeboxRole` | | 📅 | +| `jukeboxRole` | | ✔️ | | `downloadRole` | | | | `uploadRole` | | | | `playlistRole` | | | diff --git a/supysonic/api/user.py b/supysonic/api/user.py index 498348a..fc84a55 100644 --- a/supysonic/api/user.py +++ b/supysonic/api/user.py @@ -1,9 +1,7 @@ -# coding: utf-8 -# # This file is part of Supysonic. # 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. @@ -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"]) @admin_only def user_add(): username = request.values["username"] password = request.values["password"] email = request.values["email"] - admin = request.values.get("adminRole") - admin = True if admin in (True, "True", "true", 1, "1") else False + roles = get_roles_dict() password = decode_password(password) - UserManager.add(username, password, email, admin) + UserManager.add(username, password, mail=email, **roles) return request.formatter.empty diff --git a/supysonic/cli.py b/supysonic/cli.py index 09e2792..52eb469 100755 --- a/supysonic/cli.py +++ b/supysonic/cli.py @@ -1,5 +1,3 @@ -# coding: utf-8 -# # This file is part of Supysonic. # Supysonic is a Python implementation of the Subsonic server API. # @@ -375,7 +373,7 @@ class SupysonicCLI(cmd.Cmd): try: if not password: password = self._ask_password() # pragma: nocover - UserManager.add(name, password, email, False) + UserManager.add(name, password, mail=email) except ValueError as e: self.write_error_line(str(e)) diff --git a/supysonic/frontend/user.py b/supysonic/frontend/user.py index 46d2582..8e57a75 100644 --- a/supysonic/frontend/user.py +++ b/supysonic/frontend/user.py @@ -1,5 +1,3 @@ -# coding: utf-8 -# # This file is part of Supysonic. # Supysonic is a Python implementation of the Subsonic server API. # @@ -231,8 +229,9 @@ def add_user_form(): @admin_only def add_user_post(): error = False - (name, passwd, passwd_confirm, mail, admin) = map( - request.form.get, ["user", "passwd", "passwd_confirm", "mail", "admin"] + args = request.form.copy() + (name, passwd, passwd_confirm) = map( + args.pop, ["user", "passwd", "passwd_confirm"], [None] * 3 ) if not name: flash("The name is required.") @@ -244,13 +243,9 @@ def add_user_post(): flash("The passwords don't match.") error = True - admin = admin is not None - if mail is None: - mail = "" - if not error: try: - UserManager.add(name, passwd, mail, admin) + UserManager.add(name, passwd, **args) flash("User '%s' successfully added" % name) return redirect(url_for("frontend.user_index")) except ValueError as e: diff --git a/supysonic/managers/user.py b/supysonic/managers/user.py index be7fda3..c1978b4 100644 --- a/supysonic/managers/user.py +++ b/supysonic/managers/user.py @@ -1,9 +1,7 @@ -# coding: utf-8 -# # This file is part of Supysonic. # 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 # # Distributed under terms of the GNU AGPLv3 license. @@ -31,15 +29,12 @@ class UserManager: return User[uid] @staticmethod - def add(name, password, mail, admin): + def add(name, password, **kwargs): if User.exists(name=name): raise ValueError("User '{}' exists".format(name)) crypt, salt = UserManager.__encrypt_password(password) - - user = User(name=name, mail=mail, password=crypt, salt=salt, admin=admin) - - return user + return User(name=name, password=crypt, salt=salt, **kwargs) @staticmethod def delete(uid): diff --git a/tests/api/test_user.py b/tests/api/test_user.py index 5e76727..d23b968 100644 --- a/tests/api/test_user.py +++ b/tests/api/test_user.py @@ -1,10 +1,9 @@ #!/usr/bin/env python -# coding: utf-8 # # This file is part of Supysonic. # 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 # # 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("email"), "unicorn@example.com") self.assertEqual(child.get("adminRole"), "true") + self.assertEqual(child.get("jukeboxRole"), "true") # admin gives full control self._make_request( "createUser", - {"username": "dave", "password": "Dav3", "email": "dave@example.com"}, + { + "username": "dave", + "password": "Dav3", + "email": "dave@example.com", + "jukeboxRole": True, + }, skip_post=True, ) rv, child = self._make_request("getUser", {"username": "dave"}, tag="user") self.assertEqual(child.get("username"), "dave") self.assertEqual(child.get("email"), "dave@example.com") 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") - self.assertEqual(len(child), 4) + self.assertEqual(len(child), 5) def test_delete_user(self): # non admin diff --git a/tests/managers/test_manager_user.py b/tests/managers/test_manager_user.py index 7b64213..ecb1708 100644 --- a/tests/managers/test_manager_user.py +++ b/tests/managers/test_manager_user.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # # This file is part of Supysonic. # Supysonic is a Python implementation of the Subsonic server API. @@ -31,15 +30,15 @@ class UserManagerTestCase(unittest.TestCase): @db_session def create_data(self): # Create some users - self.assertIsInstance( - UserManager.add("alice", "ALICE", "test@example.com", True), db.User - ) - self.assertIsInstance( - UserManager.add("bob", "BOB", "bob@example.com", False), db.User - ) - self.assertIsInstance( - UserManager.add("charlie", "CHARLIE", "charlie@example.com", False), db.User - ) + alice = UserManager.add("alice", "ALICE", admin=True) + self.assertIsInstance(alice, db.User) + self.assertTrue(alice.admin) + + bob = UserManager.add("bob", "BOB") + self.assertIsInstance(bob, db.User) + self.assertFalse(bob.admin) + + self.assertIsInstance(UserManager.add("charlie", "CHARLIE"), db.User) folder = db.Folder(name="Root", path="tests/assets", root=True) artist = db.Artist(name="Artist") @@ -97,9 +96,7 @@ class UserManagerTestCase(unittest.TestCase): self.assertEqual(db.User.select().count(), 3) # Create duplicate - self.assertRaises( - ValueError, UserManager.add, "alice", "Alic3", "alice@example.com", True - ) + self.assertRaises(ValueError, UserManager.add, "alice", "Alic3", admin=True) @db_session def test_delete_user(self): diff --git a/tests/testbase.py b/tests/testbase.py index 0864050..6e4ceef 100644 --- a/tests/testbase.py +++ b/tests/testbase.py @@ -93,8 +93,8 @@ class TestBase(unittest.TestCase): self.client = self.__app.test_client() with db_session: - UserManager.add("alice", "Alic3", "test@example.com", True) - UserManager.add("bob", "B0b", "bob@example.com", False) + UserManager.add("alice", "Alic3", admin=True) + UserManager.add("bob", "B0b") def _patch_client(self): self.client.get = patch_method(self.client.get)