Exemple #1
0
def new_password(token):
    from notifications_utils.url_safe_token import check_token
    try:
        token_data = check_token(token, current_app.config['SECRET_KEY'],
                                 current_app.config['DANGEROUS_SALT'],
                                 current_app.config['TOKEN_MAX_AGE_SECONDS'])
    except SignatureExpired:
        flash(
            'The link in the email we sent you has expired. Enter your email address to resend.'
        )
        return redirect(url_for('.forgot_password'))

    email_address = json.loads(token_data)['email']
    user = user_api_client.get_user_by_email(email_address)
    if user.password_changed_at and datetime.strptime(user.password_changed_at, '%Y-%m-%d %H:%M:%S.%f') > \
            datetime.strptime(json.loads(token_data)['created_at'], '%Y-%m-%d %H:%M:%S.%f'):
        flash('The link in the email has already been used')
        return redirect(url_for('main.index'))

    form = NewPasswordForm()

    if form.validate_on_submit():
        user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
        session['user_details'] = {
            'id': user.id,
            'email': user.email_address,
            'password': form.new_password.data
        }
        return redirect(url_for('main.two_factor'))
    else:
        return render_template('views/new-password.html',
                               token=token,
                               form=form,
                               user=user)
Exemple #2
0
def verify_email(token):
    try:
        token_data = check_token(
            token,
            current_app.config['SECRET_KEY'],
            current_app.config['DANGEROUS_SALT'],
            current_app.config['EMAIL_EXPIRY_SECONDS']
        )
    except SignatureExpired:
        flash("The link in the email we sent you has expired. We've sent you a new one.")
        return redirect(url_for('main.resend_email_verification'))

    # token contains json blob of format: {'user_id': '...', 'secret_code': '...'} (secret_code is unused)
    token_data = json.loads(token_data)
    user = user_api_client.get_user(token_data['user_id'])
    if not user:
        abort(404)

    if user.is_active:
        flash("That verification link has expired.")
        return redirect(url_for('main.sign_in'))

    session['user_details'] = {"email": user.email_address, "id": user.id}
    user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
    return redirect(url_for('main.verify'))
def new_password(token):
    from notifications_utils.url_safe_token import check_token

    try:
        token_data = check_token(
            token,
            current_app.config["SECRET_KEY"],
            current_app.config["DANGEROUS_SALT"],
            current_app.config["TOKEN_MAX_AGE_SECONDS"],
        )
    except SignatureExpired:
        flash("The link in the email we sent you has expired. Enter your email address to resend.")
        return redirect(url_for(".forgot_password"))

    email_address = json.loads(token_data)["email"]
    user = user_api_client.get_user_by_email(email_address)
    if user.password_changed_at and datetime.strptime(
        user.password_changed_at, "%Y-%m-%d %H:%M:%S.%f"
    ) > datetime.strptime(json.loads(token_data)["created_at"], "%Y-%m-%d %H:%M:%S.%f"):
        flash("The link in the email has already been used")
        return redirect(url_for("main.index"))

    form = NewPasswordForm()

    if form.validate_on_submit():
        user_api_client.send_verify_code(user.id, "sms", user.mobile_number)
        session["user_details"] = {"id": user.id, "email": user.email_address, "password": form.new_password.data}
        return redirect(url_for("main.two_factor"))
    else:
        return render_template("views/new-password.html", token=token, form=form, user=user)
Exemple #4
0
def sign_in_email(user_id, to):
    if request.args.get('next'):
        user_api_client.send_verify_code(user_id, 'email', None,
                                         request.args.get('next'))
    else:
        user_api_client.send_verify_code(user_id, 'email', None)
    return redirect(url_for('.two_factor_email_sent'))
