Merge remote-tracking branch 'origin/master' into sign_in_fixes

This commit is contained in:
Nicholas Staples
2016-01-28 16:04:50 +00:00
7 changed files with 19 additions and 16 deletions

View File

@@ -1,13 +1,15 @@
from datetime import timedelta, datetime
from werkzeug.datastructures import CallbackDict from werkzeug.datastructures import CallbackDict
from flask.sessions import SessionInterface, SessionMixin from flask.sessions import SessionInterface, SessionMixin
from itsdangerous import URLSafeTimedSerializer, BadSignature from itsdangerous import URLSafeTimedSerializer, BadSignature
class ItsdangerousSession(CallbackDict, SessionMixin): class ItsdangerousSession(CallbackDict, SessionMixin):
def __init__(self, initial=None): def __init__(self, initial=None):
def on_update(self): def on_update(self):
self.modified = True self.modified = True
CallbackDict.__init__(self, initial, on_update) CallbackDict.__init__(self, initial, on_update)
self.modified = False self.modified = False
@@ -43,8 +45,9 @@ class ItsdangerousSessionInterface(SessionInterface):
response.delete_cookie(app.session_cookie_name, response.delete_cookie(app.session_cookie_name,
domain=domain) domain=domain)
return return
expires = self.get_expiration_time(app, session) session.permanent = True
expires = datetime.utcnow() + timedelta(app.config.get('PERMANENT_SESSION_LIFETIME'))
val = self.get_serializer(app).dumps(dict(session)) val = self.get_serializer(app).dumps(dict(session))
response.set_cookie(app.session_cookie_name, val, response.set_cookie(app.session_cookie_name, val,
expires=expires, httponly=True, expires=expires, httponly=True,
domain=domain) domain=domain, secure=app.config.get('SESSION_COOKIE_SECURE'))

View File

@@ -27,7 +27,7 @@ def verify_mobile():
@main.route("/services/<int:service_id>/send-email") @main.route("/services/<int:service_id>/send-email")
@login_required @login_required
def send_email(service_id): def send_email(service_id):
return render_template('views/send-email.html') return render_template('views/send-email.html', service_id=service_id)
@main.route("/services/<int:service_id>/check-email") @main.route("/services/<int:service_id>/check-email")

View File

@@ -64,7 +64,7 @@ def service_name_change_confirm(service_id):
# Validate password for form # Validate password for form
def _check_password(pwd): def _check_password(pwd):
return verify_password(current_user, pwd) return verify_password(current_user.id, pwd)
form = ConfirmPasswordForm(_check_password) form = ConfirmPasswordForm(_check_password)
if form.validate_on_submit(): if form.validate_on_submit():
@@ -134,7 +134,7 @@ def service_status_change_confirm(service_id):
# Validate password for form # Validate password for form
def _check_password(pwd): def _check_password(pwd):
return verify_password(current_user, pwd) return verify_password(current_user.id, pwd)
form = ConfirmPasswordForm(_check_password) form = ConfirmPasswordForm(_check_password)
if form.validate_on_submit(): if form.validate_on_submit():
@@ -183,7 +183,7 @@ def service_delete_confirm(service_id):
# Validate password for form # Validate password for form
def _check_password(pwd): def _check_password(pwd):
return verify_password(current_user, pwd) return verify_password(current_user.id, pwd)
form = ConfirmPasswordForm(_check_password) form = ConfirmPasswordForm(_check_password)
if form.validate_on_submit(): if form.validate_on_submit():

View File

@@ -39,7 +39,7 @@ def _get_and_verify_user(email_address, password):
return None return None
elif not user.is_active(): elif not user.is_active():
return None return None
elif not users_dao.verify_password(user, password): elif not users_dao.verify_password(user.id, password):
return None return None
else: else:
return user return user

View File

@@ -4,6 +4,8 @@ from client.errors import (
InvalidResponse InvalidResponse
) )
from flask.ext.login import UserMixin
class UserApiClient(BaseAPIClient): class UserApiClient(BaseAPIClient):
def __init__(self, base_url=None, client_id=None, secret=None): def __init__(self, base_url=None, client_id=None, secret=None):
@@ -84,7 +86,7 @@ class UserApiClient(BaseAPIClient):
raise e raise e
class User(object): class User(UserMixin):
def __init__(self, fields, max_failed_login_count=3): def __init__(self, fields, max_failed_login_count=3):
self._id = fields.get('id') self._id = fields.get('id')
self._name = fields.get('name') self._name = fields.get('name')
@@ -98,9 +100,6 @@ class User(object):
def get_id(self): def get_id(self):
return self.id return self.id
def is_authenticated(self):
return True
def is_active(self): def is_active(self):
return self.state == 'active' return self.state == 'active'
@@ -160,9 +159,6 @@ class User(object):
def failed_login_count(self, num): def failed_login_count(self, num):
self._failed_login_count += num self._failed_login_count += num
def is_anonymous(self):
return False
def is_locked(self): def is_locked(self):
return self.failed_login_count >= self.max_failed_login_count return self.failed_login_count >= self.max_failed_login_count

View File

@@ -20,7 +20,7 @@ class Config(object):
SESSION_COOKIE_NAME = 'notify_admin_session' SESSION_COOKIE_NAME = 'notify_admin_session'
SESSION_COOKIE_PATH = '/admin' SESSION_COOKIE_PATH = '/admin'
SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SECURE = True SESSION_COOKIE_SECURE = False
PERMANENT_SESSION_LIFETIME = 3600 # seconds PERMANENT_SESSION_LIFETIME = 3600 # seconds
API_HOST_NAME = os.getenv('API_HOST_NAME') API_HOST_NAME = os.getenv('API_HOST_NAME')
@@ -56,6 +56,8 @@ class Test(Development):
class Live(Config): class Live(Config):
DEBUG = False DEBUG = False
HTTP_PROTOCOL = 'https' HTTP_PROTOCOL = 'https'
SESSION_COOKIE_SECURE = True
configs = { configs = {
'live': Live, 'live': Live,

View File

@@ -31,6 +31,7 @@ def test_logged_in_user_redirects_to_choose_service(app_,
def test_process_sign_in_return_2fa_template(app_, def test_process_sign_in_return_2fa_template(app_,
api_user_active,
mock_send_verify_code, mock_send_verify_code,
mock_get_user, mock_get_user,
mock_get_user_by_email, mock_get_user_by_email,
@@ -43,6 +44,7 @@ def test_process_sign_in_return_2fa_template(app_,
'password': 'val1dPassw0rd!'}) 'password': 'val1dPassw0rd!'})
assert response.status_code == 302 assert response.status_code == 302
assert response.location == 'http://localhost/two-factor' assert response.location == 'http://localhost/two-factor'
mock_verify_password.assert_called_with(api_user_active.id, 'val1dPassw0rd!')
def test_should_return_locked_out_true_when_user_is_locked(app_, def test_should_return_locked_out_true_when_user_is_locked(app_,