mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-22 09:11:04 +02:00
modified userportfoliopermissions and portfolioinvitation admin forms
This commit is contained in:
parent
260d2e587f
commit
3434519a16
7 changed files with 167 additions and 65 deletions
|
@ -192,7 +192,16 @@ class MyUserAdminForm(UserChangeForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UserPortfolioPermissionsForm(forms.ModelForm):
|
class PortfolioPermissionsForm(forms.ModelForm):
|
||||||
|
"""
|
||||||
|
Form for managing portfolio permissions in Django admin. This form class is used
|
||||||
|
for both UserPortfolioPermission and PortfolioInvitation models.
|
||||||
|
|
||||||
|
Allows selecting a portfolio, assigning a role, and managing specific permissions
|
||||||
|
related to requests, domains, and members.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Define available permissions for requests, domains, and members
|
||||||
REQUEST_PERMISSIONS = [
|
REQUEST_PERMISSIONS = [
|
||||||
UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS,
|
UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS,
|
||||||
UserPortfolioPermissionChoices.EDIT_REQUESTS,
|
UserPortfolioPermissionChoices.EDIT_REQUESTS,
|
||||||
|
@ -207,111 +216,134 @@ class UserPortfolioPermissionsForm(forms.ModelForm):
|
||||||
UserPortfolioPermissionChoices.VIEW_MEMBERS,
|
UserPortfolioPermissionChoices.VIEW_MEMBERS,
|
||||||
]
|
]
|
||||||
|
|
||||||
user = forms.ModelChoiceField(
|
# Dropdown to select a portfolio
|
||||||
queryset=models.User.objects.all(),
|
portfolio = forms.ModelChoiceField(queryset=models.Portfolio.objects.all(), label="Portfolio")
|
||||||
label="User"
|
|
||||||
)
|
|
||||||
|
|
||||||
portfolio = forms.ModelChoiceField(
|
|
||||||
queryset=models.Portfolio.objects.all(),
|
|
||||||
label="Portfolio"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
# Dropdown for selecting the user role (e.g., Admin or Basic)
|
||||||
role = forms.ChoiceField(
|
role = forms.ChoiceField(
|
||||||
choices=UserPortfolioRoleChoices.choices,
|
choices=UserPortfolioRoleChoices.choices,
|
||||||
required=True,
|
required=True,
|
||||||
widget=forms.Select(attrs={"class": "admin-dropdown"}),
|
widget=forms.Select(attrs={"class": "admin-dropdown"}),
|
||||||
label="Member access"
|
label="Member access",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Dropdown for selecting request permissions, with a default "No access" option
|
||||||
request_permissions = forms.ChoiceField(
|
request_permissions = forms.ChoiceField(
|
||||||
choices=[(perm.value, perm.label) for perm in REQUEST_PERMISSIONS],
|
choices=[(None, "No access")] + [(perm.value, perm.label) for perm in REQUEST_PERMISSIONS],
|
||||||
required=False,
|
required=False,
|
||||||
widget=forms.Select(attrs={"class": "admin-dropdown"}),
|
widget=forms.Select(attrs={"class": "admin-dropdown"}),
|
||||||
label="Domain requests"
|
label="Domain requests",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Dropdown for selecting domain permissions
|
||||||
domain_permissions = forms.ChoiceField(
|
domain_permissions = forms.ChoiceField(
|
||||||
choices=[(perm.value, perm.label) for perm in DOMAIN_PERMISSIONS],
|
choices=[(perm.value, perm.label) for perm in DOMAIN_PERMISSIONS],
|
||||||
required=False,
|
required=False,
|
||||||
widget=forms.Select(attrs={"class": "admin-dropdown"}),
|
widget=forms.Select(attrs={"class": "admin-dropdown"}),
|
||||||
label="Domains"
|
label="Domains",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Dropdown for selecting member permissions, with a default "No access" option
|
||||||
member_permissions = forms.ChoiceField(
|
member_permissions = forms.ChoiceField(
|
||||||
choices=[(perm.value, perm.label) for perm in MEMBER_PERMISSIONS],
|
choices=[(None, "No access")] + [(perm.value, perm.label) for perm in MEMBER_PERMISSIONS],
|
||||||
required=False,
|
required=False,
|
||||||
widget=forms.Select(attrs={"class": "admin-dropdown"}),
|
widget=forms.Select(attrs={"class": "admin-dropdown"}),
|
||||||
label="Members"
|
label="Members",
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = models.UserPortfolioPermission
|
|
||||||
fields = ["user", "portfolio", "role", "domain_permissions", "request_permissions", "member_permissions"]
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Initialize the form and set default values based on the existing instance.
|
||||||
|
"""
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
logger.debug("Initializing form")
|
# If an instance exists, populate the form fields with existing data
|
||||||
|
|
||||||
# Populate roles
|
|
||||||
if self.instance and self.instance.pk:
|
if self.instance and self.instance.pk:
|
||||||
|
# Set the initial value for the role field
|
||||||
if self.instance.roles:
|
if self.instance.roles:
|
||||||
logger.debug(f"Setting role: {self.instance.roles[0]}")
|
self.fields["role"].initial = self.instance.roles[0] # Assuming a single role per user
|
||||||
self.fields["role"].initial = self.instance.roles[0] # Assuming single role per user
|
|
||||||
|
|
||||||
|
# Set the initial values for permissions based on the instance data
|
||||||
if self.instance.additional_permissions:
|
if self.instance.additional_permissions:
|
||||||
logger.debug(f"Existing permissions: {self.instance.additional_permissions}")
|
|
||||||
for perm in self.instance.additional_permissions:
|
for perm in self.instance.additional_permissions:
|
||||||
logger.debug(f"Processing permission: {perm}")
|
|
||||||
if perm in self.REQUEST_PERMISSIONS:
|
if perm in self.REQUEST_PERMISSIONS:
|
||||||
logger.debug("Assigning request permission")
|
|
||||||
self.fields["request_permissions"].initial = perm
|
self.fields["request_permissions"].initial = perm
|
||||||
elif perm in self.DOMAIN_PERMISSIONS:
|
elif perm in self.DOMAIN_PERMISSIONS:
|
||||||
logger.debug("Assigning domain permission")
|
|
||||||
self.fields["domain_permissions"].initial = perm
|
self.fields["domain_permissions"].initial = perm
|
||||||
elif perm in self.MEMBER_PERMISSIONS:
|
elif perm in self.MEMBER_PERMISSIONS:
|
||||||
logger.debug("Assigning member permission")
|
|
||||||
self.fields["member_permissions"].initial = perm
|
self.fields["member_permissions"].initial = perm
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
"""
|
||||||
|
Custom validation and processing of form data before saving.
|
||||||
|
"""
|
||||||
cleaned_data = super().clean()
|
cleaned_data = super().clean()
|
||||||
|
|
||||||
|
# Store the selected role as a list (assuming single role assignment)
|
||||||
self.instance.roles = [cleaned_data.get("role")] if cleaned_data.get("role") else []
|
self.instance.roles = [cleaned_data.get("role")] if cleaned_data.get("role") else []
|
||||||
logger.debug(f"Cleaned roles: {self.instance.roles}")
|
|
||||||
|
|
||||||
|
# If the selected role is "organization_member," store additional permissions
|
||||||
if self.instance.roles == [UserPortfolioRoleChoices.ORGANIZATION_MEMBER]:
|
if self.instance.roles == [UserPortfolioRoleChoices.ORGANIZATION_MEMBER]:
|
||||||
self.instance.additional_permissions = list(
|
self.instance.additional_permissions = list(
|
||||||
filter(None, [
|
filter(
|
||||||
cleaned_data.get("request_permissions"),
|
None,
|
||||||
cleaned_data.get("domain_permissions"),
|
[
|
||||||
cleaned_data.get("member_permissions"),
|
cleaned_data.get("request_permissions"),
|
||||||
])
|
cleaned_data.get("domain_permissions"),
|
||||||
|
cleaned_data.get("member_permissions"),
|
||||||
|
],
|
||||||
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
# If the user is an admin, clear any additional permissions
|
||||||
self.instance.additional_permissions = []
|
self.instance.additional_permissions = []
|
||||||
|
|
||||||
logger.debug(f"Final saved permissions: {self.instance.additional_permissions}")
|
|
||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
|
||||||
class PortfolioInvitationAdminForm(UserChangeForm):
|
class UserPortfolioPermissionsForm(PortfolioPermissionsForm):
|
||||||
"""This form utilizes the custom widget for its class's ManyToMany UIs."""
|
"""
|
||||||
|
Form for managing user portfolio permissions in Django admin.
|
||||||
|
|
||||||
|
Extends PortfolioPermissionsForm to include a user field, allowing administrators
|
||||||
|
to assign roles and permissions to specific users within a portfolio.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Dropdown to select a user from the database
|
||||||
|
user = forms.ModelChoiceField(queryset=models.User.objects.all(), label="User")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.PortfolioInvitation
|
"""
|
||||||
fields = "__all__"
|
Meta class defining the model and fields to be used in the form.
|
||||||
widgets = {
|
"""
|
||||||
"roles": FilteredSelectMultipleArrayWidget(
|
|
||||||
"roles", is_stacked=False, choices=UserPortfolioRoleChoices.choices
|
model = models.UserPortfolioPermission # Uses the UserPortfolioPermission model
|
||||||
),
|
fields = ["user", "portfolio", "role", "domain_permissions", "request_permissions", "member_permissions"]
|
||||||
"additional_permissions": FilteredSelectMultipleArrayWidget(
|
|
||||||
"additional_permissions",
|
|
||||||
is_stacked=False,
|
class PortfolioInvitationForm(PortfolioPermissionsForm):
|
||||||
choices=UserPortfolioPermissionChoices.choices,
|
"""
|
||||||
),
|
Form for sending portfolio invitations in Django admin.
|
||||||
}
|
|
||||||
|
Extends PortfolioPermissionsForm to include an email field for inviting users,
|
||||||
|
allowing them to be assigned a role and permissions within a portfolio before they join.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""
|
||||||
|
Meta class defining the model and fields to be used in the form.
|
||||||
|
"""
|
||||||
|
|
||||||
|
model = models.PortfolioInvitation # Uses the PortfolioInvitation model
|
||||||
|
fields = [
|
||||||
|
"email",
|
||||||
|
"portfolio",
|
||||||
|
"role",
|
||||||
|
"domain_permissions",
|
||||||
|
"request_permissions",
|
||||||
|
"member_permissions",
|
||||||
|
"status",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class DomainInformationAdminForm(forms.ModelForm):
|
class DomainInformationAdminForm(forms.ModelForm):
|
||||||
|
@ -1721,7 +1753,7 @@ class DomainInvitationAdmin(BaseInvitationAdmin):
|
||||||
class PortfolioInvitationAdmin(BaseInvitationAdmin):
|
class PortfolioInvitationAdmin(BaseInvitationAdmin):
|
||||||
"""Custom portfolio invitation admin class."""
|
"""Custom portfolio invitation admin class."""
|
||||||
|
|
||||||
form = PortfolioInvitationAdminForm
|
form = PortfolioInvitationForm
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.PortfolioInvitation
|
model = models.PortfolioInvitation
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
initDynamicDomainRequestFields } from './domain-request-form.js';
|
initDynamicDomainRequestFields } from './domain-request-form.js';
|
||||||
import { initDomainFormTargetBlankButtons } from './domain-form.js';
|
import { initDomainFormTargetBlankButtons } from './domain-form.js';
|
||||||
import { initDynamicPortfolioFields } from './portfolio-form.js';
|
import { initDynamicPortfolioFields } from './portfolio-form.js';
|
||||||
|
import { initDynamicPortfolioPermissionFields } from './portfolio-permissions-form.js'
|
||||||
import { initDynamicDomainInformationFields } from './domain-information-form.js';
|
import { initDynamicDomainInformationFields } from './domain-information-form.js';
|
||||||
import { initDynamicDomainFields } from './domain-form.js';
|
import { initDynamicDomainFields } from './domain-form.js';
|
||||||
import { initAnalyticsDashboard } from './analytics.js';
|
import { initAnalyticsDashboard } from './analytics.js';
|
||||||
|
@ -40,6 +41,9 @@ initDynamicDomainFields();
|
||||||
// Portfolio
|
// Portfolio
|
||||||
initDynamicPortfolioFields();
|
initDynamicPortfolioFields();
|
||||||
|
|
||||||
|
// Portfolio permissions
|
||||||
|
initDynamicPortfolioPermissionFields();
|
||||||
|
|
||||||
// Domain information
|
// Domain information
|
||||||
initDynamicDomainInformationFields();
|
initDynamicDomainInformationFields();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { hideElement, showElement } from './helpers-admin.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function for dynamically changing fields on the UserPortfolioPermissions
|
||||||
|
* and PortfolioInvitation admin forms
|
||||||
|
*/
|
||||||
|
function handlePortfolioPermissionFields(){
|
||||||
|
|
||||||
|
const roleDropdown = document.getElementById("id_role");
|
||||||
|
const domainPermissionsField = document.querySelector(".field-domain_permissions");
|
||||||
|
const domainRequestPermissionsField = document.querySelector(".field-request_permissions");
|
||||||
|
const memberPermissionsField = document.querySelector(".field-member_permissions");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the visibility of portfolio permissions fields based on the selected role.
|
||||||
|
*
|
||||||
|
* This function checks the value of the role dropdown (`roleDropdown`):
|
||||||
|
* - If the selected role is "organization_admin":
|
||||||
|
* - Hides the domain permissions field (`domainPermissionsField`).
|
||||||
|
* - Hides the domain request permissions field (`domainRequestPermissionsField`).
|
||||||
|
* - Hides the member permissions field (`memberPermissionsField`).
|
||||||
|
* - Otherwise:
|
||||||
|
* - Shows all the above fields.
|
||||||
|
*
|
||||||
|
* The function ensures that the appropriate fields are dynamically displayed
|
||||||
|
* or hidden depending on the role selection in the form.
|
||||||
|
*/
|
||||||
|
function updatePortfolioPermissionsFormVisibility() {
|
||||||
|
if (roleDropdown && domainPermissionsField && domainRequestPermissionsField && memberPermissionsField) {
|
||||||
|
if (roleDropdown.value === "organization_admin") {
|
||||||
|
hideElement(domainPermissionsField);
|
||||||
|
hideElement(domainRequestPermissionsField);
|
||||||
|
hideElement(memberPermissionsField);
|
||||||
|
} else {
|
||||||
|
showElement(domainPermissionsField);
|
||||||
|
showElement(domainRequestPermissionsField);
|
||||||
|
showElement(memberPermissionsField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets event listeners for key UI elements.
|
||||||
|
*/
|
||||||
|
function setEventListeners() {
|
||||||
|
if (roleDropdown) {
|
||||||
|
roleDropdown.addEventListener("change", function() {
|
||||||
|
updatePortfolioPermissionsFormVisibility();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run initial setup functions
|
||||||
|
updatePortfolioPermissionsFormVisibility();
|
||||||
|
setEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initDynamicPortfolioPermissionFields() {
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
let isPortfolioPermissionPage = document.getElementById("userportfoliopermission_form");
|
||||||
|
let isPortfolioInvitationPage = document.getElementById("portfolioinvitation_form")
|
||||||
|
if (isPortfolioPermissionPage || isPortfolioInvitationPage) {
|
||||||
|
handlePortfolioPermissionFields();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
""""
|
"""
|
||||||
Converts all ready and DNS needed domains with a non-default public contact
|
Converts all ready and DNS needed domains with a non-default public contact
|
||||||
to disclose their public contact. Created for Issue#1535 to resolve
|
to disclose their public contact. Created for Issue#1535 to resolve
|
||||||
disclose issue of domains with missing security emails.
|
disclose issue of domains with missing security emails.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
"""Data migration:
|
"""Data migration:
|
||||||
1 - generates a report of data integrity across all
|
1 - generates a report of data integrity across all
|
||||||
transition domain related tables
|
transition domain related tables
|
||||||
2 - allows users to run all migration scripts for
|
2 - allows users to run all migration scripts for
|
||||||
transition domain data
|
transition domain data
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
""""
|
"""
|
||||||
Data migration: Renaming deprecated Federal Agencies to
|
Data migration: Renaming deprecated Federal Agencies to
|
||||||
their new updated names ie (U.S. Peace Corps to Peace Corps)
|
their new updated names ie (U.S. Peace Corps to Peace Corps)
|
||||||
within Domain Information and Domain Requests
|
within Domain Information and Domain Requests
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
"""Views for a User Profile.
|
"""Views for a User Profile."""
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue