def new_phone_number(wallet, request): user = wallet.user if has_pending_phone_number_request(request, user): return httpexceptions.HTTPFound(request.resource_url(wallet, "confirm-phone-number")) schema = NewPhoneNumber().bind(request=request) b = deform.Button(name='process', title="Send verification code", css_class="btn-block btn-lg") form = deform.Form(schema, buttons=(b,)) # User submitted this form if request.method == "POST": if 'process' in request.POST: try: appstruct = form.validate(request.POST.items()) # Save form data from appstruct phone_number = normalize_international_phone_number(appstruct["phone_number"]) assert phone_number, "Could not normalizer phone number: {}".format(appstruct["phone_number"]) UserNewPhoneNumberConfirmation.require_confirmation(user, phone_number) return httpexceptions.HTTPFound(request.resource_url(wallet, "confirm-phone-number")) except deform.ValidationFailure as e: # Render a form version where errors are visible next to the fields, # and the submitted values are posted back rendered_form = e.render() else: # We don't know which control caused form submission raise httpexceptions.HTTPInternalServerError("Unknown form button pressed") else: # Render a form with initial values rendered_form = form.render() return locals()
def new_phone_number(wallet, request): user = wallet.user if has_pending_phone_number_request(request, user): return httpexceptions.HTTPFound(request.resource_url(wallet, "confirm-phone-number")) schema = NewPhoneNumber().bind(request=request) b = deform.Button(name='process', title="Send verification code", css_class="btn-primary btn-block btn-lg") form = deform.Form(schema, buttons=(b,)) # User submitted this form if request.method == "POST": if 'process' in request.POST: try: appstruct = form.validate(request.POST.items()) # Save form data from appstruct phone_number = normalize_international_phone_number(appstruct["phone_number"]) assert phone_number, "Could not normalizer phone number: {}".format(appstruct["phone_number"]) UserNewPhoneNumberConfirmation.require_confirmation(user, phone_number) return httpexceptions.HTTPFound(request.resource_url(wallet, "confirm-phone-number")) except deform.ValidationFailure as e: # Render a form version where errors are visible next to the fields, # and the submitted values are posted back rendered_form = e.render() else: # We don't know which control caused form submission raise httpexceptions.HTTPInternalServerError("Unknown form button pressed") else: # Render a form with initial values rendered_form = form.render() return locals()
def test_confirm_user_phone_number_cancel(dbsession, user_id): """SMS confirmation success.""" # Prepare confirmation with transaction.manager: user = dbsession.query(User).get(user_id) confirmation = UserNewPhoneNumberConfirmation.require_confirmation(user, "+15551231234") assert confirmation.created_at assert confirmation.confirmation_type == ManualConfirmationType.sms assert confirmation.state == ManualConfirmationState.pending assert UserNewPhoneNumberConfirmation.get_pending_confirmation(user) # Resolve confirmation and see user gets a phone number with transaction.manager: user = dbsession.query(User).get(user_id) confirmation = dbsession.query(UserNewPhoneNumberConfirmation).first() confirmation.cancel() assert confirmation.action_taken_at assert confirmation.state == ManualConfirmationState.cancelled assert "phone_number" not in user.user_data assert not UserNewPhoneNumberConfirmation.get_pending_confirmation(user)
def test_confirm_user_phone_number_success(dbsession, user_id): """SMS confirmation success.""" # Prepare confirmation with transaction.manager: user = dbsession.query(User).get(user_id) confirmation = UserNewPhoneNumberConfirmation.require_confirmation(user, "+15551231234") assert confirmation.created_at assert confirmation.confirmation_type == ManualConfirmationType.sms assert confirmation.state == ManualConfirmationState.pending assert UserNewPhoneNumberConfirmation.get_pending_confirmation(user) # Resolve confirmation and see user gets a phone number with transaction.manager: user = dbsession.query(User).get(user_id) confirmation = dbsession.query(UserNewPhoneNumberConfirmation).first() code = confirmation.other_data["sms_code"] confirmation.resolve_sms(code, None) assert confirmation.action_taken_at assert confirmation.state == ManualConfirmationState.resolved assert user.user_data["phone_number"] == "+15551231234" assert not UserNewPhoneNumberConfirmation.get_pending_confirmation(user)
def inner(*args, **kwargs): context, request = args wallet = get_wallet(context) user = request.user if not user: messages.add(request, kind="warning", msg="Please sign in to view the page.") return httpexceptions.HTTPFound(request.route_url("home")) # Redirect user to the phone number confirmation if request.registry.settings.get("websauna.wallet.require_phone_number"): if not UserNewPhoneNumberConfirmation.has_confirmed_phone_number(user): return httpexceptions.HTTPFound(request.resource_url(wallet, "new-phone-number")) return func(*args, **kwargs)
def test_ui_confirm_phone_number(require_phone_number, logged_in_wallet_user_browser: DriverAPI, dbsession: Session, mock_eth_service, test_request): """User needs a confirmed phone number before entering the wallet.""" # Run functional tests against a Waitress web server running in another thread b = logged_in_wallet_user_browser b.find_by_css("#nav-wallet").click() assert b.is_element_present_by_css("#heading-new-phone-number") b.fill("phone_number", "+15551231234") b.find_by_css("button[type='submit']").click() # We arrived to SMS code verification page assert b.is_element_present_by_css("#heading-confirm-phone-number") # Peek into SMS code with transaction.manager: user = dbsession.query(User).first() confirmation = UserNewPhoneNumberConfirmation.get_pending_confirmation( user) sms_code = confirmation.other_data["sms_code"] # Get a dummy SMS backend that's configured in test fixtures backend = get_sms_backend(test_request) # Make sure code got out to the user msg = backend.get_last_message() assert sms_code in msg # Enter the code b.fill("code", sms_code) b.find_by_css("button[type='submit']").click() # We arrived to wallet overview assert b.is_element_present_by_css("#heading-wallet-overview") # We have a notification for phone number verified assert b.is_element_present_by_css("#msg-phone-confirmed")
def test_ui_confirm_phone_number(require_phone_number, logged_in_wallet_user_browser: DriverAPI, dbsession: Session, mock_eth_service, test_request): """User needs a confirmed phone number before entering the wallet.""" # Run functional tests against a Waitress web server running in another thread b = logged_in_wallet_user_browser b.find_by_css("#nav-wallet").click() assert b.is_element_present_by_css("#heading-new-phone-number") b.fill("phone_number", "+15551231234") b.find_by_css("button[type='submit']").click() # We arrived to SMS code verification page assert b.is_element_present_by_css("#heading-confirm-phone-number") # Peek into SMS code with transaction.manager: user = dbsession.query(User).first() confirmation = UserNewPhoneNumberConfirmation.get_pending_confirmation(user) sms_code = confirmation.other_data["sms_code"] # Get a dummy SMS backend that's configured in test fixtures backend = get_sms_backend(test_request) # Make sure code got out to the user msg = backend.get_last_message() assert sms_code in msg # Enter the code b.fill("code", sms_code) b.find_by_css("button[type='submit']").click() # We arrived to wallet overview assert b.is_element_present_by_css("#heading-wallet-overview") # We have a notification for phone number verified assert b.is_element_present_by_css("#msg-phone-confirmed")
def manual_confirmation(self) -> UserNewPhoneNumberConfirmation: wallet = self.context return UserNewPhoneNumberConfirmation.get_pending_confirmation(wallet.user)