-
-
Notifications
You must be signed in to change notification settings - Fork 218
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
Allow WebUser invites to be editable before the invited user accepts it #35538
Changes from 7 commits
4a73e0c
a13bfba
71b8fc6
c1f1b8e
2471e5b
ff8a2db
5029d11
dbb5e96
f297dd2
de3df56
1ef0d0e
1bee3fc
64a805f
44696ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -494,8 +494,9 @@ class AdminInvitesUserForm(SelectUserLocationForm): | |
|
||
def __init__(self, data=None, is_add_user=None, | ||
role_choices=(), should_show_location=False, can_edit_tableau_config=False, | ||
custom_data=None, *, domain, **kwargs): | ||
custom_data=None, invitation=None, *, domain, **kwargs): | ||
self.custom_data = custom_data | ||
self.invite = invitation | ||
if data and self.custom_data: | ||
data = data.copy() | ||
custom_data_post_dict = self.custom_data.form.data | ||
|
@@ -519,16 +520,24 @@ def __init__(self, data=None, is_add_user=None, | |
programs = Program.by_domain(domain_obj.name) | ||
choices = [('', '')] + list((prog.get_id, prog.name) for prog in programs) | ||
self.fields['program'].choices = choices | ||
if self.invite: | ||
self.fields['program'].initial = self.invite.program | ||
|
||
if self.can_edit_tableau_config: | ||
self._initialize_tableau_fields(data, domain) | ||
self._initialize_tableau_fields(data, domain, self.invite) | ||
|
||
self.helper = FormHelper() | ||
self.helper.form_method = 'POST' | ||
self.helper.form_class = 'form-horizontal form-ko-validation' | ||
|
||
self.helper.label_class = 'col-sm-3 col-md-2' | ||
self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6' | ||
|
||
save_button_text = "Send Invite" | ||
if self.invite: | ||
self.fields['email'].widget.attrs["readonly"] = True | ||
save_button_text = "Update Invite" | ||
|
||
fields = [ | ||
crispy.Fieldset( | ||
gettext("Information for new Web User"), | ||
|
@@ -575,8 +584,7 @@ def __init__(self, data=None, is_add_user=None, | |
), | ||
hqcrispy.FormActions( | ||
twbscrispy.StrictButton( | ||
(gettext("Add User") if is_add_user | ||
else gettext("Send Invite")), | ||
(gettext("Add User") if is_add_user else gettext(save_button_text)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. passing a variable to |
||
type="submit", | ||
css_class="btn-primary", | ||
data_bind="enable: isSubmitEnabled", | ||
|
@@ -594,7 +602,7 @@ def clean_email(self): | |
email = self.cleaned_data['email'].strip() | ||
|
||
from corehq.apps.registration.validation import AdminInvitesUserFormValidator | ||
error = AdminInvitesUserFormValidator.validate_email(self.domain, email) | ||
error = AdminInvitesUserFormValidator.validate_email(self.domain, email, bool(self.invite)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it make sense to skip all this validation if the field is set as read only? And then add a validation that the email didn't change like
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think what I have currently is simpler |
||
if error: | ||
raise forms.ValidationError(error) | ||
return email | ||
|
@@ -632,8 +640,14 @@ def clean(self): | |
raise forms.ValidationError(error) | ||
return cleaned_data | ||
|
||
def _initialize_tableau_fields(self, data, domain): | ||
self.tableau_form = BaseTableauUserForm(data, domain=domain) | ||
def _initialize_tableau_fields(self, data, domain, invitation=None): | ||
Jtang-1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
initial = {} | ||
if invitation: | ||
initial = { | ||
minhaminha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'tableau_role': invitation.tableau_role, | ||
'tableau_group_indices': invitation.tableau_group_ids, | ||
} | ||
self.tableau_form = BaseTableauUserForm(data, domain=domain, initial=initial) | ||
self.fields['tableau_group_indices'] = self.tableau_form.fields["groups"] | ||
self.fields['tableau_group_indices'].label = _('Tableau Groups') | ||
self.fields['tableau_role'] = self.tableau_form.fields['role'] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1140,9 +1140,23 @@ def invite_web_user_form(self): | |
role_choices = get_editable_role_choices(self.domain, self.request.couch_user, allow_admin_role=True) | ||
domain_request = DomainRequest.objects.get(id=self.request_id) if self.request_id else None | ||
is_add_user = self.request_id is not None | ||
initial = { | ||
'email': domain_request.email if domain_request else None, | ||
} | ||
invitation = self.invitation | ||
if invitation: | ||
assigned_location = invitation.assigned_locations.filter() | ||
assigned_location_ids = [loc.location_id for loc in assigned_location] | ||
Jtang-1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
primary_location_id = None | ||
if assigned_location_ids: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this check |
||
primary_location_id = invitation.primary_location.location_id | ||
initial = { | ||
'email': invitation.email, | ||
'role': invitation.role, | ||
'assigned_locations': assigned_location_ids, | ||
'primary_location': primary_location_id, | ||
} | ||
else: | ||
initial = { | ||
'email': domain_request.email if domain_request else None, | ||
} | ||
can_edit_tableau_config = (self.request.couch_user.has_permission(self.domain, 'edit_user_tableau_config') | ||
and toggles.TABLEAU_USER_SYNCING.enabled(self.domain)) | ||
if self.request.method == 'POST': | ||
|
@@ -1154,7 +1168,8 @@ def invite_web_user_form(self): | |
should_show_location=self.request.project.uses_locations, | ||
can_edit_tableau_config=can_edit_tableau_config, | ||
request=self.request, | ||
custom_data=self.custom_data | ||
custom_data=self.custom_data, | ||
invitation=invitation | ||
) | ||
return AdminInvitesUserForm( | ||
initial=initial, | ||
|
@@ -1164,7 +1179,8 @@ def invite_web_user_form(self): | |
should_show_location=self.request.project.uses_locations, | ||
can_edit_tableau_config=can_edit_tableau_config, | ||
request=self.request, | ||
custom_data=self.custom_data | ||
custom_data=self.custom_data, | ||
invitation=invitation | ||
) | ||
|
||
@cached_property | ||
|
@@ -1194,7 +1210,7 @@ def page_context(self): | |
ctx = { | ||
'registration_form': self.invite_web_user_form, | ||
**self.custom_data.field_view.get_field_page_context( | ||
self.domain, self.request.couch_user, self.custom_data, None | ||
self.domain, self.request.couch_user, self.custom_data, None, self.invitation | ||
) | ||
} | ||
return ctx | ||
|
@@ -1204,6 +1220,14 @@ def _assert_user_has_permission_to_access_locations(self, assigned_location_ids) | |
self.domain, self.request.couch_user).values_list('location_id', flat=True))): | ||
raise Http404() | ||
|
||
@property | ||
def invitation(self): | ||
invitation_id = self.kwargs.get("invitation_id") | ||
try: | ||
return Invitation.objects.get(uuid=invitation_id) | ||
except Invitation.DoesNotExist: | ||
return None | ||
|
||
def post(self, request, *args, **kwargs): | ||
if self.invite_web_user_form.is_valid(): | ||
# If user exists and has already requested access, just add them to the project | ||
|
@@ -1215,7 +1239,22 @@ def post(self, request, *args, **kwargs): | |
profile = CustomDataFieldsProfile.objects.get( | ||
id=profile_id, | ||
definition__domain=self.domain) if profile_id else None | ||
if domain_request is not None: | ||
invitation = self.invitation | ||
if invitation: | ||
create_invitation = False | ||
invitation.profile = profile | ||
invitation.primary_location, assigned_locations = self.get_sql_locations( | ||
data.pop("primary_location", None), data.pop("assigned_locations", [])) | ||
invitation.assigned_locations.set(assigned_locations) | ||
invitation.custom_user_data = data.get("custom_user_data", {}) | ||
|
||
invitation.role = data.get("role", None) | ||
Jtang-1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
invitation.program = data.get("program", None) | ||
invitation.tableau_role = data.get("tableau_role", None) | ||
invitation.tableau_group_ids = data.get("tableau_group_ids", None) | ||
invitation.save() | ||
messages.success(request, "Invite to %s was successfully updated." % data["email"]) | ||
Jtang-1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
elif domain_request is not None: | ||
domain_request.is_approved = True | ||
domain_request.save() | ||
user = CouchUser.get_by_username(domain_request.email) | ||
|
@@ -1243,20 +1282,11 @@ def post(self, request, *args, **kwargs): | |
data["invited_by"] = request.couch_user.user_id | ||
data["invited_on"] = datetime.utcnow() | ||
data["domain"] = self.domain | ||
primary_location_id = data.pop("primary_location", None) | ||
data["primary_location"] = (SQLLocation.by_location_id(primary_location_id) | ||
if primary_location_id else None) | ||
assigned_location_ids = data.pop("assigned_locations", []) | ||
if primary_location_id: | ||
assert primary_location_id in assigned_location_ids | ||
self._assert_user_has_permission_to_access_locations(assigned_location_ids) | ||
data["profile"] = profile | ||
data["primary_location"], assigned_locations = self.get_sql_locations( | ||
data.pop("primary_location", None), data.pop("assigned_locations", [])) | ||
invite = Invitation(**data) | ||
invite.save() | ||
|
||
assigned_locations = [SQLLocation.by_location_id(assigned_location_id) | ||
for assigned_location_id in assigned_location_ids | ||
if assigned_location_id is not None] | ||
invite.assigned_locations.set(assigned_locations) | ||
invite.send_activation_email() | ||
|
||
|
@@ -1271,6 +1301,16 @@ def post(self, request, *args, **kwargs): | |
)) | ||
return self.get(request, *args, **kwargs) | ||
|
||
def get_sql_locations(self, primary_location_id, assigned_location_ids): | ||
Jtang-1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
primary_location = (SQLLocation.by_location_id(primary_location_id) if primary_location_id else None) | ||
if primary_location_id: | ||
assert primary_location_id in assigned_location_ids | ||
self._assert_user_has_permission_to_access_locations(assigned_location_ids) | ||
assigned_locations = [SQLLocation.by_location_id(assigned_location_id) | ||
for assigned_location_id in assigned_location_ids | ||
if assigned_location_id is not None] | ||
return primary_location, assigned_locations | ||
|
||
|
||
class BaseUploadUser(BaseUserSettingsView): | ||
def post(self, request, *args, **kwargs): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this and the alternate text should be marked for translation