mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-26 01:04:00 -04:00
Merge remote-tracking branch 'origin/master' into sign_in_fixes
This commit is contained in:
@@ -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'))
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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():
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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_,
|
||||||
|
|||||||
Reference in New Issue
Block a user