diff --git a/app/models.py b/app/models.py index 97ac89f87..d11f83cc6 100644 --- a/app/models.py +++ b/app/models.py @@ -114,7 +114,9 @@ class User(db.Model): platform_admin = db.Column(db.Boolean, nullable=False, default=False) current_session_id = db.Column(UUID(as_uuid=True), nullable=True) auth_type = db.Column(db.String, db.ForeignKey('auth_type.name'), index=True, nullable=False, default=SMS_AUTH_TYPE) - email_access_validated_at = db.Column(db.DateTime, index=False, unique=False, nullable=False) + email_access_validated_at = db.Column( + db.DateTime, index=False, unique=False, nullable=False, default=datetime.datetime.utcnow + ) # either email auth or a mobile number must be provided CheckConstraint("auth_type = 'email_auth' or mobile_number is not null") @@ -163,15 +165,11 @@ class User(db.Model): 'auth_type': self.auth_type, 'current_session_id': self.current_session_id, 'failed_login_count': self.failed_login_count, - 'email_access_validated_at': self.email_access_validated_at, + 'email_access_validated_at': self.email_access_validated_at.strftime(DATETIME_FORMAT), 'logged_in_at': self.logged_in_at.strftime(DATETIME_FORMAT) if self.logged_in_at else None, 'mobile_number': self.mobile_number, 'organisations': [x.id for x in self.organisations if x.active], - 'password_changed_at': ( - self.password_changed_at.strftime(DATETIME_FORMAT_NO_TIMEZONE) - if self.password_changed_at - else None - ), + 'password_changed_at': self.password_changed_at.strftime(DATETIME_FORMAT_NO_TIMEZONE), 'permissions': self.get_permissions(), 'platform_admin': self.platform_admin, 'services': [x.id for x in self.services if x.active], diff --git a/app/user/rest.py b/app/user/rest.py index 7eed40c43..3d60f7319 100644 --- a/app/user/rest.py +++ b/app/user/rest.py @@ -197,7 +197,7 @@ def verify_user_code(user_id): user_to_verify.current_session_id = str(uuid.uuid4()) user_to_verify.logged_in_at = datetime.utcnow() - if user_to_verify.auth_type == 'email_auth': + if data['code_type'] == 'email': user_to_verify.email_access_validated_at = datetime.utcnow() user_to_verify.failed_login_count = 0 save_model_user(user_to_verify) diff --git a/tests/app/user/test_rest_verify.py b/tests/app/user/test_rest_verify.py index 2af880f5f..3af486979 100644 --- a/tests/app/user/test_rest_verify.py +++ b/tests/app/user/test_rest_verify.py @@ -344,6 +344,8 @@ def test_reset_failed_login_count_returns_404_when_user_does_not_exist(client): assert resp.status_code == 404 +# we send sms_auth users email code to validate their email access +@pytest.mark.parametrize('auth_type', ['email_auth', 'sms_auth']) @pytest.mark.parametrize('data, expected_auth_url', ( ( {}, @@ -365,8 +367,10 @@ def test_send_user_email_code( email_2fa_code_template, data, expected_auth_url, + auth_type ): deliver_email = mocker.patch('app.celery.provider_tasks.deliver_email.apply_async') + sample_user.auth_type = auth_type admin_request.post( 'user.send_user_2fa_code', @@ -417,10 +421,12 @@ def test_send_email_code_returns_404_for_bad_input_data(admin_request): @freeze_time('2016-01-01T12:00:00') -def test_user_verify_email_code(admin_request, sample_user): +# we send sms_auth users email code to validate their email access +@pytest.mark.parametrize('auth_type', ['email_auth', 'sms_auth']) +def test_user_verify_email_code(admin_request, sample_user, auth_type): sample_user.logged_in_at = datetime.utcnow() - timedelta(days=1) sample_user.email_access_validated_at = datetime.utcnow() - timedelta(days=1) - sample_user.auth_type = "email_auth" + sample_user.auth_type = auth_type magic_code = str(uuid.uuid4()) verify_code = create_user_code(sample_user, magic_code, EMAIL_TYPE)