diff --git a/.travis.yml b/.travis.yml index 5d1f570a..d59e8bf9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,7 +61,7 @@ deploy: secure: xzhkM+54+dmI7aFxWdMxTkHcMfOzuAxcGOpBanY367MyETtmNZUQx1VAQh5381UHiQ0+mg433srWrR4V1h0tsSB31KZAPazeh44zxpJRCv9b5Fx+46PmYW6ZpY8+vqUpFrKCcaLX5ZmEf62xXY3cvMbp0ubAURiV6N+hHyuH90w+3xucrSnFOuVHVuI3Eqp5Bz6zxEKscrIaZiT9CPh0F2jBpGZT8qXCYT1N8xeyH0SCszvKsIIoaPitpQDnoSkBfy6VHiNU6Tznseer6uLzrW80ynKu5mZwjT4mGT0j/rBUcbIpAYHajnsHXL27Gu32mli7beOkgd2vEpb14x5JygkPoYoUnSJlwhRUgAkNZVR5teNOcP87wU6ZAdv1jhfuQA/NUUpZucVpzASojAxf2996krT4hjYz7KJ2z5lSOww016EZ5mxyktGF23KXH9zrCWUv24r1K9JOUH+6OuQHFF40q1YiL2ro63raUdLm/Y3DLgeO6oDXZPMI2DFdRFCSpY2sGI6ZBrU89MuCJhju5Y838hOWQS330UcA71MpcsnmSZDsJ9o+Rrty6wowOdMqx4bmrm0G8ILNK4MosO7KwXZUMj/iV4SLUQjhBLhOTS+vLO8sa7PCZssK7z8C+378Y4Q+hrfsctCCGVBgRhuIr5KSLtKeD3bObQ/4VfIdK9E= distributions: "compile_catalog sdist bdist_wheel" on: - repo: inveniosoftware/flask-security-fork + repo: mattupstate/flask-security tags: true python: "2.7" condition: $REQUIREMENTS = release diff --git a/CHANGES b/CHANGES index 82a53d95..50d52f4d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,24 +1,18 @@ -Flask-Security-Fork Changelog -============================= +Flask-Security Changelog +======================== -Here you can see the full list of changes between each Flask-Security-Fork release. +Here you can see the full list of changes between each Flask-Security release. -Version 2.0.1 +Version 3.0.0 ------------- -Released January 18th 2017 +Released TBD - Added options `SECURITY_EMAIL_PLAINTEXT` and `SECURITY_EMAIL_HTML` for sending respecively plaintext and HTML version of email. - Fixed validation when missing login information. - Fixed condition for token extraction from JSON body. - Better support for universal bdist wheel. - -Version 2.0.0 -------------- - -Released January 11th 2017 - - Added port of CLI using Click configurable using options `SECURITY_CLI_USERS_NAME` and `SECURITY_CLI_ROLES_NAME`. - Added new configuration option `SECURITY_DATETIME_FACTORY` which can @@ -27,30 +21,12 @@ Released January 11th 2017 - Better IP tracking if using Flask 0.12. - Renamed deprecated Flask-WFT base form class. - Added tests for custom forms configured using app config. - -Version 1.8.2 -------------- - -Released December 20th 2016 - - Added validation and tests for next argument in logout endpoint. (see #499) - Bumped minimal required versions of several packages. - Extended test matric on Travis CI for minimal and released package versions. - Added of .editorconfig and forced tests for code style. - -Version 1.8.1 -------------- - -Released November 15th 2016 - - Fixed a security bug when validating a confirmation token, also checks if the email that the token was created with matches the user's current email. - -Version 1.8.0 -------------- - -Released October 28th 2016 - - Replaced token loader with request loader. - Changed trackable behavior of `login_user` when IP can not be detected from a request from 'untrackable' to `None` value. - Use ProxyFix instead of inspecting X-Forwarded-For header. @@ -70,11 +46,6 @@ Released October 28th 2016 - Removed a duplicate line ('retype_password': 'Retype Password') in forms.py. - Various documentation improvement. -Flask-Security Changelog -======================== - -Here you can see the full list of changes between each Flask-Security release. - Version 1.7.5 ------------- diff --git a/README.rst b/README.rst index 28243de3..443106fb 100644 --- a/README.rst +++ b/README.rst @@ -1,30 +1,28 @@ -Flask-Security-Fork +Flask-Security =================== -.. image:: https://img.shields.io/travis/inveniosoftware/flask-security-fork.svg - :target: https://travis-ci.org/inveniosoftware/flask-security-fork +.. image:: https://img.shields.io/travis/mattupstate/flask-security.svg + :target: https://travis-ci.org/mattupstate/flask-security -.. image:: https://img.shields.io/coveralls/inveniosoftware/flask-security-fork.svg - :target: https://coveralls.io/r/inveniosoftware/flask-security-fork +.. image:: https://img.shields.io/coveralls/mattupstate/flask-security.svg + :target: https://coveralls.io/r/mattupstate/flask-security -.. image:: https://img.shields.io/github/tag/inveniosoftware/flask-security-fork.svg - :target: https://github.com/inveniosoftware/flask-security-fork/releases +.. image:: https://img.shields.io/github/tag/mattupstate/flask-security.svg + :target: https://github.com/mattupstate/flask-security/releases -.. image:: https://img.shields.io/pypi/dm/flask-security-fork.svg - :target: https://pypi.python.org/pypi/flask-security-fork +.. image:: https://img.shields.io/pypi/dm/flask-security.svg + :target: https://pypi.python.org/pypi/flask-security :alt: Downloads -.. image:: https://img.shields.io/github/license/inveniosoftware/flask-security-fork.svg - :target: https://github.com/inveniosoftware/flask-security-fork/blob/master/LICENSE +.. image:: https://img.shields.io/github/license/mattupstate/flask-security.svg + :target: https://github.com/mattupstate/flask-security/blob/master/LICENSE :alt: License -This is a fork of the official Flask-Security extension. - It quickly adds security features to your Flask application. Resources --------- -- `Documentation `_ +- `Documentation `_ - `Issue Tracker `_ -- `Code `_ +- `Code `_ diff --git a/docs/conf.py b/docs/conf.py index 7b53817c..84fa5310 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -100,7 +100,7 @@ # further. For a list of options available for each theme, see the # documentation. html_theme_options = { - # 'github_fork': 'mattupstate/flask-security', + 'github_fork': 'mattupstate/flask-security', # 'index_logo': False 'touch_icon': 'touch-icon.png', 'index_logo': 'logo-full.png' diff --git a/docs/features.rst b/docs/features.rst index e28bea2f..1b427682 100644 --- a/docs/features.rst +++ b/docs/features.rst @@ -129,8 +129,8 @@ Run ``flask --help`` and look for users and roles. .. _Click: http://packages.python.org/Click/ -.. _Flask-Login: http://packages.python.org/Flask-Login/ -.. _alternative token: http://packages.python.org/Flask-Login/#alternative-tokens +.. _Flask-Login: https://flask-login.readthedocs.org/en/latest/ +.. _alternative token: https://flask-login.readthedocs.io/en/latest/#alternative-tokens .. _Flask-Principal: http://packages.python.org/Flask-Principal/ .. _documentation on this topic: http://packages.python.org/Flask-Principal/#granular-resource-protection .. _passlib: http://packages.python.org/passlib/ diff --git a/docs/index.rst b/docs/index.rst index 3c1633c6..585908fa 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,7 +18,7 @@ Flask application. They include: Many of these features are made possible by integrating various Flask extensions and libraries. They include: -1. `Flask-Login `_ +1. `Flask-Login `_ 2. `Flask-Mail `_ 3. `Flask-Principal `_ 4. `Flask-WTF `_ diff --git a/docs/quickstart.rst b/docs/quickstart.rst index a279be4e..2910e429 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -17,7 +17,7 @@ SQLAlchemy Install requirements :: $ mkvirtualenv - $ pip install flask-security-fork flask-sqlalchemy + $ pip install flask-security flask-sqlalchemy SQLAlchemy Application @@ -90,7 +90,7 @@ SQLAlchemy Install requirements :: $ mkvirtualenv - $ pip install flask-security-fork sqlalchemy + $ pip install flask-security sqlalchemy Also, you can use the extension `Flask-SQLAlchemy-Session documentation `_. @@ -206,7 +206,7 @@ MongoEngine Install requirements :: $ mkvirtualenv - $ pip install flask-security-fork flask-mongoengine + $ pip install flask-security flask-mongoengine MongoEngine Application ~~~~~~~~~~~~~~~~~~~~~~~ @@ -273,7 +273,7 @@ Peewee Install requirements :: $ mkvirtualenv - $ pip install flask-security-fork flask-peewee + $ pip install flask-security flask-peewee Peewee Application ~~~~~~~~~~~~~~~~~~ diff --git a/flask_security/core.py b/flask_security/core.py index 00133f5b..ccb81821 100644 --- a/flask_security/core.py +++ b/flask_security/core.py @@ -250,7 +250,7 @@ def _on_identity_loaded(sender, identity): if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) - for role in current_user.roles: + for role in getattr(current_user, 'roles', []): identity.provides.add(RoleNeed(role.name)) identity.user = current_user diff --git a/flask_security/datastore.py b/flask_security/datastore.py index 8b86b44b..f8ff7ac7 100644 --- a/flask_security/datastore.py +++ b/flask_security/datastore.py @@ -133,6 +133,13 @@ def _prepare_create_user_args(self, **kwargs): kwargs['roles'] = roles return kwargs + def _is_numeric(self, value): + try: + int(value) + except (TypeError, ValueError): + return False + return True + def get_user(self, id_or_email): """Returns a user matching the specified ID or email address.""" raise NotImplementedError @@ -233,21 +240,15 @@ def __init__(self, db, user_model, role_model): UserDatastore.__init__(self, user_model, role_model) def get_user(self, identifier): - if self._is_numeric(identifier): - return self.user_model.query.get(identifier) + rv = self.user_model.query.get(identifier) + if rv is not None: + return rv for attr in get_identity_attributes(): query = getattr(self.user_model, attr).ilike(identifier) rv = self.user_model.query.filter(query).first() if rv is not None: return rv - def _is_numeric(self, value): - try: - int(value) - except (TypeError, ValueError): - return False - return True - def find_user(self, **kwargs): return self.user_model.query.filter_by(**kwargs).first() @@ -296,10 +297,13 @@ def get_user(self, identifier): from mongoengine import ValidationError try: return self.user_model.objects(id=identifier).first() - except ValidationError: + except (ValidationError, ValueError): pass + + is_numeric = self._is_numeric(identifier) + for attr in get_identity_attributes(): - query_key = '%s__iexact' % attr + query_key = attr if is_numeric else '%s__iexact' % attr query = {query_key: identifier} rv = self.user_model.objects(**query).first() if rv is not None: @@ -347,7 +351,7 @@ def __init__(self, db, user_model, role_model, role_link): def get_user(self, identifier): try: return self.user_model.get(self.user_model.id == identifier) - except ValueError: + except (self.user_model.DoesNotExist, ValueError): pass for attr in get_identity_attributes(): @@ -429,22 +433,21 @@ def __init__(self, db, user_model, role_model): @with_pony_session def get_user(self, identifier): - if self._is_numeric(identifier): + from pony.orm.core import ObjectNotFound + try: return self.user_model[identifier] + except (ObjectNotFound, ValueError): + pass for attr in get_identity_attributes(): # this is a nightmare, tl;dr we need to get the thing that # corresponds to email (usually) - user = self.user_model.get(**{attr: identifier}) - if user is not None: - return user - - def _is_numeric(self, value): - try: - int(value) - except ValueError: - return False - return True + try: + user = self.user_model.get(**{attr: identifier}) + if user is not None: + return user + except TypeError: + pass @with_pony_session def find_user(self, **kwargs): diff --git a/flask_security/translations/da_DK/LC_MESSAGES/messages.po b/flask_security/translations/da_DK/LC_MESSAGES/flask_security.po similarity index 100% rename from flask_security/translations/da_DK/LC_MESSAGES/messages.po rename to flask_security/translations/da_DK/LC_MESSAGES/flask_security.po diff --git a/flask_security/translations/de_DE/LC_MESSAGES/flask_security.po b/flask_security/translations/de_DE/LC_MESSAGES/flask_security.po new file mode 100644 index 00000000..64aaed7d --- /dev/null +++ b/flask_security/translations/de_DE/LC_MESSAGES/flask_security.po @@ -0,0 +1,327 @@ +# German translation for Flask-Security (Du/Sie distinction has been avoided) +# Copyright (C) 2017 ORGANIZATION +# This file is distributed under the same license as the Flask-Security +# project. +# Ingo Kleiber , 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: Flask-Security 2.0.1\n" +"Report-Msgid-Bugs-To: info@inveniosoftware.org\n" +"POT-Creation-Date: 2017-04-03 08:59+0200\n" +"PO-Revision-Date: 2017-04-30 17:00+0200\n" +"Last-Translator: Ingo Kleiber \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.3.4\n" + +#: flask_security/core.py:98 +msgid "Login Required" +msgstr "Login erforderlich" + +#: flask_security/core.py:99 +msgid "Welcome" +msgstr "Willkommen" + +#: flask_security/core.py:100 +msgid "Please confirm your email" +msgstr "Bitte E-Mail Adresse bestätigen" + +#: flask_security/core.py:101 +msgid "Login instructions" +msgstr "Anmeldeinstruktionen" + +#: flask_security/core.py:102 +#: flask_security/templates/security/email/reset_notice.html:1 +msgid "Your password has been reset" +msgstr "Das Passwort wurde zurückgesetzt" + +#: flask_security/core.py:103 +msgid "Your password has been changed" +msgstr "Das Passwort wurde geändert" + +#: flask_security/core.py:105 +msgid "Password reset instructions" +msgstr "Anleitung zur Passwortwiederherstellung" + +#: flask_security/core.py:131 +msgid "You do not have permission to view this resource." +msgstr "Keine Berechtigung um diese Ressource zu sehen." + +#: flask_security/core.py:133 +#, python-format +msgid "Thank you. Confirmation instructions have been sent to %(email)s." +msgstr "Vielen Dank. Bestätigungsinstruktionen wurden an %(email)s gesendet." + +#: flask_security/core.py:137 +msgid "Thank you. Your email has been confirmed." +msgstr "Vielen Dank. Die E-Mail Adresse wurde bestätigt." + +#: flask_security/core.py:139 +msgid "Your email has already been confirmed." +msgstr "Die E-Mail Adresse wurde bereits bestätigt." + +#: flask_security/core.py:141 +msgid "Invalid confirmation token." +msgstr "Ungültiger Bestätigungscode." + +#: flask_security/core.py:143 +#, python-format +msgid "%(email)s is already associated with an account." +msgstr "%(email)s is bereits mit einem Konto verknüpft." + +#: flask_security/core.py:145 +msgid "Password does not match" +msgstr "Das Passwort stimmt nicht überein" + +#: flask_security/core.py:147 +msgid "Passwords do not match" +msgstr "Die Passwörter stimmen nicht überein" + +#: flask_security/core.py:149 +msgid "Redirections outside the domain are forbidden" +msgstr "Weiterleitungen außerhalb der Domain sind verboten" + +#: flask_security/core.py:151 +#, python-format +msgid "Instructions to reset your password have been sent to %(email)s." +msgstr "Instruktionen um das Passwort wiederherzustellen wurden an $(email)s gesendet." + +#: flask_security/core.py:154 +#, python-format +msgid "" +"You did not reset your password within %(within)s. New instructions have" +" been sent to %(email)s." +msgstr "" +"Das Passwort wurde nicht innerhab von %(within)s zurückgesetzt. Neue Instruktionen" +" wurden an %(email)s gesendet." + +#: flask_security/core.py:157 +msgid "Invalid reset password token." +msgstr "Ungültiger Passwortwiederherstellungscode." + +#: flask_security/core.py:159 +msgid "Email requires confirmation." +msgstr "Die E-Mail Adresse muss bestätigt werden." + +#: flask_security/core.py:161 +#, python-format +msgid "Confirmation instructions have been sent to %(email)s." +msgstr "Bestätigungsinstruktionen wurden an %(email)s gesendet." + +#: flask_security/core.py:163 +#, python-format +msgid "" +"You did not confirm your email within %(within)s. New instructions to " +"confirm your email have been sent to %(email)s." +msgstr "" +"Die E-Mail Adresse wurden nicht innerhalb von %(within)s bestätigt. Neue Instruktionen" +" wurden an %(email)s gesendet." + + +#: flask_security/core.py:167 +#, python-format +msgid "" +"You did not login within %(within)s. New instructions to login have been" +" sent to %(email)s." +msgstr "" +"Die Anmeldung erfolgte nicht in %(within)s. Neue Instruktionen" +" wurden an %(email)s gesendet." + +#: flask_security/core.py:170 +#, python-format +msgid "Instructions to login have been sent to %(email)s." +msgstr "Instruktionen zur Anmeldung wurden an %(email)s gesendet." + +#: flask_security/core.py:172 +msgid "Invalid login token." +msgstr "Ungülter Anmeldecode." + +#: flask_security/core.py:174 +msgid "Account is disabled." +msgstr "Konto ist deaktiviert." + +#: flask_security/core.py:176 +msgid "Email not provided" +msgstr "Keine E-Mail Adresse angegeben" + +#: flask_security/core.py:178 +msgid "Invalid email address" +msgstr "Ungültige E-Mail Adresse" + +#: flask_security/core.py:180 +msgid "Password not provided" +msgstr "Kein Passwort angegeben" + +#: flask_security/core.py:182 +msgid "No password is set for this user" +msgstr "Für diesen Benutzer ist kein Passwort gesetzt" + +#: flask_security/core.py:184 +msgid "Password must be at least 6 characters" +msgstr "Das Passwort muss mindestens 6 Zeichen lang sein" + +#: flask_security/core.py:186 +msgid "Specified user does not exist" +msgstr "Spezifizierter Benutzer existiert nicht" + +#: flask_security/core.py:188 +msgid "Invalid password" +msgstr "Ungültiges Passwort" + +#: flask_security/core.py:190 +msgid "You have successfully logged in." +msgstr "Die Anmeldung war erfolgreich." + +#: flask_security/core.py:192 +msgid "Forgot password?" +msgstr "Passwort vergessen?" + +#: flask_security/core.py:194 +msgid "" +"You successfully reset your password and you have been logged in " +"automatically." +msgstr "" +"Das Passwort wurde erfolgreich wiederhergestellt und der Login" +" erfolgte automatisch." + +#: flask_security/core.py:197 +msgid "Your new password must be different than your previous password." +msgstr "Das neue Passwort muss sich vom vorherigen unterscheiden." + +#: flask_security/core.py:200 +msgid "You successfully changed your password." +msgstr "Das Passwort wurde erfolgreich geändert." + +#: flask_security/core.py:202 +msgid "Please log in to access this page." +msgstr "Bitte Anmelden um diese Seite zu sehen." + +#: flask_security/core.py:204 +msgid "Please reauthenticate to access this page." +msgstr "Bitte neu authentifizieren um auf diese Seite zuzugreifen." + +#: flask_security/forms.py:31 +msgid "Email Address" +msgstr "E-Mail Adresse" + +#: flask_security/forms.py:32 +msgid "Password" +msgstr "Passwort" + +#: flask_security/forms.py:33 +msgid "Remember Me" +msgstr "Erinnern" + +#: flask_security/forms.py:34 flask_security/templates/security/_menu.html:4 +#: flask_security/templates/security/login_user.html:3 +#: flask_security/templates/security/send_login.html:3 +msgid "Login" +msgstr "Anmelden" + +#: flask_security/forms.py:35 flask_security/templates/security/_menu.html:6 +#: flask_security/templates/security/register_user.html:3 +msgid "Register" +msgstr "Registrieren" + +#: flask_security/forms.py:36 +msgid "Resend Confirmation Instructions" +msgstr "Bestätigungsinstruktionen neu senden" + +#: flask_security/forms.py:37 +msgid "Recover Password" +msgstr "Passwort wiederherstellen" + +#: flask_security/forms.py:38 +msgid "Reset Password" +msgstr "Passwort zurücksetzen" + +#: flask_security/forms.py:39 +msgid "Retype Password" +msgstr "Passwort neu eingeben" + +#: flask_security/forms.py:40 +msgid "New Password" +msgstr "Neues Passwort" + +#: flask_security/forms.py:41 +msgid "Change Password" +msgstr "Passwort ändern" + +#: flask_security/forms.py:42 +msgid "Send Login Link" +msgstr "Login-Link versenden" + +#: flask_security/templates/security/_menu.html:2 +msgid "Menu" +msgstr "Menü" + +#: flask_security/templates/security/_menu.html:9 +msgid "Forgot password" +msgstr "Passwort vergessen" + +#: flask_security/templates/security/_menu.html:12 +msgid "Confirm account" +msgstr "Konto bestätigen" + +#: flask_security/templates/security/change_password.html:3 +msgid "Change password" +msgstr "Passwort ändern" + +#: flask_security/templates/security/forgot_password.html:3 +msgid "Send password reset instructions" +msgstr "Senden von Instruktionen zur Passwortzurücksetzung" + +#: flask_security/templates/security/reset_password.html:3 +msgid "Reset password" +msgstr "Passwort zurücksetzen" + +#: flask_security/templates/security/send_confirmation.html:3 +msgid "Resend confirmation instructions" +msgstr "Bestätigungsinstruktionen erneut versenden" + +#: flask_security/templates/security/email/change_notice.html:1 +msgid "Your password has been changed." +msgstr "Das Passwort wurde geändert." + +#: flask_security/templates/security/email/change_notice.html:3 +msgid "If you did not change your password," +msgstr "Falls das Passwort nicht geändert wurde" + +#: flask_security/templates/security/email/change_notice.html:3 +msgid "click here to reset it" +msgstr "hier klicken um es zurückzusetzen" + +#: flask_security/templates/security/email/confirmation_instructions.html:1 +msgid "Please confirm your email through the link below:" +msgstr "Bitte die E-Mail Adresse durch den Link unten bestätigen:" + +#: flask_security/templates/security/email/confirmation_instructions.html:3 +#: flask_security/templates/security/email/welcome.html:6 +msgid "Confirm my account" +msgstr "Den Account bestätigen" + +#: flask_security/templates/security/email/login_instructions.html:1 +#: flask_security/templates/security/email/welcome.html:1 +#, python-format +msgid "Welcome %(email)s!" +msgstr "Willkommen %(email)s!" + +#: flask_security/templates/security/email/login_instructions.html:3 +msgid "You can log into your through the link below:" +msgstr "Die Anmeldung kann über den Link unten erfolgen:" + +#: flask_security/templates/security/email/login_instructions.html:5 +msgid "Login now" +msgstr "Jetzt anmelden" + +#: flask_security/templates/security/email/reset_instructions.html:1 +msgid "Click here to reset your password" +msgstr "Hier klicken um das Passwort zurückzusetzen" + +#: flask_security/templates/security/email/welcome.html:4 +msgid "You can confirm your email through the link below:" +msgstr "Die E-Mail Adresse kann über den Link unten bestätigt werden" + diff --git a/flask_security/translations/flask_security.pot b/flask_security/translations/flask_security.pot index 33c198aa..f8679fb0 100644 --- a/flask_security/translations/flask_security.pot +++ b/flask_security/translations/flask_security.pot @@ -1,13 +1,13 @@ -# Translations template for Flask-Security-Fork. +# Translations template for Flask-Security. # Copyright (C) 2017 CERN -# This file is distributed under the same license as the Flask-Security-Fork +# This file is distributed under the same license as the Flask-Security # project. # FIRST AUTHOR , 2017. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Flask-Security-Fork 2.0.1\n" +"Project-Id-Version: Flask-Security 2.0.1\n" "Report-Msgid-Bugs-To: info@inveniosoftware.org\n" "POT-Creation-Date: 2017-04-03 08:59+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" diff --git a/flask_security/translations/ru_RU/LC_MESSAGES/messages.po b/flask_security/translations/ru_RU/LC_MESSAGES/flask_security.po similarity index 99% rename from flask_security/translations/ru_RU/LC_MESSAGES/messages.po rename to flask_security/translations/ru_RU/LC_MESSAGES/flask_security.po index 5d88faec..467cc2c3 100644 --- a/flask_security/translations/ru_RU/LC_MESSAGES/messages.po +++ b/flask_security/translations/ru_RU/LC_MESSAGES/flask_security.po @@ -1,12 +1,12 @@ -# Russian Translations for Flask-Security-Fork. +# Russian Translations for Flask-Security. # Copyright (C) 2017 CERN, leovp -# This file is distributed under the same license as the Flask-Security-Fork +# This file is distributed under the same license as the Flask-Security # project. # FIRST AUTHOR , 2017. # msgid "" msgstr "" -"Project-Id-Version: Flask-Security-Fork 2.0.1\n" +"Project-Id-Version: Flask-Security 2.0.1\n" "Report-Msgid-Bugs-To: info@inveniosoftware.org\n" "POT-Creation-Date: 2017-04-15 12:38+0300\n" "PO-Revision-Date: 2017-04-15 15:15+0300\n" diff --git a/flask_security/utils.py b/flask_security/utils.py index 3f994030..5e417981 100644 --- a/flask_security/utils.py +++ b/flask_security/utils.py @@ -135,7 +135,7 @@ def verify_password(password, password_hash): :param password_hash: The expected hash value of the password (usually from your database) """ - if use_double_hash(): + if use_double_hash(password_hash): password = get_hmac(password) return _pwd_context.verify(password, password_hash) @@ -150,11 +150,8 @@ def verify_and_update_password(password, user): :param password: A plaintext password to verify :param user: The user to verify against """ - if use_double_hash(): - verified = ( - _pwd_context.verify(get_hmac(password), user.password) or - _pwd_context.verify(password, user.password) - ) + if use_double_hash(user.password): + verified = _pwd_context.verify(get_hmac(password), user.password) else: # Try with original password. verified = _pwd_context.verify(password, user.password) @@ -327,7 +324,7 @@ def strip_prefix(tup): def get_message(key, **kwargs): rv = config_value('MSG_' + key) - return _security.i18n_domain.lazy_gettext(rv[0], **kwargs), rv[1] + return _security.i18n_domain.gettext(rv[0], **kwargs), rv[1] def config_value(key, app=None, default=None): @@ -441,13 +438,19 @@ def get_identity_attributes(app=None): return attrs -def use_double_hash(): +def use_double_hash(password_hash=None): """Return a bool indicating whether a password should be hashed twice.""" single_hash = config_value('PASSWORD_SINGLE_HASH') if single_hash and _security.password_salt: raise RuntimeError('You may not specify a salt with ' 'SECURITY_PASSWORD_SINGLE_HASH') - return not (_security.password_hash == 'plaintext' or single_hash) + + if password_hash is None: + is_plaintext = _security.password_hash == 'plaintext' + else: + is_plaintext = _pwd_context.identify(password_hash) == 'plaintext' + + return not (is_plaintext or single_hash) @contextmanager diff --git a/setup.cfg b/setup.cfg index 9d4554da..415bc3ee 100644 --- a/setup.cfg +++ b/setup.cfg @@ -13,6 +13,7 @@ upload-dir = docs/_build/html [compile_catalog] directory = flask_security/translations/ +domain = flask_security [extract_messages] copyright_holder = CERN @@ -22,9 +23,11 @@ output-file = flask_security/translations/flask_security.pot add-comments = NOTE [init_catalog] +domain = flask_security input-file = flask_security/translations/flask_security.pot output-dir = flask_security/translations/ [update_catalog] +domain = flask_security input-file = flask_security/translations/flask_security.pot output-dir = flask_security/translations/ diff --git a/setup.py b/setup.py index 8ce4793d..2c1c33b2 100755 --- a/setup.py +++ b/setup.py @@ -58,7 +58,7 @@ packages = find_packages() setup( - name='Flask-Security-Fork', + name='Flask-Security', version='2.0.1', description=__doc__, long_description=readme, @@ -66,7 +66,7 @@ license='MIT', author='Matt Wright', author_email='matt@nobien.net', - url='https://github.com/inveniosoftware/flask-security-fork', + url='https://github.com/mattupstate/flask-security', packages=packages, zip_safe=False, include_package_data=True, diff --git a/tests/conftest.py b/tests/conftest.py index fcdf9261..cdababc8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -156,6 +156,7 @@ class User(db.Document, UserMixin): email = db.StringField(unique=True, max_length=255) username = db.StringField(max_length=255) password = db.StringField(required=False, max_length=255) + security_number = db.IntField(unique=True) last_login_at = db.DateTimeField() current_login_at = db.DateTimeField() last_login_ip = db.StringField(max_length=100) @@ -195,6 +196,7 @@ class Role(db.Model, RoleMixin): class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(255), unique=True) + security_number = db.Column(db.Integer, unique=True) username = db.Column(db.String(255)) password = db.Column(db.String(255)) last_login_at = db.Column(db.DateTime()) @@ -255,6 +257,7 @@ class User(Base, UserMixin): email = Column(String(255), unique=True) username = Column(String(255)) password = Column(String(255)) + security_number = Column(Integer, unique=True) last_login_at = Column(DateTime()) current_login_at = Column(DateTime()) last_login_ip = Column(String(100)) @@ -296,6 +299,7 @@ class Role(db.Model, RoleMixin): class User(db.Model, UserMixin): email = TextField() username = TextField() + security_number = IntegerField(null=True) password = TextField(null=True) last_login_at = DateTimeField(null=True) current_login_at = DateTimeField(null=True) @@ -338,6 +342,7 @@ class Role(db.Entity): class User(db.Entity): email = Required(str) username = Optional(str) + security_number = Optional(int) password = Optional(str, nullable=True) last_login_at = Optional(datetime) current_login_at = Optional(datetime) diff --git a/tests/test_datastore.py b/tests/test_datastore.py index e3c0ece9..d8ab0ecd 100644 --- a/tests/test_datastore.py +++ b/tests/test_datastore.py @@ -83,7 +83,8 @@ def test_activate_returns_false_if_already_true(): def test_get_user(app, datastore): init_app_with_options(app, datastore, **{ - 'SECURITY_USER_IDENTITY_ATTRIBUTES': ('email', 'username') + 'SECURITY_USER_IDENTITY_ATTRIBUTES': ('email', 'username', + 'security_number') }) with app.app_context(): @@ -98,6 +99,9 @@ def test_get_user(app, datastore): user = datastore.get_user('matt') assert user is not None + user = datastore.get_user(123456) + assert user is not None + def test_find_role(app, datastore): init_app_with_options(app, datastore) diff --git a/tests/utils.py b/tests/utils.py index 8d7710a3..ebea02fc 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -48,12 +48,13 @@ def create_roles(ds): def create_users(ds, count=None): - users = [('matt@lp.com', 'matt', 'password', ['admin'], True), - ('joe@lp.com', 'joe', 'password', ['editor'], True), - ('dave@lp.com', 'dave', 'password', ['admin', 'editor'], True), - ('jill@lp.com', 'jill', 'password', ['author'], True), - ('tiya@lp.com', 'tiya', 'password', [], False), - ('jess@lp.com', 'jess', None, [], True)] + users = [('matt@lp.com', 'matt', 'password', ['admin'], True, 123456), + ('joe@lp.com', 'joe', 'password', ['editor'], True, 234567), + ('dave@lp.com', 'dave', 'password', ['admin', 'editor'], True, + 345678), + ('jill@lp.com', 'jill', 'password', ['author'], True, 456789), + ('tiya@lp.com', 'tiya', 'password', [], False, 567890), + ('jess@lp.com', 'jess', None, [], True, 678901)] count = count or len(users) for u in users[:count]: @@ -66,7 +67,8 @@ def create_users(ds, count=None): email=u[0], username=u[1], password=pw, - active=u[4]) + active=u[4], + security_number=u[5]) ds.commit() for role in roles: ds.add_role_to_user(user, role)