Skip to content

Commit

Permalink
Fix part of 19858: Catch and Log Mailchimp Signup Errors (#20143)
Browse files Browse the repository at this point in the history
* Add URI to schema validation failure logs

* Let users register if MailChimp signup fails

If registering the user for bulk emails via MailChimp fails, show an
error message directing the user to sign up for bulk emails manually.
Then, the user can proceed with registration by de-selecting the option
to sign up for emails on the registration form.

* Update tests

* Catch all exceptions from mailchip signup

* Document Exception raised by MailChimp utils

* Fix backend controller tests for new logging

* Fix typo

* Fix typo

* Remove variable ID from feedback controller test

* Backend test fixes

* Controller backend test fixes

* Fix backend controller tests
  • Loading branch information
U8NWXD authored and lkbhitesh07 committed Apr 22, 2024
1 parent 8ddb22f commit fae99a3
Show file tree
Hide file tree
Showing 30 changed files with 329 additions and 101 deletions.
51 changes: 45 additions & 6 deletions core/controllers/admin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 963,7 @@ def test_update_param_rules_with_param_name_of_non_string_type_returns_400(
expected_status_int=400
)
error_msg = (
'At \'http://localhost/adminhandler\' these errors are happening:\n'
'Schema validation for \'platform_param_name\' failed: Expected '
'string, received 123')
self.assertEqual(response['error'], error_msg)
Expand All @@ -986,6 987,7 @@ def test_update_param_rules_with_message_of_non_string_type_returns_400(
expected_status_int=400
)
error_msg = (
'At \'http://localhost/adminhandler\' these errors are happening:\n'
'Schema validation for \'commit_message\' failed: Expected '
'string, received 123')
self.assertEqual(response['error'], error_msg)
Expand All @@ -1009,6 1011,7 @@ def test_update_param_rules_with_rules_of_non_list_type_returns_400(
expected_status_int=400
)
error_msg = (
'At \'http://localhost/adminhandler\' these errors are happening:\n'
'Schema validation for \'new_rules\' failed: Expected list, '
'received {}')
self.assertEqual(response['error'], error_msg)
Expand All @@ -1022,6 1025,7 @@ def test_update_param_rules_with_rules_of_non_list_of_dict_type_returns_400(
csrf_token = self.get_new_csrf_token()

error_msg = (
'At \'http://localhost/adminhandler\' these errors are happening:\n'
'Schema validation for \'new_rules\' failed: \'int\' '
'object is not subscriptable')
response = self.post_json(
Expand Down Expand Up @@ -1125,7 1129,11 @@ def test_grant_super_admin_privileges_fails_without_username(self) -> None:
'/adminsuperadminhandler', {}, csrf_token=self.get_new_csrf_token(),
expected_status_int=400)

error_msg = 'Missing key in handler args: username.'
error_msg = (
'At \'http://localhost/adminsuperadminhandler\' '
'these errors are happening:\n'
'Missing key in handler args: username.'
)
self.assertEqual(response['error'], error_msg)

def test_grant_super_admin_privileges_fails_with_invalid_username(
Expand Down Expand Up @@ -1177,7 1185,11 @@ def test_revoke_super_admin_privileges_fails_without_username(self) -> None:
response = self.delete_json(
'/adminsuperadminhandler', params={}, expected_status_int=400)

error_msg = 'Missing key in handler args: username.'
error_msg = (
'At \'http://localhost/adminsuperadminhandler\' '
'these errors are happening:\n'
'Missing key in handler args: username.'
)
self.assertEqual(response['error'], error_msg)

def test_revoke_super_admin_privileges_fails_with_invalid_username(
Expand Down Expand Up @@ -1268,6 1280,7 @@ def test_handler_raises_error_with_non_int_num_dummy_exps_to_generate(
}, csrf_token=csrf_token, expected_status_int=400)

error_msg = (
'At \'http://localhost/adminhandler\' these errors are happening:\n'
'Schema validation for \'num_dummy_exps_to_generate\' failed: '
'Could not convert str to int: invalid_type')
self.assertEqual(response['error'], error_msg)
Expand All @@ -1292,6 1305,7 @@ def test_handler_raises_error_with_non_int_num_dummy_exps_to_publish(
}, csrf_token=csrf_token, expected_status_int=400)

error_msg = (
'At \'http://localhost/adminhandler\' these errors are happening:\n'
'Schema validation for \'num_dummy_exps_to_publish\' failed: '
'Could not convert str to int: invalid_type')
self.assertEqual(response['error'], error_msg)
Expand Down Expand Up @@ -1441,6 1455,9 @@ def test_cannot_view_role_with_invalid_view_filter_criterion(self) -> None:
params={'filter_criterion': 'invalid', 'username': 'user1'},
expected_status_int=400)
error_msg = (
'At \'http://localhost/adminrolehandler?'
'filter_criterion=invalid&username=user1\' '
'these errors are happening:\n'
'Schema validation for \'filter_criterion\' failed: Received '
'invalid which is not in the allowed range of choices: '
'[\'role\', \'username\']')
Expand Down Expand Up @@ -2286,6 2303,9 @@ def test_handler_when_exp_version_is_not_int_throws_exception(self) -> None:
}

