Hello community,
here is the log from the commit of package python-Flask-Login for
openSUSE:Factory checked in at 2017-12-04 12:16:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Flask-Login (Old)
and /work/SRC/openSUSE:Factory/.python-Flask-Login.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Flask-Login"
Mon Dec 4 12:16:47 2017 rev:2 rq:548014 version:0.4.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Flask-Login/python-Flask-Login.changes
2017-09-09 20:27:08.316983462 +0200
+++
/work/SRC/openSUSE:Factory/.python-Flask-Login.new/python-Flask-Login.changes
2017-12-04 12:17:12.194788557 +0100
@@ -1,0 +2,11 @@
+Sun Dec 3 18:32:18 UTC 2017 - [email protected]
+
+- update to version 0.4.1:
+ * New config option USE_SESSION_FOR_NEXT to enable storing next url
+ in session instead of url. #330
+ * Accept int seconds along with timedelta for
+ REMEMBER_COOKIE_DURATION. #370
+ * New config option FORCE_HOST_FOR_REDIRECTS to force host for
+ redirects. #371
+
+-------------------------------------------------------------------
Old:
----
Flask-Login-0.4.0.tar.gz
New:
----
Flask-Login-0.4.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-Flask-Login.spec ++++++
--- /var/tmp/diff_new_pack.0zhWfp/_old 2017-12-04 12:17:12.762767935 +0100
+++ /var/tmp/diff_new_pack.0zhWfp/_new 2017-12-04 12:17:12.762767935 +0100
@@ -13,22 +13,23 @@
# published by the Open Source Initiative.
# Please submit bugfixes or comments via http://bugs.opensuse.org/
+#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%bcond_without test
Name: python-Flask-Login
-Version: 0.4.0
+Version: 0.4.1
Release: 0
-License: MIT
Summary: User session management for Flask
-Url: https://github.com/maxcountryman/flask-login
+License: MIT
Group: Development/Languages/Python
+Url: https://github.com/maxcountryman/flask-login
Source:
https://files.pythonhosted.org/packages/source/F/Flask-Login/Flask-Login-%{version}.tar.gz
-BuildRequires: fdupes
-BuildRequires: python-rpm-macros
BuildRequires: %{python_module devel}
BuildRequires: %{python_module setuptools}
+BuildRequires: fdupes
+BuildRequires: python-rpm-macros
%if %{with test}
BuildRequires: %{python_module Flask}
%endif
++++++ Flask-Login-0.4.0.tar.gz -> Flask-Login-0.4.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Login-0.4.0/Flask_Login.egg-info/PKG-INFO
new/Flask-Login-0.4.1/Flask_Login.egg-info/PKG-INFO
--- old/Flask-Login-0.4.0/Flask_Login.egg-info/PKG-INFO 2016-10-26
19:39:37.000000000 +0200
+++ new/Flask-Login-0.4.1/Flask_Login.egg-info/PKG-INFO 2017-12-02
03:35:27.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: Flask-Login
-Version: 0.4.0
+Version: 0.4.1
Summary: User session management for Flask
Home-page: https://github.com/maxcountryman/flask-login
Author: Matthew Frazier
@@ -21,7 +21,7 @@
Links
`````
- * `documentation <http://packages.python.org/Flask-Login>`_
+ * `documentation <https://flask-login.readthedocs.io/en/latest/>`_
* `development version <https://github.com/maxcountryman/flask-login>`_
Platform: any
@@ -36,5 +36,9 @@
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Login-0.4.0/PKG-INFO
new/Flask-Login-0.4.1/PKG-INFO
--- old/Flask-Login-0.4.0/PKG-INFO 2016-10-26 19:39:37.000000000 +0200
+++ new/Flask-Login-0.4.1/PKG-INFO 2017-12-02 03:35:27.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: Flask-Login
-Version: 0.4.0
+Version: 0.4.1
Summary: User session management for Flask
Home-page: https://github.com/maxcountryman/flask-login
Author: Matthew Frazier
@@ -21,7 +21,7 @@
Links
`````
- * `documentation <http://packages.python.org/Flask-Login>`_
+ * `documentation <https://flask-login.readthedocs.io/en/latest/>`_
* `development version <https://github.com/maxcountryman/flask-login>`_
Platform: any
@@ -36,5 +36,9 @@
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Login-0.4.0/README.md
new/Flask-Login-0.4.1/README.md
--- old/Flask-Login-0.4.0/README.md 2016-10-26 19:27:51.000000000 +0200
+++ new/Flask-Login-0.4.1/README.md 2017-12-02 03:30:55.000000000 +0100
@@ -1,6 +1,7 @@
# Flask-Login
-[](https://travis-ci.org/#!/maxcountryman/flask-login)
+[](https://travis-ci.org/maxcountryman/flask-login)
+[](https://coveralls.io/github/maxcountryman/flask-login?branch=master)
Flask-Login provides user session management for Flask. It handles the common
tasks of logging in, logging out, and remembering your users' sessions over
@@ -13,13 +14,7 @@
## Installation
-Install the extension with one of the following commands:
-
-```sh
-$ easy_install flask-login
-```
-
-or alternatively if you have pip installed:
+Install the extension with pip:
```sh
$ pip install flask-login
@@ -58,7 +53,7 @@
```python
# Our mock database.
-users = {'[email protected]': {'pw': 'secret'}}
+users = {'[email protected]': {'password': 'secret'}}
```
We also need to tell Flask-Login how to load a user from a Flask request and
@@ -91,7 +86,7 @@
# DO NOT ever store passwords in plaintext and always compare password
# hashes using constant-time comparison!
- user.is_authenticated = request.form['pw'] == users[email]['pw']
+ user.is_authenticated = request.form['password'] ==
users[email]['password']
return user
```
@@ -106,14 +101,14 @@
if flask.request.method == 'GET':
return '''
<form action='login' method='POST'>
- <input type='text' name='email' id='email'
placeholder='email'></input>
- <input type='password' name='pw' id='pw'
placeholder='password'></input>
- <input type='submit' name='submit'></input>
+ <input type='text' name='email' id='email'
placeholder='email'/>
+ <input type='password' name='password' id='password'
placeholder='password'/>
+ <input type='submit' name='submit'/>
</form>
'''
email = flask.request.form['email']
- if flask.request.form['pw'] == users[email]['pw']:
+ if flask.request.form['password'] == users[email]['password']:
user = User()
user.id = email
flask_login.login_user(user)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Login-0.4.0/flask_login/__about__.py
new/Flask-Login-0.4.1/flask_login/__about__.py
--- old/Flask-Login-0.4.0/flask_login/__about__.py 2016-10-26
19:38:25.000000000 +0200
+++ new/Flask-Login-0.4.1/flask_login/__about__.py 2017-12-02
03:34:22.000000000 +0100
@@ -1,7 +1,7 @@
__title__ = 'Flask-Login'
__description__ = 'User session management for Flask'
__url__ = 'https://github.com/maxcountryman/flask-login'
-__version_info__ = ('0', '4', '0')
+__version_info__ = ('0', '4', '1')
__version__ = '.'.join(__version_info__)
__author__ = 'Matthew Frazier'
__author_email__ = '[email protected]'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Login-0.4.0/flask_login/__init__.py
new/Flask-Login-0.4.1/flask_login/__init__.py
--- old/Flask-Login-0.4.0/flask_login/__init__.py 2016-10-26
19:27:51.000000000 +0200
+++ new/Flask-Login-0.4.1/flask_login/__init__.py 2017-12-02
03:30:55.000000000 +0100
@@ -8,6 +8,7 @@
:license: MIT/X11, see LICENSE for more details.
'''
+from .__about__ import __version__
from .config import (COOKIE_NAME, COOKIE_DURATION, COOKIE_SECURE,
COOKIE_HTTPONLY, LOGIN_MESSAGE, LOGIN_MESSAGE_CATEGORY,
REFRESH_MESSAGE, REFRESH_MESSAGE_CATEGORY, ID_ATTRIBUTE,
@@ -28,6 +29,7 @@
LoginManager.__name__,
UserMixin.__name__,
AnonymousUserMixin.__name__,
+ __version__,
'COOKIE_NAME',
'COOKIE_DURATION',
'COOKIE_SECURE',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Login-0.4.0/flask_login/config.py
new/Flask-Login-0.4.1/flask_login/config.py
--- old/Flask-Login-0.4.0/flask_login/config.py 2016-10-26 19:27:51.000000000
+0200
+++ new/Flask-Login-0.4.1/flask_login/config.py 2017-12-02 03:30:55.000000000
+0100
@@ -42,8 +42,13 @@
#: A set of session keys that are populated by Flask-Login. Use this set to
#: purge keys safely and accurately.
-SESSION_KEYS = set(['user_id', 'remember', '_id', '_fresh'])
+SESSION_KEYS = set(['user_id', 'remember', '_id', '_fresh', 'next'])
#: A set of HTTP methods which are exempt from `login_required` and
#: `fresh_login_required`. By default, this is just ``OPTIONS``.
EXEMPT_METHODS = set(['OPTIONS'])
+
+#: If true, the page the user is attempting to access is stored in the session
+#: rather than a url parameter when redirecting to the login view; defaults to
+#: ``False``.
+USE_SESSION_FOR_NEXT = False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Login-0.4.0/flask_login/login_manager.py
new/Flask-Login-0.4.1/flask_login/login_manager.py
--- old/Flask-Login-0.4.0/flask_login/login_manager.py 2016-10-26
19:27:51.000000000 +0200
+++ new/Flask-Login-0.4.1/flask_login/login_manager.py 2017-12-02
03:30:55.000000000 +0100
@@ -7,7 +7,7 @@
import warnings
-from datetime import datetime
+from datetime import datetime, timedelta
from flask import (_request_ctx_stack, abort, current_app, flash, redirect,
request, session)
@@ -16,20 +16,20 @@
from .config import (COOKIE_NAME, COOKIE_DURATION, COOKIE_SECURE,
COOKIE_HTTPONLY, LOGIN_MESSAGE, LOGIN_MESSAGE_CATEGORY,
REFRESH_MESSAGE, REFRESH_MESSAGE_CATEGORY, ID_ATTRIBUTE,
- AUTH_HEADER_NAME, SESSION_KEYS)
+ AUTH_HEADER_NAME, SESSION_KEYS, USE_SESSION_FOR_NEXT)
from .mixins import AnonymousUserMixin
from .signals import (user_loaded_from_cookie, user_loaded_from_header,
user_loaded_from_request, user_unauthorized,
user_needs_refresh, user_accessed, session_protected)
-from .utils import (_get_user, login_url, _create_identifier,
- _user_context_processor, encode_cookie, decode_cookie)
+from .utils import (_get_user, login_url as make_login_url, _create_identifier,
+ _user_context_processor, encode_cookie, decode_cookie,
+ make_next_param, expand_login_view)
class LoginManager(object):
- '''
- This object is used to hold the settings used for logging in. Instances of
- :class:`LoginManager` are *not* bound to specific apps, so you can create
- one in the main body of your code and then bind it to your
+ '''This object is used to hold the settings used for logging in. Instances
+ of :class:`LoginManager` are *not* bound to specific apps, so you can
+ create one in the main body of your code and then bind it to your
app in a factory function.
'''
def __init__(self, app=None, add_context_processor=True):
@@ -87,6 +87,8 @@
self.request_callback = None
+ self._session_identifier_generator = _create_identifier
+
if app is not None:
self.init_app(app, add_context_processor)
@@ -131,10 +133,12 @@
the current blueprint using `blueprint_login_views`. If the app
is not using blueprints or the login view for the current
blueprint is not specified use the value of `login_view`.
- Redirect the user to the login view. (The page they were
+
+ - Redirect the user to the login view. (The page they were
attempting to access will be passed in the ``next`` query
string variable, so you can redirect there if present instead
- of the homepage.)
+ of the homepage. Alternatively, it will be added to the session
+ as ``next`` if USE_SESSION_FOR_NEXT is set.)
If :attr:`LoginManager.login_view` is not defined, then it will simply
raise a HTTP 401 (Unauthorized) error instead.
@@ -162,7 +166,15 @@
else:
flash(self.login_message, category=self.login_message_category)
- return redirect(login_url(login_view, request.url))
+ config = current_app.config
+ if config.get('USE_SESSION_FOR_NEXT', USE_SESSION_FOR_NEXT):
+ login_url = expand_login_view(login_view)
+ session['next'] = make_next_param(login_url, request.url)
+ redirect_url = make_login_url(login_view)
+ else:
+ redirect_url = make_login_url(login_view, next_url=request.url)
+
+ return redirect(redirect_url)
def user_loader(self, callback):
'''
@@ -178,6 +190,9 @@
def header_loader(self, callback):
'''
+ This function has been deprecated. Please use
+ :meth:`LoginManager.request_loader` instead.
+
This sets the callback for loading a user from a header value.
The function you set should take an authentication token and
return a user object, or `None` if the user does not exist.
@@ -261,9 +276,35 @@
flash(self.needs_refresh_message,
category=self.needs_refresh_message_category)
- return redirect(login_url(self.refresh_view, request.url))
+ config = current_app.config
+ if config.get('USE_SESSION_FOR_NEXT', USE_SESSION_FOR_NEXT):
+ login_url = expand_login_view(self.refresh_view)
+ session['next'] = make_next_param(login_url, request.url)
+ redirect_url = make_login_url(self.refresh_view)
+ else:
+ login_url = self.refresh_view
+ redirect_url = make_login_url(login_url, next_url=request.url)
+
+ return redirect(redirect_url)
def reload_user(self, user=None):
+ '''
+ This set the ctx.user with the user object loaded by your customized
+ user_loader callback function, which should retrieved the user object
+ with the user_id got from session.
+
+ Syntax example:
+ from flask_login import LoginManager
+ @login_manager.user_loader
+ def any_valid_func_name(user_id):
+ # get your user object using the given user_id,
+ # if you use SQLAlchemy, for example:
+ user_obj = User.query.get(int(user_id))
+ return user_obj
+
+ Reason to let YOU define this self.user_callback:
+ Because we won't know how/where you will load you user object.
+ '''
ctx = _request_ctx_stack.top
if user is None:
@@ -274,8 +315,9 @@
if self.user_callback is None:
raise Exception(
"No user_loader has been installed for this "
- "LoginManager. Add one with the "
- "'LoginManager.user_loader' decorator.")
+ "LoginManager. Refer to"
+ "https://flask-login.readthedocs.io/"
+ "en/latest/#how-it-works for more info.")
user = self.user_callback(user_id)
if user is None:
ctx.user = self.anonymous_user()
@@ -318,7 +360,7 @@
def _session_protection(self):
sess = session._get_current_object()
- ident = _create_identifier()
+ ident = self._session_identifier_generator()
app = current_app._get_current_object()
mode = app.config.get('SESSION_PROTECTION', self.session_protection)
@@ -377,6 +419,10 @@
def _update_remember_cookie(self, response):
# Don't modify the session unless there's something to do.
+ if 'remember' not in session and \
+ current_app.config.get('REMEMBER_COOKIE_REFRESH_EACH_REQUEST'):
+ session['remember'] = 'set'
+
if 'remember' in session:
operation = session.pop('remember', None)
@@ -391,22 +437,29 @@
# cookie settings
config = current_app.config
cookie_name = config.get('REMEMBER_COOKIE_NAME', COOKIE_NAME)
- duration = config.get('REMEMBER_COOKIE_DURATION', COOKIE_DURATION)
domain = config.get('REMEMBER_COOKIE_DOMAIN')
path = config.get('REMEMBER_COOKIE_PATH', '/')
secure = config.get('REMEMBER_COOKIE_SECURE', COOKIE_SECURE)
httponly = config.get('REMEMBER_COOKIE_HTTPONLY', COOKIE_HTTPONLY)
+ if 'remember_seconds' in session:
+ duration = timedelta(seconds=session['remember_seconds'])
+ else:
+ duration = config.get('REMEMBER_COOKIE_DURATION', COOKIE_DURATION)
+
# prepare data
data = encode_cookie(text_type(session['user_id']))
+ if isinstance(duration, int):
+ duration = timedelta(seconds=duration)
+
try:
expires = datetime.utcnow() + duration
except TypeError:
raise Exception('REMEMBER_COOKIE_DURATION must be a ' +
'datetime.timedelta, instead got: {0}'.format(
- duration))
+ duration))
# actually set it
response.set_cookie(cookie_name,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Login-0.4.0/flask_login/utils.py
new/Flask-Login-0.4.1/flask_login/utils.py
--- old/Flask-Login-0.4.0/flask_login/utils.py 2016-10-26 19:27:51.000000000
+0200
+++ new/Flask-Login-0.4.1/flask_login/utils.py 2017-12-02 03:30:55.000000000
+0100
@@ -75,12 +75,30 @@
return current_url
+def expand_login_view(login_view):
+ '''
+ Returns the url for the login view, expanding the view name to a url if
+ needed.
+
+ :param login_view: The name of the login view or a URL for the login view.
+ :type login_view: str
+ '''
+ if login_view.startswith(('https://', 'http://', '/')):
+ return login_view
+ else:
+ return url_for(login_view)
+
+
def login_url(login_view, next_url=None, next_field='next'):
'''
Creates a URL for redirecting to a login page. If only `login_view` is
provided, this will just return the URL for it. If `next_url` is provided,
however, this will append a ``next=URL`` parameter to the query string
- so that the login view can redirect back to that URL.
+ so that the login view can redirect back to that URL. Flask-Login's default
+ unauthorized handler uses this function when redirecting to your login url.
+ To force the host name used, set `FORCE_HOST_FOR_REDIRECTS` to a host. This
+ prevents from redirecting to external sites if request headers Host or
+ X-Forwarded-For are present.
:param login_view: The name of the login view. (Alternately, the actual
URL to the login view.)
@@ -91,19 +109,19 @@
``next``.)
:type next_field: str
'''
- if login_view.startswith(('https://', 'http://', '/')):
- base = login_view
- else:
- base = url_for(login_view)
+ base = expand_login_view(login_view)
if next_url is None:
return base
- parts = list(urlparse(base))
- md = url_decode(parts[4])
+ parsed_result = urlparse(base)
+ md = url_decode(parsed_result.query)
md[next_field] = make_next_param(base, next_url)
- parts[4] = url_encode(md, sort=True)
- return urlunparse(parts)
+ netloc = current_app.config.get('FORCE_HOST_FOR_REDIRECTS') or \
+ parsed_result.netloc
+ parsed_result = parsed_result._replace(netloc=netloc,
+ query=url_encode(md, sort=True))
+ return urlunparse(parsed_result)
def login_fresh():
@@ -113,7 +131,7 @@
return session.get('_fresh', False)
-def login_user(user, remember=False, force=False, fresh=True):
+def login_user(user, remember=False, duration=None, force=False, fresh=True):
'''
Logs a user in. You should pass the actual user object to this. If the
user's `is_active` property is ``False``, they will not be logged in
@@ -127,6 +145,9 @@
:param remember: Whether to remember the user after their session expires.
Defaults to ``False``.
:type remember: bool
+ :param duration: The amount of time before the remember cookie expires. If
+ ``None`` the value set in the settings is used. Defaults to ``None``.
+ :type duration: :class:`datetime.timedelta`
:param force: If the user is inactive, setting this to ``True`` will log
them in regardless. Defaults to ``False``.
:type force: bool
@@ -140,10 +161,20 @@
user_id = getattr(user, current_app.login_manager.id_attribute)()
session['user_id'] = user_id
session['_fresh'] = fresh
- session['_id'] = _create_identifier()
+ session['_id'] = current_app.login_manager._session_identifier_generator()
if remember:
session['remember'] = 'set'
+ if duration is not None:
+ try:
+ # equal to timedelta.total_seconds() but works with Python 2.6
+ session['remember_seconds'] = (duration.microseconds +
+ (duration.seconds +
+ duration.days * 24 * 3600) *
+ 10**6) / 10.0**6
+ except AttributeError:
+ raise Exception('duration must be a datetime.timedelta, '
+ 'instead got: {0}'.format(duration))
_request_ctx_stack.top.user = user
user_logged_in.send(current_app._get_current_object(), user=_get_user())
@@ -167,6 +198,8 @@
cookie_name = current_app.config.get('REMEMBER_COOKIE_NAME', COOKIE_NAME)
if cookie_name in request.cookies:
session['remember'] = 'clear'
+ if 'remember_seconds' in session:
+ session.pop('remember_seconds')
user_logged_out.send(current_app._get_current_object(), user=user)
@@ -180,7 +213,7 @@
are reloaded from a cookie.
'''
session['_fresh'] = True
- session['_id'] = _create_identifier()
+ session['_id'] = current_app.login_manager._session_identifier_generator()
user_login_confirmed.send(current_app._get_current_object())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Login-0.4.0/setup.py
new/Flask-Login-0.4.1/setup.py
--- old/Flask-Login-0.4.0/setup.py 2016-10-26 19:27:51.000000000 +0200
+++ new/Flask-Login-0.4.1/setup.py 2017-12-02 03:30:55.000000000 +0100
@@ -13,7 +13,7 @@
Links
`````
-* `documentation <http://packages.python.org/Flask-Login>`_
+* `documentation <https://flask-login.readthedocs.io/en/latest/>`_
* `development version <https://github.com/maxcountryman/flask-login>`_
'''
import os
@@ -54,6 +54,10 @@
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Software Development :: Libraries :: Python Modules'
])