Skip to content

Commit

Permalink
Merge pull request #6363 from OCHA-DAP/feature/HDX-9453-build-page-c2…
Browse files Browse the repository at this point in the history
…-reenter-email

HDX-9545 build page C2 - re-enter email address
  • Loading branch information
danmihaila authored Jun 14, 2024
2 parents e0f8a5b + e6025dc commit 78b71ec
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from ckanext.hdx_theme.helpers.ui_constants.onboarding.user_info import CONSTANTS as USER_INFO_CONSTANTS
from ckanext.hdx_theme.helpers.ui_constants.onboarding.value_proposition import CONSTANTS as VALUE_PROPOSITION_CONSTANTS
from ckanext.hdx_theme.helpers.ui_constants.onboarding.verify_email import CONSTANTS as VERIFY_EMAIL_CONSTANTS
from ckanext.hdx_theme.helpers.ui_constants.onboarding.change_email import CONSTANTS as CHANGE_EMAIL_CONSTANTS
from ckanext.hdx_theme.helpers.ui_constants.onboarding.account_validated import CONSTANTS as ACCOUNT_VALIDATED_CONSTANTS
from ckanext.hdx_theme.helpers.ui_constants.onboarding.request_join_organisation import CONSTANTS as REQUEST_JOIN_ORGANISATION_CONSTANTS
from ckanext.hdx_theme.helpers.ui_constants.onboarding.confirm_organisation_choice import CONSTANTS as CONFIRM_ORGANISATION_CHOICE_CONSTANTS
Expand All @@ -15,6 +16,7 @@
'USER_INFO': USER_INFO_CONSTANTS,
'VALUE_PROPOSITION': VALUE_PROPOSITION_CONSTANTS,
'VERIFY_EMAIL': VERIFY_EMAIL_CONSTANTS,
'CHANGE_EMAIL': CHANGE_EMAIL_CONSTANTS,
'ACCOUNT_VALIDATED': ACCOUNT_VALIDATED_CONSTANTS,
'REQUEST_JOIN_ORGANISATION': REQUEST_JOIN_ORGANISATION_CONSTANTS,
'CONFIRM_ORGANISATION_CHOICE': CONFIRM_ORGANISATION_CHOICE_CONSTANTS,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from ckanext.hdx_theme.helpers.ui_constants.onboarding.user_info import CONSTANTS as USER_INFO_CONSTANTS