error_msg = (
'At \'http://localhost/explorationdataextractionhandler?'
'exp_id=exp&exp_version=a&state_name=Introduction&num_answers=0\' '
'these errors are happening:\n'
'Schema validation for \'exp_version\' failed: '
'Could not convert str to int: a')
response = self.get_json(
Expand Down Expand Up @@ -2433,7 2453,11 @@ def test_update_username_with_none_new_username(self) -> None:
'new_username': None},
csrf_token=csrf_token,
expected_status_int=400)
error_msg = 'Missing key in handler args: new_username.'
error_msg = (
'At \'http://localhost/updateusernamehandler\' '
'these errors are happening:\n'
'Missing key in handler args: new_username.'
)
self.assertEqual(response['error'], error_msg)

def test_update_username_with_none_old_username(self) -> None:
Expand All @@ -2446,7 2470,11 @@ def test_update_username_with_none_old_username(self) -> None:
'new_username': self.NEW_USERNAME},
csrf_token=csrf_token,
expected_status_int=400)
error_msg = 'Missing key in handler args: old_username.'
error_msg = (
'At \'http://localhost/updateusernamehandler\' '
'these errors are happening:\n'
'Missing key in handler args: old_username.'
)
self.assertEqual(response['error'], error_msg)

def test_update_username_with_non_string_new_username(self) -> None:
Expand All @@ -2460,7 2488,10 @@ def test_update_username_with_non_string_new_username(self) -> None:
csrf_token=csrf_token,
expected_status_int=400)
self.assertEqual(
response['error'], 'Schema validation for \'new_username\' failed:'
response['error'],
'At \'http://localhost/updateusernamehandler\' '
'these errors are happening:\n'
'Schema validation for \'new_username\' failed:'
' Expected string, received 123')

def test_update_username_with_non_string_old_username(self) -> None:
Expand All @@ -2474,6 2505,8 @@ def test_update_username_with_non_string_old_username(self) -> None:
csrf_token=csrf_token,
expected_status_int=400)
error_msg = (
'At \'http://localhost/updateusernamehandler\' '
'these errors are happening:\n'
'Schema validation for \'old_username\' failed: Expected'
' string, received 123')
self.assertEqual(response['error'], error_msg)
Expand All @@ -2490,6 2523,8 @@ def test_update_username_with_long_new_username(self) -> None:
csrf_token=csrf_token,
expected_status_int=400)
error_msg = (
'At \'http://localhost/updateusernamehandler\' '
'these errors are happening:\n'
'Schema validation for \'new_username\' failed: Validation failed'
': has_length_at_most ({\'max_value\': %s}) for object %s'
% (constants.MAX_USERNAME_LENGTH, long_username))
Expand Down Expand Up @@ -2940,6 2975,7 @@ def test_handler_raises_error_with_invalid_blog_post_title(self) -> None:
}, csrf_token=csrf_token, expected_status_int=400)

error_msg = (
'At \'http://localhost/adminhandler\' these errors are happening:\n'
'Schema validation for \'blog_post_title\' failed: Received %s '
'which is not in the allowed range of choices: [\'Leading The '
'Arabic Translations Team\', \'Education\', \'Blog with different'
Expand Down Expand Up @@ -2996,4 3032,7 @@ def test_handler_with_without_exploration_id_in_payload_raise_error(self) -> Non
'/interactions', params={},
expected_status_int=400)
self.assertEqual(
response['error'], 'Missing key in handler args: exp_id.')
response['error'],
'At \'http://localhost/interactions\' these errors are happening:\n'
'Missing key in handler args: exp_id.'
)
6 changes: 5 additions & 1 deletion core/controllers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 523,11 @@ def validate_and_normalize_args(self) -> None:
'Use self.normalized_payload instead of self.payload.')

if errors:
raise self.InvalidInputException('\n'.join(errors))
raise self.InvalidInputException(
'At \'%s\' these errors are happening:\n%s' % (
self.request.uri, '\n'.join(errors)
)
)

@property
def current_user_is_site_maintainer(self) -> bool:
Expand Down
2 changes: 2 additions & 0 deletions core/controllers/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2065,6 2065,8 @@ def test_cannot_access_exploration_with_incorrect_schema(self) -> None:
'/mock_play_exploration?exploration_id=%s' % self.exp_id,
expected_status_int=400)
error_msg = (
'At \'http://localhost/mock_play_exploration?'
'exploration_id=exp_id\' these errors are happening:\n'
'Schema validation for \'exploration_id\' failed: Could not '
'convert str to int: %s' % self.exp_id)
self.assertEqual(response['error'], error_msg)
Expand Down
5 changes: 4 additions & 1 deletion core/controllers/beam_jobs_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 130,7 @@ def test_get_raises_when_job_id_missing(self) -> None:
self.get_json('/beam_job_run_result', expected_status_int=400))

self.assertEqual(
response['error'], 'Missing key in handler args: job_id.')
response['error'],
'At \'http://localhost/beam_job_run_result\' these errors are '
'happening:\n'
'Missing key in handler args: job_id.')
15 changes: 12 additions & 3 deletions core/controllers/blog_admin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 179,10 @@ def test_invalid_value_type_for_updating_platform_parameters(self) -> None:
'/blogadminhandler', payload, csrf_token=csrf_token,
expected_status_int=400)
self.assertEqual(
response_dict['error'], 'Schema validation for \'new_platform_'
response_dict['error'],
'At \'http://localhost/blogadminhandler\' '
'these errors are happening:\n'
'Schema validation for \'new_platform_'
'parameter_values\' failed: The value of max_number_of_tags_'
'assigned_to_blog_post platform parameter is not of valid type, '
'it should be one of typing.Union[str, int, bool, float].')
Expand Down Expand Up @@ -233,7 236,10 @@ def test_raise_error_for_updating_value_to_less_than_0_for_max_tags(
'/blogadminhandler', payload, csrf_token=csrf_token,
expected_status_int=400)
self.assertEqual(
response_dict['error'], 'Schema validation for \'new_platform_'
response_dict['error'],
'At \'http://localhost/blogadminhandler\' '
'these errors are happening:\n'
'Schema validation for \'new_platform_'
'parameter_values\' failed: The value of max_number_of_tags_'
'assigned_to_blog_post should be greater than 0, it is -2.')

