implement password reset command
This commit is contained in:
		| @@ -102,6 +102,9 @@ class User(object): | ||||
|             "password": self.password.toJson() | ||||
|         } | ||||
|  | ||||
|     def setPassword(self, password: Password): | ||||
|         self.password = password | ||||
|  | ||||
|  | ||||
| class UserList(object): | ||||
|     sharedInstance = None | ||||
| @@ -142,7 +145,7 @@ class UserList(object): | ||||
|     def _userToJson(self, u): | ||||
|         return u.toJson() | ||||
|  | ||||
|     def _store(self): | ||||
|     def store(self): | ||||
|         usersFile = self._getUsersFile() | ||||
|         users = [u.toJson() for u in self.users.values()] | ||||
|         try: | ||||
| @@ -169,7 +172,7 @@ class UserList(object): | ||||
|         if key not in self.users: | ||||
|             raise KeyError("User {user} doesn't exist".format(user=key)) | ||||
|         del self.users[key] | ||||
|         self._store() | ||||
|         self.store() | ||||
|  | ||||
|     def __getitem__(self, item): | ||||
|         return self.users[item] | ||||
| @@ -181,4 +184,4 @@ class UserList(object): | ||||
|         if key in self.users: | ||||
|             raise KeyError("User {user} already exists".format(user=key)) | ||||
|         self.users[key] = value | ||||
|         self._store() | ||||
|         self.store() | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| from owrx.version import openwebrx_version | ||||
| from owrxadmin.commands import NewUser, DeleteUser | ||||
| from owrxadmin.commands import NewUser, DeleteUser, ResetPassword | ||||
| import argparse | ||||
| import sys | ||||
| import traceback | ||||
| @@ -9,7 +9,7 @@ def main(): | ||||
|     print("OpenWebRX admin version {version}".format(version=openwebrx_version)) | ||||
|  | ||||
|     parser = argparse.ArgumentParser() | ||||
|     parser.add_argument("command", help="One of the following commands: adduser, removeuser") | ||||
|     parser.add_argument("command", help="One of the following commands: adduser, removeuser, resetpassword") | ||||
|     parser.add_argument( | ||||
|         "--noninteractive", action="store_true", help="Don't ask for any user input (useful for automation)" | ||||
|     ) | ||||
| @@ -21,6 +21,8 @@ def main(): | ||||
|         command = NewUser() | ||||
|     elif args.command == "removeuser": | ||||
|         command = DeleteUser() | ||||
|     elif args.command == "resetpassword": | ||||
|         command = ResetPassword() | ||||
|     else: | ||||
|         if not args.silent: | ||||
|             print("Unknown command: {command}".format(command=args.command)) | ||||
|   | ||||
| @@ -23,6 +23,26 @@ class UserCommand(Command, metaclass=ABCMeta): | ||||
|             else: | ||||
|                 return input("Please enter the user name: ") | ||||
|  | ||||
|     def getPassword(self, args, username): | ||||
|         if args.noninteractive: | ||||
|             print("Generating password for user {username}...".format(username=username)) | ||||
|             password = self.getRandomPassword() | ||||
|             print('Password for {username} is "{password}".'.format(username=username, password=password)) | ||||
|             # TODO implement this threat | ||||
|             print('This password is suitable for initial setup only, you will be asked to reset it on initial use.') | ||||
|             print('This password cannot be recovered from the system, please copy it now.') | ||||
|         else: | ||||
|             password = getpass("Please enter the new password for {username}: ".format(username=username)) | ||||
|             confirm = getpass("Please confirm the new password: ") | ||||
|             if password != confirm: | ||||
|                 print("ERROR: Password mismatch.") | ||||
|                 sys.exit(1) | ||||
|         return password | ||||
|  | ||||
|     def getRandomPassword(self, length=10): | ||||
|         printable = list(string.ascii_letters) + list(string.digits) | ||||
|         return ''.join(random.choices(printable, k=length)) | ||||
|  | ||||
|  | ||||
| class NewUser(UserCommand): | ||||
|     def run(self, args): | ||||
| @@ -32,28 +52,12 @@ class NewUser(UserCommand): | ||||
|         if username in userList: | ||||
|             raise KeyError("User {username} already exists".format(username=username)) | ||||
|  | ||||
|         if args.noninteractive: | ||||
|             print("Generating password for user {username}...".format(username=username)) | ||||
|             password = self.getRandomPassword() | ||||
|             print('Password for {username} is "{password}".'.format(username=username, password=password)) | ||||
|             # TODO implement this threat | ||||
|             print('This password is suitable for initial setup only, you will be asked to reset it on initial use.') | ||||
|             print('This password cannot be recovered from the system, please copy it now.') | ||||
|         else: | ||||
|             password = getpass("Please enter the password for {username}: ".format(username=username)) | ||||
|             confirm = getpass("Please confirm password: ") | ||||
|             if password != confirm: | ||||
|                 print("ERROR: Password mismatch.") | ||||
|                 sys.exit(1) | ||||
|         password = self.getPassword(args, username) | ||||
|  | ||||
|         print("Creating user {username}...".format(username=username)) | ||||
|         user = User(name=username, enabled=True, password=DefaultPasswordClass(password)) | ||||
|         userList.addUser(user) | ||||
|  | ||||
|     def getRandomPassword(self, length=10): | ||||
|         printable = list(string.ascii_letters) + list(string.digits) | ||||
|         return ''.join(random.choices(printable, k=length)) | ||||
|  | ||||
|  | ||||
| class DeleteUser(UserCommand): | ||||
|     def run(self, args): | ||||
| @@ -61,3 +65,14 @@ class DeleteUser(UserCommand): | ||||
|         print("Deleting user {username}...".format(username=username)) | ||||
|         userList = UserList() | ||||
|         userList.deleteUser(username) | ||||
|  | ||||
|  | ||||
| class ResetPassword(UserCommand): | ||||
|     def run(self, args): | ||||
|         username = self.getUser(args) | ||||
|         password = self.getPassword(args, username) | ||||
|         userList = UserList() | ||||
|         userList[username].setPassword(DefaultPasswordClass(password)) | ||||
|         # this is a change to an object in the list, not the list itself | ||||
|         # in this case, store() is explicit | ||||
|         userList.store() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jakob Ketterl
					Jakob Ketterl