示例#1
0
def test_user_private(client, logged_in_dummy_user, make_user):
    """A user with fasIsPrivate should be anonymized as much as possible."""
    make_user("testuser")
    ipa_admin.user_mod("testuser", fasisprivate=True)
    result = client.get('/user/testuser/')
    assert result.status_code == 200
    page = BeautifulSoup(result.data, 'html.parser')
    # print(page.prettify())
    user_fullname = page.select_one("#user_fullname")
    assert user_fullname is not None
    assert user_fullname.get_text(strip=True) == "testuser"
    user_attributes = page.select_one("ul#user_attributes")
    assert user_attributes is not None
    assert len(user_attributes.find_all("li")) == 0
示例#2
0
def dummy_user_with_gpg_key(client, dummy_user):
    ipa_admin.user_mod(a_uid="dummy", fasgpgkeyid=["dummygpgkeyid"])
示例#3
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 = read_token(token_string, audience=Audience.email_validation)
    except jwt.exceptions.DecodeError:
        flash(_("The token is invalid, please register again."), "warning")
        return redirect(register_url)
    except jwt.exceptions.ExpiredSignatureError:
        flash(_("This token is no longer valid, please register again."),
              "warning")
        return redirect(register_url)

    try:
        user = User(ipa_admin.stageuser_show(token["sub"])["result"])
    except python_freeipa.exceptions.NotFound:
        flash(_("This user cannot be found, please register again."),
              "warning")
        return redirect(register_url)

    token_mail = token["mail"]
    if not user.mail == token_mail:
        current_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:
                current_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 creating your account, "
                      "please try again later."),
                )
            # User activation succeeded. Send signal.
            user_registered.send(user, request=request._get_current_object())
            # 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(current_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 created, 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:
                current_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 created, 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(current_app, session, user.username,
                                      password)
            except python_freeipa.exceptions.FreeIPAError:
                ipa = None
            if ipa:
                flash(
                    _(
                        'Congratulations, your account has been created! 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 has been created! Go ahead and sign in '
                      'to proceed.'),
                    'success',
                )
            return redirect(url_for('.root'))

    return render_template('registration-activation.html',
                           user=user,
                           form=form)
示例#4
0
def forgot_password_change():
    token = request.args.get('token')
    if not token:
        flash('No token provided, please request one.', 'warning')
        return redirect(url_for('.forgot_password_ask'))
    try:
        token_data = read_token(token, audience=Audience.password_reset)
    except jwt.exceptions.DecodeError:
        flash(_("The token is invalid, please request a new one."), "warning")
        return redirect(url_for('.forgot_password_ask'))
    username = token_data["sub"]
    lock = PasswordResetLock(username)
    valid_until = lock.valid_until()
    now = datetime.datetime.now()
    if valid_until is None or now > valid_until:
        lock.delete()
        flash(_("The token has expired, please request a new one."), "warning")
        return redirect(url_for('.forgot_password_ask'))
    user = User(ipa_admin.user_show(a_uid=username)['result'])
    if user.last_password_change != token_data["lpc"]:
        lock.delete()
        flash(
            _("Your password has been changed since you requested this token, please request "
              "a new one."),
            "warning",
        )
        return redirect(url_for('.forgot_password_ask'))

    form = NewPasswordForm()
    if form.validate_on_submit():
        password = form.password.data
        # Generate a random temporary number.
        temp_password = ''.join(
            random.choices(string.ascii_letters + string.digits, k=24))
        try:
            # Force change password to the random password, so that the password is not actually
            # changed to the given one in case the next step fails (because the OTP is wrong for
            # example)
            ipa_admin.user_mod(username, userpassword=temp_password)
            # Change the password as the user, so it's not expired.
            ipa = untouched_ipa_client(current_app)
            ipa.change_password(
                username,
                new_password=password,
                old_password=temp_password,
                otp=form.otp.data,
            )
        except python_freeipa.exceptions.PWChangePolicyError as e:
            lock.delete()
            flash(
                _(
                    'Your password has been changed, but it 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',
            )
            current_app.logger.info(
                f"Password for {username} was changed to a non-compliant password after "
                f"completing the forgotten password process.")
            # Send them to the login page, they will have to change their password
            # after login.
            return redirect(url_for('.root'))
        except python_freeipa.exceptions.PWChangeInvalidPassword:
            # The provided OTP was wrong
            current_app.logger.info(
                f"Password for {username} was changed to a random string because "
                f"the OTP token they provided was wrong.")
            # Oh noes, the token is now invalid since the user's password was changed! Let's
            # re-generate a token so they can keep going.
            user = User(ipa_admin.user_show(a_uid=username)['result'])
            token = make_token(
                {
                    "sub": user.username,
                    "lpc": user.last_password_change
                },
                audience=Audience.password_reset,
            )
            form.otp.errors.append(_("Incorrect value."))
        except python_freeipa.exceptions.FreeIPAError as e:
            # If we made it here, we hit something weird not caught above.
            current_app.logger.error(
                f'An unhandled error {e.__class__.__name__} happened while reseting '
                f'the password for user {username}: {e.message}')
            form.non_field_errors.errors.append(
                _('Could not change password, please try again.'))
        else:
            lock.delete()
            flash(_('Your password has been changed.'), 'success')
            current_app.logger.info(
                f"Password for {username} was changed after completing the forgotten "
                f"password process.")
            messaging.publish(
                UserUpdateV1({
                    "msg": {
                        "agent": username,
                        "user": username,
                        "fields": ["password"],
                    }
                }))
            return redirect(url_for('.root'))
    return render_template('forgot-password-change.html',
                           username=username,
                           form=form,
                           token=token)