def _do_registration(form, send_sms=True, send_email=True):
    if user_api_client.is_email_unique(form.email_address.data):
        user = user_api_client.register_user(form.name.data,
                                             form.email_address.data,
                                             form.mobile_number.data or None,
                                             form.password.data,
                                             form.auth_type.data)

        # TODO possibly there should be some exception handling
        # for sending sms and email codes.
        # How do we report to the user there is a problem with
        # sending codes apart from service unavailable?
        # at the moment i believe http 500 is fine.

        if send_email:
            user_api_client.send_verify_email(user.id, user.email_address)

        if send_sms:
            user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
        session['expiry_date'] = str(datetime.utcnow() + timedelta(hours=1))
        session['user_details'] = {"email": user.email_address, "id": user.id}
    else:
        user = user_api_client.get_user_by_email(form.email_address.data)
        if send_email:
            user_api_client.send_already_registered_email(user.id, user.email_address)
        session['expiry_date'] = str(datetime.utcnow() + timedelta(hours=1))
        session['user_details'] = {"email": user.email_address, "id": user.id}
def _do_registration(form, service=None, send_sms=True, send_email=True):
    if user_api_client.is_email_unique(form.email_address.data):
        user = user_api_client.register_user(form.name.data,
                                             form.email_address.data,
                                             form.mobile_number.data,
                                             form.password.data)

        # TODO possibly there should be some exception handling
        # for sending sms and email codes.
        # How do we report to the user there is a problem with
        # sending codes apart from service unavailable?
        # at the moment i believe http 500 is fine.

        if send_email:
            user_api_client.send_verify_email(user.id, user.email_address)

        if send_sms:
            user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
        session['expiry_date'] = str(datetime.utcnow() + timedelta(hours=1))
        session['user_details'] = {"email": user.email_address, "id": user.id}
    else:
        if send_email:
            user = user_api_client.get_user_by_email(form.email_address.data)
            user_api_client.send_already_registered_email(user.id, user.email_address)
        session['expiry_date'] = str(datetime.utcnow() + timedelta(hours=1))
        session['user_details'] = {"email": user.email_address, "id": user.id}
def new_password(token):
    try:
        token_data = check_token(token, current_app.config['SECRET_KEY'], current_app.config['DANGEROUS_SALT'],
                                 current_app.config['EMAIL_EXPIRY_SECONDS'])
    except SignatureExpired:
        flash('The link in the email we sent you has expired. Enter your email address to resend.')
        return redirect(url_for('.forgot_password'))

    email_address = json.loads(token_data)['email']
    user = user_api_client.get_user_by_email(email_address)
    if user.password_changed_at and datetime.strptime(user.password_changed_at, '%Y-%m-%d %H:%M:%S.%f') > \
            datetime.strptime(json.loads(token_data)['created_at'], '%Y-%m-%d %H:%M:%S.%f'):
        flash('The link in the email has already been used')
        return redirect(url_for('main.index'))

    form = NewPasswordForm()

    if form.validate_on_submit():
        user_api_client.reset_failed_login_count(user.id)
        session['user_details'] = {
            'id': user.id,
            'email': user.email_address,
            'password': form.new_password.data}
        if user.auth_type == 'email_auth':
            # they've just clicked an email link, so have done an email auth journey anyway. Just log them in.
            return log_in_user(user.id)
        else:
            # send user a 2fa sms code
            user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
            return redirect(url_for('main.two_factor'))
    else:
        return render_template('views/new-password.html', token=token, form=form, user=user)
Exemple #8
0
def _do_registration(form, send_sms=True, send_email=True, organisation_id=None):
    if user_api_client.is_email_already_in_use(form.email_address.data):
        user = user_api_client.get_user_by_email(form.email_address.data)
        if send_email:
            user_api_client.send_already_registered_email(user.id, user.email_address)
        session['expiry_date'] = str(datetime.utcnow() + timedelta(hours=1))
        session['user_details'] = {"email": user.email_address, "id": user.id}
    else:
        user = user_api_client.register_user(form.name.data,
                                             form.email_address.data,
                                             form.mobile_number.data or None,
                                             form.password.data,
                                             form.auth_type.data)
        if send_email:
            user_api_client.send_verify_email(user.id, user.email_address)

        if send_sms:
            user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)

        if form.research_consent.data:
            user_api_client.send_research_consent_email(user.id)

        session['expiry_date'] = str(datetime.utcnow() + timedelta(hours=1))
        session['user_details'] = {"email": user.email_address, "id": user.id}
    if organisation_id:
        session['organisation_id'] = organisation_id
