def test_get_respondent_by_party_id_fail(self): with responses.RequestsMock() as rsps: rsps.add(rsps.GET, url_get_respondent_party, status=500) with app.app_context(): with self.assertRaises(ApiError): party_controller.get_respondent_party_by_id( respondent_party['id'])
def change_account_details(session): form = ContactDetailsChangeForm(request.values) party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) update_required_flag = False attributes_changed = [] if request.method == 'POST' and form.validate(): logger.info('Attempting to update contact details changes on the account') update_required_flag = check_attribute_change(form, attributes_changed, respondent_details, update_required_flag) if update_required_flag: try: party_controller.update_account(respondent_details) except ApiError as exc: logger.error('Failed to updated account', status=exc.status_code) raise exc logger.info('Successfully updated account') success_panel = create_success_message(attributes_changed, "We've updated your ") flash(success_panel) return redirect(url_for('surveys_bp.get_survey_list', tag='todo')) else: return redirect(url_for('surveys_bp.get_survey_list', tag='todo')) else: return render_template('account/account-contact-detail-change.html', form=form, errors=form.errors, respondent=respondent_details)
def change_account_details(session): form = ContactDetailsChangeForm(request.values) party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) is_contact_details_update_required = False attributes_changed = [] if request.method == "POST" and form.validate(): logger.info("Attempting to update contact details changes on the account", party_id=party_id) # check_attribute changes also magically updates the respondent_details as a side effect of running this # function is_contact_details_update_required = check_attribute_change( form, attributes_changed, respondent_details, is_contact_details_update_required ) if is_contact_details_update_required: try: party_controller.update_account(respondent_details) except ApiError as exc: logger.error("Failed to updated account", status=exc.status_code) raise exc logger.info("Successfully updated account", party_id=party_id) success_panel = create_success_message(attributes_changed, "We have updated your ") flash(success_panel) is_email_update_required = form["email_address"].data != respondent_details["emailAddress"] if is_email_update_required: return render_template( "account/account-change-email-address.html", new_email=form["email_address"].data, form=ConfirmEmailChangeForm(), ) return redirect(url_for("surveys_bp.get_survey_list", tag="todo")) else: return render_template( "account/account-contact-detail-change.html", form=form, errors=form.errors, respondent=respondent_details )
def change_password(session): form = ChangePasswordFrom(request.values) party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) if request.method == 'POST' and form.validate(): username = respondent_details['emailAddress'] password = request.form.get('password') new_password = request.form.get('new_password') if new_password == password: return render_template('account/account-change-password.html', form=form, errors={"new_password": ["Your new password is the same as your old password"]}) bound_logger = logger.bind(email=obfuscate_email(username)) bound_logger.info("Attempting to find user in auth service") try: # We call the sign in function to verify that the password provided is correct auth_controller.sign_in(username, password) bound_logger.info("Attempting to change password via party service") party_controller.change_password(username, new_password) bound_logger.info("password changed via party service") flash('Your password has been changed.') return redirect(url_for('surveys_bp.get_survey_list', tag='todo')) except AuthError as exc: error_message = exc.auth_error if BAD_CREDENTIALS_ERROR in error_message: bound_logger.info('Bad credentials provided') return render_template('account/account-change-password.html', form=form, errors={"password": ["Incorrect current password"]}) else: errors = form.errors return render_template('account/account-change-password.html', form=form, errors=errors)
def accept_share_surveys_existing_account(session, batch): """ Accept redirect endpoint for accepting share surveys for existing account :param session: :type session: :param batch: batch number :type batch: str """ logger.info("Attempting to confirm share surveys for existing account", batch_number=batch) party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) response = party_controller.get_pending_surveys_batch_number(batch) if respondent_details["emailAddress"].lower() != response.json( )[0]["email_address"].lower(): logger.warning("The user has entered invalid login for share survey.") flash( "Invalid share survey login. This share survey is not assigned to you.", "error") return redirect(url_for("surveys_bp.get_survey_list", tag="todo")) try: party_controller.confirm_pending_survey(batch) except ApiError as exc: logger.error("Failed to confirm share survey for existing account", status=exc.status_code, batch_number=batch) raise exc logger.info("Successfully completed share survey for existing account", batch_number=batch) return render_template( "surveys/surveys-share/share-survey-complete-thank-you.html")
def test_get_respondent_by_party_id_not_found(self): with responses.RequestsMock() as rsps: rsps.add(rsps.GET, url_get_respondent_party, status=404) with app.app_context(): party = party_controller.get_respondent_party_by_id( respondent_party['id']) self.assertTrue(party is None)
def get_account(session): form = OptionsForm() party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) is_share_survey_enabled = app.config['SHARE_SURVEY_ENABLED'] return render_template('account/account.html', form=form, respondent=respondent_details, is_share_survey_enabled=is_share_survey_enabled)
def send_instruction(session): form = ConfirmEmailChangeForm(request.values) email = flask_session['share_survey_recipient_email_address'] party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) if form['email_address'].data != email: raise ShareSurveyProcessError('Process failed due to session error') json_data = build_payload(respondent_details['id']) register_pending_shares(json_data) return render_template('surveys/surveys-share/almost-done.html')
def test_get_respondent_by_party_id_success(self): with responses.RequestsMock() as rsps: rsps.add(rsps.GET, url_get_respondent_party, json=respondent_party, status=200) with app.app_context(): party = party_controller.get_respondent_party_by_id( respondent_party['id']) self.assertEqual(party['id'], respondent_party['id']) self.assertEqual(party['emailAddress'], respondent_party['emailAddress'])
def change_email_address(session): form = ConfirmEmailChangeForm(request.values) party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) respondent_details['email_address'] = respondent_details['emailAddress'] respondent_details['new_email_address'] = form['email_address'].data respondent_details['change_requested_by_respondent'] = True logger.info('Attempting to update email address changes on the account', party_id=party_id) try: party_controller.update_account(respondent_details) except ApiError as exc: logger.error('Failed to updated email on account', status=exc.status_code, party_id=party_id) raise exc logger.info('Successfully updated email on account', party_id=party_id) return render_template('account/account-change-email-address-almost-done.html')
def send_instruction(session): form = ConfirmEmailChangeForm(request.values) email = flask_session["share_survey_recipient_email_address"] party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) if form["email_address"].data != email: raise ShareSurveyProcessError("Process failed due to session error") json_data = build_payload(respondent_details["id"]) response = register_pending_shares(json_data) if response.status_code == 400: flash( "You have already transferred or shared these surveys with someone with this email address. They have 72 " "hours to accept your request. If you have made an error then wait for the transfer/share to expire or " "contact us.", ) return redirect(url_for("account_bp.send_instruction_get")) return render_template("surveys/surveys-share/almost-done.html")
def delete_user_account(session): party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) if "associations" in respondent_details: for association in respondent_details["associations"]: for enrolment in association["enrolments"]: if enrolment["enrolmentStatus"] == "ENABLED": flash( "This operation is not allowed as you are currently assigned to a survey.", "info") return render_template("account/account-delete.html", is_validated=False) if request.method == "POST": delete_account(respondent_details["emailAddress"]) return redirect(url_for("sign_in_bp.logout")) return render_template("account/account-delete.html", is_validated=True)
def change_email_address(session): form = ConfirmEmailChangeForm(request.values) party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) respondent_details["email_address"] = respondent_details["emailAddress"] respondent_details["new_email_address"] = form["email_address"].data respondent_details["change_requested_by_respondent"] = True logger.info("Attempting to update email address changes on the account", party_id=party_id) try: party_controller.update_account(respondent_details) except ApiError as exc: logger.error("Failed to updated email on account", status=exc.status_code, party_id=party_id) if exc.status_code == 409: logger.info("The email requested already registered in our system. Request denied", party_id=party_id) return render_template("account/account-change-email-address-conflict.html") else: raise exc logger.info("Successfully updated email on account", party_id=party_id) return render_template("account/account-change-email-address-almost-done.html")
def change_password(session): form = ChangePasswordFrom(request.values) party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) if request.method == "POST" and form.validate(): username = respondent_details["emailAddress"] password = request.form.get("password") new_password = request.form.get("new_password") if new_password == password: return render_template( "account/account-change-password.html", form=form, errors={"new_password": ["Your new password is the same as your old password"]}, ) bound_logger = logger.bind(email=obfuscate_email(username)) bound_logger.info("Attempting to find user in auth service") try: # We call the sign in function to verify that the password provided is correct auth_controller.sign_in(username, password) bound_logger.info("Attempting to change password via party service") party_controller.change_password(username, new_password) bound_logger.info("password changed via party service") flash("Your password has been changed. Please login with your new password.", "success") return redirect(url_for("sign_in_bp.logout")) except AuthError as exc: error_message = exc.auth_error if BAD_CREDENTIALS_ERROR in error_message: bound_logger.info("Bad credentials provided") return render_template( "account/account-change-password.html", form=form, errors={"password": ["Incorrect current password"]}, ) else: errors = form.errors return render_template("account/account-change-password.html", form=form, errors=errors)
def change_account_details(session): form = ContactDetailsChangeForm(request.values) party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) is_contact_details_update_required = False attributes_changed = [] # TODO: is_account_detail_change_enabled to be removed once account change is worked again is_account_email_change_enabled = app.config['ACCOUNT_EMAIL_CHANGE_ENABLED'] if request.method == 'POST' and form.validate(): logger.info('Attempting to update contact details changes on the account', party_id=party_id) # check_attribute changes also magically updates the respondent_details as a side effect of running this # function is_contact_details_update_required = check_attribute_change(form, attributes_changed, respondent_details, is_contact_details_update_required) if is_contact_details_update_required: try: party_controller.update_account(respondent_details) except ApiError as exc: logger.error('Failed to updated account', status=exc.status_code) raise exc logger.info('Successfully updated account', party_id=party_id) success_panel = create_success_message(attributes_changed, "We have updated your ") flash(success_panel) if is_account_email_change_enabled: is_email_update_required = form['email_address'].data != respondent_details['emailAddress'] if is_email_update_required: return render_template('account/account-change-email-address.html', new_email=form['email_address'].data, form=ConfirmEmailChangeForm()) return redirect(url_for('surveys_bp.get_survey_list', tag='todo')) else: return render_template('account/account-contact-detail-change.html', form=form, errors=form.errors, respondent=respondent_details, is_email_change_enabled=is_account_email_change_enabled)
def share_survey_post_email_entry(session): form = AccountSurveyShareRecipientEmailForm(request.values) party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) if not form.validate(): errors = form.errors return render_template( "surveys/surveys-share/recipient-email-address.html", form=form, errors=errors) if "emailAddress" in respondent_details: if respondent_details["emailAddress"].lower( ) == form.data["email_address"].lower(): errors = { "email_address": ["You can not share surveys with yourself."] } return render_template( "surveys/surveys-share/recipient-email-address.html", form=form, errors=errors) flask_session["share_survey_recipient_email_address"] = form.data[ "email_address"] return redirect(url_for("account_bp.send_instruction_get"))
def get_share_survey_summary(token): """ Endpoint to verify token and retrieve the summary page :param token: share survey token :type token: str """ logger.info("Getting share survey summary", token=token) try: response = party_controller.verify_pending_survey_token(token) pending_share_surveys = response.json() share_dict = {} distinct_businesses = set() batch_number = pending_share_surveys[0]["batch_no"] originator_party = party_controller.get_respondent_party_by_id( pending_share_surveys[0]["shared_by"]) shared_by = originator_party["emailAddress"] for pending_share_survey in pending_share_surveys: distinct_businesses.add(pending_share_survey["business_id"]) for business_id in distinct_businesses: business_surveys = [] for pending_share_survey in pending_share_surveys: if pending_share_survey["business_id"] == business_id: business_surveys.append( survey_controller.get_survey( app.config["SURVEY_URL"], app.config["BASIC_AUTH"], pending_share_survey["survey_id"])) selected_business = get_business_by_id(business_id) share_dict[selected_business[0]["id"]] = { "name": selected_business[0]["name"], "trading_as": selected_business[0]["trading_as"], "surveys": business_surveys, } return render_template("surveys/surveys-share/summary.html", share_dict=share_dict, batch_no=batch_number, shared_by=shared_by) except ApiError as exc: # Handle api errors if exc.status_code == 409: logger.info( "Expired share survey email verification token", token=token, api_url=exc.url, api_status_code=exc.status_code, ) return render_template("surveys/surveys-link-expired.html", is_transfer=False) elif exc.status_code == 404: logger.warning( "Unrecognised share survey email verification token", token=token, api_url=exc.url, api_status_code=exc.status_code, ) return render_template("surveys/surveys-link-not-valid.html", is_transfer=False) else: logger.info("Failed to verify share survey email", token=token, api_url=exc.url, api_status_code=exc.status_code) raise exc
def get_survey_list(session, tag): """ Displays the list of surveys for the respondent by tag. A tag represents the state the survey is in (e.g., todo, history, etc) """ flask_session.pop("help_survey_ref", None) flask_session.pop("help_ru_ref", None) party_id = session.get_party_id() business_id = request.args.get("business_party_id") survey_id = request.args.get("survey_id") already_enrolled = request.args.get("already_enrolled") logger.info( "Retrieving survey list", party_id=party_id, business_id=business_id, survey_id=survey_id, already_enrolled=already_enrolled, tag=tag, ) # This logic is added to make sure a user is provided an option to delete an account if there is no # active enrolment which is ENABLED respondent = party_controller.get_respondent_party_by_id(party_id) delete_option_allowed = is_delete_account_respondent_allowed(respondent) survey_list = party_controller.get_survey_list_details_for_party( respondent, tag, business_party_id=business_id, survey_id=survey_id) sorted_survey_list = sorted( survey_list, key=lambda k: datetime.strptime(k["submit_by"], "%d %b %Y"), reverse=True) logger.info( "Successfully retrieved survey list", party_id=party_id, business_id=business_id, survey_id=survey_id, already_enrolled=already_enrolled, tag=tag, ) unread_message_count = { "unread_message_count": conversation_controller.try_message_count_from_session(session) } if tag == "todo": added_survey = True if business_id and survey_id and not already_enrolled else None response = make_response( render_template( "surveys/surveys-todo.html", sorted_surveys_list=sorted_survey_list, added_survey=added_survey, already_enrolled=already_enrolled, unread_message_count=unread_message_count, delete_option_allowed=delete_option_allowed, )) # Ensure any return to list of surveys (e.g. browser back) round trips the server to display the latest statuses response.headers.set("Cache-Control", "no-cache, max-age=0, must-revalidate, no-store") return response else: return render_template( "surveys/surveys-history.html", sorted_surveys_list=sorted_survey_list, history=True, unread_message_count=unread_message_count, )
def get_account(session): form = OptionsForm() party_id = session.get_party_id() respondent_details = party_controller.get_respondent_party_by_id(party_id) return render_template("account/account.html", form=form, respondent=respondent_details)