Ejemplo n.º 1
0
def root():
    ipa = maybe_ipa_session(app, session)
    username = session.get('noggin_username')
    if ipa and username:
        return redirect(url_for('user', username=username))

    # Kick any non-authed user back to the login form.

    activetab = request.args.get("tab", "login")

    register_form = RegisterUserForm(prefix="register")
    login_form = LoginUserForm(prefix="login")

    if login_form.validate_on_submit():
        with handle_form_errors(login_form):
            return handle_login_form(login_form)

    if register_form.validate_on_submit():
        with handle_form_errors(register_form):
            return handle_register_form(register_form)

    return render_template(
        'index.html',
        register_form=register_form,
        login_form=login_form,
        activetab=activetab,
    )
Ejemplo n.º 2
0
def test_handle_form_errors(client):
    with current_app.test_request_context('/'):
        form = LoginUserForm()
        error = FormError("username", "error_message")
        with mock.patch.object(error, "populate_form") as populate_form:
            with handle_form_errors(form):
                raise error
    populate_form.assert_called_once_with(form)
Ejemplo n.º 3
0
def forgot_password_ask():
    form = ForgottenPasswordForm()
    if form.validate_on_submit():
        username = form.username.data
        lock = PasswordResetLock(username)
        valid_until = lock.valid_until()
        now = datetime.datetime.now()
        with handle_form_errors(form):
            if valid_until is not None and now < valid_until:
                wait_min = int((valid_until - now).total_seconds() / 60)
                wait_sec = int((valid_until - now).total_seconds() % 60)
                raise FormError(
                    "non_field_errors",
                    _(
                        'You have already requested a password reset, you need to wait '
                        '%(wait_min)s minute(s) and %(wait_sec)s seconds before you can request '
                        'another.',
                        wait_min=wait_min,
                        wait_sec=wait_sec,
                    ),
                )
            try:
                user = User(ipa_admin.user_show(username))
            except python_freeipa.exceptions.NotFound:
                raise FormError(
                    "username",
                    _("User %(username)s does not exist", username=username))
            token = PasswordResetToken.from_user(user).as_string()
            # Send the email
            email_context = {"token": token, "username": username}
            email = Message(
                body=render_template("forgot-password-email.txt",
                                     **email_context),
                html=render_template("forgot-password-email.html",
                                     **email_context),
                recipients=[user.mail],
                subject="Password reset procedure",
            )
            try:
                mailer.send(email)
            except ConnectionRefusedError as e:
                app.logger.error(
                    f"Impossible to send a password reset email: {e}")
                flash(_("We could not send you an email, please retry later"),
                      "danger")
                return redirect(url_for('root'))
            if app.config["DEBUG"]:  # pragma: no cover
                app.logger.debug(email)
            lock.store()
            app.logger.info(
                f'{username} forgot their password and requested a token')
            flash(
                _('An email has been sent to your address with instructions on how to reset '
                  'your password'),
                "success",
            )
            return redirect(url_for('root'))
    return render_template('forgot-password-ask.html', form=form)
Ejemplo n.º 4
0
def _user_mod(ipa, form, username, details, redirect_to):
    with handle_form_errors(form):
        try:
            ipa.user_mod(username, **details)
        except python_freeipa.exceptions.BadRequest as e:
            if e.message == 'no modifications to be performed':
                raise FormError("non_field_errors", e.message)
            else:
                app.logger.error(
                    f'An error happened while editing user {username}: {e.message}'
                )
                raise FormError("non_field_errors", e.message)
        flash(
            Markup(
                f'Profile Updated: <a href=\"{url_for("user", username=username)}\">'
                'view your profile</a>'),
            'success',
        )
        return redirect(url_for(redirect_to, username=username))
Ejemplo n.º 5
0
def otp_sync():
    form = SyncTokenForm()
    if form.validate_on_submit():
        with handle_form_errors(form):
            try:
                ipa = untouched_ipa_client(app)
                ipa.otptoken_sync(
                    user=form.username.data,
                    password=form.password.data,
                    first_code=form.first_code.data,
                    second_code=form.second_code.data,
                    token=form.token.data,
                )

                flash(_('Token successfully synchronized'), category='success')
                return redirect(url_for('root'))

            except python_freeipa.exceptions.BadRequest as e:
                app.logger.error(
                    f'An error {e.__class__.__name__} happened while syncing a token for user '
                    f'{form.username}: {e}')
                raise FormError("non_field_errors", e.message)

    return render_template('sync-token.html', sync_form=form)
Ejemplo n.º 6
0
def activate_account():
    register_url = f"{url_for('root')}?tab=register"
    token_string = request.args.get('token')
    if not token_string:
        flash(_('No token provided, please check your email validation link.'),
              'warning')
        return redirect(register_url)
    try:
        token = EmailValidationToken.from_string(token_string)
    except jwt.exceptions.DecodeError:
        flash(_("The token is invalid, please register again."), "warning")
        return redirect(register_url)
    if not token.is_valid():
        flash(_("This token is no longer valid, please register again."),
              "warning")
        return redirect(register_url)
    try:
        user = User(ipa_admin.stageuser_show(token.username))
    except python_freeipa.exceptions.NotFound:
        flash(_("This user cannot be found, please register again."),
              "warning")
        return redirect(register_url)
    if not user.mail == token.mail:
        app.logger.error(
            f'User {user.username} tried to validate a token for address {token.mail} while they '
            f'are registered with address {user.mail}, something fishy may be going on.'
        )
        flash(
            _("The username and the email address don't match the token you used, "
              "please register again."),
            "warning",
        )
        return redirect(register_url)

    form = PasswordSetForm()

    if form.validate_on_submit():
        with handle_form_errors(form):
            password = form.password.data
            # First we activate the stage user
            try:
                ipa_admin.stageuser_activate(user.username)
            except python_freeipa.exceptions.FreeIPAError as e:
                app.logger.error(
                    f'An unhandled error {e.__class__.__name__} happened while activating '
                    f'stage user {user.username}: {e.message}')
                raise FormError(
                    "non_field_errors",
                    _("Something went wrong while activating your account, "
                      "please try again later."),
                )
            # User activation succeeded. Send message.
            messaging.publish(
                UserCreateV1(
                    {"msg": {
                        "agent": user.username,
                        "user": user.username
                    }}))
            # Now we set the password.
            try:
                # First, set it as an admin. This will mark it as expired.
                ipa_admin.user_mod(user.username, userpassword=password)
                # And now we set it again as the user, so it is not expired any more.
                ipa = untouched_ipa_client(app)
                ipa.change_password(user.username,
                                    new_password=password,
                                    old_password=password)
            except python_freeipa.exceptions.PWChangePolicyError as e:
                # The user is active but the password does not match the policy.
                # Tell the user what's going to happen.
                flash(
                    _(
                        'Your account has been activated, but the password you chose does not '
                        'comply with the policy (%(policy_error)s) and has thus been set as '
                        'expired. You will be asked to change it after logging in.',
                        policy_error=e.policy_error,
                    ),
                    'warning',
                )
                return redirect(url_for("root"))
            except python_freeipa.exceptions.ValidationError as e:
                # for example: invalid username. We don't know which field to link it to
                _handle_registration_validation_error(user.username, e)
            except python_freeipa.exceptions.FreeIPAError as e:
                app.logger.error(
                    f'An unhandled error {e.__class__.__name__} happened while changing initial '
                    f'password for user {user.username}: {e.message}')
                # At this point the user has been activated, they can't register again. Send them to
                # the login page with an appropriate warning.
                flash(
                    _(
                        'Your account has been activated, but an error occurred while setting your '
                        'password (%(message)s). You may need to change it after logging in.',
                        message=e.message,
                    ),
                    'warning',
                )
                return redirect(url_for("root"))

            # Try to log them in directly, so they don't have to type their password again.
            try:
                ipa = maybe_ipa_login(app, session, user.username, password)
            except python_freeipa.exceptions.FreeIPAError:
                ipa = None
            if ipa:
                flash(
                    _(
                        'Congratulations, your account is now active! Welcome, %(name)s.',
                        name=user.name,
                    ),
                    'success',
                )
            else:
                # No shortcut for you, you'll have to login properly (maybe the password is
                # expired).
                flash(
                    _('Congratulations, your account is now active! Go ahead and sign in '
                      'to proceed.'),
                    'success',
                )
            return redirect(url_for('root'))

    return render_template('registration-activation.html',
                           user=user,
                           form=form)