Skip to content

Commit

Permalink
Patch41 (#586)
Browse files Browse the repository at this point in the history
* Fix an example command in the documentation (#539)

Co-authored-by: Kazuhei Hamada <kazuhei.hamada@genialtech.io>
(cherry picked from commit c7da03c)

* Patch release - 4.1.3

Cherrypick some small fixes.
Backport some documentation changes.

Co-authored-by: Kazuhei Hamada <hamatantanko2@hotmail.co.jp>
  • Loading branch information
jwag956 and kazuhei2 committed Mar 2, 2022
1 parent 71e0f72 commit fe79e2f
Show file tree
Hide file tree
Showing 17 changed files with 102 additions and 38 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ default_language_version:
python: python3.8
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
rev: v4.1.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
Expand All @@ -14,12 +14,12 @@ repos:
- id: check-merge-conflict
- id: fix-byte-order-marker
- repo: https://github.com/asottile/pyupgrade
rev: v2.26.0
rev: v2.31.0
hooks:
- id: pyupgrade
args: [--py36-plus]
- repo: https://github.com/psf/black
rev: 21.9b0
rev: 22.1.0
hooks:
- id: black
- repo: https://gitlab.com/pycqa/flake8
Expand Down
24 changes: 19 additions & 5 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,38 @@ Flask-Security Changelog

Here you can see the full list of changes between each Flask-Security release.

Version 4.1.3
-------------

Released March 2, 2022

Fixes
+++++
- (:issue:`581`) Fix bug when attempting to disable register_blueprint. (halali)
- (:pr:`539`) Fix example documentation re: generating localized messages. (kazuhei2)
- (:pr:`546`) Make roles joinedload compatible with SQLAlchemy 2.0. (keats)
- (:pr:`586`) Ship py.typed as part of package.
- (:issue:`580`) Improve documentation around use of bleach and include in common install extra.


Version 4.1.2
-------------

Released September 22, 2021

Fixes
-----
-(:issue:`526`) default_reauthn_handler doesn't honor SECURITY_URL_PREFIX
-(:pr:`528`) Improve German translations (sr-verde)
-(:pr:`527`) Fix two-factor sample code (djpnewton)
+++++
- (:issue:`526`) default_reauthn_handler doesn't honor SECURITY_URL_PREFIX
- (:pr:`528`) Improve German translations (sr-verde)
- (:pr:`527`) Fix two-factor sample code (djpnewton)

Version 4.1.1
--------------

Released September 10, 2021

Fixes
-----
+++++
- (:issue:`518`) Fix corner case where Security object was being reused in tests.
- (:issue:`512`) If USERNAME_ENABLE is set, change LoginForm field from EmailField
to StringField. Also - dynamically add fields to Login and Registration forms
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ include babel.ini
include pytest.ini
include tox.ini
include requirements/*.txt
include flask_security/py.typed
graft docs
graft flask_security/templates
graft flask_security/translations
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
# built documents.
#
# The short X.Y version.
version = "4.1.2"
version = "4.1.3"
# The full version, including alpha/beta/rc tags.
release = version

Expand Down
18 changes: 11 additions & 7 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,8 @@ Registerable

Validation and normalization is encapsulated in :class:`.UsernameUtil`.
Note that the default validation restricts username input to be unicode
letters and numbers.
letters and numbers. It also uses ``bleach`` to scrub any risky input. Be
sure your application requirements includes ``bleach``.

Default: ``False``

Expand Down Expand Up @@ -763,7 +764,7 @@ Registerable

.. py:data:: SECURITY_USERNAME_NORMALIZE_FORM
Usernames can be unicode normalization is performed using the Python unicodedata.normalize() method.
Usernames, by default, are normalized using the Python unicodedata.normalize() method.

Default: ``"NFKD"``

Expand Down Expand Up @@ -1090,6 +1091,9 @@ Configuration related to the two-factor authentication feature.
Unified Signin
--------------

Unified sign in provides a generalized sign in endpoint that takes an `identity`
and a `passcode`.

.. versionadded:: 3.4.0

.. py:data:: SECURITY_UNIFIED_SIGNIN
Expand Down Expand Up @@ -1406,8 +1410,8 @@ The default messages and error levels can be found in ``core.py``.
* ``SECURITY_MSG_US_SPECIFY_IDENTITY``
* ``SECURITY_MSG_USE_CODE``
* ``SECURITY_MSG_USER_DOES_NOT_EXIST``
* ``SECURITY_USERNAME_INVALID_LENGTH``
* ``SECURITY_USERNAME_ILLEGAL_CHARACTERS``
* ``SECURITY_USERNAME_DISALLOWED_CHARACTERS``
* ``SECURITY_USERNAME_NOT_PROVIDED``
* ``SECURITY_USERNAME_ALREADY_ASSOCIATED``
* ``SECURITY_MSG_USERNAME_INVALID_LENGTH``
* ``SECURITY_MSG_USERNAME_ILLEGAL_CHARACTERS``
* ``SECURITY_MSG_USERNAME_DISALLOWED_CHARACTERS``
* ``SECURITY_MSG_USERNAME_NOT_PROVIDED``
* ``SECURITY_MSG_USERNAME_ALREADY_ASSOCIATED``
2 changes: 1 addition & 1 deletion docs/customizing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ In this example, create a file ``flask_security.po`` under a directory:

Then compile it with::

pybabel compile -d translations/ -i translations/fr_FR/LC_MESSAGES/flask_security.po -l fr_FR
pybabel compile -d translations/ -i translations/fr_FR/LC_MESSAGES/flask_security.po -l fr_FR -D flask_security

Finally add your translations directory to your configuration::

Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ extensions out of the box for data persistence:
1. `Flask-SQLAlchemy <https://pypi.python.org/pypi/flask-sqlalchemy/>`_
2. `Flask-MongoEngine <https://pypi.python.org/pypi/flask-mongoengine/>`_
3. `Peewee Flask utils <https://docs.peewee-orm.com/en/latest/peewee/playhouse.html#flask-utils>`_
4. `PonyORM <https://pypi.python.org/pypi/pony/>`_
4. `PonyORM <https://pypi.python.org/pypi/pony/>`_ - NOTE: not currently supported.
5. `SQLAlchemy sessions <https://docs.sqlalchemy.org/en/14/orm/session_basics.html>`_


Expand Down
19 changes: 13 additions & 6 deletions docs/models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ which are a bit of a pain. To make things easier - Flask-Security includes mixin
contain ALL the fields and tables required for all features. They also contain
various `best practice` fields - such as update and create times. These mixins can
be easily extended to add any sort of custom fields and can be found in the
`models` module (today there is just one for using Flask-SqlAlchemy).
`models` module (today there is just one for using Flask-SQLAlchemy).

The provided models are versioned since they represent actual DB models, and any
changes require a schema migration (and perhaps a data migration). Applications
Expand All @@ -33,7 +33,7 @@ At the bare minimum your `User` and `Role` model should include the following fi
* ``email`` (for most features - unique, non-nullable)
* ``password`` (non-nullable)
* ``active`` (boolean, non-nullable)
* ``fs_uniquifier`` (unique, non-nullable)
* ``fs_uniquifier`` (string, 64 bytes, unique, non-nullable)


**Role**
Expand Down Expand Up @@ -78,13 +78,13 @@ If you enable two-factor by setting your application's `SECURITY_TWO_FACTOR`
configuration value to `True`, your `User` model will require the following
additional fields:

* ``tf_totp_secret`` (string)
* ``tf_totp_secret`` (string, 255 bytes, nullable)
* ``tf_primary_method`` (string)

If you include 'sms' in `SECURITY_TWO_FACTOR_ENABLED_METHODS`, your `User` model
will require the following additional field:

* ``tf_phone_number`` (string)
* ``tf_phone_number`` (string, 255 bytes, nullable)

Unified Sign In
^^^^^^^^^^^^^^^
Expand All @@ -105,12 +105,19 @@ Separate Identity Domains
If you want authentication tokens to not be invalidated when the user changes their
password add the following to your `User` model:

* ``fs_token_uniquifier`` (unique, non-nullable)
* ``fs_token_uniquifier`` (string, 64 bytes, unique, non-nullable)

Username
~~~~~~~~~
If you set :py:data:`SECURITY_USERNAME_ENABLE` to `True`, then your `User` model
requires the following additional field:

* ``username`` (string, 64 bytes, unique, nullable)

Permissions
^^^^^^^^^^^
If you want to protect endpoints with permissions, and assign permissions to roles
that are then assigned to users the Role model requires:
that are then assigned to users, the ``Role`` model requires:

* ``permissions`` (UnicodeText)

Expand Down
1 change: 1 addition & 0 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ possible using Flask-SQLAlchemy and the built-in model mixins:
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {
"pool_pre_ping": True,
}
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

# Create database connection object
db = SQLAlchemy(app)
Expand Down
2 changes: 1 addition & 1 deletion flask_security/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,4 @@
verify_and_update_password,
)

__version__ = "4.1.2"
__version__ = "4.1.3"
1 change: 0 additions & 1 deletion flask_security/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ def decorator(__ctx, *args, **kwargs):

return functools.update_wrapper(decorator, f)


else:
import flask.cli

Expand Down
2 changes: 1 addition & 1 deletion flask_security/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1118,7 +1118,7 @@ def init_app(
raise ValueError("Datastore must be provided")
self.datastore = self._datastore

if register_blueprint:
if register_blueprint is not None:
self._register_blueprint = register_blueprint
self.register_blueprint = self._register_blueprint

Expand Down
2 changes: 1 addition & 1 deletion flask_security/datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ def find_user(
if config_value("JOIN_USER_ROLES") and hasattr(self.user_model, "roles"):
from sqlalchemy.orm import joinedload

query = query.options(joinedload("roles"))
query = query.options(joinedload(self.user_model.roles))

if case_insensitive:
# While it is of course possible to pass in multiple keys to filter on
Expand Down
1 change: 0 additions & 1 deletion flask_security/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ async def view_commit(response=None):
_datastore.commit()
return response


else:

def view_commit(response=None):
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ fsqla=
common=
bcrypt>=3.1.5
flask_mail>=0.9.1
bleach>=3.3.1
mfa=
cryptography>=3.0.0
pyqrcode>=1.2
Expand Down
37 changes: 37 additions & 0 deletions tests/test_recoverable.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,3 +566,40 @@ def test_email_normalization(client, get_message):
)
assert response.status_code == 200
assert get_message("PASSWORD_RESET_REQUEST", email="joe@lp.com") in response.data


def test_password_normalization(app, client, get_message):
with capture_reset_password_requests() as requests:
response = client.post(
"/reset",
json=dict(email="matt@lp.com"),
)
assert response.status_code == 200
token = requests[0]["token"]

response = client.post(
"/reset/" + token,
json=dict(password="HöheHöhe", password_confirm="HöheHöhe"),
)
assert response.status_code == 200
logout(client)

# make sure can log in with new password both normnalized or not
response = client.post(
"/login",
json=dict(email="matt@lp.com", password="HöheHöhe"),
)
assert response.status_code == 200
# verify actually logged in
response = client.get("/profile", follow_redirects=False)
assert response.status_code == 200
logout(client)

response = client.post(
"/login",
json=dict(email="matt@lp.com", password="Ho\u0308heHo\u0308he"),
)
assert response.status_code == 200
# verify actually logged in
response = client.get("/profile", follow_redirects=False)
assert response.status_code == 200
19 changes: 10 additions & 9 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
envlist =
py{36,37,38,39,py3}-{low,release}
py{36,37,38,39,py38}-{low,release}
mypy
nobabel
style
Expand All @@ -9,14 +9,14 @@ envlist =
makedist
skip_missing_interpreters = true

[testenv:py{36,37,38,39,py3}-release]
[testenv:py{36,37,38,39,py38}-release]
deps =
-r requirements/tests.txt
commands =
python setup.py compile_catalog
pytest --basetemp={envtmpdir} {posargs:tests}

[testenv:py{36,37,38,39,py3}-low]
[testenv:py{36,37,38,39,py38}-low]
deps =
pytest

Expand All @@ -30,14 +30,15 @@ deps =
argon2_cffi==20.1.0
babel==2.7.0
bcrypt==3.2.0
bleach==3.1.5
bleach==3.2.2
cryptography==3.0.0
# next 2 come from minimums from Flask 1.1.1
jinja2==2.10.1
itsdangerous==0.24
mongoengine==0.20.0
mongomock==3.21.0
pony==0.7.14
jinja2==2.11.0
itsdangerous==1.1.0
markupsafe==2.0.1
mongoengine==0.22.1
mongomock==3.22.0
pony==0.7.14;python_version<'3.10'
phonenumberslite==8.11.1
pyqrcode==1.2
sqlalchemy==1.3.19
Expand Down

0 comments on commit fe79e2f

Please sign in to comment.