* Support Python 3.12 changes. OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:flask/python-Flask-Security-Too?expand=0&rev=43
793 lines
29 KiB
Diff
793 lines
29 KiB
Diff
From f7733559de7c8cd8a5bd683b2c53b523b6fb639b Mon Sep 17 00:00:00 2001
|
|
From: Chris Wagner <jwag.wagner@gmail.com>
|
|
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:
|