diff --git a/Flask-Security-Too-5.3.3.tar.gz b/Flask-Security-Too-5.3.3.tar.gz deleted file mode 100644 index e8d1701..0000000 --- a/Flask-Security-Too-5.3.3.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c1ed93aae536f2a3ff8abe1e13aec9d0d95fb7ff082fcc3b372df2a5213970d9 -size 616595 diff --git a/Flask-Security-Too-5.4.3.tar.gz b/Flask-Security-Too-5.4.3.tar.gz new file mode 100644 index 0000000..75a365f --- /dev/null +++ b/Flask-Security-Too-5.4.3.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62b19397e8d71a8d4cb8dc0d4409cc7a1497982549030396960aee518755e583 +size 652228 diff --git a/python-Flask-Security-Too.changes b/python-Flask-Security-Too.changes index 1e8e825..daba2f9 100644 --- a/python-Flask-Security-Too.changes +++ b/python-Flask-Security-Too.changes @@ -1,3 +1,78 @@ +------------------------------------------------------------------- +Fri May 31 12:12:17 UTC 2024 - Antonio Larrosa + +- Update to 5.4.3: + + Fixes + * Regression - some templates no longer getting correct config + * CSRF not properly ignored for application forms using + :py SECURITY_CSRF_PROTECT_MECHANISMS. + * Improve jp translations + * Regression - datetime_factory should still be an attribute + * :py SECURITY_RETURN_GENERIC_RESPONSES hide email + validation/syntax errors. + +- Update to 5.4.2: + + Fixes + * OpenAPI spec missing. + * Doc fixes + * Update ES/IT translations + +- Update to 5.4.0 & 5.4.1: + + Features and improvements: + * Work with Flask[async]. view decorators and signals support + async handlers. + * CI support for python 3.12 + * Work with py_webauthn 2.0 (and only 2.0+) + * Improve (and simplify) Two-Factor setup. See below for + backwards compatability issues and new functionality. + * Improve oauth debugging support. Handle next propagation in a + more general way. + * Make AnonymousUser (Flask-Login) optional and deprecated. + * Remove undocumented and untested looking in session for + possible 'next' redirect location. + * No longer rely on Flask-Login.unauthorized callback. See + below for implications. + * Changes to default unauthorized handler - remove use of + referrer header (see below) and document precise behavior. + * The authentication_token format has changed - adding + per-token expiry time and future session ID. Old tokens are + still accepted. + + Docs and Chores + * Improve method translations for unified signin and two + factor. Remove support for Flask-Babelex. + * Chore - stop setting all config as attributes. + init_app(**kwargs) can only set forms, flags, and utility + classes (see below for compatibility concerns). + * Update Spanish and Italian translations. + * Improve translations for two-factor method selection. + * Improve German translations. + * Remove deprecation of AUTO_LOGIN_AFTER_CONFIRM - it has a + reasonable use case. + * Update message extraction - note that the + CONFIRM_REGISTRATION message was changed to improve + readability. + + Fixes + * us-signin magic link should use fs_uniquifier (not email). + * Improve open-redirect vulnerability mitigation. (see below) + * user_datastore.create_user has side effects on mutable + inputs. (NoRePercussions) + * The long deprecated _unauthorized_callback/handler has been + removed. + * Oauth re-used POST_LOGIN_VIEW which caused confusion. See + below for the new configuration and implications. + * Improve CSRF documentation and testing. Fix bug where a CSRF + failure could return an HTML page even if the request was + JSON. + * Register with JSON and authentication token failed CSRF. + * Fix 2 issues with CSRF configuration. + * It was possible that if SECURITY_EMAIL_VALIDATOR_ARGS were + set that deliverability would be checked even for login. + + Backwards Compatibility Concerns + Please read the full changelog at + https://github.com/Flask-Middleware/flask-security/blob/master/CHANGES.rst#version-540--541 +- Drop patch that's already included by upstream: + * support-python-312.patch + ------------------------------------------------------------------- Mon Feb 12 04:11:51 UTC 2024 - Steve Kowalik diff --git a/python-Flask-Security-Too.spec b/python-Flask-Security-Too.spec index 3ab7b24..e98d0fb 100644 --- a/python-Flask-Security-Too.spec +++ b/python-Flask-Security-Too.spec @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-Flask-Security-Too -Version: 5.3.3 +Version: 5.4.3 Release: 0 Summary: Security for Flask apps License: MIT @@ -27,8 +27,6 @@ Source: https://files.pythonhosted.org/packages/source/F/Flask-Security- Patch0: no-mongodb.patch # PATCH-FIX-OPENSUSE Use pyqrcodeng, we do not ship qrcode in OpenSUSE. Patch1: use-pyqrcodeng.patch -# PATCH-FIX-UPSTREAM Based on gh#Flask-Middleware/flask-security#900 -Patch2: support-python-312.patch BuildRequires: %{python_module Authlib} BuildRequires: %{python_module Babel >= 2.10.0} BuildRequires: %{python_module Flask >= 2.3.2} @@ -37,7 +35,7 @@ BuildRequires: %{python_module Flask-Login >= 0.6.2} BuildRequires: %{python_module Flask-Mailman >= 0.3.0} BuildRequires: %{python_module Flask-Principal >= 0.4.0} BuildRequires: %{python_module Flask-SQLAlchemy >= 3.0.3} -BuildRequires: %{python_module Flask-WTF >= 1.1.1} +BuildRequires: %{python_module Flask-WTF >= 1.1.2} BuildRequires: %{python_module MarkupSafe >= 2.1.0} BuildRequires: %{python_module PyQRCode >= 1.2} BuildRequires: %{python_module SQLAlchemy} @@ -49,8 +47,8 @@ BuildRequires: %{python_module bcrypt >= 4.0.1} BuildRequires: %{python_module bleach >= 6.0.0} BuildRequires: %{python_module cachetools >= 3.1.0} BuildRequires: %{python_module cryptography >= 40.0.2} -BuildRequires: %{python_module dateutil} BuildRequires: %{python_module email-validator >= 2.0} +BuildRequires: %{python_module freezegun} BuildRequires: %{python_module importlib_resources >= 5.10.0} BuildRequires: %{python_module itsdangerous >= 1.1.0} BuildRequires: %{python_module passlib >= 1.7.4} @@ -61,6 +59,7 @@ BuildRequires: %{python_module pony if %python-base < 3.11} BuildRequires: %{python_module pytest >= 6.2.5} BuildRequires: %{python_module requests} BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module webauthn >= 2.0.0} BuildRequires: %{python_module wheel} BuildRequires: %{python_module zxcvbn >= 4.4.28} BuildRequires: fdupes @@ -69,7 +68,7 @@ Requires: python-Flask >= 2.3.2 Requires: python-Flask-Babel >= 3.1.0 Requires: python-Flask-Login >= 0.6.2 Requires: python-Flask-Principal >= 0.4.0 -Requires: python-Flask-WTF >= 1.1.1 +Requires: python-Flask-WTF >= 1.1.2 Requires: python-MarkupSafe >= 2.1.0 Requires: python-WTForms >= 3.0.0 Requires: python-Werkzeug >= 2.3.3 @@ -80,6 +79,7 @@ Requires: python-email-validator >= 2.0 Requires: python-importlib_resources >= 5.10.0 Requires: python-itsdangerous >= 1.1.0 Requires: python-passlib >= 1.7.4 +Requires: python-webauthn >= 2.0.0 Recommends: python-PyQRCode >= 1.2 Recommends: python-SQLAlchemy Recommends: python-zxcvbn >= 4.4.28 diff --git a/support-python-312.patch b/support-python-312.patch deleted file mode 100644 index 3fd2afa..0000000 --- a/support-python-312.patch +++ /dev/null @@ -1,792 +0,0 @@ -From f7733559de7c8cd8a5bd683b2c53b523b6fb639b Mon Sep 17 00:00:00 2001 -From: Chris Wagner -Date: Sun, 7 Jan 2024 15:38:43 -0800 -Subject: [PATCH] Updates for python 3.12 - -- add CI support -- utcnow is deprecated - create our own so DB is still naive UTC timestamps -- remove use of dateutil (it was just used for tests) -- many places didn't use DATETIME_FACTORY - now they do -- update translations -- many copyright dates -- remove JSON compatibility code for Flask pre 2.x ---- - .github/workflows/tests.yml | 12 +- - .pre-commit-config.yaml | 2 +- - CHANGES.rst | 1 + - LICENSE | 2 +- - README.rst | 2 +- - docs/conf.py | 4 +- - docs/configuration.rst | 5 +- - examples/unified_signin/server/api.py | 6 +- - flask_security/__init__.py | 7 +- - flask_security/core.py | 6 +- - flask_security/datastore.py | 30 +- - flask_security/json.py | 40 +-- - flask_security/models/fsqla.py | 9 +- - flask_security/password_util.py | 2 +- - .../af_ZA/LC_MESSAGES/flask_security.po | 284 +++++++++-------- - .../ca_ES/LC_MESSAGES/flask_security.po | 275 ++++++++-------- - .../da_DK/LC_MESSAGES/flask_security.po | 275 ++++++++-------- - .../de_DE/LC_MESSAGES/flask_security.po | 294 +++++++++--------- - .../es_ES/LC_MESSAGES/flask_security.po | 292 ++++++++--------- - .../eu_ES/LC_MESSAGES/flask_security.po | 281 +++++++++-------- - .../translations/flask_security.pot | 267 ++++++++-------- - .../fr_FR/LC_MESSAGES/flask_security.po | 282 +++++++++-------- - .../hu_HU/LC_MESSAGES/flask_security.po | 285 +++++++++-------- - .../hy_AM/LC_MESSAGES/flask_security.po | 289 ++++++++--------- - .../is_IS/LC_MESSAGES/flask_security.po | 275 ++++++++-------- - .../it_IT/LC_MESSAGES/flask_security.po | 285 +++++++++-------- - .../ja_JP/LC_MESSAGES/flask_security.po | 275 ++++++++-------- - .../nl_NL/LC_MESSAGES/flask_security.po | 287 +++++++++-------- - .../pl_PL/LC_MESSAGES/flask_security.po | 287 +++++++++-------- - .../pt_BR/LC_MESSAGES/flask_security.po | 275 ++++++++-------- - .../pt_PT/LC_MESSAGES/flask_security.po | 275 ++++++++-------- - .../ru_RU/LC_MESSAGES/flask_security.po | 287 +++++++++-------- - .../tr_TR/LC_MESSAGES/flask_security.po | 275 ++++++++-------- - .../zh_Hans_CN/LC_MESSAGES/flask_security.po | 277 +++++++++-------- - flask_security/utils.py | 35 ++- - flask_security/webauthn.py | 7 +- - pyproject.toml | 4 +- - pytest.ini | 2 + - requirements/tests.txt | 5 +- - tests/conftest.py | 7 +- - tests/test_datastore.py | 16 +- - tests/test_webauthn.py | 7 +- - tests/view_scaffold.py | 17 +- - tox.ini | 6 +- - 44 files changed, 3028 insertions(+), 2828 deletions(-) - -Index: Flask-Security-Too-5.3.3/LICENSE -=================================================================== ---- Flask-Security-Too-5.3.3.orig/LICENSE -+++ Flask-Security-Too-5.3.3/LICENSE -@@ -1,7 +1,7 @@ - MIT License - - Copyright (C) 2012-2021 by Matthew Wright --Copyright (C) 2019-2021 by Chris Wagner -+Copyright (C) 2019-2024 by Chris Wagner - - Permission is hereby granted, free of charge, to any person obtaining a copy of - this software and associated documentation files (the "Software"), to deal in -Index: Flask-Security-Too-5.3.3/docs/configuration.rst -=================================================================== ---- Flask-Security-Too-5.3.3.orig/docs/configuration.rst -+++ Flask-Security-Too-5.3.3/docs/configuration.rst -@@ -578,9 +578,10 @@ Core - rarely need changing - - .. py:data:: SECURITY_DATETIME_FACTORY - -- Specifies the default datetime factory. -+ Specifies the default datetime factory. The default is naive-UTC which -+ corresponds to many DB's DateTime type. - -- Default:``datetime.datetime.utcnow``. -+ Default:``flask_security.naive_utcnow``. - - .. py:data:: SECURITY_CONFIRM_SALT - -Index: Flask-Security-Too-5.3.3/examples/unified_signin/server/api.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/examples/unified_signin/server/api.py -+++ Flask-Security-Too-5.3.3/examples/unified_signin/server/api.py -@@ -1,10 +1,10 @@ - """ --Copyright 2020 by J. Christopher Wagner (jwag). All rights reserved. -+Copyright 2020-2024 by J. Christopher Wagner (jwag). All rights reserved. - :license: MIT, see LICENSE for more details. - - """ - --from datetime import datetime -+from datetime import datetime, timezone - - from flask import Blueprint, abort, current_app, jsonify - from flask_security import auth_required -@@ -17,7 +17,7 @@ api = Blueprint("api", __name__) - @api.route("/health", methods=["GET"]) - @auth_required("session") - def health(): -- return jsonify(secret="lush oranges", date=datetime.utcnow()) -+ return jsonify(secret="lush oranges", date=datetime.now(timezone.utc)) - - - @api.route("/popmail", methods=["GET"]) -Index: Flask-Security-Too-5.3.3/flask_security/__init__.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/flask_security/__init__.py -+++ Flask-Security-Too-5.3.3/flask_security/__init__.py -@@ -2,11 +2,11 @@ - flask_security - ~~~~~~~~~~~~~~ - -- Flask-Security is a Flask extension that aims to add quick and simple -- security via Flask-Login, Flask-Principal, Flask-WTF, and passlib. -+ Flask-Security is a Flask extension that aims to add comprehensive security -+ to Flask applications. - - :copyright: (c) 2012-2019 by Matt Wright. -- :copyright: (c) 2019-2023 by J. Christopher Wagner. -+ :copyright: (c) 2019-2024 by J. Christopher Wagner. - :license: MIT, see LICENSE for more details. - """ - -@@ -111,6 +111,7 @@ from .utils import ( - login_user, - logout_user, - lookup_identity, -+ naive_utcnow, - password_breached_validator, - password_complexity_validator, - password_length_validator, -Index: Flask-Security-Too-5.3.3/flask_security/core.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/flask_security/core.py -+++ Flask-Security-Too-5.3.3/flask_security/core.py -@@ -7,7 +7,7 @@ - :copyright: (c) 2012 by Matt Wright. - :copyright: (c) 2017 by CERN. - :copyright: (c) 2017 by ETH Zurich, Swiss Data Science Center. -- :copyright: (c) 2019-2023 by J. Christopher Wagner (jwag). -+ :copyright: (c) 2019-2024 by J. Christopher Wagner (jwag). - :license: MIT, see LICENSE for more details. - """ - -@@ -95,6 +95,7 @@ from .utils import ( - get_identity_attributes, - get_message, - get_request_attr, -+ naive_utcnow, - localize_callback, - set_request_attr, - uia_email_mapper, -@@ -283,7 +284,7 @@ _default_config: t.Dict[str, t.Any] = { - "API_ENABLED_METHODS": ["session", "token"], - "HASHING_SCHEMES": ["sha256_crypt", "hex_md5"], - "DEPRECATED_HASHING_SCHEMES": ["hex_md5"], -- "DATETIME_FACTORY": datetime.utcnow, -+ "DATETIME_FACTORY": naive_utcnow, - "TOTP_SECRETS": None, - "TOTP_ISSUER": None, - "SMS_SERVICE": "Dummy", -@@ -1255,6 +1256,7 @@ class Security: - self.register_blueprint: bool - self.two_factor_plugins: TfPlugin - self.oauthglue: t.Optional[OAuthGlue] = None -+ self.datetime_factory: t.Callable[[], datetime] - - self.login_manager: "flask_login.LoginManager" - self._mail_util: MailUtil -Index: Flask-Security-Too-5.3.3/flask_security/datastore.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/flask_security/datastore.py -+++ Flask-Security-Too-5.3.3/flask_security/datastore.py -@@ -5,10 +5,10 @@ - This module contains an user datastore classes. - - :copyright: (c) 2012 by Matt Wright. -- :copyright: (c) 2019-2023 by J. Christopher Wagner (jwag). -+ :copyright: (c) 2019-2024 by J. Christopher Wagner (jwag). - :license: MIT, see LICENSE for more details. - """ --import datetime -+from datetime import datetime - import json - import typing as t - import uuid -@@ -817,6 +817,8 @@ class SQLAlchemyUserDatastore(SQLAlchemy - extensions: t.Optional[str] = None, - **kwargs: t.Any, - ) -> None: -+ from .proxies import _security -+ - if not hasattr(self, "webauthn_model") or not self.webauthn_model: - raise NotImplementedError - -@@ -830,7 +832,7 @@ class SQLAlchemyUserDatastore(SQLAlchemy - backup_state=backup_state, - transports=transports, - extensions=extensions, -- lastuse_datetime=datetime.datetime.utcnow(), -+ lastuse_datetime=_security.datetime_factory(), - **kwargs, - ) - user.webauthn.append(webauthn) -@@ -944,6 +946,8 @@ class MongoEngineUserDatastore(MongoEngi - extensions: t.Optional[str] = None, - **kwargs: t.Any, - ) -> None: -+ from .proxies import _security -+ - if not hasattr(self, "webauthn_model") or not self.webauthn_model: - raise NotImplementedError - webauthn = self.webauthn_model( -@@ -957,7 +961,7 @@ class MongoEngineUserDatastore(MongoEngi - backup_state=backup_state, - transports=transports, - extensions=extensions, -- lastuse_datetime=datetime.datetime.utcnow(), -+ lastuse_datetime=_security.datetime_factory(), - **kwargs, - ) - user.webauthn.append(webauthn) -@@ -1079,6 +1083,8 @@ class PeeweeUserDatastore(PeeweeDatastor - extensions: t.Optional[str] = None, - **kwargs: t.Any, - ) -> None: -+ from .proxies import _security -+ - if not hasattr(self, "webauthn_model") or not self.webauthn_model: - raise NotImplementedError - webauthn = self.webauthn_model( -@@ -1092,7 +1098,7 @@ class PeeweeUserDatastore(PeeweeDatastor - backup_state=backup_state, - transports=transports, - extensions=extensions, -- lastuse_datetime=datetime.datetime.utcnow(), -+ lastuse_datetime=_security.datetime_factory(), - **kwargs, - ) - self.put(webauthn) # type: ignore -@@ -1164,9 +1170,9 @@ if t.TYPE_CHECKING: # pragma: no cover - fs_uniquifier: str - fs_token_uniquifier: str - fs_webauthn_user_handle: str -- confirmed_at: t.Optional[datetime.datetime] -- last_login_at: datetime.datetime -- current_login_at: datetime.datetime -+ confirmed_at: t.Optional[datetime] -+ last_login_at: datetime -+ current_login_at: datetime - last_login_ip: t.Optional[str] - current_login_ip: t.Optional[str] - login_count: int -@@ -1176,8 +1182,8 @@ if t.TYPE_CHECKING: # pragma: no cover - mf_recovery_codes: t.Optional[t.List[str]] - us_phone_number: t.Optional[str] - us_totp_secrets: t.Optional[t.Union[str, bytes]] -- create_datetime: datetime.datetime -- update_datetime: datetime.datetime -+ create_datetime: datetime -+ update_datetime: datetime - roles: t.List["Role"] - webauthn: t.List["WebAuthn"] - -@@ -1189,7 +1195,7 @@ if t.TYPE_CHECKING: # pragma: no cover - name: str - description: t.Optional[str] - permissions: t.Optional[t.List[str]] -- update_datetime: datetime.datetime -+ update_datetime: datetime - - def __init__(self, **kwargs): - ... -@@ -1204,7 +1210,7 @@ if t.TYPE_CHECKING: # pragma: no cover - backup_state: bool - device_type: str - extensions: t.Optional[str] -- lastuse_datetime: datetime.datetime -+ lastuse_datetime: datetime - user_id: int - usage: str - -Index: Flask-Security-Too-5.3.3/flask_security/json.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/flask_security/json.py -+++ Flask-Security-Too-5.3.3/flask_security/json.py -@@ -1,32 +1,13 @@ - """ - Flask-Security JSON extensions. - -- :copyright: (c) 2022-2023 by J. Christopher Wagner (jwag). -+ :copyright: (c) 2022-2024 by J. Christopher Wagner (jwag). - :license: MIT, see LICENSE for more details. - - Pieces of this code liberally copied from flask-mongoengine. - """ - - --def _use_encoder(superclass): # pragma: no cover -- """Flask < 2.2""" -- -- class FsJsonEncoder(superclass): -- """Flask-Security JSON encoder. -- Extends Flask's JSONencoder to handle lazy-text. -- """ -- -- def default(self, obj): -- from .babel import is_lazy_string -- -- if is_lazy_string(obj): -- return str(obj) -- else: -- return super().default(obj) -- -- return FsJsonEncoder -- -- - def _use_provider(superclass): - """Flask 2.2 onwards - customize JSONProvider""" - -@@ -44,19 +25,6 @@ def _use_provider(superclass): - - def setup_json(app, bp=None): - # Called at init_app time. -- if hasattr(app, "json_provider_class"): -- # Flask >= 2.2 -- app.json_provider_class = _use_provider(app.json_provider_class) -- app.json = app.json_provider_class(app) -- # a bit if a hack - if a package (e.g. flask-mongoengine) hasn't -- # converted yet - they might use json_encoder. This ONLY applies -- # to this specific version of Flask that happens to use _json_encoder to -- # signal if any app/extension has registered an old style encoder. -- # (app.json_encoder is always set) -- # (If they do, then Flask 2.2.x won't use json_provider at all) -- # Of course if they do this AFTER we're initialized all bets are off. -- if getattr(app, "_json_encoder", None): -- app.json_encoder = _use_encoder(app.json_encoder) -- -- elif bp: # pragma: no cover -- bp.json_encoder = _use_encoder(app.json_encoder) -+ # Flask >= 2.2 -+ app.json_provider_class = _use_provider(app.json_provider_class) -+ app.json = app.json_provider_class(app) -Index: Flask-Security-Too-5.3.3/flask_security/models/fsqla.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/flask_security/models/fsqla.py -+++ Flask-Security-Too-5.3.3/flask_security/models/fsqla.py -@@ -1,5 +1,5 @@ - """ --Copyright 2019-2021 by J. Christopher Wagner (jwag). All rights reserved. -+Copyright 2019-2024 by J. Christopher Wagner (jwag). All rights reserved. - :license: MIT, see LICENSE for more details. - - -@@ -11,7 +11,6 @@ BE AWARE: Once any version of this is sh - a new version needs to be created. - """ - --import datetime - from typing import cast - from sqlalchemy import ( - Boolean, -@@ -25,7 +24,7 @@ from sqlalchemy.ext.declarative import d - from sqlalchemy.ext.mutable import MutableList - from sqlalchemy.sql import func - --from flask_security import AsaList, RoleMixin, UserMixin -+from flask_security import AsaList, RoleMixin, UserMixin, naive_utcnow - - - class FsModels: -@@ -77,7 +76,7 @@ class FsRoleMixin(RoleMixin): - type_=DateTime, - nullable=False, - server_default=func.now(), -- onupdate=datetime.datetime.utcnow, -+ onupdate=naive_utcnow, - ) - - -@@ -126,5 +125,5 @@ class FsUserMixin(UserMixin): - type_=DateTime, - nullable=False, - server_default=func.now(), -- onupdate=datetime.datetime.utcnow, -+ onupdate=naive_utcnow, - ) -Index: Flask-Security-Too-5.3.3/flask_security/password_util.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/flask_security/password_util.py -+++ Flask-Security-Too-5.3.3/flask_security/password_util.py -@@ -4,7 +4,7 @@ - - Utility class providing methods for validating and normalizing passwords. - -- :copyright: (c) 2020-2021 by J. Christopher Wagner (jwag). -+ :copyright: (c) 2020-2024 by J. Christopher Wagner (jwag). - :license: MIT, see LICENSE for more details. - - """ -Index: Flask-Security-Too-5.3.3/flask_security/utils.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/flask_security/utils.py -+++ Flask-Security-Too-5.3.3/flask_security/utils.py -@@ -5,12 +5,12 @@ - Flask-Security utils module - - :copyright: (c) 2012-2019 by Matt Wright. -- :copyright: (c) 2019-2023 by J. Christopher Wagner (jwag). -+ :copyright: (c) 2019-2024 by J. Christopher Wagner (jwag). - :license: MIT, see LICENSE for more details. - """ - import abc - import base64 --import datetime -+from datetime import datetime, timedelta, timezone - from functools import partial - import hashlib - import hmac -@@ -104,6 +104,25 @@ else: - return response - - -+# From a miguel grinberg blog around dealing with 3.12. -+# Our default SQLAlchemy Datetime is naive. -+# Note that most code should call _security.datetime_factory() -+def aware_utcnow(): -+ return datetime.now(timezone.utc) -+ -+ -+def aware_utcfromtimestamp(timestamp): -+ return datetime.fromtimestamp(timestamp, timezone.utc) -+ -+ -+def naive_utcnow(): -+ return aware_utcnow().replace(tzinfo=None) -+ -+ -+def naive_utcfromtimestamp(timestamp): -+ return aware_utcfromtimestamp(timestamp).replace(tzinfo=None) -+ -+ - def find_csrf_field_name(): - """ - We need to clear it on logout (since that isn't being done by Flask-WTF). -@@ -207,8 +226,8 @@ def logout_user() -> None: - - - def check_and_update_authn_fresh( -- within: datetime.timedelta, -- grace: datetime.timedelta, -+ within: timedelta, -+ grace: timedelta, - method: t.Optional[str] = None, - ) -> bool: - """Check if user authenticated within specified time and update grace period. -@@ -255,7 +274,7 @@ def check_and_update_authn_fresh( - # No session, you can't play. - return False - -- now = datetime.datetime.utcnow() -+ now = naive_utcnow() - new_exp = now + grace - grace_ts = int(new_exp.timestamp()) - -@@ -271,7 +290,7 @@ def check_and_update_authn_fresh( - session["fs_gexp"] = grace_ts - return False - -- authn_time = datetime.datetime.utcfromtimestamp(session["fs_paa"]) -+ authn_time = naive_utcfromtimestamp(session["fs_paa"]) - # allow for some time drift where it's possible authn_time is in the future - # but let's be cautious and not allow arbitrary future times - delta = now - authn_time -@@ -673,7 +692,7 @@ def get_within_delta(key, app=None): - """ - txt = config_value(key, app=app) - values = txt.split() -- return datetime.timedelta(**{values[1]: int(values[0])}) -+ return timedelta(**{values[1]: int(values[0])}) - - - def send_mail(subject, recipient, template, **context): -@@ -758,7 +777,7 @@ def get_token_status(token, serializer, - - - def check_and_get_token_status( -- token: str, serializer_name: str, within: datetime.timedelta -+ token: str, serializer_name: str, within: timedelta - ) -> t.Tuple[bool, bool, t.Any]: - """Get the status of a token and return data. - -Index: Flask-Security-Too-5.3.3/flask_security/webauthn.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/flask_security/webauthn.py -+++ Flask-Security-Too-5.3.3/flask_security/webauthn.py -@@ -4,7 +4,7 @@ - - Flask-Security WebAuthn module - -- :copyright: (c) 2021-2023 by J. Christopher Wagner (jwag). -+ :copyright: (c) 2021-2024 by J. Christopher Wagner (jwag). - :license: MIT, see LICENSE for more details. - - This implements support for webauthn/FIDO2 Level 2 using the py_webauthn package. -@@ -36,7 +36,6 @@ - - """ - --import datetime - import json - import time - import typing as t -@@ -677,7 +676,7 @@ def webauthn_signin_response(token: str) - after_this_request(view_commit) - assert form.cred - assert form.user -- form.cred.lastuse_datetime = datetime.datetime.utcnow() -+ form.cred.lastuse_datetime = _security.datetime_factory() - form.cred.sign_count = form.authentication_verification.new_sign_count - form.cred.backup_state = getattr( - form.authentication_verification, "credential_backed_up", False -@@ -833,7 +832,7 @@ def webauthn_verify_response(token: str) - # update last use and sign count - after_this_request(view_commit) - assert form.cred -- form.cred.lastuse_datetime = datetime.datetime.utcnow() -+ form.cred.lastuse_datetime = _security.datetime_factory() - form.cred.sign_count = form.authentication_verification.new_sign_count - _datastore.put(form.cred) - -Index: Flask-Security-Too-5.3.3/pyproject.toml -=================================================================== ---- Flask-Security-Too-5.3.3.orig/pyproject.toml -+++ Flask-Security-Too-5.3.3/pyproject.toml -@@ -31,6 +31,7 @@ classifiers=[ - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", -+ "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Development Status :: 5 - Production/Stable", -@@ -70,7 +71,6 @@ low = [ - "babel==2.12.1", - "bcrypt==4.0.1", - "bleach==6.0.0", -- "python-dateutil==2.8.2", - "jinja2==3.1.2", - "itsdangerous==2.1.2", - "markupsafe==2.1.2", -@@ -82,6 +82,8 @@ low = [ - "qrcode==7.4.2", - # authlib requires requests - "requests", -+ # passlib required setuptools -+ "setuptools", - "sqlalchemy==2.0.12", - "sqlalchemy-utils==0.41.1", - "webauthn==1.11.0", -Index: Flask-Security-Too-5.3.3/pytest.ini -=================================================================== ---- Flask-Security-Too-5.3.3.orig/pytest.ini -+++ Flask-Security-Too-5.3.3/pytest.ini -@@ -20,6 +20,8 @@ filterwarnings = - ignore::DeprecationWarning:mongoengine: - ignore::DeprecationWarning:flask_login:0 - ignore::DeprecationWarning:pydantic_core:0 -+ # next for py 3.12 -+ ignore::DeprecationWarning:pkg_resources:0 - ignore::UserWarning:cbor2:0 - ignore:.*passwordless feature.*:DeprecationWarning:flask_security:0 - ignore::DeprecationWarning:passlib:0 -Index: Flask-Security-Too-5.3.3/requirements/tests.txt -=================================================================== ---- Flask-Security-Too-5.3.3.orig/requirements/tests.txt -+++ Flask-Security-Too-5.3.3/requirements/tests.txt -@@ -3,7 +3,7 @@ Babel - Flask-Login@git+https://github.com/maxcountryman/flask-login@main - Flask-Mailman - Flask-Principal --peewee -+peewee; python_version < '3.12' - Flask-SQLAlchemy - argon2_cffi - authlib -@@ -13,7 +13,6 @@ check-manifest - coverage - cryptography - djlint --python-dateutil - mongoengine - mongomock - msgcheck -@@ -27,6 +26,8 @@ pytest - qrcode - # authlib requires requests - requests -+# passlib requires setuptools which is deprecated -+setuptools - sqlalchemy - sqlalchemy-utils - webauthn -Index: Flask-Security-Too-5.3.3/tests/conftest.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/tests/conftest.py -+++ Flask-Security-Too-5.3.3/tests/conftest.py -@@ -5,7 +5,7 @@ - Test fixtures and what not - - :copyright: (c) 2017 by CERN. -- :copyright: (c) 2019-2022 by J. Christopher Wagner (jwag). -+ :copyright: (c) 2019-2024 by J. Christopher Wagner (jwag). - :license: MIT, see LICENSE for more details. - """ - -@@ -37,6 +37,7 @@ from flask_security import ( - auth_token_required, - http_auth_required, - get_request_attr, -+ naive_utcnow, - login_required, - roles_accepted, - roles_required, -@@ -563,7 +564,7 @@ def sqlalchemy_session_setup(request, ap - DateTime, - nullable=False, - server_default=func.now(), -- onupdate=datetime.utcnow, -+ onupdate=naive_utcnow, - ) - - class User(Base, UserMixin): -@@ -597,7 +598,7 @@ def sqlalchemy_session_setup(request, ap - DateTime, - nullable=False, - server_default=func.now(), -- onupdate=datetime.utcnow, -+ onupdate=naive_utcnow, - ) - - @declared_attr -Index: Flask-Security-Too-5.3.3/tests/test_datastore.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/tests/test_datastore.py -+++ Flask-Security-Too-5.3.3/tests/test_datastore.py -@@ -5,15 +5,21 @@ - Datastore tests - - :copyright: (c) 2012 by Matt Wright. -- :copyright: (c) 2019-2022 by J. Christopher Wagner (jwag). -+ :copyright: (c) 2019-2024 by J. Christopher Wagner (jwag). - :license: MIT, see LICENSE for more details. - """ - --import datetime - from pytest import raises, skip, importorskip - from tests.test_utils import init_app_with_options, get_num_queries, is_sqlalchemy - --from flask_security import RoleMixin, Security, UserMixin, LoginForm, RegisterForm -+from flask_security import ( -+ RoleMixin, -+ Security, -+ UserMixin, -+ LoginForm, -+ RegisterForm, -+ naive_utcnow, -+) - from flask_security.datastore import Datastore, UserDatastore - - -@@ -294,7 +300,7 @@ def test_modify_permissions(app, datasto - assert perms == t1.get_permissions() - if hasattr(t1, "update_datetime"): - orig_update_time = t1.update_datetime -- assert t1.update_datetime <= datetime.datetime.utcnow() -+ assert t1.update_datetime <= naive_utcnow() - - ds.add_permissions_to_role(t1, "execute") - ds.commit() -@@ -414,7 +420,7 @@ def test_uuid(app, request, tmpdir, real - username = Column(String(255), unique=True, nullable=True) - password = Column(String(255)) - active = Column(Boolean()) -- created_at = Column(DateTime, default=datetime.datetime.utcnow) -+ created_at = Column(DateTime, default=naive_utcnow()) - confirmed_at = Column(DateTime()) - roles = relationship( - "Role", secondary="roles_users", backref=backref("users", lazy="dynamic") -Index: Flask-Security-Too-5.3.3/tests/test_webauthn.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/tests/test_webauthn.py -+++ Flask-Security-Too-5.3.3/tests/test_webauthn.py -@@ -4,7 +4,7 @@ - - WebAuthn tests - -- :copyright: (c) 2021-2023 by J. Christopher Wagner (jwag). -+ :copyright: (c) 2021-2024 by J. Christopher Wagner (jwag). - :license: MIT, see LICENSE for more details. - - """ -@@ -12,7 +12,6 @@ - from base64 import urlsafe_b64encode - import copy - import datetime --from dateutil import parser - import json - import re - import typing as t -@@ -383,7 +382,7 @@ def test_basic_json(app, clients, get_me - response = clients.get("/wan-register", headers=headers) - active_creds = response.json["response"]["registered_credentials"] - assert active_creds[0]["name"] == "testr1" -- assert parser.parse(active_creds[0]["lastuse"]) == fake_dt -+ assert datetime.datetime.fromisoformat(active_creds[0]["lastuse"]) == fake_dt - - # sign in - simple case use identity so we get back allowCredentials - logout(clients) -@@ -409,7 +408,7 @@ def test_basic_json(app, clients, get_me - # fetch credentials and verify lastuse was updated - response = clients.get("/wan-register", headers=headers) - active_creds = response.json["response"]["registered_credentials"] -- assert parser.parse(active_creds[0]["lastuse"]) != fake_dt -+ assert datetime.datetime.fromisoformat(active_creds[0]["lastuse"]) != fake_dt - assert active_creds[0]["transports"] == ["usb"] - assert active_creds[0]["usage"] == "first" - -Index: Flask-Security-Too-5.3.3/tests/view_scaffold.py -=================================================================== ---- Flask-Security-Too-5.3.3.orig/tests/view_scaffold.py -+++ Flask-Security-Too-5.3.3/tests/view_scaffold.py -@@ -1,4 +1,4 @@ --# :copyright: (c) 2019-2023 by J. Christopher Wagner (jwag). -+# :copyright: (c) 2019-2024 by J. Christopher Wagner (jwag). - # :license: MIT, see LICENSE for more details. - - """ -@@ -21,7 +21,7 @@ data and a mail sender that flashes what - - """ - --import datetime -+from datetime import timedelta - import os - import typing as t - -@@ -46,7 +46,12 @@ from flask_security.signals import ( - user_not_registered, - user_registered, - ) --from flask_security.utils import hash_password, uia_email_mapper, uia_phone_mapper -+from flask_security.utils import ( -+ hash_password, -+ naive_utcnow, -+ uia_email_mapper, -+ uia_phone_mapper, -+) - - - def _find_bool(v): -@@ -101,8 +106,8 @@ def create_app(): - app.config["SECURITY_TOTP_SECRETS"] = { - "1": "TjQ9Qa31VOrfEzuPy4VHQWPCTmRzCnFzMKLxXYiZu9B" - } -- app.config["SECURITY_FRESHNESS"] = datetime.timedelta(minutes=1) -- app.config["SECURITY_FRESHNESS_GRACE_PERIOD"] = datetime.timedelta(minutes=2) -+ app.config["SECURITY_FRESHNESS"] = timedelta(minutes=1) -+ app.config["SECURITY_FRESHNESS_GRACE_PERIOD"] = timedelta(minutes=2) - app.config["SECURITY_USERNAME_ENABLE"] = True - app.config["SECURITY_USERNAME_REQUIRED"] = True - app.config["SECURITY_PASSWORD_REQUIRED"] = True -@@ -286,7 +291,7 @@ def add_user(ds, email, password, roles) - roles = [ds.find_or_create_role(rn) for rn in roles] - ds.commit() - user = ds.create_user( -- email=email, password=pw, active=True, confirmed_at=datetime.datetime.utcnow() -+ email=email, password=pw, active=True, confirmed_at=naive_utcnow() - ) - ds.commit() - for role in roles: