Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Custom Data to Web User Invite #35124

Merged
merged 17 commits into from
Oct 7, 2024
Merged

Conversation

Jtang-1
Copy link
Contributor

@Jtang-1 Jtang-1 commented Sep 13, 2024

Product Description

Allows the user to define "user data" when creating a web user invite.

Screen Shot 2024-09-13 at 3 10 12 PM

Technical Summary

USH-4895
Editing custom user data uses the CustomDataEditor class which generates the profile and user data fields for CustomDataForm. The need here is very similar from the form UI side. However, it does not require populating existing user data.

In order to reuse the CustomDataForm, I initialized an instance of CustomDataEditor which initializes the form. Then this instance of CustomDataEditor is injected into AdminInvitesUserForm. The fields and fieldsets created as part of CustomDataForm is then pulled out to create the field and fieldsets for AdminInvitesUserForm. One issue faced is that CustomDataForm applies a form level defined prefix for each field but this prefix is applied only upon rendering the form. But since we are not using that form directly and are only extracting the fields, adding the prefix needs to be manually handled in AdminInvitesUserForm.

Additionally, when a user data field is defined and populated by the profile, the field is disabled. Because of this, posted data will not include data for this field. CustomDataForm already handles that and adds profile related fields to the post data. AdminInvitesUserForm takes advantage of that by accessing post data via self.custom_data.form.data.

Feature Flag

New feature flag: WEB_USER_INVITE_ADDITIONAL_FIELDS

Safety Assurance

Safety story

Locally tested and both backend and frontend changes are gated behind a FF which limits the blast radius.

Automated test coverage

No automated test

QA Plan

QA-7109

Rollback instructions

  • This PR can be reverted after deploy with no further considerations

Labels & Review

  • Risk label is set correctly
  • The set of people pinged as reviewers is appropriate for the level of risk of the change

@dimagimon dimagimon added Risk: High Change affects files that have been flagged as high risk. Risk: Medium Change affects files that have been flagged as medium risk. labels Sep 13, 2024
@Jtang-1 Jtang-1 force-pushed the jt/add-custom-data-web-user-invite branch from 58d6529 to e0fc01e Compare September 13, 2024 22:30
@Jtang-1 Jtang-1 added the awaiting QA QA in progress. Do not merge label Sep 13, 2024
@Jtang-1 Jtang-1 requested review from a team, MartinRiese, minhaminha and Robert-Costello and removed request for a team September 13, 2024 23:52
@Jtang-1 Jtang-1 marked this pull request as ready for review September 14, 2024 00:11
@@ -2528,6 +2528,13 @@ def _commtrackify(domain_name, toggle_is_enabled):
namespaces=[NAMESPACE_DOMAIN]
)

WEB_USER_INVITE_ADDITIONAL_FIELDS = StaticToggle(
'web_user_invite_additional_fields',
'Enable additional fields in web user invite form for enhanced user details',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this have a "USH:" in front or is the automatically GAed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it should 63273ea

if assigned_location_ids is None:
assigned_location_ids = []
if custom_user_data is None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed? It seems like the check on line 572 would take care of this and I don's see custom_user_data used anywhere else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, that's not needed. 8405864

Copy link
Contributor

@minhaminha minhaminha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May have to read through again but looks good so far.

self.request = kwargs.get('request')
super(AdminInvitesUserForm, self).__init__(domain=domain, data=data, **kwargs)
self.can_edit_tableau_config = can_edit_tableau_config
domain_obj = Domain.get_by_name(domain)
self.fields['role'].choices = [('', _("Select a role"))] + role_choices
if domain_obj:
if domain_has_privilege(domain_obj.name, privileges.APP_USER_PROFILES):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be missing something but why is this FF not being used anymore? Is it effectively putting all this behind the new flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should still be behind the domain privilege check, but it's now done from the CustomDataEditor form here If that conditional is false, then the profile field here won't be added to the fields meaning that self.custom_data.form.fields will also not contain the profile field.

if domain_has_privilege(domain_obj.name, privileges.APP_USER_PROFILES) and profile:
user_data = self.get_user_data(domain_obj.name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does still require the domain privilege check for profiles and I believe it does do the check. Or maybe i'm misunderstanding your comment

… needs to be manually removed for conditional check
… the prefix within the name

as defined by the user
@Jtang-1 Jtang-1 added QA Passed and removed awaiting QA QA in progress. Do not merge labels Oct 2, 2024
@Jtang-1
Copy link
Contributor Author

Jtang-1 commented Oct 2, 2024

bump for review

@@ -584,13 +584,12 @@ def __init__(self, data=None, excluded_emails=None, is_add_user=None,
),
)

def clean_profile(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this not used anywhere else? I don't see any renaming where it is called.

Copy link
Contributor Author

@Jtang-1 Jtang-1 Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clean_<fieldname>() method is a hook for performing custom validation or any cleaning that is specific to that particular attribute on a specific field in a Django form. Here, the field containing the profile will actually have the field name <prefix>_profile so clean_profile won't work. So I moved the cleaning to the general clean() and handle it via _validate_profile()

@Jtang-1 Jtang-1 merged commit 1af7a8f into master Oct 7, 2024
11 of 13 checks passed
@Jtang-1 Jtang-1 deleted the jt/add-custom-data-web-user-invite branch October 7, 2024 14:05
@Jtang-1 Jtang-1 restored the jt/add-custom-data-web-user-invite branch October 10, 2024 21:25
@Jtang-1 Jtang-1 deleted the jt/add-custom-data-web-user-invite branch October 10, 2024 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
QA Passed Risk: High Change affects files that have been flagged as high risk. Risk: Medium Change affects files that have been flagged as medium risk.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants