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() "password": self.password.toJson()
} }
def setPassword(self, password: Password):
self.password = password
class UserList(object): class UserList(object):
sharedInstance = None sharedInstance = None
@ -142,7 +145,7 @@ class UserList(object):
def _userToJson(self, u): def _userToJson(self, u):
return u.toJson() return u.toJson()
def _store(self): def store(self):
usersFile = self._getUsersFile() usersFile = self._getUsersFile()
users = [u.toJson() for u in self.users.values()] users = [u.toJson() for u in self.users.values()]
try: try:
@ -169,7 +172,7 @@ class UserList(object):
if key not in self.users: if key not in self.users:
raise KeyError("User {user} doesn't exist".format(user=key)) raise KeyError("User {user} doesn't exist".format(user=key))
del self.users[key] del self.users[key]
self._store() self.store()
def __getitem__(self, item): def __getitem__(self, item):
return self.users[item] return self.users[item]
@ -181,4 +184,4 @@ class UserList(object):
if key in self.users: if key in self.users:
raise KeyError("User {user} already exists".format(user=key)) raise KeyError("User {user} already exists".format(user=key))
self.users[key] = value self.users[key] = value
self._store() self.store()

View File

@ -1,5 +1,5 @@
from owrx.version import openwebrx_version from owrx.version import openwebrx_version
from owrxadmin.commands import NewUser, DeleteUser from owrxadmin.commands import NewUser, DeleteUser, ResetPassword
import argparse import argparse
import sys import sys
import traceback import traceback
@ -9,7 +9,7 @@ def main():
print("OpenWebRX admin version {version}".format(version=openwebrx_version)) print("OpenWebRX admin version {version}".format(version=openwebrx_version))
parser = argparse.ArgumentParser() 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( parser.add_argument(
"--noninteractive", action="store_true", help="Don't ask for any user input (useful for automation)" "--noninteractive", action="store_true", help="Don't ask for any user input (useful for automation)"
) )
@ -21,6 +21,8 @@ def main():
command = NewUser() command = NewUser()
elif args.command == "removeuser": elif args.command == "removeuser":
command = DeleteUser() command = DeleteUser()
elif args.command == "resetpassword":
command = ResetPassword()
else: else:
if not args.silent: if not args.silent:
print("Unknown command: {command}".format(command=args.command)) print("Unknown command: {command}".format(command=args.command))

View File

@ -23,6 +23,26 @@ class UserCommand(Command, metaclass=ABCMeta):
else: else:
return input("Please enter the user name: ") 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): class NewUser(UserCommand):
def run(self, args): def run(self, args):
@ -32,28 +52,12 @@ class NewUser(UserCommand):
if username in userList: if username in userList:
raise KeyError("User {username} already exists".format(username=username)) raise KeyError("User {username} already exists".format(username=username))
if args.noninteractive: password = self.getPassword(args, username)
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)
print("Creating user {username}...".format(username=username)) print("Creating user {username}...".format(username=username))
user = User(name=username, enabled=True, password=DefaultPasswordClass(password)) user = User(name=username, enabled=True, password=DefaultPasswordClass(password))
userList.addUser(user) 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): class DeleteUser(UserCommand):
def run(self, args): def run(self, args):
@ -61,3 +65,14 @@ class DeleteUser(UserCommand):
print("Deleting user {username}...".format(username=username)) print("Deleting user {username}...".format(username=username))
userList = UserList() userList = UserList()
userList.deleteUser(username) 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()