modified userportfoliopermissions and portfolioinvitation admin forms

This commit is contained in:
David Kennedy 2025-02-21 22:57:12 -05:00
parent 260d2e587f
commit 3434519a16
No known key found for this signature in database
GPG key ID: 6528A5386E66B96B
7 changed files with 167 additions and 65 deletions

View file

@ -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 = [
UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS,
UserPortfolioPermissionChoices.EDIT_REQUESTS,
@ -207,111 +216,134 @@ class UserPortfolioPermissionsForm(forms.ModelForm):
UserPortfolioPermissionChoices.VIEW_MEMBERS,
]
user = forms.ModelChoiceField(
queryset=models.User.objects.all(),
label="User"
)
portfolio = forms.ModelChoiceField(
queryset=models.Portfolio.objects.all(),
label="Portfolio"
)
# Dropdown to select a portfolio
portfolio = forms.ModelChoiceField(queryset=models.Portfolio.objects.all(), label="Portfolio")
# Dropdown for selecting the user role (e.g., Admin or Basic)
role = forms.ChoiceField(
choices=UserPortfolioRoleChoices.choices,
required=True,
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(
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,
widget=forms.Select(attrs={"class": "admin-dropdown"}),
label="Domain requests"
label="Domain requests",
)
# Dropdown for selecting domain permissions
domain_permissions = forms.ChoiceField(
choices=[(perm.value, perm.label) for perm in DOMAIN_PERMISSIONS],
required=False,
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(
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,
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):
"""
Initialize the form and set default values based on the existing instance.
"""
super().__init__(*args, **kwargs)
logger.debug("Initializing form")
# Populate roles
# If an instance exists, populate the form fields with existing data
if self.instance and self.instance.pk:
# Set the initial value for the role field
if self.instance.roles:
logger.debug(f"Setting role: {self.instance.roles[0]}")
self.fields["role"].initial = self.instance.roles[0] # Assuming single role per user
self.fields["role"].initial = self.instance.roles[0] # Assuming a single role per user
# Set the initial values for permissions based on the instance data
if self.instance.additional_permissions:
logger.debug(f"Existing permissions: {self.instance.additional_permissions}")
for perm in self.instance.additional_permissions:
logger.debug(f"Processing permission: {perm}")
if perm in self.REQUEST_PERMISSIONS:
logger.debug("Assigning request permission")
self.fields["request_permissions"].initial = perm
elif perm in self.DOMAIN_PERMISSIONS:
logger.debug("Assigning domain permission")
self.fields["domain_permissions"].initial = perm
elif perm in self.MEMBER_PERMISSIONS:
logger.debug("Assigning member permission")
self.fields["member_permissions"].initial = perm
def clean(self):
"""
Custom validation and processing of form data before saving.
"""
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 []
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]:
self.instance.additional_permissions = list(
filter(None, [
filter(
None,
[
cleaned_data.get("request_permissions"),
cleaned_data.get("domain_permissions"),
cleaned_data.get("member_permissions"),
])
],
)
)
else:
# If the user is an admin, clear any additional permissions
self.instance.additional_permissions = []
logger.debug(f"Final saved permissions: {self.instance.additional_permissions}")
return cleaned_data
class PortfolioInvitationAdminForm(UserChangeForm):
"""This form utilizes the custom widget for its class's ManyToMany UIs."""
class UserPortfolioPermissionsForm(PortfolioPermissionsForm):
"""
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:
model = models.PortfolioInvitation
fields = "__all__"
widgets = {
"roles": FilteredSelectMultipleArrayWidget(
"roles", is_stacked=False, choices=UserPortfolioRoleChoices.choices
),
"additional_permissions": FilteredSelectMultipleArrayWidget(
"additional_permissions",
is_stacked=False,
choices=UserPortfolioPermissionChoices.choices,
),
}
"""
Meta class defining the model and fields to be used in the form.
"""
model = models.UserPortfolioPermission # Uses the UserPortfolioPermission model
fields = ["user", "portfolio", "role", "domain_permissions", "request_permissions", "member_permissions"]
class PortfolioInvitationForm(PortfolioPermissionsForm):
"""
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):
@ -1721,7 +1753,7 @@ class DomainInvitationAdmin(BaseInvitationAdmin):
class PortfolioInvitationAdmin(BaseInvitationAdmin):
"""Custom portfolio invitation admin class."""
form = PortfolioInvitationAdminForm
form = PortfolioInvitationForm
class Meta:
model = models.PortfolioInvitation

View file

@ -13,6 +13,7 @@ import {
initDynamicDomainRequestFields } from './domain-request-form.js';
import { initDomainFormTargetBlankButtons } from './domain-form.js';
import { initDynamicPortfolioFields } from './portfolio-form.js';
import { initDynamicPortfolioPermissionFields } from './portfolio-permissions-form.js'
import { initDynamicDomainInformationFields } from './domain-information-form.js';
import { initDynamicDomainFields } from './domain-form.js';
import { initAnalyticsDashboard } from './analytics.js';
@ -40,6 +41,9 @@ initDynamicDomainFields();
// Portfolio
initDynamicPortfolioFields();
// Portfolio permissions
initDynamicPortfolioPermissionFields();
// Domain information
initDynamicDomainInformationFields();

View file

@ -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();
}
});
}

View file

@ -1,4 +1,4 @@
""""
"""
Converts all ready and DNS needed domains with a non-default public contact
to disclose their public contact. Created for Issue#1535 to resolve
disclose issue of domains with missing security emails.

View file

@ -1,8 +1,8 @@
"""Data migration:
1 - generates a report of data integrity across all
transition domain related tables
2 - allows users to run all migration scripts for
transition domain data
1 - generates a report of data integrity across all
transition domain related tables
2 - allows users to run all migration scripts for
transition domain data
"""
import logging

View file

@ -1,4 +1,4 @@
""""
"""
Data migration: Renaming deprecated Federal Agencies to
their new updated names ie (U.S. Peace Corps to Peace Corps)
within Domain Information and Domain Requests

View file

@ -1,5 +1,4 @@
"""Views for a User Profile.
"""
"""Views for a User Profile."""
import logging