def verify_email(token):
    try:
        token_data = check_token(token,
                                 current_app.config['SECRET_KEY'],
                                 current_app.config['DANGEROUS_SALT'],
                                 current_app.config['EMAIL_EXPIRY_SECONDS'])

        token_data = json.loads(token_data)
        verified = user_api_client.check_verify_code(token_data['user_id'], token_data['secret_code'], 'email')
        user = user_api_client.get_user(token_data['user_id'])
        if not user:
            abort(404)

        if user.is_active:
            flash("That verification link has expired.")
            return redirect(url_for('main.sign_in'))

        session['user_details'] = {"email": user.email_address, "id": user.id}
        if verified[0]:
            user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
            return redirect('verify')
        else:
            if verified[1] == 'Code has expired':
                flash("The link in the email we sent you has expired. We've sent you a new one.")
                return redirect(url_for('main.resend_email_verification'))
            else:
                message = "There was a problem verifying your account. Error message: '{}'".format(verified[1])
                flash(message)
                return redirect(url_for('main.index'))

    except SignatureExpired:
        flash('The link in the email we sent you has expired')
        return redirect(url_for('main.resend_email_verification'))
Exemple #10
0
def check_and_resend_verification_code():
    user = user_api_client.get_user_by_email(session['user_details']['email'])
    user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
    if user.state == 'pending':
        return redirect(url_for('main.verify'))
    else:
        return redirect(url_for('main.two_factor'))
def check_and_resend_verification_code():
    user = user_api_client.get_user_by_email(session['user_details']['email'])
    user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
    if user.state == 'pending':
        return redirect(url_for('main.verify'))
    else:
        return redirect(url_for('main.two_factor'))
def sign_in():

    if current_user and current_user.is_authenticated:
        return redirect(url_for('main.choose_service'))

    form = LoginForm()
    if form.validate_on_submit():

        user = user_api_client.get_user_by_email_or_none(form.email_address.data)
        user = _get_and_verify_user(user, form.password.data)
        if user and user.state == 'pending':
            flash("You haven't verified your email or mobile number yet.")
            return redirect(url_for('main.sign_in'))

        if user and session.get('invited_user'):
            invited_user = session.get('invited_user')
            if user.email_address != invited_user['email_address']:
                flash("You can't accept an invite for another person.")
                session.pop('invited_user', None)
                abort(403)
            else:
                invite_api_client.accept_invite(invited_user['service'], invited_user['id'])
        if user:
            # Remember me login
            if not login_fresh() and \
               not current_user.is_anonymous and \
               current_user.id == user.id and \
               user.is_active:

                confirm_login()
                services = service_api_client.get_services({'user_id': str(user.id)}).get('data', [])
                if (len(services) == 1):
                    return redirect(url_for('main.service_dashboard', service_id=services[0]['id']))
                else:
                    return redirect(url_for('main.choose_service'))

            session['user_details'] = {"email": user.email_address, "id": user.id}
            if user.is_active:
                user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
                if request.args.get('next'):
                    return redirect(url_for('.two_factor', next=request.args.get('next')))
                else:
                    return redirect(url_for('.two_factor'))
        # Vague error message for login in case of user not known, locked, inactive or password not verified
        flash(Markup((
            "The email address or password you entered is incorrect."
            " <a href={password_reset}>Forgot your password</a>?"
            ).format(password_reset=url_for('.forgot_password'))
        ))

    return render_template('views/signin.html', form=form)
def check_and_resend_text_code():
    user = user_api_client.get_user_by_email(session['user_details']['email'])

    if user.state == 'active':
        # this is a verified user and therefore redirect to page to request resend without edit mobile
        return render_template('views/verification-not-received.html')

    form = TextNotReceivedForm(mobile_number=user.mobile_number)
    if form.validate_on_submit():
        user_api_client.send_verify_code(user.id, 'sms', to=form.mobile_number.data)
        user = user_api_client.update_user_attribute(user.id, mobile_number=form.mobile_number.data)
        return redirect(url_for('.verify'))

    return render_template('views/text-not-received.html', form=form)
Exemple #14
0
def sign_in():
    if current_user and current_user.is_authenticated:
        return redirect(url_for('main.choose_service'))

    form = LoginForm()
    if form.validate_on_submit():

        user = user_api_client.get_user_by_email_or_none(form.email_address.data)
        user = _get_and_verify_user(user, form.password.data)
        if user and user.state == 'pending':
            return redirect(url_for('main.resend_email_verification'))

        if user and session.get('invited_user'):
            invited_user = session.get('invited_user')
            if user.email_address != invited_user['email_address']:
                flash("You can't accept an invite for another person.")
                session.pop('invited_user', None)
                abort(403)
            else:
                invite_api_client.accept_invite(invited_user['service'], invited_user['id'])
        if user:
            # Remember me login
            if not login_fresh() and \
               not current_user.is_anonymous and \
               current_user.id == user.id and \
               user.is_active:

                confirm_login()
                services = service_api_client.get_services({'user_id': str(user.id)}).get('data', [])
                if (len(services) == 1):
                    return redirect(url_for('main.service_dashboard', service_id=services[0]['id']))
                else:
                    return redirect(url_for('main.choose_service'))

            session['user_details'] = {"email": user.email_address, "id": user.id}
            if user.is_active:
                user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
                if request.args.get('next'):
                    return redirect(url_for('.two_factor', next=request.args.get('next')))
                else:
                    return redirect(url_for('.two_factor'))
        # Vague error message for login in case of user not known, locked, inactive or password not verified
        flash(Markup((
            "The email address or password you entered is incorrect."
            " <a href={password_reset}>Forgot your password</a>?"
            ).format(password_reset=url_for('.forgot_password'))
        ))

    return render_template('views/signin.html', form=form)
def check_and_resend_text_code():
    user = user_api_client.get_user_by_email(session['user_details']['email'])

    if user.state == 'active':
        # this is a verified user and therefore redirect to page to request resend without edit mobile
        return render_template('views/verification-not-received.html')

    form = TextNotReceivedForm(mobile_number=user.mobile_number)
    if form.validate_on_submit():
        user_api_client.send_verify_code(user.id, 'sms', to=form.mobile_number.data)
        user.mobile_number = form.mobile_number.data
        user_api_client.update_user(user)
        return redirect(url_for('.verify'))

    return render_template('views/text-not-received.html', form=form)
def test_client_passes_admin_url_when_sending_email_auth(
    app_,
    mocker,
    fake_uuid,
):
    mock_post = mocker.patch('app.notify_client.user_api_client.UserApiClient.post')

    user_api_client.send_verify_code(fake_uuid, 'email', '*****@*****.**')

    mock_post.assert_called_once_with(
        '/user/{}/email-code'.format(fake_uuid),
        data={
            'to': '*****@*****.**',
            'email_auth_link_host': 'http://localhost:6012',
        }
    )
Exemple #17
0
def two_factor():
    user_id = session['user_details']['id']
    user = User.from_id(user_id)

    def _check_code(code):
        return user_api_client.check_verify_code(user_id, code, "sms")

    form = TwoFactorForm(_check_code)

    if form.validate_on_submit():
        if is_less_than_90_days_ago(user.email_access_validated_at):
            return log_in_user(user_id)
        else:
            user_api_client.send_verify_code(user.id, 'email', None, request.args.get('next'))
            return redirect(url_for('.revalidate_email_sent'))

    return render_template('views/two-factor.html', form=form)
