codekingpro/portable-devtools
114k
1"""2 flask_security.changeable3 ~~~~~~~~~~~~~~~~~~~~~~~~~4 5 Flask-Security change password module6 7 :copyright: (c) 2012 by Matt Wright.8 :copyright: (c) 2019-2024 by J. Christopher Wagner (jwag).9 :author: Eskil Heyn Olsen10 :license: MIT, see LICENSE for more details.11"""12 13from __future__ import annotations14 15import typing as t16 17from flask import current_app, request, session18from flask_login import COOKIE_NAME as REMEMBER_COOKIE_NAME19 20from .proxies import _datastore21from .signals import password_changed22from .utils import config_value as cv, hash_password, login_user, send_mail23 24if t.TYPE_CHECKING: # pragma: no cover25 from .datastore import User26 27 28def send_password_changed_notice(user):29 """Sends the password changed notice email for the specified user.30 31 :param user: The user to send the notice to32 """33 if cv("SEND_PASSWORD_CHANGE_EMAIL"):34 subject = cv("EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE")35 send_mail(subject, user.email, "change_notice", user=user)36 37 38def change_user_password(39 user: User, password: str | None, notify: bool = True, autologin: bool = True40) -> None:41 """Change the specified user's password42 43 :param user: The user object44 :param password: The unhashed new password45 :param notify: if True send notification (if configured) to user46 :param autologin: if True, login user47 """48 49 if password:50 user.password = hash_password(password)51 else:52 user.password = None53 # Change uniquifier - this will cause ALL sessions to be invalidated.54 _datastore.set_uniquifier(user)55 _datastore.put(user)56 57 if autologin:58 # re-login user - this will update session, optional remember etc.59 remember_cookie_name = current_app.config.get(60 "REMEMBER_COOKIE_NAME", REMEMBER_COOKIE_NAME61 )62 has_remember_cookie = (63 remember_cookie_name in request.cookies64 and session.get("remember") != "clear"65 )66 login_user(user, remember=has_remember_cookie, authn_via=["change"])67 if notify:68 send_password_changed_notice(user)69 password_changed.send(70 current_app._get_current_object(), # type: ignore71 _async_wrapper=current_app.ensure_sync,72 user=user,73 )74 75 76def admin_change_password(user: User, new_passwd: str, notify: bool = True) -> None:77 """78 Administratively change a user's password.79 Note that this will immediately render the user's existing sessions (and possibly80 authentication tokens) invalid.81 82 It is up to the caller to inform the user of their new password by some83 out-of-band means.84 85 :param user: The user object to change86 :param new_passwd: The new plain-text password to assign to the user.87 :param notify: If True and :py:data:`SECURITY_SEND_PASSWORD_CHANGE_EMAIL` is True88 send the 'change_notice' email to the user.89 """90 change_user_password(user, new_passwd, notify=notify, autologin=False)91 