diff --git a/app/its_dangerous_session.py b/app/its_dangerous_session.py index d281b32d9..25f7aef20 100644 --- a/app/its_dangerous_session.py +++ b/app/its_dangerous_session.py @@ -1,13 +1,15 @@ +from datetime import timedelta, datetime + from werkzeug.datastructures import CallbackDict from flask.sessions import SessionInterface, SessionMixin from itsdangerous import URLSafeTimedSerializer, BadSignature class ItsdangerousSession(CallbackDict, SessionMixin): - def __init__(self, initial=None): def on_update(self): self.modified = True + CallbackDict.__init__(self, initial, on_update) self.modified = False @@ -43,8 +45,9 @@ class ItsdangerousSessionInterface(SessionInterface): response.delete_cookie(app.session_cookie_name, domain=domain) 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)) response.set_cookie(app.session_cookie_name, val, expires=expires, httponly=True, - domain=domain) + domain=domain, secure=app.config.get('SESSION_COOKIE_SECURE')) diff --git a/app/main/views/index.py b/app/main/views/index.py index 8d9e55390..daa532fc8 100644 --- a/app/main/views/index.py +++ b/app/main/views/index.py @@ -27,7 +27,7 @@ def verify_mobile(): @main.route("/services//send-email") @login_required 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//check-email") diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 81e218227..3e2897d98 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -64,7 +64,7 @@ def service_name_change_confirm(service_id): # Validate password for form def _check_password(pwd): - return verify_password(current_user, pwd) + return verify_password(current_user.id, pwd) form = ConfirmPasswordForm(_check_password) if form.validate_on_submit(): @@ -134,7 +134,7 @@ def service_status_change_confirm(service_id): # Validate password for form def _check_password(pwd): - return verify_password(current_user, pwd) + return verify_password(current_user.id, pwd) form = ConfirmPasswordForm(_check_password) if form.validate_on_submit(): @@ -183,7 +183,7 @@ def service_delete_confirm(service_id): # Validate password for form def _check_password(pwd): - return verify_password(current_user, pwd) + return verify_password(current_user.id, pwd) form = ConfirmPasswordForm(_check_password) if form.validate_on_submit(): diff --git a/app/main/views/sign_in.py b/app/main/views/sign_in.py index af96db8e9..3aed7a5ae 100644 --- a/app/main/views/sign_in.py +++ b/app/main/views/sign_in.py @@ -39,7 +39,7 @@ def _get_and_verify_user(email_address, password): return None elif not user.is_active(): return None - elif not users_dao.verify_password(user, password): + elif not users_dao.verify_password(user.id, password): return None else: return user diff --git a/app/notify_client/user_api_client.py b/app/notify_client/user_api_client.py index a083310d3..7e318c20a 100644 --- a/app/notify_client/user_api_client.py +++ b/app/notify_client/user_api_client.py @@ -4,6 +4,8 @@ from client.errors import ( InvalidResponse ) +from flask.ext.login import UserMixin + class UserApiClient(BaseAPIClient): def __init__(self, base_url=None, client_id=None, secret=None): @@ -84,7 +86,7 @@ class UserApiClient(BaseAPIClient): raise e -class User(object): +class User(UserMixin): def __init__(self, fields, max_failed_login_count=3): self._id = fields.get('id') self._name = fields.get('name') @@ -98,9 +100,6 @@ class User(object): def get_id(self): return self.id - def is_authenticated(self): - return True - def is_active(self): return self.state == 'active' @@ -160,9 +159,6 @@ class User(object): def failed_login_count(self, num): self._failed_login_count += num - def is_anonymous(self): - return False - def is_locked(self): return self.failed_login_count >= self.max_failed_login_count diff --git a/config.py b/config.py index b810d9229..e8d51e092 100644 --- a/config.py +++ b/config.py @@ -20,7 +20,7 @@ class Config(object): SESSION_COOKIE_NAME = 'notify_admin_session' SESSION_COOKIE_PATH = '/admin' SESSION_COOKIE_HTTPONLY = True - SESSION_COOKIE_SECURE = True + SESSION_COOKIE_SECURE = False PERMANENT_SESSION_LIFETIME = 3600 # seconds API_HOST_NAME = os.getenv('API_HOST_NAME') @@ -56,6 +56,8 @@ class Test(Development): class Live(Config): DEBUG = False HTTP_PROTOCOL = 'https' + SESSION_COOKIE_SECURE = True + configs = { 'live': Live, diff --git a/tests/app/main/views/test_sign_in.py b/tests/app/main/views/test_sign_in.py index a1eeb3f1f..35420f7dc 100644 --- a/tests/app/main/views/test_sign_in.py +++ b/tests/app/main/views/test_sign_in.py @@ -31,6 +31,7 @@ def test_logged_in_user_redirects_to_choose_service(app_, def test_process_sign_in_return_2fa_template(app_, + api_user_active, mock_send_verify_code, mock_get_user, mock_get_user_by_email, @@ -43,6 +44,7 @@ def test_process_sign_in_return_2fa_template(app_, 'password': 'val1dPassw0rd!'}) assert response.status_code == 302 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_,