Accepting request 1007165 from devel:languages:python:flask
- Upate to 5.0.2: * Role permissions backwards compatibility bug. * Fix Change Password regression. * Support for WebAuthn. * Support Two-factor recovery codes. * Provide option to prevent user enumeration (i.e. Generic Responses). * Support for Python 3.10. * Support for Flask >= 2.2. * Add custom HTML attributes to improve user experience. * Make the required zxcvbn complexity score configurable. * Get rid of Flask-Mail. Flask-Mailman is now the default preferred email package. * A delete option has been added to us-setup (form and view). * Improve username support - the LoginForm now has a separate field for username. * Fix test and other failures with newer Flask-Login/Werkzeug versions. * Fix test failures with newer Flask versions. - Drop patch endswith-assert.patch: * Included upstream. - Rebase patches no-mongodb.patch and use-pyqrcodeng.patch - Update {Build,}Requires versions. OBS-URL: https://build.opensuse.org/request/show/1007165 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python-Flask-Security-Too?expand=0&rev=12
This commit is contained in:
commit
f90de4f67f
@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:996d8d286789a72478462ee6f8a1371254a0dc4f8feea6f33534c2a3772c91cf
|
|
||||||
size 446589
|
|
3
Flask-Security-Too-5.0.2.tar.gz
Normal file
3
Flask-Security-Too-5.0.2.tar.gz
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:36fee0da5d1b3d211caf274553b7753478c208997c624abb84ebba4261de65c2
|
||||||
|
size 556637
|
@ -1,260 +0,0 @@
|
|||||||
---
|
|
||||||
tests/test_changeable.py | 4 ++--
|
|
||||||
tests/test_common.py | 4 ++--
|
|
||||||
tests/test_configuration.py | 4 ++--
|
|
||||||
tests/test_confirmable.py | 2 +-
|
|
||||||
tests/test_misc.py | 23 +++++++----------------
|
|
||||||
tests/test_recoverable.py | 2 +-
|
|
||||||
tests/test_response.py | 7 ++-----
|
|
||||||
tests/test_two_factor.py | 10 ++++------
|
|
||||||
tests/test_unified_signin.py | 11 ++++-------
|
|
||||||
9 files changed, 25 insertions(+), 42 deletions(-)
|
|
||||||
|
|
||||||
--- a/tests/test_changeable.py
|
|
||||||
+++ b/tests/test_changeable.py
|
|
||||||
@@ -193,7 +193,7 @@ def test_change_invalidates_session(app,
|
|
||||||
# try to access protected endpoint - shouldn't work
|
|
||||||
response = client.get("/profile")
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.headers["Location"] == "http://localhost/login?next=%2Fprofile"
|
|
||||||
+ assert response.headers["Location"].endswith("/login?next=%2Fprofile")
|
|
||||||
|
|
||||||
|
|
||||||
def test_change_updates_remember(app, client):
|
|
||||||
@@ -243,7 +243,7 @@ def test_change_invalidates_auth_token(a
|
|
||||||
# authtoken should now be invalid
|
|
||||||
response = client.get("/token", headers=headers)
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.headers["Location"] == "http://localhost/login?next=%2Ftoken"
|
|
||||||
+ assert response.headers["Location"].endswith("/login?next=%2Ftoken")
|
|
||||||
|
|
||||||
|
|
||||||
def test_auth_uniquifier(app):
|
|
||||||
--- a/tests/test_common.py
|
|
||||||
+++ b/tests/test_common.py
|
|
||||||
@@ -324,7 +324,7 @@ def test_unauthorized_access_with_referr
|
|
||||||
response = client.get(
|
|
||||||
"/admin?a=b", headers={"referer": "http://localhost/admin?x=y"}
|
|
||||||
)
|
|
||||||
- assert response.headers["Location"] == "http://localhost/"
|
|
||||||
+ assert response.headers["Location"].endswith("/")
|
|
||||||
client.get(response.headers["Location"])
|
|
||||||
|
|
||||||
response = client.get(
|
|
||||||
@@ -336,7 +336,7 @@ def test_unauthorized_access_with_referr
|
|
||||||
# we expect a temp redirect (302) to the referer
|
|
||||||
response = client.get("/admin?w=s", headers={"referer": "/profile"})
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.headers["Location"] == "http://localhost/profile"
|
|
||||||
+ assert response.headers["Location"].endswith("/profile")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.settings(unauthorized_view="/unauthz")
|
|
||||||
--- a/tests/test_configuration.py
|
|
||||||
+++ b/tests/test_configuration.py
|
|
||||||
@@ -24,11 +24,11 @@ def test_view_configuration(client):
|
|
||||||
|
|
||||||
response = authenticate(client, endpoint="/custom_login")
|
|
||||||
assert "location" in response.headers
|
|
||||||
- assert response.headers["Location"] == "http://localhost/post_login"
|
|
||||||
+ assert response.headers["Location"].endswith("/post_login")
|
|
||||||
|
|
||||||
response = logout(client, endpoint="/custom_logout")
|
|
||||||
assert "location" in response.headers
|
|
||||||
- assert response.headers["Location"] == "http://localhost/post_logout"
|
|
||||||
+ assert response.headers["Location"].endswith("/post_logout")
|
|
||||||
|
|
||||||
response = client.get(
|
|
||||||
"/http",
|
|
||||||
--- a/tests/test_confirmable.py
|
|
||||||
+++ b/tests/test_confirmable.py
|
|
||||||
@@ -522,7 +522,7 @@ def test_email_not_identity(app, sqlalch
|
|
||||||
token = registrations[0]["confirm_token"]
|
|
||||||
response = client.get("/confirm/" + token, headers={"Accept": "application/json"})
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.location == "http://localhost/"
|
|
||||||
+ assert response.location.endswith("/")
|
|
||||||
|
|
||||||
logout(client)
|
|
||||||
|
|
||||||
--- a/tests/test_misc.py
|
|
||||||
+++ b/tests/test_misc.py
|
|
||||||
@@ -813,10 +813,7 @@ def test_authn_freshness(
|
|
||||||
with capture_flashes() as flashes:
|
|
||||||
response = client.get("/myspecialview", follow_redirects=False)
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert (
|
|
||||||
- response.location
|
|
||||||
- == "http://localhost/verify?next=http%3A%2F%2Flocalhost%2Fmyspecialview"
|
|
||||||
- )
|
|
||||||
+ assert response.location.endswith("/verify?next=http%3A%2F%2Flocalhost%2Fmyspecialview")
|
|
||||||
assert flashes[0]["category"] == "error"
|
|
||||||
assert flashes[0]["message"].encode("utf-8") == get_message(
|
|
||||||
"REAUTHENTICATION_REQUIRED"
|
|
||||||
@@ -896,10 +893,7 @@ def test_default_authn_bp(app, client):
|
|
||||||
time.sleep(0.1)
|
|
||||||
response = client.get("/myview", follow_redirects=False)
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert (
|
|
||||||
- response.location
|
|
||||||
- == "http://localhost/myprefix/verify?next=http%3A%2F%2Flocalhost%2Fmyview"
|
|
||||||
- )
|
|
||||||
+ assert response.location.endswith("/myprefix/verify?next=http%3A%2F%2Flocalhost%2Fmyview")
|
|
||||||
|
|
||||||
|
|
||||||
def test_authn_freshness_grace(app, client, get_message):
|
|
||||||
@@ -941,10 +935,7 @@ def test_authn_freshness_nc(app, client_
|
|
||||||
# This should fail - should be a redirect
|
|
||||||
response = client_nc.get("/myview", headers=h, follow_redirects=False)
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert (
|
|
||||||
- response.location
|
|
||||||
- == "http://localhost/verify?next=http%3A%2F%2Flocalhost%2Fmyview"
|
|
||||||
- )
|
|
||||||
+ assert response.location.endswith("/verify?next=http%3A%2F%2Flocalhost%2Fmyview")
|
|
||||||
|
|
||||||
|
|
||||||
def test_verify_fresh(app, client, get_message):
|
|
||||||
@@ -1106,11 +1097,11 @@ def test_post_security_with_application_
|
|
||||||
"/login", data=dict(email="matt@lp.com", password="password")
|
|
||||||
)
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.headers["Location"] == "http://localhost/root"
|
|
||||||
+ assert response.headers["Location"].endswith("/root")
|
|
||||||
|
|
||||||
response = client.get("/logout")
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.headers["Location"] == "http://localhost/root"
|
|
||||||
+ assert response.headers["Location"].endswith("/root")
|
|
||||||
|
|
||||||
|
|
||||||
def test_post_security_with_application_root_and_views(app, sqlalchemy_datastore):
|
|
||||||
@@ -1129,11 +1120,11 @@ def test_post_security_with_application_
|
|
||||||
"/login", data=dict(email="matt@lp.com", password="password")
|
|
||||||
)
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.headers["Location"] == "http://localhost/post_login"
|
|
||||||
+ assert response.headers["Location"].endswith("/post_login")
|
|
||||||
|
|
||||||
response = client.get("/logout")
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.headers["Location"] == "http://localhost/post_logout"
|
|
||||||
+ assert response.headers["Location"].endswith("/post_logout")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.settings(redirect_validate_mode="regex")
|
|
||||||
--- a/tests/test_recoverable.py
|
|
||||||
+++ b/tests/test_recoverable.py
|
|
||||||
@@ -289,7 +289,7 @@ def test_recover_invalidates_session(app
|
|
||||||
# try to access protected endpoint with old session - shouldn't work
|
|
||||||
response = other_client.get("/profile")
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.headers["Location"] == "http://localhost/login?next=%2Fprofile"
|
|
||||||
+ assert response.headers["Location"].endswith("/login?next=%2Fprofile")
|
|
||||||
|
|
||||||
|
|
||||||
def test_login_form_description(sqlalchemy_app):
|
|
||||||
--- a/tests/test_response.py
|
|
||||||
+++ b/tests/test_response.py
|
|
||||||
@@ -52,7 +52,7 @@ def test_default_unauthn(app, client):
|
|
||||||
|
|
||||||
response = client.get("/profile")
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.headers["Location"] == "http://localhost/login?next=%2Fprofile"
|
|
||||||
+ assert response.headers["Location"].endswith("/login?next=%2Fprofile")
|
|
||||||
|
|
||||||
response = client.get("/profile", headers={"Accept": "application/json"})
|
|
||||||
assert response.status_code == 401
|
|
||||||
@@ -68,10 +68,7 @@ def test_default_unauthn_bp(app, client)
|
|
||||||
|
|
||||||
response = client.get("/profile")
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert (
|
|
||||||
- response.headers["Location"]
|
|
||||||
- == "http://localhost/myprefix/mylogin?next=%2Fprofile"
|
|
||||||
- )
|
|
||||||
+ assert response.headers["Location"].endswith("/myprefix/mylogin?next=%2Fprofile")
|
|
||||||
|
|
||||||
|
|
||||||
def test_default_unauthn_myjson(app, client):
|
|
||||||
--- a/tests/test_two_factor.py
|
|
||||||
+++ b/tests/test_two_factor.py
|
|
||||||
@@ -851,7 +851,7 @@ def test_admin_setup_reset(app, client,
|
|
||||||
# we shouldn't be logged in
|
|
||||||
response = client.get("/profile", follow_redirects=False)
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.location == "http://localhost/login?next=%2Fprofile"
|
|
||||||
+ assert response.location.endswith("/login?next=%2Fprofile")
|
|
||||||
|
|
||||||
# Use admin to setup gene's SMS/phone.
|
|
||||||
with app.app_context():
|
|
||||||
@@ -1105,7 +1105,7 @@ def test_bad_sender(app, client, get_mes
|
|
||||||
data = {"email": "gal@lp.com", "password": "password"}
|
|
||||||
response = client.post("login", data=data, follow_redirects=False)
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.location == "http://localhost/login"
|
|
||||||
+ assert response.location.endswith("/login")
|
|
||||||
assert get_message("FAILED_TO_SEND_CODE") in flashes[0]["message"].encode("utf-8")
|
|
||||||
|
|
||||||
# test w/ JSON
|
|
||||||
@@ -1187,9 +1187,7 @@ def test_verify(app, client, get_message
|
|
||||||
authenticate(client)
|
|
||||||
response = client.get("tf-setup", follow_redirects=False)
|
|
||||||
verify_url = response.location
|
|
||||||
- assert (
|
|
||||||
- verify_url == "http://localhost/verify?next=http%3A%2F%2Flocalhost%2Ftf-setup"
|
|
||||||
- )
|
|
||||||
+ assert verify_url.endswith("/verify?next=http%3A%2F%2Flocalhost%2Ftf-setup")
|
|
||||||
logout(client)
|
|
||||||
|
|
||||||
# Now try again - follow redirects to get to verify form
|
|
||||||
@@ -1220,7 +1218,7 @@ def test_verify(app, client, get_message
|
|
||||||
follow_redirects=False,
|
|
||||||
)
|
|
||||||
assert response.status_code == 302
|
|
||||||
- assert response.location == "http://localhost/tf-setup"
|
|
||||||
+ assert response.location.endswith("/tf-setup")
|
|
||||||
assert get_message("REAUTHENTICATION_SUCCESSFUL") == flashes[0]["message"].encode(
|
|
||||||
"utf-8"
|
|
||||||
)
|
|
||||||
--- a/tests/test_unified_signin.py
|
|
||||||
+++ b/tests/test_unified_signin.py
|
|
||||||
@@ -513,7 +513,7 @@ def test_verify_link(app, client, get_me
|
|
||||||
|
|
||||||
# Try with no code
|
|
||||||
response = client.get("us-verify-link?email=matt@lp.com", follow_redirects=False)
|
|
||||||
- assert response.location == "http://localhost/us-signin"
|
|
||||||
+ assert response.location.endswith("/us-signin")
|
|
||||||
response = client.get("us-verify-link?email=matt@lp.com", follow_redirects=True)
|
|
||||||
assert get_message("API_ERROR") in response.data
|
|
||||||
|
|
||||||
@@ -837,10 +837,7 @@ def test_verify(app, client, get_message
|
|
||||||
us_authenticate(client)
|
|
||||||
response = client.get("us-setup", follow_redirects=False)
|
|
||||||
verify_url = response.location
|
|
||||||
- assert (
|
|
||||||
- verify_url
|
|
||||||
- == "http://localhost/us-verify?next=http%3A%2F%2Flocalhost%2Fus-setup"
|
|
||||||
- )
|
|
||||||
+ assert verify_url.endswith("/us-verify?next=http%3A%2F%2Flocalhost%2Fus-setup")
|
|
||||||
logout(client)
|
|
||||||
us_authenticate(client)
|
|
||||||
|
|
||||||
@@ -1099,7 +1096,7 @@ def test_next(app, client, get_message):
|
|
||||||
data=dict(identity="matt@lp.com", passcode=requests[0]["token"]),
|
|
||||||
follow_redirects=False,
|
|
||||||
)
|
|
||||||
- assert response.location == "http://localhost/post_login"
|
|
||||||
+ assert response.location.endswith("/post_login")
|
|
||||||
|
|
||||||
logout(client)
|
|
||||||
response = client.post(
|
|
||||||
@@ -1109,7 +1106,7 @@ def test_next(app, client, get_message):
|
|
||||||
),
|
|
||||||
follow_redirects=False,
|
|
||||||
)
|
|
||||||
- assert response.location == "http://localhost/post_login"
|
|
||||||
+ assert response.location.endswith("/post_login")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.registerable()
|
|
@ -1,22 +1,22 @@
|
|||||||
Index: Flask-Security-Too-4.1.2/tests/conftest.py
|
Index: Flask-Security-Too-5.0.2/tests/conftest.py
|
||||||
===================================================================
|
===================================================================
|
||||||
--- Flask-Security-Too-4.1.2.orig/tests/conftest.py
|
--- Flask-Security-Too-5.0.2.orig/tests/conftest.py
|
||||||
+++ Flask-Security-Too-4.1.2/tests/conftest.py
|
+++ Flask-Security-Too-5.0.2/tests/conftest.py
|
||||||
@@ -683,7 +683,7 @@ def client_nc(request, sqlalchemy_app):
|
@@ -862,7 +862,7 @@ def client_nc(request, sqlalchemy_app):
|
||||||
return app.test_client(use_cookies=False)
|
return app.test_client(use_cookies=False)
|
||||||
|
|
||||||
|
|
||||||
-@pytest.fixture(params=["cl-sqlalchemy", "c2", "cl-mongo", "cl-peewee"])
|
-@pytest.fixture(params=["cl-sqlalchemy", "c2", "cl-mongo", "cl-peewee"])
|
||||||
+@pytest.fixture(params=["cl-sqlalchemy", "c2", "cl-peewee"])
|
+@pytest.fixture(params=["cl-sqlalchemy", "c2", "cl-peewee"])
|
||||||
def clients(request, app, tmpdir, realdburl):
|
def clients(request, app, tmpdir, realdburl, realmongodburl):
|
||||||
if request.param == "cl-sqlalchemy":
|
if request.param == "cl-sqlalchemy":
|
||||||
ds = sqlalchemy_setup(request, app, tmpdir, realdburl)
|
ds = sqlalchemy_setup(request, app, tmpdir, realdburl)
|
||||||
@@ -729,7 +729,7 @@ def get_message_local(app):
|
@@ -908,7 +908,7 @@ def get_message_local(app):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(
|
@pytest.fixture(
|
||||||
- params=["sqlalchemy", "sqlalchemy-session", "mongoengine", "peewee", "pony"]
|
- params=["sqlalchemy", "sqlalchemy-session", "mongoengine", "peewee", "pony"]
|
||||||
+ params=["sqlalchemy", "sqlalchemy-session", "peewee", "pony"]
|
+ params=["sqlalchemy", "sqlalchemy-session", "peewee", "pony"]
|
||||||
)
|
)
|
||||||
def datastore(request, app, tmpdir, realdburl):
|
def datastore(request, app, tmpdir, realdburl, realmongodburl):
|
||||||
if request.param == "sqlalchemy":
|
if request.param == "sqlalchemy":
|
||||||
|
@ -1,3 +1,28 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Sep 30 06:52:16 UTC 2022 - Steve Kowalik <steven.kowalik@suse.com>
|
||||||
|
|
||||||
|
- Upate to 5.0.2:
|
||||||
|
* Role permissions backwards compatibility bug.
|
||||||
|
* Fix Change Password regression.
|
||||||
|
* Support for WebAuthn.
|
||||||
|
* Support Two-factor recovery codes.
|
||||||
|
* Provide option to prevent user enumeration (i.e. Generic Responses).
|
||||||
|
* Support for Python 3.10.
|
||||||
|
* Support for Flask >= 2.2.
|
||||||
|
* Add custom HTML attributes to improve user experience.
|
||||||
|
* Make the required zxcvbn complexity score configurable.
|
||||||
|
* Get rid of Flask-Mail. Flask-Mailman is now the default preferred email
|
||||||
|
package.
|
||||||
|
* A delete option has been added to us-setup (form and view).
|
||||||
|
* Improve username support - the LoginForm now has a separate field for
|
||||||
|
username.
|
||||||
|
* Fix test and other failures with newer Flask-Login/Werkzeug versions.
|
||||||
|
* Fix test failures with newer Flask versions.
|
||||||
|
- Drop patch endswith-assert.patch:
|
||||||
|
* Included upstream.
|
||||||
|
- Rebase patches no-mongodb.patch and use-pyqrcodeng.patch
|
||||||
|
- Update {Build,}Requires versions.
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Thu Sep 8 06:45:05 UTC 2022 - Steve Kowalik <steven.kowalik@suse.com>
|
Thu Sep 8 06:45:05 UTC 2022 - Steve Kowalik <steven.kowalik@suse.com>
|
||||||
|
|
||||||
|
@ -19,41 +19,39 @@
|
|||||||
%define skip_python2 1
|
%define skip_python2 1
|
||||||
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
|
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
|
||||||
Name: python-Flask-Security-Too
|
Name: python-Flask-Security-Too
|
||||||
Version: 4.1.3
|
Version: 5.0.2
|
||||||
Release: 0
|
Release: 0
|
||||||
Summary: Security for Flask apps
|
Summary: Security for Flask apps
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: https://github.com/jwag956/flask-security
|
URL: https://github.com/Flask-Middleware/flask-security
|
||||||
Source: https://files.pythonhosted.org/packages/source/F/Flask-Security-Too/Flask-Security-Too-%{version}.tar.gz
|
Source: https://files.pythonhosted.org/packages/source/F/Flask-Security-Too/Flask-Security-Too-%{version}.tar.gz
|
||||||
Patch0: no-mongodb.patch
|
Patch0: no-mongodb.patch
|
||||||
Patch1: use-pyqrcodeng.patch
|
Patch1: use-pyqrcodeng.patch
|
||||||
# PATCH-FIX-UPSTREAM endswith-assert.patch gh#Flask-Middleware/flask-security#605 mcepl@suse.com
|
BuildRequires: %{python_module Babel >= 2.9.1}
|
||||||
# don't test for euqality of response.headers['Location'], just for .endswith
|
|
||||||
Patch2: endswith-assert.patch
|
|
||||||
BuildRequires: %{python_module Babel >= 1.3}
|
|
||||||
BuildRequires: %{python_module Flask >= 1.1.1}
|
BuildRequires: %{python_module Flask >= 1.1.1}
|
||||||
BuildRequires: %{python_module Flask-Babel}
|
BuildRequires: %{python_module Flask-Babel >= 2.0.0}
|
||||||
BuildRequires: %{python_module Flask-Login >= 0.4.1}
|
BuildRequires: %{python_module Flask-Login >= 0.4.1}
|
||||||
BuildRequires: %{python_module Flask-Mail >= 0.9.1}
|
BuildRequires: %{python_module Flask-Mailman >= 0.3.0}
|
||||||
BuildRequires: %{python_module Flask-Principal >= 0.4.0}
|
BuildRequires: %{python_module Flask-Principal >= 0.4.0}
|
||||||
BuildRequires: %{python_module Flask-SQLAlchemy >= 2.3}
|
BuildRequires: %{python_module Flask-SQLAlchemy >= 2.5.1}
|
||||||
BuildRequires: %{python_module Flask-WTF >= 0.14.3}
|
BuildRequires: %{python_module Flask-WTF >= 0.14.3}
|
||||||
BuildRequires: %{python_module PyQRCode >= 1.2}
|
BuildRequires: %{python_module PyQRCode >= 1.2}
|
||||||
BuildRequires: %{python_module SQLAlchemy >= 1.2.6}
|
BuildRequires: %{python_module SQLAlchemy >= 1.3.24}
|
||||||
BuildRequires: %{python_module WTForms-lang}
|
BuildRequires: %{python_module WTForms-lang}
|
||||||
BuildRequires: %{python_module WTForms}
|
BuildRequires: %{python_module WTForms}
|
||||||
BuildRequires: %{python_module Werkzeug >= 0.14.1}
|
BuildRequires: %{python_module Werkzeug >= 0.14.1}
|
||||||
BuildRequires: %{python_module argon2_cffi >= 19.1.0}
|
BuildRequires: %{python_module argon2_cffi >= 19.1.0}
|
||||||
BuildRequires: %{python_module bcrypt >= 3.1.4}
|
BuildRequires: %{python_module bcrypt >= 3.1.4}
|
||||||
BuildRequires: %{python_module bleach}
|
BuildRequires: %{python_module bleach >= 3.3.1}
|
||||||
BuildRequires: %{python_module blinker >= 1.4}
|
BuildRequires: %{python_module blinker >= 1.4}
|
||||||
BuildRequires: %{python_module cachetools >= 3.1.0}
|
BuildRequires: %{python_module cachetools >= 3.1.0}
|
||||||
BuildRequires: %{python_module cryptography >= 2.1.4}
|
BuildRequires: %{python_module cryptography >= 3.4.8}
|
||||||
|
BuildRequires: %{python_module dateutil}
|
||||||
BuildRequires: %{python_module email-validator >= 1.1.1}
|
BuildRequires: %{python_module email-validator >= 1.1.1}
|
||||||
BuildRequires: %{python_module itsdangerous >= 1.1.0}
|
BuildRequires: %{python_module itsdangerous >= 1.1.0}
|
||||||
BuildRequires: %{python_module passlib >= 1.7.2}
|
BuildRequires: %{python_module passlib >= 1.7.2}
|
||||||
BuildRequires: %{python_module peewee >= 3.7.1}
|
BuildRequires: %{python_module peewee >= 3.7.1}
|
||||||
BuildRequires: %{python_module phonenumbers >= 8.11.1}
|
BuildRequires: %{python_module phonenumbers >= 8.12.18}
|
||||||
BuildRequires: %{python_module pony}
|
BuildRequires: %{python_module pony}
|
||||||
BuildRequires: %{python_module pytest >= 6.2.5}
|
BuildRequires: %{python_module pytest >= 6.2.5}
|
||||||
BuildRequires: %{python_module setuptools}
|
BuildRequires: %{python_module setuptools}
|
||||||
@ -61,22 +59,23 @@ BuildRequires: %{python_module zxcvbn >= 4.4.28}
|
|||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
BuildRequires: python-rpm-macros
|
BuildRequires: python-rpm-macros
|
||||||
Requires: python-Flask >= 1.1.1
|
Requires: python-Flask >= 1.1.1
|
||||||
Requires: python-Flask-Babel
|
Requires: python-Flask-Babel >= 2.0.0
|
||||||
Requires: python-Flask-Login >= 0.4.1
|
Requires: python-Flask-Login >= 0.4.1
|
||||||
Requires: python-Flask-Principal >= 0.4.0
|
Requires: python-Flask-Principal >= 0.4.0
|
||||||
Requires: python-Flask-WTF >= 0.14.3
|
Requires: python-Flask-WTF >= 0.14.3
|
||||||
Requires: python-Werkzeug >= 0.14.1
|
Requires: python-Werkzeug >= 0.14.1
|
||||||
Requires: python-bcrypt >= 3.1.4
|
Requires: python-bcrypt >= 3.1.4
|
||||||
|
Requires: python-bleach >= 3.3.1
|
||||||
Requires: python-blinker >= 1.4
|
Requires: python-blinker >= 1.4
|
||||||
Requires: python-cryptography >= 2.1.4
|
Requires: python-cryptography >= 3.4.8
|
||||||
Requires: python-email-validator >= 1.1.1
|
Requires: python-email-validator >= 1.1.1
|
||||||
Requires: python-itsdangerous >= 1.1.0
|
Requires: python-itsdangerous >= 1.1.0
|
||||||
Requires: python-passlib >= 1.7.2
|
Requires: python-passlib >= 1.7.2
|
||||||
Recommends: python-PyQRCode >= 1.2
|
Recommends: python-PyQRCode >= 1.2
|
||||||
Recommends: python-SQLAlchemy >= 1.2.6
|
Recommends: python-SQLAlchemy >= 1.3.24
|
||||||
Recommends: python-zxcvbn >= 4.4.28
|
Recommends: python-zxcvbn >= 4.4.28
|
||||||
Suggests: python-argon2_cffi >= 19.1.0
|
Suggests: python-argon2_cffi >= 19.1.0
|
||||||
Suggests: python-phonenumbers >= 8.11.1
|
Suggests: python-phonenumbers >= 8.12.18
|
||||||
Conflicts: python-Flask-Security < 3.2.0
|
Conflicts: python-Flask-Security < 3.2.0
|
||||||
Obsoletes: python-Flask-Security < 3.2.0
|
Obsoletes: python-Flask-Security < 3.2.0
|
||||||
Provides: python-Flask-Security = %{version}
|
Provides: python-Flask-Security = %{version}
|
||||||
|
@ -1,29 +1,36 @@
|
|||||||
Index: Flask-Security-Too-4.1.2/flask_security/core.py
|
Index: Flask-Security-Too-5.0.2/flask_security/core.py
|
||||||
===================================================================
|
===================================================================
|
||||||
--- Flask-Security-Too-4.1.2.orig/flask_security/core.py
|
--- Flask-Security-Too-5.0.2.orig/flask_security/core.py
|
||||||
+++ Flask-Security-Too-4.1.2/flask_security/core.py
|
+++ Flask-Security-Too-5.0.2/flask_security/core.py
|
||||||
@@ -1411,7 +1411,7 @@ class Security:
|
@@ -1523,7 +1523,7 @@ class Security:
|
||||||
and "authenticator" in cv("TWO_FACTOR_ENABLED_METHODS", app=app)
|
and "authenticator" in cv("TWO_FACTOR_ENABLED_METHODS", app=app)
|
||||||
)
|
)
|
||||||
if need_qrcode:
|
if need_qrcode:
|
||||||
- self._check_modules("pyqrcode", "TWO_FACTOR or UNIFIED_SIGNIN")
|
- self._check_modules("qrcode", "TWO_FACTOR or UNIFIED_SIGNIN")
|
||||||
+ self._check_modules("pyqrcodeng", "TWO_FACTOR or UNIFIED_SIGNIN")
|
+ self._check_modules("pyqrcodeng", "TWO_FACTOR or UNIFIED_SIGNIN")
|
||||||
|
|
||||||
need_sms = (
|
need_sms = (
|
||||||
cv("UNIFIED_SIGNIN", app=app)
|
cv("UNIFIED_SIGNIN", app=app)
|
||||||
Index: Flask-Security-Too-4.1.2/flask_security/totp.py
|
Index: Flask-Security-Too-5.0.2/flask_security/totp.py
|
||||||
===================================================================
|
===================================================================
|
||||||
--- Flask-Security-Too-4.1.2.orig/flask_security/totp.py
|
--- Flask-Security-Too-5.0.2.orig/flask_security/totp.py
|
||||||
+++ Flask-Security-Too-4.1.2/flask_security/totp.py
|
+++ Flask-Security-Too-5.0.2/flask_security/totp.py
|
||||||
@@ -139,9 +139,9 @@ class Totp:
|
@@ -140,15 +140,11 @@ class Totp:
|
||||||
.. versionadded:: 4.0.0
|
.. versionadded:: 4.0.0
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
- import pyqrcode
|
- import qrcode
|
||||||
|
- import qrcode.image.svg
|
||||||
+ import pyqrcodeng
|
+ import pyqrcodeng
|
||||||
|
|
||||||
- code = pyqrcode.create(self.get_totp_uri(username, totp))
|
- image = qrcode.make(
|
||||||
+ code = pyqrcodeng.create(self.get_totp_uri(username, totp))
|
- self.get_totp_uri(username, totp),
|
||||||
|
- image_factory=qrcode.image.svg.SvgImage,
|
||||||
|
- )
|
||||||
|
+ image = pyqrcodeng.create(self.get_totp_uri(username, totp))
|
||||||
with io.BytesIO() as virtual_file:
|
with io.BytesIO() as virtual_file:
|
||||||
code.svg(file=virtual_file, scale=3)
|
- image.save(virtual_file)
|
||||||
|
+ image.svg(virtual_file, scale=1)
|
||||||
image_as_str = base64.b64encode(virtual_file.getvalue()).decode("ascii")
|
image_as_str = base64.b64encode(virtual_file.getvalue()).decode("ascii")
|
||||||
|
|
||||||
|
return f"data:image/svg+xml;base64,{image_as_str}"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user