CONSTANTS = {
'STEPS_1': USER_INFO_CONSTANTS['STEPS_1'],
'STEPS_2': USER_INFO_CONSTANTS['STEPS_2'],
'STEPS_3': USER_INFO_CONSTANTS['STEPS_3'],

'PAGE_TITLE': '''Re-enter your email address''',

'INPUT_EMAIL_LABEL': '''Enter your email address''',
'INPUT_EMAIL_PLACEHOLDER': USER_INFO_CONSTANTS['INPUT_EMAIL_PLACEHOLDER'],
'INPUT_EMAIL_ERROR': USER_INFO_CONSTANTS['INPUT_EMAIL_ERROR'],
'INPUT_EMAIL2_LABEL': USER_INFO_CONSTANTS['INPUT_EMAIL2_LABEL'],
'INPUT_EMAIL2_PLACEHOLDER': USER_INFO_CONSTANTS['INPUT_EMAIL2_PLACEHOLDER'],
'INPUT_EMAIL2_ERROR': USER_INFO_CONSTANTS['INPUT_EMAIL2_ERROR'],

'BUTTON_SUBMIT': '''Next''',
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@

'PAGE_TITLE': '''Verify your email address''',
'BODY_MAIN_TEXT': '''We have sent an email to {0} so that you can verify your email address. If you don’t see the email, please check your spam or junk folder.''',
'BODY_MAIN_TEXT_WITHOUT_EMAIL': '''We have sent an email so that you can verify your email address. If you don’t see the email, please check your spam or junk folder.'''
'BODY_MAIN_TEXT_WITHOUT_EMAIL': '''We have sent an email so that you can verify your email address. If you don’t see the email, please check your spam or junk folder.''',

'CHANGE_EMAIL_TEXT': '''If you need to change your email address, <a href="{0}" title="Change email address">click here</a>''',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{% extends "onboarding/base.html" %}

{% block scripts %}
{{ super() }}
{% asset 'hdx_theme/hdx-form-validator' %}
{% endblock %}

{% set CONST = h.HDX_CONST('UI_CONSTANTS')['ONBOARDING']['CHANGE_EMAIL'] %}

{% block subtitle %}{{ _('Re-enter email address') }}{% endblock %}

{% block breadcrumb_content %}
<li class="breadcrumb-item active">{{ h.nav_link(_('Sign up'), named_route='hdx_user_onboarding.user-info') }}</li>
{% endblock %}

{% block content %}

<div class="container">

<div class="row">
<div class="col-12 col-md-7 mx-auto">
{{ h.snippet('bem.blocks/stepper.html', steps=[CONST.STEPS_1, CONST.STEPS_2, CONST.STEPS_3], spacing_class="my-5", current_step=2) }}
<div class="text-center">
{{ h.snippet('bem.blocks/heading.html', title=CONST.PAGE_TITLE, spacing_class="mb-4") }}
</div>
</div>
</div>

<div class="row">
<div class="col-12 col-md-6 mx-auto">
<form method="post" action="{{ h.url_for('hdx_user_onboarding.change_email') }}" novalidate
data-module="hdx-form-validator" class="mb-5">
{{ h.csrf_input() }}
{{ h.snippet('bem.blocks/input_field.html', type="email", required=True, autocomplete='new-email', label=CONST.INPUT_EMAIL_LABEL, data_attributes={"validation": "email", "validation-error": CONST.INPUT_EMAIL_ERROR}, name="email", errors=errors.get('email'), placeholder=CONST.INPUT_EMAIL_PLACEHOLDER, spacing_class="mb-4") }}
{{ h.snippet('bem.blocks/input_field.html', type="email", required=True, autocomplete='new-email', label=CONST.INPUT_EMAIL2_LABEL, data_attributes={"validation": "email,match", "validation-match": "email", "validation-error": CONST.INPUT_EMAIL2_ERROR}, name="email2", errors=errors.get('email2'), placeholder=CONST.INPUT_EMAIL2_PLACEHOLDER, spacing_class="mb-4") }}
{{ h.snippet('bem.blocks/form_button.html', type="submit", title=CONST.BUTTON_SUBMIT, disabled=True, button_classes=["form-button__btn_font-size_big", "btn-primary", "btn-lg", "d-block", "w-100"]) }}
</form>
</div>
</div>

</div>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
{{ h.snippet('bem.blocks/heading.html', title=CONST.PAGE_TITLE, spacing_class="mb-5") }}
{% set main_text = CONST.BODY_MAIN_TEXT.format(session.get('user_info_email')) if session.get('user_info_email') else CONST.BODY_MAIN_TEXT_WITHOUT_EMAIL %}
{{ h.snippet('bem.blocks/paragraph.html', text=main_text, paragraph_classes=["paragraph__text_font-size-big"], spacing_class="mb-5") }}
{% if session.get('user_info_id') %}
{{ h.snippet('bem.blocks/paragraph.html', text='--', spacing_class="mb-5") }}
{{ h.snippet('bem.blocks/paragraph.html', text=CONST.CHANGE_EMAIL_TEXT.format(h.url_for('hdx_user_onboarding.change_email')), spacing_class="mb-5") }}
{% endif %}
</div>
</div>
</div>
Expand Down
9 changes: 9 additions & 0 deletions ckanext-hdx_users/ckanext/hdx_users/logic/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,12 @@ def onboarding_user_edit_form_schema(not_empty, strip_value, user_email_validato
schema['email'] = [not_empty, strip_value, user_email_validator, unicode_safe]

return schema


@validator_args
def onboarding_user_change_email_form_schema(not_empty, strip_value, user_email_validator, user_emails_match):
schema = {
'email': [not_empty, strip_value, user_email_validator, user_emails_match, unicode_safe],
'email2': [unicode_safe],
}
return schema
86 changes: 85 additions & 1 deletion ckanext-hdx_users/ckanext/hdx_users/views/onboarding.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from ckanext.hdx_users.helpers.constants import ONBOARDING_CAME_FROM_EXTRAS_KEY, ONBOARDING_CAME_FROM_STATE_EXTRAS_KEY, \
ONBOARDING_MAILCHIMP_OPTIN_KEY
from ckanext.hdx_users.views.user_view_helper import CaptchaNotValid, OnbCaptchaErr, error_message
from ckanext.hdx_users.logic.schema import onboarding_user_new_form_schema
from ckanext.hdx_users.logic.schema import onboarding_user_new_form_schema, onboarding_user_change_email_form_schema

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -151,6 +151,7 @@ def post(self) -> Union[Response, str]:
validation_link=h.url_for('hdx_user_onboarding.validate_account', token=token['token'], qualified=True)
)

session['user_info_id'] = user_dict.get('id')
session['user_info_email'] = user_dict.get('email')

return redirect('hdx_user_onboarding.verify_email', user_id=user_dict.get('id'))
Expand Down Expand Up @@ -196,6 +197,85 @@ def verify_email(user_id: str) -> str:
return abort(404, _(u'Page not found'))


def change_email() -> str:
if session.get('user_info_id'):
user_id = session.get('user_info_id')

try:
context = {
'model': model,
'session': model.Session,
'schema': onboarding_user_change_email_form_schema(),
'keep_email': True,
'ignore_auth': True
}

user_dict = get_action('user_show')(context, {'id': user_id})

is_user_validated_and_token_disabled = tokens.is_user_validated_and_token_disabled(user_dict)
if is_user_validated_and_token_disabled:
return redirect('hdx_user_onboarding.validated_account', user_id=user_id)

if request.method == 'POST':
try:
data_dict = logic.clean_dict(
dictization_functions.unflatten(logic.tuplize_dict(logic.parse_params(request.form))))
except dictization_functions.DataError:
abort(400, _(u'Integrity Error'))

# email update
try:
updated_user = get_action('user_patch')(context, {
'id': user_dict['id'],
'email': data_dict.get('email'),
'email2': data_dict.get('email2'),
})

old_token = tokens.token_show(context, user_dict)
new_token = tokens.refresh_token(context, old_token)
subject = h.HDX_CONST('UI_CONSTANTS')['ONBOARDING']['EMAIL_SUBJECTS']['EMAIL_CONFIRMATION']
tokens.send_validation_email(
updated_user,
new_token,
subject,
'email/content/onboarding/email_confirmation.html',
validation_link=h.url_for('hdx_user_onboarding.validate_account', token=new_token['token'],
qualified=True)
)

session['user_info_email'] = updated_user.get('email')
return redirect('hdx_user_onboarding.verify_email', user_id=user_dict.get('id'))
except NotAuthorized:
log.error(f'Unauthorized to change email address for user "{user_id}"')
abort(403, _(u'Unauthorized to edit user %s') % user_id)
except NotFound:
log.error(f'User "{user_id}" could not be found to change email address')
abort(404, _(u'User not found'))
except ValidationError as e:
errors = e.error_dict
error_summary = e.error_summary
template_data = {
u'errors': errors,
u'error_summary': error_summary,
}
return render('onboarding/signup/change-email.html', template_data)
except Exception as e:
log.error(e)
abort(404, _(u'Something went wrong. Please contact support'))

template_data = {
u'errors': {},
u'error_summary': {},
}
return render('onboarding/signup/change-email.html', template_data)

except NotFound:
log.error(f'User "{user_id}" could not be found to change email address')
abort(404, _(u'User not found'))

return abort(404, _(u'Page not found'))


def validate_account(token: str) -> str:
if request.user_agent.string.strip() and request.method == 'GET':
# we don't want to run this for 'HEAD' requests or for requests that don't come from a browser
Expand Down Expand Up @@ -233,6 +313,8 @@ def validate_account(token: str) -> str:

if session.get('user_info_email'):
session.pop('user_info_email')
if session.get('user_info_id'):
session.pop('user_info_id')

template_data = {
'fullname': user_dict.get('fullname', '')
Expand Down Expand Up @@ -269,6 +351,8 @@ def validated_account(user_id: str) -> str:
methods=[u'GET', u'POST'], strict_slashes=False)
hdx_user_onboarding.add_url_rule(u'/verify-email/<user_id>/', view_func=verify_email, methods=[u'GET'],
strict_slashes=False)
hdx_user_onboarding.add_url_rule(u'/change-email/', view_func=change_email, methods=[u'GET', u'POST'],
strict_slashes=False)
hdx_user_onboarding.add_url_rule(u'/validate-account/<token>/', view_func=validate_account,
methods=[u'GET'], strict_slashes=False)
hdx_user_onboarding.add_url_rule(u'/validated-account/<user_id>/', view_func=validated_account, methods=[u'GET'],
Expand Down

0 comments on commit 78b71ec

Please sign in to comment.