implement password reset command

This commit is contained in:
Jakob Ketterl 2021-02-06 19:12:44 +01:00
parent 635bf55465
commit 01c58327aa
3 changed files with 42 additions and 22 deletions

View File

@ -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()

View File

@ -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))

View File

@ -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()