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 - a...@gmx.de + +- 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 -[![build status](https://secure.travis-ci.org/maxcountryman/flask-login.png?branch=master)](https://travis-ci.org/#!/maxcountryman/flask-login) +[![build status](https://travis-ci.org/maxcountryman/flask-login.svg?branch=master)](https://travis-ci.org/maxcountryman/flask-login) +[![coverage](https://coveralls.io/repos/maxcountryman/flask-login/badge.svg?branch=master&service=github)](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 = {'f...@bar.tld': {'pw': 'secret'}} +users = {'f...@bar.tld': {'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__ = 'leafstormr...@gmail.com' 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' ])