Fix migrations + readonly views

This commit is contained in:
zandercymatics 2024-09-23 11:29:01 -06:00
parent afe498978c
commit 280bc23fa6
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
10 changed files with 118 additions and 13 deletions

View file

@ -1242,8 +1242,10 @@ class UserDomainRoleResource(resources.ModelResource):
model = models.UserDomainRole model = models.UserDomainRole
# Note: This is "viewonly" for analysts
class UserPortfolioPermissionAdmin(ListHeaderAdmin): class UserPortfolioPermissionAdmin(ListHeaderAdmin):
form = UserPortfolioPermissionsForm form = UserPortfolioPermissionsForm
change_form_template = "django/admin/user_portfolio_permission_change_form.html"
class Meta: class Meta:
"""Contains meta information about this class""" """Contains meta information about this class"""
@ -1261,6 +1263,14 @@ class UserPortfolioPermissionAdmin(ListHeaderAdmin):
autocomplete_fields = ["user", "portfolio"] autocomplete_fields = ["user", "portfolio"]
def change_view(self, request, object_id, form_url="", extra_context=None):
"""Adds a readonly display for roles and permissions"""
obj = self.get_object(request, object_id)
extra_context = extra_context or {}
extra_context["display_roles"] = ", ".join(obj.get_readable_roles())
extra_context["display_permissions"] = ", ".join(obj.get_readable_additional_permissions())
return super().change_view(request, object_id, form_url, extra_context)
class UserDomainRoleAdmin(ListHeaderAdmin, ImportExportModelAdmin): class UserDomainRoleAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"""Custom user domain role admin class.""" """Custom user domain role admin class."""
@ -2961,7 +2971,6 @@ class PortfolioAdmin(ListHeaderAdmin):
analyst_readonly_fields = [ analyst_readonly_fields = [
"organization_name", "organization_name",
"organization_type",
] ]
def get_readonly_fields(self, request, obj=None): def get_readonly_fields(self, request, obj=None):

View file