Exemple #18
0
def test_client_passes_admin_url_when_sending_email_auth(
    app_,
    mocker,
    fake_uuid,
):
    mock_post = mocker.patch(
        "app.notify_client.user_api_client.UserApiClient.post")

    user_api_client.send_verify_code(fake_uuid, "email", "*****@*****.**")

    mock_post.assert_called_once_with(
        "/user/{}/email-code".format(fake_uuid),
        data={
            "to": "*****@*****.**",
            "email_auth_link_host": "http://localhost:6012",
        },
    )
def user_profile_mobile_number_authenticate():

    # Validate password for form
    def _check_password(pwd):
        return user_api_client.verify_password(current_user.id, pwd)
    form = ConfirmPasswordForm(_check_password)

    if NEW_MOBILE not in session:
        return redirect(url_for('.user_profile_mobile_number'))

    if form.validate_on_submit():
        session[NEW_MOBILE_PASSWORD_CONFIRMED] = True
        user_api_client.send_verify_code(current_user.id, 'sms', session[NEW_MOBILE])
        return redirect(url_for('.user_profile_mobile_number_confirm'))

    return render_template(
        'views/user-profile/authenticate.html',
        thing='mobile number',
        form=form,
        back_link=url_for('.user_profile_mobile_number_confirm')
    )
def user_profile_mobile_number_authenticate():

    # Validate password for form
    def _check_password(pwd):
        return user_api_client.verify_password(current_user.id, pwd)
    form = ConfirmPasswordForm(_check_password)

    if NEW_MOBILE not in session:
        return redirect(url_for('.user_profile_mobile_number'))

    if form.validate_on_submit():
        session[NEW_MOBILE_PASSWORD_CONFIRMED] = True
        user_api_client.send_verify_code(current_user.id, 'sms', session[NEW_MOBILE])
        return redirect(url_for('.user_profile_mobile_number_confirm'))

    return render_template(
        'views/user-profile/authenticate.html',
        thing='mobile number',
        form=form,
        back_link=url_for('.user_profile_mobile_number_confirm')
    )
def verify_email(token):
    try:
        token_data = check_token(token, current_app.config['SECRET_KEY'],
                                 current_app.config['DANGEROUS_SALT'],
                                 current_app.config['EMAIL_EXPIRY_SECONDS'])

        token_data = json.loads(token_data)
        verified = user_api_client.check_verify_code(token_data['user_id'],
                                                     token_data['secret_code'],
                                                     'email')
        user = user_api_client.get_user(token_data['user_id'])
        if not user:
            abort(404)

        if user.is_active:
            flash("That verification link has expired.")
            return redirect(url_for('main.sign_in'))

        session['user_details'] = {"email": user.email_address, "id": user.id}
        if verified[0]:
            user_api_client.send_verify_code(user.id, 'sms',
                                             user.mobile_number)
            return redirect('verify')
        else:
            if verified[1] == 'Code has expired':
                flash(
                    "The link in the email we sent you has expired. We've sent you a new one."
                )
                return redirect(url_for('main.resend_email_verification'))
            else:
                message = "There was a problem verifying your account. Error message: '{}'".format(
                    verified[1])
                flash(message)
                return redirect(url_for('main.index'))

    except SignatureExpired:
        flash('The link in the email we sent you has expired')
        return redirect(url_for('main.resend_email_verification'))
def resend_email_link():
    user_api_client.send_verify_code(session["user_details"]["id"], "email", None)
    return redirect(url_for("main.two_factor_email_sent", email_resent=True))
Exemple #23
0
def resend_email_link():
    user_api_client.send_verify_code(session['user_details']['id'], 'email',
                                     None)
    session.pop('user_details')
    return redirect(url_for('main.two_factor_email_sent', email_resent=True))
Exemple #24
0
def sign_in_sms(user_id, to):
    user_api_client.send_verify_code(user_id, 'sms', to)
    if request.args.get('next'):
        return redirect(url_for('.two_factor', next=request.args.get('next')))
    else:
        return redirect(url_for('.two_factor'))