[System][Plugin] users: Send users a link to set their own password and initially set random password
This commit is contained in:
parent
f42d5956db
commit
69ec4472c3
|
@ -41,6 +41,11 @@ welcome_subject = "Welcome to Flaschengeist {name}"
|
|||
welcome_text = '''
|
||||
Hello {name}!
|
||||
Welcome to Flaschengeist!
|
||||
|
||||
Your username is {username}, please set your password:
|
||||
{password_link}
|
||||
(If the link expires, please just use the Forgot-Password-function).
|
||||
|
||||
Have fun :)
|
||||
'''
|
||||
|
||||
|
|
|
@ -11,6 +11,23 @@ from flaschengeist.models.user import User, Role, _PasswordReset
|
|||
from flaschengeist.controller import messageController, sessionController
|
||||
|
||||
|
||||
def _generate_password_reset(user):
|
||||
"""Generate a password reset link for the user"""
|
||||
reset = _PasswordReset.query.get(user._id)
|
||||
if not reset:
|
||||
reset = _PasswordReset(_user_id=user._id)
|
||||
db.session.add(reset)
|
||||
|
||||
expires = datetime.now(tz=timezone.utc)
|
||||
if not reset.expires or reset.expires < expires:
|
||||
expires = expires + timedelta(hours=12)
|
||||
reset.expires = expires
|
||||
reset.token = secrets.token_urlsafe(24)
|
||||
db.session.commit()
|
||||
|
||||
return reset
|
||||
|
||||
|
||||
def login_user(username, password):
|
||||
logger.info("login user {{ {} }}".format(username))
|
||||
|
||||
|
@ -27,17 +44,7 @@ def login_user(username, password):
|
|||
|
||||
def request_reset(user: User):
|
||||
logger.debug(f"New password reset request for {user.userid}")
|
||||
reset = _PasswordReset.query.get(user._id)
|
||||
if not reset:
|
||||
reset = _PasswordReset(_user_id=user._id)
|
||||
db.session.add(reset)
|
||||
|
||||
expires = datetime.now(tz=timezone.utc)
|
||||
if not reset.expires or reset.expires < expires:
|
||||
expires = expires + timedelta(hours=12)
|
||||
reset.expires = expires
|
||||
reset.token = secrets.token_urlsafe(24)
|
||||
db.session.commit()
|
||||
reset = _generate_password_reset(user)
|
||||
|
||||
subject = str(config["MESSAGES"]["password_subject"]).format(name=user.display_name, username=user.userid)
|
||||
text = str(config["MESSAGES"]["password_text"]).format(
|
||||
|
@ -161,25 +168,24 @@ def delete(user):
|
|||
|
||||
|
||||
def register(data):
|
||||
for required in ["firstname", "lastname", "mail"]:
|
||||
if required not in data:
|
||||
raise BadRequest("Missing required parameters")
|
||||
allowed_keys = User().serialize().keys()
|
||||
values = {key: value for key, value in data.items() if key in allowed_keys}
|
||||
roles = values.pop("roles", [])
|
||||
user = User(**values)
|
||||
set_roles(user, roles)
|
||||
|
||||
current_app.config["FG_AUTH_BACKEND"].create_user(user, data["password"])
|
||||
|
||||
password = secrets.token_bytes(16)
|
||||
current_app.config["FG_AUTH_BACKEND"].create_user(user, password)
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
|
||||
if user.mail and len(user.mail) > 3:
|
||||
reset = _generate_password_reset(user)
|
||||
|
||||
subject = str(config["MESSAGES"]["welcome_subject"]).format(name=user.display_name, username=user.userid)
|
||||
text = str(config["MESSAGES"]["welcome_text"]).format(
|
||||
name=user.display_name,
|
||||
username=user.userid,
|
||||
password_link=f'https://{config["FLASCHENGEIST"]["domain"]}/reset?token={reset.token}'
|
||||
)
|
||||
messageController.send_message(messageController.Message(user, text, subject))
|
||||
|
||||
|
|
|
@ -24,17 +24,19 @@ _permission_register = "users_register"
|
|||
|
||||
|
||||
class UsersPlugin(Plugin):
|
||||
def __init__(self, config):
|
||||
def __init__(self, cfg):
|
||||
super().__init__(blueprint=users_bp, permissions=[_permission_edit, _permission_delete, _permission_set_roles])
|
||||
|
||||
|
||||
@users_bp.route("/users", methods=["POST"])
|
||||
def register():
|
||||
"""Register a new user
|
||||
The password will be set to a random string of at lease 16byte entropy.
|
||||
The user will receive a mail containing a link to set their own password.
|
||||
|
||||
Route: ``/users`` | Method: ``POST``
|
||||
|
||||
POST-data: Same as `flaschengeist.models.user.User` + ``password?: string``
|
||||
POST-data: Same as `flaschengeist.models.user.User`
|
||||
|
||||
Returns:
|
||||
JSON encoded `flaschengeist.models.user.User` or HTTP error
|
||||
|
@ -49,6 +51,9 @@ def register():
|
|||
data = request.get_json()
|
||||
if not data:
|
||||
raise BadRequest
|
||||
for required in ["firstname", "lastname", "mail"]:
|
||||
if required not in data:
|
||||
raise BadRequest("Missing required parameters")
|
||||
|
||||
logger.debug("Register new User...")
|
||||
return make_response(jsonify(userController.register(data)), CREATED)
|
||||
|
|
Loading…
Reference in New Issue