Expand Down Expand Up @@ -264,7 270,10 @@ def test_invalid_value_for_platform_param_raises_error(self) -> None:
'/blogadminhandler', payload, csrf_token=csrf_token,
expected_status_int=400)
self.assertEqual(
response_dict['error'], 'Schema validation for \'new_platform_'
response_dict['error'],
'At \'http://localhost/blogadminhandler\' '
'these errors are happening:\n'
'Schema validation for \'new_platform_'
'parameter_values\' failed: The value of platform parameter '
'max_number_of_tags_assigned_to_blog_post is of type \'string\', '
'expected it to be of type \'number\'')
8 changes: 5 additions & 3 deletions core/controllers/blog_dashboard_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 410,11 @@ def test_update_blog_post_with_invalid_change_dict(self) -> None:
response = self.put_json(
'%s/%s' % (feconf.BLOG_EDITOR_DATA_URL_PREFIX, self.blog_post.id),
payload, csrf_token=csrf_token, expected_status_int=400)
self.assertEqual(
response['error'], 'Schema validation for \'change_dict\''
' failed: Title should be a string.')
self.assertIn(
'Schema validation for \'change_dict\''
' failed: Title should be a string.',
response['error'],
)

def test_publishing_unpublishing_blog_post(self) -> None:
self.login(self.BLOG_EDITOR_EMAIL)
Expand Down
2 changes: 2 additions & 0 deletions core/controllers/collection_editor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 253,8 @@ def test_cannot_put_long_commit_message(self) -> None:
long_message_dict, csrf_token=csrf_token, expected_status_int=400)

error_msg = (
'At \'http://localhost/collection_editor_handler/data/0\' '
'these errors are happening:\n'
'Schema validation for \'commit_message\' failed: Validation '
'failed: has_length_at_most ({\'max_value\': 375}) for object %s'
% long_message)
Expand Down
2 changes: 2 additions & 0 deletions core/controllers/contributor_dashboard_admin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 548,8 @@ def test_get_stats_without_username_raises_error(self) -> None:

self.assertEqual(
response['error'],
'At \'http://localhost/translationcontributionstatshandler\' these '
'errors are happening:\n'
'Missing key in handler args: username.')

def test_get_stats_with_invalid_username_raises_error(self) -> None:
Expand Down
23 changes: 12 additions & 11 deletions core/controllers/contributor_dashboard_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1363,8 1363,8 @@ def test_handler_with_invalid_language_code_raises_exception(self) -> None:
'Schema validation for \'target_language_code\' failed: '
'Validation failed: is_supported_audio_language_code ({}) for '
'object invalid_language_code')
self.assertEqual(
output['error'], error_msg)
self.assertIn(
error_msg, output['error'])

def test_handler_with_no_target_language_code_raises_exception(
self
Expand All @@ -1376,9 1376,10 @@ def test_handler_with_no_target_language_code_raises_exception(
'content_ids': '["content"]',
}, expected_status_int=400)

error_msg = 'Missing key in handler args: target_language_code.'
self.assertEqual(
output['error'], error_msg)
self.assertIn(
'Missing key in handler args: target_language_code.',
output['error'],
)

def test_handler_with_invalid_exploration_id_returns_not_found(
self
Expand All @@ -1400,8 1401,8 @@ def test_handler_with_no_exploration_id_raises_exception(self) -> None:
}, expected_status_int=400)

error_msg = 'Missing key in handler args: exp_id.'
self.assertEqual(
output['error'], error_msg)
self.assertIn(
error_msg, output['error'])

def test_handler_with_invalid_state_name_returns_not_found(self) -> None:
self.get_json(
Expand All @@ -1421,8 1422,8 @@ def test_handler_with_no_state_name_raises_exception(self) -> None:
}, expected_status_int=400)

error_msg = 'Missing key in handler args: state_name.'
self.assertEqual(
output['error'], error_msg)
self.assertIn(
error_msg, output['error'])

