diff --git a/docs/man/supysonic-cli-user.rst b/docs/man/supysonic-cli-user.rst index b4f51d5..3803d09 100644 --- a/docs/man/supysonic-cli-user.rst +++ b/docs/man/supysonic-cli-user.rst @@ -18,6 +18,7 @@ Synopsis | ``supysonic-cli user delete`` `user` | ``supysonic-cli user changepass`` `user` `password` | ``supysonic-cli user setroles`` [``--admin``\|\ ``--noadmin``] [``--jukebox``\|\ ``--nojukebox``] `user` +| ``supysonic-cli user rename`` `user` `newname` Description =========== @@ -42,6 +43,9 @@ a new user, delete an existing user, and change their password or roles. ``supysonic-cli user setroles`` [``--admin``\|\ ``--noadmin``] [``--jukebox``\|\ ``--nojukebox``] `user` Give or remove rights to user `user`. +``supysonic-cli user rename`` `user` `newname` + Rename the user `user` to `newname` + Options ======= diff --git a/supysonic/cli.py b/supysonic/cli.py index e40db65..7c8b292 100644 --- a/supysonic/cli.py +++ b/supysonic/cli.py @@ -1,7 +1,7 @@ # This file is part of Supysonic. # Supysonic is a Python implementation of the Subsonic server API. # -# Copyright (C) 2013-2019 Alban 'spl0k' Féron +# Copyright (C) 2013-2021 Alban 'spl0k' Féron # # Distributed under terms of the GNU AGPLv3 license. @@ -347,6 +347,11 @@ class SupysonicCLI(cmd.Cmd): "name", help="Name/login of the user to which change the password" ) user_pass_parser.add_argument("password", nargs="?", help="New password") + user_rename_parser = user_subparsers.add_parser( + "rename", help="Rename a user", add_help=False + ) + user_rename_parser.add_argument("name", help="Name of the user to rename") + user_rename_parser.add_argument("newname", help="New name for the user") @db_session def user_list(self): @@ -414,6 +419,27 @@ class SupysonicCLI(cmd.Cmd): except ObjectNotFound as e: self.write_error_line(str(e)) + @db_session + def user_rename(self, name, newname): + if not name or not newname: + self.write_error_line("Missing user current name or new name") + return + + if name == newname: + return + + user = User.get(name=name) + if user is None: + self.write_error_line("No such user") + return + + if User.get(name=newname) is not None: + self.write_error_line("This name is already taken") + return + + user.name = newname + self.write_line("User '{}' renamed to '{}'".format(name, newname)) + def main(): config = IniConfig.from_common_locations() diff --git a/tests/base/test_cli.py b/tests/base/test_cli.py index 5c3b692..f72ca3f 100644 --- a/tests/base/test_cli.py +++ b/tests/base/test_cli.py @@ -1,7 +1,7 @@ # This file is part of Supysonic. # Supysonic is a Python implementation of the Subsonic server API. # -# Copyright (C) 2017-2020 Alban 'spl0k' Féron +# Copyright (C) 2017-2021 Alban 'spl0k' Féron # # Distributed under terms of the GNU AGPLv3 license. @@ -137,6 +137,25 @@ class CLITestCase(unittest.TestCase): self.__cli.onecmd("user changepass alice newpass") self.__cli.onecmd("user changepass bob B0b") + def test_user_rename(self): + self.__cli.onecmd("user add -p Alic3 alice") + self.__cli.onecmd("user rename alice alice") + self.__cli.onecmd("user rename bob charles") + + self.__cli.onecmd("user rename alice ''") + with db_session: + self.assertEqual(User.select().first().name, "alice") + + self.__cli.onecmd("user rename alice bob") + with db_session: + self.assertEqual(User.select().first().name, "bob") + + self.__cli.onecmd("user add -p Ch4rl3s charles") + self.__cli.onecmd("user rename bob charles") + with db_session: + self.assertEqual(User.select(lambda u: u.name == "bob").count(), 1) + self.assertEqual(User.select(lambda u: u.name == "charles").count(), 1) + def test_other(self): self.assertTrue(self.__cli.do_EOF("")) self.__cli.onecmd("unknown command")