@ -858,11 +858,13 @@ function initializeWidgetOnList(list, parentId) {
// $ symbolically denotes that this is using jQuery // $ symbolically denotes that this is using jQuery
let $federalAgency = django.jQuery("#id_federal_agency"); let $federalAgency = django.jQuery("#id_federal_agency");
let organizationType = document.getElementById("id_organization_type"); let organizationType = document.getElementById("id_organization_type");
let readonlyOrganizationType = document.querySelector(".field-organization_type .readonly");
let federalType = document.getElementById("id_federal_type") let federalType = document.getElementById("id_federal_type")
if ($federalAgency && organizationType && federalType) { if ($federalAgency && (organizationType || readonlyOrganizationType) && federalType) {
// Attach the change event listener // Attach the change event listener
$federalAgency.on("change", function() { $federalAgency.on("change", function() {
handleFederalAgencyChange($federalAgency, organizationType, federalType); handleFederalAgencyChange($federalAgency, organizationType, readonlyOrganizationType, federalType);
}); });
} }
@ -880,7 +882,7 @@ function initializeWidgetOnList(list, parentId) {
} }
}); });
function handleFederalAgencyChange(federalAgency, organizationType, federalType) { function handleFederalAgencyChange(federalAgency, organizationType, readonlyOrganizationType, federalType) {
// Don't do anything on page load // Don't do anything on page load
if (isInitialPageLoad) { if (isInitialPageLoad) {
isInitialPageLoad = false; isInitialPageLoad = false;
@ -895,13 +897,22 @@ function initializeWidgetOnList(list, parentId) {
return; return;
} }
let organizationTypeValue = organizationType ? organizationType.value : readonlyOrganizationType.innerText.toLowerCase();
if (selectedText !== "Non-Federal Agency") { if (selectedText !== "Non-Federal Agency") {
if (organizationType.value !== "federal") { if (organizationTypeValue !== "federal") {
organizationType.value = "federal"; if (organizationType){
organizationType.value = "federal";
}else {
readonlyOrganizationType.innerText = "Federal"
}
} }
}else { }else {
if (organizationType.value === "federal") { if (organizationTypeValue === "federal") {
organizationType.value = ""; if (organizationType){
organizationType.value = "";
}else {
readonlyOrganizationType.innerText = "-"
}
} }
} }
@ -912,10 +923,12 @@ function initializeWidgetOnList(list, parentId) {
return; return;
} }
organizationTypeValue = organizationType ? organizationType.value : readonlyOrganizationType.innerText.toLowerCase();
// Determine if any changes are necessary to the display of portfolio type or federal type // Determine if any changes are necessary to the display of portfolio type or federal type
// based on changes to the Federal Agency // based on changes to the Federal Agency
let federalPortfolioApi = document.getElementById("federal_and_portfolio_types_from_agency_json_url").value; let federalPortfolioApi = document.getElementById("federal_and_portfolio_types_from_agency_json_url").value;
fetch(`${federalPortfolioApi}?organization_type=${organizationType.value}&agency_name=${selectedText}`) fetch(`${federalPortfolioApi}?organization_type=${organizationTypeValue}&agency_name=${selectedText}`)
.then(response => { .then(response => {
const statusCode = response.status; const statusCode = response.status;
return response.json().then(data => ({ statusCode, data })); return response.json().then(data => ({ statusCode, data }));

View file

@ -6,7 +6,7 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("registrar", "0128_create_groups_v17"), ("registrar", "0128_alter_domaininformation_state_territory_and_more"),
] ]
operations = [ operations = [

View file

@ -25,7 +25,7 @@ def create_groups(apps, schema_editor) -> Any:
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("registrar", "0127_remove_domaininformation_submitter_and_more"), ("registrar", "0129_portfolio_federal_type"),
] ]
operations = [ operations = [

View file

@ -79,7 +79,7 @@ class UserGroup(Group):
{ {
"app_label": "registrar", "app_label": "registrar",
"model": "userportfoliopermission", "model": "userportfoliopermission",
"permissions": ["add_userportfoliopermission", "change_userportfoliopermission", "delete_userportfoliopermission"], "permissions": ["view_userportfoliopermission"],
}, },
] ]

View file

@ -75,7 +75,24 @@ class UserPortfolioPermission(TimeStampedModel):
) )
def __str__(self): def __str__(self):
return f"User '{self.user}' on Portfolio '{self.portfolio}' " f"<Roles: {self.roles}>" if self.roles else "" readable_roles = []
if self.roles:
readable_roles = sorted([UserPortfolioRoleChoices.get_user_portfolio_role_label(role) for role in self.roles])
return f"{self.user}' " f"<Roles: {', '.join(readable_roles)}>" if self.roles else ""
def get_readable_roles(self):
"""Returns a list of labels of each role in self.roles"""
role_labels = []
for role in self.roles:
role_labels.append(UserPortfolioRoleChoices.get_user_portfolio_role_label(role))
return role_labels
def get_readable_additional_permissions(self):
"""Returns a list of labels of each additional_permission in self.additional_permissions"""
perm_labels = []
for perm in self.additional_permissions:
perm_labels.append(UserPortfolioPermissionChoices.get_user_portfolio_permission_label(perm))
return perm_labels
def _get_portfolio_permissions(self): def _get_portfolio_permissions(self):
""" """

View file

@ -10,6 +10,10 @@ class UserPortfolioRoleChoices(models.TextChoices):
ORGANIZATION_ADMIN_READ_ONLY = "organization_admin_read_only", "Admin read only" ORGANIZATION_ADMIN_READ_ONLY = "organization_admin_read_only", "Admin read only"
ORGANIZATION_MEMBER = "organization_member", "Member" ORGANIZATION_MEMBER = "organization_member", "Member"
@classmethod
def get_user_portfolio_role_label(cls, user_portfolio_role):
return cls(user_portfolio_role).label if user_portfolio_role else None
class UserPortfolioPermissionChoices(models.TextChoices): class UserPortfolioPermissionChoices(models.TextChoices):
""" """ """ """
@ -29,3 +33,7 @@ class UserPortfolioPermissionChoices(models.TextChoices):
# Domain: field specific permissions # Domain: field specific permissions
VIEW_SUBORGANIZATION = "view_suborganization", "View suborganization" VIEW_SUBORGANIZATION = "view_suborganization", "View suborganization"
EDIT_SUBORGANIZATION = "edit_suborganization", "Edit suborganization" EDIT_SUBORGANIZATION = "edit_suborganization", "Edit suborganization"
@classmethod
def get_user_portfolio_permission_label(cls, user_portfolio_permission):
return cls(user_portfolio_permission).label if user_portfolio_permission else None

View file

@ -13,6 +13,22 @@
<p>No additional members found.</p> <p>No additional members found.</p>
{% endif %} {% endif %}
</div> </div>
{% elif field.field.name == "roles" %}
<div class="readonly">
{% if get_readable_roles %}
{{ get_readable_roles }}
{% else %}
<p>No roles found.</p>
{% endif %}
</div>
{% elif field.field.name == "additional_permissions" %}
<div class="readonly">
{% if display_permissions %}
{{ display_permissions }}
{% else %}
<p>No additional permissions found.</p>
{% endif %}
</div>
{% else %} {% else %}
<div class="readonly">{{ field.contents }}</div> <div class="readonly">{{ field.contents }}</div>
{% endif %} {% endif %}

View file

@ -0,0 +1,26 @@
{% extends "django/admin/includes/detail_table_fieldset.html" %}
{% load custom_filters %}
{% load static url_helpers %}
{% block field_readonly %}
{% if field.field.name == "roles" %}
<div class="readonly">
{% if display_roles %}
{{ display_roles }}
{% else %}
No roles found.
{% endif %}
</div>
{% elif field.field.name == "additional_permissions" %}
<div class="readonly">
{% if display_permissions %}
{{ display_permissions }}
{% else %}
No additional permissions found.
{% endif %}
</div>
{% else %}
<div class="readonly">{{ field.contents }}</div>
{% endif %}
{% endblock field_readonly%}

View file

@ -0,0 +1,16 @@
{% extends 'django/admin/email_clipboard_change_form.html' %}
{% load custom_filters %}
{% load i18n static %}
{% block field_sets %}
{% for fieldset in adminform %}
{% comment %}
This is a placeholder for now.
Disclaimer:
When extending the fieldset view consider whether you need to make a new one that extends from detail_table_fieldset.
detail_table_fieldset is used on multiple admin pages, so a change there can have unintended consequences.
{% endcomment %}
{% include "django/admin/includes/user_portfolio_permission_fieldset.html" with original_object=original %}
{% endfor %}
{% endblock %}