def user_settings_keys(ipa, username): user = User(user_or_404(ipa, username)) form = UserSettingsKeysForm(obj=user) if form.validate_on_submit(): result = _user_mod( ipa, form, user, { 'o_ipasshpubkey': form.sshpubkeys.data, 'fasgpgkeyid': form.gpgkeys.data }, ".user_settings_keys", ) if result: return result # if the form has errors, we don't want to add new fields. otherwise, # more fields will show up with every validation error if not form.errors: # Append 2 empty entries at the bottom of the gpgkeys fieldlist for i in range(2): form.gpgkeys.append_entry() form.sshpubkeys.append_entry() return render_template('user-settings-keys.html', user=user, form=form, activetab="keys")
def user(ipa, username): user = User(user_or_404(ipa, username)) # As a speed optimization, we make two separate calls. # Just doing a group_find (with all=True) is super slow here, with a lot of # groups. member_groups = [ Group(group) for group in ipa.group_find( o_user=username, o_all=False, fasgroup=True)['result'] ] managed_groups = [ Group(group) for group in ipa.group_find(o_membermanager_user=username, o_all=False, fasgroup=True)['result'] ] groups = [group for group in managed_groups if group not in member_groups ] + member_groups # Privacy setting if user != g.current_user and user.is_private: user.anonymize() return render_template( 'user.html', user=user, groups=groups, managed_groups=managed_groups, member_groups=member_groups, )
def user_settings_otp(ipa, username): addotpform = UserSettingsAddOTPForm() user = User(user_or_404(ipa, username)) if addotpform.validate_on_submit(): try: maybe_ipa_login(current_app, session, username, addotpform.password.data) result = ipa.otptoken_add( o_ipatokenowner=username, o_ipatokenotpalgorithm='sha512', o_description=addotpform.description.data, )['result'] uri = urlparse(result['uri']) # Use the provided description in the token, so it shows up in the user's app instead of # the token's UUID principal = uri.path.split(":", 1)[0] new_uri = uri._replace( path=f"{principal.lower()}:{quote(addotpform.description.data)}" ) session['otp_uri'] = new_uri.geturl() except python_freeipa.exceptions.InvalidSessionPassword: addotpform.password.errors.append(_("Incorrect password")) except python_freeipa.exceptions.FreeIPAError as e: current_app.logger.error( f'An error happened while creating an OTP token for user {username}: {e.message}' ) addotpform.non_field_errors.errors.append( _('Cannot create the token.')) else: return redirect(url_for('.user_settings_otp', username=username)) otp_uri = session.get('otp_uri') session['otp_uri'] = None tokens = [ OTPToken(t) for t in ipa.otptoken_find(o_ipatokenowner=username)["result"] ] tokens.sort(key=lambda t: t.description or "") return render_template( 'user-settings-otp.html', addotpform=addotpform, user=user, activetab="otp", tokens=tokens, otp_uri=otp_uri, )
def user_settings_profile(ipa, username): user = User(user_or_404(ipa, username)) form = UserSettingsProfileForm(obj=user) if form.validate_on_submit(): result = _user_mod( ipa, form, user, { 'o_givenname': form.firstname.data, 'o_sn': form.lastname.data, 'o_cn': '%s %s' % (form.firstname.data, form.lastname.data), 'o_displayname': '%s %s' % (form.firstname.data, form.lastname.data), 'o_mail': form.mail.data, 'fasircnick': form.ircnick.data, 'faslocale': form.locale.data, 'fastimezone': form.timezone.data, 'fasgithubusername': form.github.data.lstrip('@'), 'fasgitlabusername': form.gitlab.data.lstrip('@'), 'fasrhbzemail': form.rhbz_mail.data, 'faswebsiteurl': form.website_url.data, 'fasisprivate': form.is_private.data, 'faspronoun': form.pronouns.data, }, ".user_settings_profile", ) if result: return result return render_template('user-settings-profile.html', user=user, form=form, activetab="profile")
def user_settings_agreements(ipa, username): user = User(user_or_404(ipa, username)) agreements = [ Agreement(a) for a in ipa.fasagreement_find(all=False, ipaenabledflag=True) ] form = UserSettingsAgreementSign() if form.validate_on_submit(): agreement_name = form.agreement.data if agreement_name not in [a.name for a in agreements]: flash(_("Unknown agreement: %(name)s.", name=agreement_name), "warning") return redirect( url_for('.user_settings_agreements', username=username)) try: ipa.fasagreement_add_user(agreement_name, user=user.username) except python_freeipa.exceptions.BadRequest as e: current_app.logger.error( f"Cannot sign the agreement {agreement_name!r}: {e}") flash( _( 'Cannot sign the agreement "%(name)s": %(error)s', name=agreement_name, error=e, ), 'danger', ) else: flash( _('You signed the "%(name)s" agreement.', name=agreement_name), "success", ) return redirect(url_for('.user_settings_agreements', username=username)) return render_template( 'user-settings-agreements.html', user=user, activetab="agreements", agreementslist=agreements, raw=ipa.fasagreement_find(all=True), )
def user_settings_password(ipa, username): user = User(user_or_404(ipa, username)) form = PasswordResetForm() # check if an OTP token exists. If so, the user is using OTP. using_otp = bool(ipa.otptoken_find(o_ipatokenowner=username)["result"]) if not using_otp: form.current_password.description = "" if form.validate_on_submit(): res = _validate_change_pw_form(form, username, ipa) if res and res.ok: return redirect(url_for('.root')) return render_template( 'user-settings-password.html', user=user, password_reset_form=form, activetab="password", using_otp=using_otp, )
def user(ipa, username): user = User(user_or_404(ipa, username)) # As a speed optimization, we make two separate calls. # Just doing a group_find (with all=True) is super slow here, with a lot of # groups. batch_methods = [{ "method": "group_show", "params": [[name], { "no_members": True }] } for name in user.groups] # Don't call remote batch method with an empty list if batch_methods: member_groups = [ Group(g["result"]) for g in ipa.batch(batch_methods)["results"] if g["result"].get("fasgroup", False) ] else: member_groups = [] managed_groups = [ Group(group) for group in ipa.group_find(o_membermanager_user=username, o_all=False, fasgroup=True)['result'] ] groups = sorted(list(set(managed_groups + member_groups)), key=lambda g: g.name) # Privacy setting if user != g.current_user and user.is_private: user.anonymize() return render_template( 'user.html', user=user, groups=groups, managed_groups=managed_groups, member_groups=member_groups, )
def user(ipa, username): user = User(user_or_404(ipa, username)) # As a speed optimization, we make two separate calls. # Just doing a group_find (with all=True) is super slow here, with a lot of # groups. member_groups = [ Group(g) for g in ipa.group_find( o_user=username, o_all=False, fasgroup=True)['result'] ] managed_groups = [ Group(g) for g in ipa.group_find(o_membermanager_user=username, o_all=False, fasgroup=True)['result'] ] groups = [g for g in managed_groups if g not in member_groups ] + member_groups return render_template( 'user.html', user=user, groups=groups, managed_groups=managed_groups, member_groups=member_groups, )
def test_user_or_404_unknown(client, logged_in_dummy_user): """Test the user_or_404 method on an unknown user""" with pytest.raises(NotFound): user_or_404(logged_in_dummy_user, "unknown")
def test_user_or_404(client, logged_in_dummy_user): """Test the user_or_404 method""" result = user_or_404(logged_in_dummy_user, "dummy") assert result is not None assert result['uid'] == ['dummy']
def user_settings_otp(ipa, username): addotpform = UserSettingsAddOTPForm(prefix="add-") confirmotpform = UserSettingsConfirmOTPForm(prefix="confirm-") user = User(user_or_404(ipa, username)) secret = None if addotpform.validate_on_submit(): description = addotpform.description.data password = addotpform.password.data if addotpform.otp.data: password += addotpform.otp.data try: maybe_ipa_login(current_app, session, username, password) except python_freeipa.exceptions.InvalidSessionPassword: addotpform.password.errors.append(_("Incorrect password")) else: secret = b32encode(os.urandom(OTP_KEY_LENGTH)).decode('ascii') # Prefill the form for the next step confirmotpform.process( MultiDict({ "confirm-secret": secret, "confirm-description": description })) if confirmotpform.validate_on_submit(): try: ipa.otptoken_add( o_ipatokenowner=username, o_description=confirmotpform.description.data, o_ipatokenotpkey=confirmotpform.secret.data, ) except python_freeipa.exceptions.FreeIPAError as e: current_app.logger.error( f'An error happened while creating an OTP token for user {username}: {e.message}' ) confirmotpform.non_field_errors.errors.append( _('Cannot create the token.')) else: flash(_('The token has been created.'), "success") return redirect(url_for('.user_settings_otp', username=username)) if confirmotpform.is_submitted(): # This form is inside the modal. Keep a value in otp_uri or the modal will not open # to show the errors. secret = confirmotpform.secret.data # Compute the token URI if secret: description = addotpform.description.data or confirmotpform.description.data token = TOTP(secret) otp_uri = token.provisioning_uri(name=description, issuer_name=user.krbname) else: otp_uri = None # List existing tokens tokens = [ OTPToken(t) for t in ipa.otptoken_find(o_ipatokenowner=username)["result"] ] tokens.sort(key=lambda t: t.description or "") return render_template( 'user-settings-otp.html', addotpform=addotpform, confirmotpform=confirmotpform, user=user, activetab="otp", tokens=tokens, otp_uri=otp_uri, )