diff --git a/endpoints/api/user.py b/endpoints/api/user.py index daf7d4741..581f56b40 100644 --- a/endpoints/api/user.py +++ b/endpoints/api/user.py @@ -806,6 +806,10 @@ class Recovery(ApiResource): 'type': 'string', 'description': 'The user\'s email address', }, + 'recaptcha_response': { + 'type': 'string', + 'description': 'The (may be disabled) recaptcha response code for verification', + }, }, }, } @@ -826,10 +830,26 @@ class Recovery(ApiResource): return v - email = request.get_json()['email'] + recovery_data = request.get_json() + + # If recaptcha is enabled, then verify the user is a human. + if features.RECAPTCHA: + recaptcha_response = recovery_data.get('recaptcha_response', '') + result = recaptcha2.verify(app.config['RECAPTCHA_SECRET_KEY'], + recaptcha_response, + request.remote_addr) + + if not result['success']: + return { + 'message': 'Are you a bot? If not, please revalidate the captcha.' + }, 400 + + email = recovery_data['email'] user = model.user.find_user_by_email(email) if not user: - raise model.InvalidEmailAddressException('Email address was not found.') + return { + 'status': 'sent', + } if user.organization: send_org_recovery_email(user, model.organization.get_admin_users(user)) diff --git a/static/css/directives/ui/recovery-form.css b/static/css/directives/ui/recovery-form.css index 69718b44d..06a04c641 100644 --- a/static/css/directives/ui/recovery-form.css +++ b/static/css/directives/ui/recovery-form.css @@ -5,4 +5,24 @@ .recovery-form-element input { margin-bottom: 10px; +} + +.recovery-form-element .captcha { + display: block; + text-align: center; +} + +.recovery-form-element .captcha div { + display: inline-block; + margin: 2px; +} + +.recovery-form-element .captcha { + height: 0px; + transition: height ease-in-out 250ms; + overflow: hidden; +} + +.recovery-form-element .captcha.expanded { + height: 94px; } \ No newline at end of file diff --git a/static/directives/recovery-form.html b/static/directives/recovery-form.html index 5c49db179..267c7b74b 100644 --- a/static/directives/recovery-form.html +++ b/static/directives/recovery-form.html @@ -5,7 +5,7 @@
- Account recovery email was sent to {{ recovery.email }}. + Instructions on how to reset your password have been sent to {{ recovery.email }}. If you do not receive the email, please try again shortly.
{{ errorMessage }}
@@ -18,6 +18,14 @@
diff --git a/test/test_api_security.py b/test/test_api_security.py index 59ba9cc7c..085310c2c 100644 --- a/test/test_api_security.py +++ b/test/test_api_security.py @@ -457,16 +457,16 @@ class TestRecovery(ApiTestCase): self._set_url(Recovery) def test_post_anonymous(self): - self._run_test('POST', 400, None, {u'email': '826S'}) + self._run_test('POST', 200, None, {u'email': '826S'}) def test_post_freshuser(self): - self._run_test('POST', 400, 'freshuser', {u'email': '826S'}) + self._run_test('POST', 200, 'freshuser', {u'email': '826S'}) def test_post_reader(self): - self._run_test('POST', 400, 'reader', {u'email': '826S'}) + self._run_test('POST', 200, 'reader', {u'email': '826S'}) def test_post_devtable(self): - self._run_test('POST', 400, 'devtable', {u'email': '826S'}) + self._run_test('POST', 200, 'devtable', {u'email': '826S'}) class TestSignout(ApiTestCase):