def test_handler_with_invalid_content_ids_returns_none(self) -> None:
exp_services.update_exploration(
Expand Down Expand Up @@ -1495,8 1496,8 @@ def test_handler_with_missing_content_ids_parameter_raises_exception(
)

error_msg = 'Missing key in handler args: content_ids.'
self.assertEqual(
output['error'], error_msg)
self.assertIn(
error_msg, output['error'])

def test_handler_with_valid_input_returns_translation(self) -> None:
exp_services.update_exploration(
Expand Down
14 changes: 14 additions & 0 deletions core/controllers/editor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 896,8 @@ def test_exploration_download_handler_with_invalid_output_format(
% (exp_id), expected_status_int=400)

error_msg = (
'At \'http://localhost/createhandler/download/exp_id1?output_'
'format=invalid_output_format\' these errors are happening:\n'
'Schema validation for \'output_format\' failed: Received '
'invalid_output_format which is not in the allowed range of '
'choices: [\'zip\', \'json\']'
Expand Down Expand Up @@ -1447,6 1449,8 @@ def test_revert_with_invalid_current_version_raises_error(self) -> None:
}, csrf_token=csrf_token, expected_status_int=400)

error_msg = (
'At \'http://localhost/createhandler/revert/0\' '
'these errors are happening:\n'
'Schema validation for \'current_version\' failed: Could not '
'convert str to int: invalid_version'
)
Expand Down Expand Up @@ -2257,6 2261,8 @@ def test_put_with_long_commit_message_raises_error(self) -> None:
)

error_msg = (
'At \'http://localhost/createhandler/data/eid\' these errors are '
'happening:\n'
'Schema validation for \'commit_message\' failed: Validation '
'failed: has_length_at_most ({\'max_value\': 375}) for object %s'
% long_commit_message
Expand Down Expand Up @@ -2388,6 2394,8 @@ def test_can_not_assign_roles_with_invalid_payload_version(self) -> None:

self.assertEqual(
response_dict['error'],
'At \'http://localhost/createhandler/rights/eid\' '
'these errors are happening:\n'
'Missing key in handler args: version.')

# Raises error as version from payload does not match the exploration
Expand Down Expand Up @@ -2472,6 2480,8 @@ def test_put_with_invalid_message_type_raises_error(self) -> None:
csrf_token=csrf_token, expected_status_int=400)

error_msg = (
'At \'http://localhost/createhandler/notificationpreferences/eid\' '
'these errors are happening:\n'
'Schema validation for \'message_type\' failed: Received '
'invalid_message_type which is not in the allowed range '
'of choices: [\'feedback\', \'suggestion\']'
Expand Down Expand Up @@ -3119,6 3129,8 @@ def test_exploration_not_updated_because_cmd_is_invalid(self) -> None:
csrf_token=self.csrf_token, expected_status_int=400)

error_msg = (
'At \'http://localhost/createhandler/data/3\' these errors '
'are happening:\n'
'Schema validation for \'change_list\' failed: Command '
'edit_exploration_propert is not allowed'
)
Expand Down Expand Up @@ -3152,6 3164,8 @@ def test_draft_not_updated_because_cmd_is_invalid(self) -> None:
csrf_token=self.csrf_token, expected_status_int=400)

error_msg = (
'At \'http://localhost/createhandler/autosave_draft/1\' these '
'errors are happening:\n'
'Schema validation for \'change_list\' failed: Command '
'edit_exploration_propert is not allowed'
)
Expand Down
2 changes: 2 additions & 0 deletions core/controllers/email_dashboard_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 533,8 @@ def test_handler_with_invalid_num_queries_to_fetch_raises_error_400(
expected_status_int=400)

error_msg = (
'At \'http://localhost/emaildashboarddatahandler?'
'invalid_param_key=2\' these errors are happening:\n'
'Missing key in handler args: num_queries_to_fetch.\n'
'Found extra args: [\'invalid_param_key\'].')
self.assertEqual(
Expand Down
Loading

0 comments on commit fae99a3

Please sign in to comment.