1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
"""
flask_security.password_util
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Utility class providing methods for validating and normalizing passwords.
:copyright: (c) 2020-2024 by J. Christopher Wagner (jwag).
:license: MIT, see LICENSE for more details.
"""
from __future__ import annotations
import typing as t
import unicodedata
from .utils import (
config_value,
password_length_validator,
password_breached_validator,
password_complexity_validator,
)
if t.TYPE_CHECKING: # pragma: no cover
import flask
class PasswordUtil:
"""
Utility class providing methods for validating and normalizing passwords.
To provide your own implementation, pass in the class as ``password_util_cls``
at init time. Your class will be instantiated once as part of app initialization.
.. versionadded:: 4.0.0
"""
def __init__(self, app: flask.Flask):
"""Instantiate class.
:param app: The Flask application being initialized.
"""
pass
def normalize(self, password: str) -> str:
"""
Given an input password - return a normalized version (using Python's
unicodedata.normalize()).
Must be called in app context and uses
:py:data:`SECURITY_PASSWORD_NORMALIZE_FORM` config variable.
"""
cf = config_value("PASSWORD_NORMALIZE_FORM")
if cf:
return unicodedata.normalize(cf, password)
return password
def validate(
self, password: str, is_register: bool, **kwargs: t.Any
) -> tuple[list | None, str]:
"""
Password validation.
Called in app/request context.
If is_register is True then kwargs will be the contents of the register form.
If is_register is False, then there is a single kwarg "user" which has the
current user data model.
The password is first normalized then validated.
Return value is a tuple ([msgs], normalized_password)
"""
pnorm = self.normalize(password)
notok = password_length_validator(pnorm)
if notok:
return notok, pnorm
notok = password_breached_validator(pnorm)
if notok:
return notok, pnorm
return password_complexity_validator(pnorm, is_register, **kwargs), pnorm
|