mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-17 01:57:03 +02:00
handle DJA ui and handle permission test for UserDomainRole
This commit is contained in:
parent
777be646a4
commit
72ee81a43c
3 changed files with 72 additions and 14 deletions
|
@ -35,6 +35,8 @@ from django_admin_multiple_choice_list_filter.list_filters import MultipleChoice
|
|||
from import_export import resources
|
||||
from import_export.admin import ImportExportModelAdmin
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.contrib.postgres.forms import SimpleArrayField
|
||||
from django.contrib.admin.widgets import FilteredSelectMultiple
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
@ -89,12 +91,33 @@ class UserResource(resources.ModelResource):
|
|||
class Meta:
|
||||
model = models.User
|
||||
|
||||
class FilteredSelectMultipleArrayWidget(FilteredSelectMultiple):
|
||||
def __init__(self, verbose_name, is_stacked=False, choices=(), **kwargs):
|
||||
super().__init__(verbose_name, is_stacked, **kwargs)
|
||||
self.choices = choices
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
values = super().value_from_datadict(data, files, name)
|
||||
# print(f'value_from_datadict - values: {values}')
|
||||
return values or []
|
||||
|
||||
def get_context(self, name, value, attrs):
|
||||
# print(f'get_context - initial value: {value}')
|
||||
if value is None:
|
||||
value = []
|
||||
elif isinstance(value, str):
|
||||
value = value.split(',')
|
||||
# print(f'get_context - processed value: {value}')
|
||||
self.choices = [(choice, label) for choice, label in self.choices if choice in value] + [(choice, label) for choice, label in self.choices if choice not in value]
|
||||
# print(f'get_context - choices: {self.choices}')
|
||||
context = super().get_context(name, value, attrs)
|
||||
return context
|
||||
|
||||
class MyUserAdminForm(UserChangeForm):
|
||||
"""This form utilizes the custom widget for its class's ManyToMany UIs.
|
||||
|
||||
It inherits from UserChangeForm which has special handling for the password and username fields."""
|
||||
|
||||
|
||||
class Meta:
|
||||
model = models.User
|
||||
fields = "__all__"
|
||||
|
@ -102,6 +125,8 @@ class MyUserAdminForm(UserChangeForm):
|
|||
widgets = {
|
||||
"groups": NoAutocompleteFilteredSelectMultiple("groups", False),
|
||||
"user_permissions": NoAutocompleteFilteredSelectMultiple("user_permissions", False),
|
||||
"portfolio_roles": FilteredSelectMultipleArrayWidget("portfolio_roles", is_stacked=False, choices=User.UserPortfolioRoleChoices.choices),
|
||||
"portfolio_additional_permissions": FilteredSelectMultipleArrayWidget("portfolio_additional_permissions", is_stacked=False, choices=User.UserPortfolioPermissionChoices.choices),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -625,6 +650,10 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
"status",
|
||||
)
|
||||
|
||||
# For each filter_horizontal, init in admin js extendFilterHorizontalWidgets
|
||||
# to activate the edit/delete/view buttons
|
||||
# filter_horizontal = ("portfolio_roles",)
|
||||
|
||||
# Renames inherited AbstractUser label 'email_address to 'email'
|
||||
def formfield_for_dbfield(self, dbfield, **kwargs):
|
||||
field = super().formfield_for_dbfield(dbfield, **kwargs)
|
||||
|
@ -654,6 +683,7 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
"user_permissions",
|
||||
"portfolio",
|
||||
"portfolio_roles",
|
||||
"portfolio_additional_permissions",
|
||||
)
|
||||
},
|
||||
),
|
||||
|
@ -684,6 +714,7 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
"groups",
|
||||
"portfolio",
|
||||
"portfolio_roles",
|
||||
"portfolio_additional_permissions",
|
||||
)
|
||||
},
|
||||
),
|
||||
|
@ -715,6 +746,7 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
"date_joined",
|
||||
"portfolio",
|
||||
"portfolio_roles",
|
||||
"portfolio_additional_permissions",
|
||||
]
|
||||
|
||||
list_filter = (
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 4.2.10 on 2024-07-17 17:12
|
||||
# Generated by Django 4.2.10 on 2024-07-17 19:10
|
||||
|
||||
from django.conf import settings
|
||||
import django.contrib.postgres.fields
|
||||
|
@ -24,6 +24,29 @@ class Migration(migrations.Migration):
|
|||
to="registrar.portfolio",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="user",
|
||||
name="portfolio_additional_permissions",
|
||||
field=django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.CharField(
|
||||
choices=[
|
||||
("view_domains", "View all domains and domain reports"),
|
||||
("edit_domains", "User is a manager on a domain"),
|
||||
("view_member", "View members"),
|
||||
("edit_member", "Create and edit members"),
|
||||
("view_requests", "View requests"),
|
||||
("edit_requests", "Create and edit requests"),
|
||||
("view_portfolio", "View organization"),
|
||||
("edit_portfolio", "Edit organization"),
|
||||
],
|
||||
max_length=50,
|
||||
),
|
||||
blank=True,
|
||||
help_text="Select one or more additional permissions.",
|
||||
null=True,
|
||||
size=None,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="user",
|
||||
name="portfolio_roles",
|
|
@ -78,6 +78,7 @@ class User(AbstractUser):
|
|||
# EDIT_DOMAINS is really self.domains. We add is hear and leverage it in has_permission
|
||||
# so we have one way to test for portfolio and domain edit permissions
|
||||
# Do we need to check for portfolio domains specifically?
|
||||
# NOTE: A user on an org can currently invite a user outside the org
|
||||
EDIT_DOMAINS = "edit_domains", "User is a manager on a domain"
|
||||
|
||||
VIEW_MEMBER = "view_member", "View members"
|
||||
|
@ -150,15 +151,15 @@ class User(AbstractUser):
|
|||
help_text="Select one or more roles.",
|
||||
)
|
||||
|
||||
# portfolio_permissions = ArrayField(
|
||||
# models.CharField(
|
||||
# max_length=50,
|
||||
# choices=UserPortfolioPermissionChoices.choices,
|
||||
# ),
|
||||
# null=True,
|
||||
# blank=True,
|
||||
# help_text="Select one or more permissions.",
|
||||
# )
|
||||
portfolio_additional_permissions = ArrayField(
|
||||
models.CharField(
|
||||
max_length=50,
|
||||
choices=UserPortfolioPermissionChoices.choices,
|
||||
),
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Select one or more additional permissions.",
|
||||
)
|
||||
|
||||
phone = PhoneNumberField(
|
||||
null=True,
|
||||
|
@ -256,9 +257,10 @@ class User(AbstractUser):
|
|||
def has_portfolio_permission(self, portfolio_permission):
|
||||
"""The views should only call this guy when testing for perms and not rely on roles"""
|
||||
|
||||
# TODO: this does not seem to be working
|
||||
# if portfolio_permission == self.UserPortfolioPermissionChoices.EDIT_DOMAINS and self.domains.exists():
|
||||
# return True
|
||||
# EDIT_DOMAINS === user is a manager on a domain (has UserDomainRole)
|
||||
# NOTE: Should we check whether the domain is in the portfolio?
|
||||
if portfolio_permission == self.UserPortfolioPermissionChoices.EDIT_DOMAINS and self.domains.exists():
|
||||
return True
|
||||
|
||||
if not self.portfolio:
|
||||
return False
|
||||
|
@ -276,6 +278,7 @@ class User(AbstractUser):
|
|||
for role in self.portfolio_roles:
|
||||
if role in self.PORTFOLIO_ROLE_PERMISSIONS:
|
||||
portfolio_permissions.update(self.PORTFOLIO_ROLE_PERMISSIONS[role])
|
||||
portfolio_permissions.update(self.portfolio_additional_permissions)
|
||||
return list(portfolio_permissions) # Convert back to list if necessary
|
||||
|
||||
@classmethod
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue