Skip to content

Commit

Permalink
Merge pull request #311 from fasrc/cp_managerpermissions
Browse files Browse the repository at this point in the history
Cp managerpermissions
  • Loading branch information
claire-peters authored Aug 1, 2024
2 parents 61d30ff + 3e6d648 commit 965fc14
Show file tree
Hide file tree
Showing 25 changed files with 271 additions and 270 deletions.
5 changes: 5 additions & 0 deletions coldfront/config/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@
PENDING_ACTIVE_ALLOCATION_STATUSES = PENDING_ALLOCATION_STATUSES + ACTIVE_ALLOCATION_STATUSES
INACTIVE_ALLOCATION_STATUSES = ['Denied', 'Expired', 'Inactive', 'Pending Deactivation']

# Categorization of project manager permissions
MANAGERS = ['General Manager', 'Access Manager', 'Data Manager']
ACCESS_MANAGERS = ['General Manager', 'Access Manager']
DATA_MANAGERS = ['General Manager', 'Data Manager']

#------------------------------------------------------------------------------
# DjangoQ settings
#------------------------------------------------------------------------------
Expand Down
6 changes: 4 additions & 2 deletions coldfront/core/allocation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,10 +467,12 @@ def user_permissions(self, user):

project_perms = self.project.user_permissions(user)

if ProjectPermission.PI in project_perms or ProjectPermission.MANAGER in project_perms:
if ProjectPermission.PI in project_perms or ProjectPermission.DATA_MANAGER in project_perms:
return [AllocationPermission.USER, AllocationPermission.MANAGER]

if self.allocationuser_set.filter(user=user, status__name__in=['Active', 'New', ]).exists():
if self.project.projectuser_set.filter(user=user, status__name='Active').exists():
return [AllocationPermission.USER]
if self.allocationuser_set.filter(user=user, status__name__in=['Active', 'New']).exists():
return [AllocationPermission.USER]

return []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ <h2>Allocation Detail</h2>
<div class="col">
<h3><i class="fas fa-list" aria-hidden="true"></i> Allocation Information</h3>
</div>
{% if allocation.is_changeable and not allocation.is_locked and is_allowed_to_update_project and allocation.status.name in 'Active, Renewal Requested, Payment Pending, Payment Requested, Paid' %}
{% if allocation.is_changeable and not allocation.is_locked and is_allowed_to_update_project and allocation.status.name in 'Active, Renewal Requested, Payment Pending, Payment Requested, Paid' %}
<div class="col">
<a class="btn btn-primary" href="{% url 'allocation-change' allocation.pk %}" role="button" style="float: right;">
Request Change
</a>
</div>
{% endif %}
{% endif %}
</div>
</div>

Expand Down
158 changes: 60 additions & 98 deletions coldfront/core/allocation/tests/test_views.py

Large diffs are not rendered by default.

25 changes: 8 additions & 17 deletions coldfront/core/allocation/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def get_context_data(self, **kwargs):

# Can the user update the project?
project_update_perm = allocation_obj.project.has_perm(
self.request.user, ProjectPermission.UPDATE
self.request.user, ProjectPermission.DATA_MANAGER
)
context['is_allowed_to_update_project'] = project_update_perm
context['allocation_users'] = allocation_users
Expand Down Expand Up @@ -464,8 +464,7 @@ def get_queryset(self):
# Q(project__projectuser__status__name='Active') &
# Q(project__projectuser__user=self.request.user) &
(
(Q(project__projectuser__role__name='Manager') &
Q(project__projectuser__user=self.request.user) )|
Q(project__projectuser__user=self.request.user) |
Q(project__pi=self.request.user) |
(
Q(allocationuser__user=self.request.user)
Expand Down Expand Up @@ -544,7 +543,7 @@ class AllocationCreateView(LoginRequiredMixin, UserPassesTestMixin, FormView):
def test_func(self):
"""UserPassesTestMixin Tests"""
project_obj = get_object_or_404(Project, pk=self.kwargs.get('project_pk'))
if project_obj.has_perm(self.request.user, ProjectPermission.UPDATE):
if project_obj.has_perm(self.request.user, ProjectPermission.DATA_MANAGER):
return True
err = 'You do not have permission to create a new allocation.'
messages.error(self.request, err)
Expand Down Expand Up @@ -766,8 +765,7 @@ class AllocationAddUsersView(LoginRequiredMixin, UserPassesTestMixin, TemplateVi

def test_func(self):
"""UserPassesTestMixin Tests"""
allocation_obj = get_object_or_404(Allocation, pk=self.kwargs.get('pk'))
if allocation_obj.has_perm(self.request.user, AllocationPermission.MANAGER):
if self.request.user.is_superuser:
return True
err = 'You do not have permission to add users to the allocation.'
messages.error(self.request, err)
Expand Down Expand Up @@ -874,10 +872,8 @@ class AllocationRemoveUsersView(LoginRequiredMixin, UserPassesTestMixin, Templat

def test_func(self):
"""UserPassesTestMixin Tests"""
allocation_obj = get_object_or_404(Allocation, pk=self.kwargs.get('pk'))
if allocation_obj.has_perm(self.request.user, AllocationPermission.MANAGER):
if self.request.user.is_superuser:
return True

err = 'You do not have permission to remove users from allocation.'
messages.error(self.request, err)
return False
Expand Down Expand Up @@ -1045,13 +1041,13 @@ def get_allocation_attrs_to_change(self, allocation_obj):
return attributes_to_change

def get(self, request, *args, **kwargs):
context = {}
allocation_obj = get_object_or_404(Allocation, pk=self.kwargs.get('pk'))
attrs_to_change = self.get_allocation_attrs_to_change(allocation_obj)
context = {}

form = AllocationChangeForm(**self.get_form_kwargs())
context['form'] = form

attrs_to_change = self.get_allocation_attrs_to_change(allocation_obj)
if attrs_to_change:
formset = formset_factory(self.formset_class, max_num=len(attrs_to_change))
formset = formset(initial=attrs_to_change, prefix='attributeform')
Expand All @@ -1067,7 +1063,6 @@ def get(self, request, *args, **kwargs):
return render(request, self.template_name, context)

def post(self, request, *args, **kwargs):
attribute_changes_to_make = set({})
pk = self.kwargs.get('pk')
allocation_obj = get_object_or_404(Allocation, pk=pk)

Expand Down Expand Up @@ -1097,9 +1092,6 @@ def post(self, request, *args, **kwargs):
messages.error(request, error)
return HttpResponseRedirect(reverse('allocation-attribute-edit', kwargs={'pk': pk}))

# ID changes
change_requested = False

if attrs_to_change:
for entry in formset:
formset_data = entry.cleaned_data
Expand Down Expand Up @@ -1284,7 +1276,6 @@ def post(self, request, *args, **kwargs):
return HttpResponseRedirect(reverse('allocation-detail', kwargs={'pk': pk}))



class AllocationRenewView(LoginRequiredMixin, UserPassesTestMixin, TemplateView):
template_name = 'allocation/allocation_renew.html'

Expand Down Expand Up @@ -1536,7 +1527,7 @@ def get_context_data(self, **kwargs):

# Can the user update the project?
project_update_perm = allocation_obj.project.has_perm(
self.request.user, ProjectPermission.UPDATE
self.request.user, ProjectPermission.DATA_MANAGER
)
context['is_allowed_to_update_project'] = project_update_perm
context['allocation_users'] = allocation_users
Expand Down
10 changes: 7 additions & 3 deletions coldfront/core/grant/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_func(self):
if project_obj.pi == self.request.user:
return True

if project_obj.projectuser_set.filter(user=self.request.user, role__name='Manager', status__name='Active').exists():
if project_obj.projectuser_set.filter(user=self.request.user, role__name__contains='Manager', status__name='Active').exists():
return True

messages.error(self.request, 'You do not have permission to add a new grant to this project.')
Expand Down Expand Up @@ -85,7 +85,9 @@ def test_func(self):
if grant_obj.project.pi == self.request.user:
return True

if grant_obj.project.projectuser_set.filter(user=self.request.user, role__name='Manager', status__name='Active').exists():
if grant_obj.project.projectuser_set.filter(
user=self.request.user, role__name__contains='Manager', status__name='Active'
).exists():
return True

messages.error(self.request, 'You do not have permission to update grant from this project.')
Expand Down Expand Up @@ -113,7 +115,9 @@ def test_func(self):
if project_obj.pi == self.request.user:
return True

if project_obj.projectuser_set.filter(user=self.request.user, role__name='Manager', status__name='Active').exists():
if project_obj.projectuser_set.filter(
user=self.request.user, role__name__contains='Manager', status__name='Active'
).exists():
return True

messages.error(self.request, 'You do not have permission to delete grants from this project.')
Expand Down
6 changes: 4 additions & 2 deletions coldfront/core/portal/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
from coldfront.core.resource.models import Resource
from coldfront.config.env import ENV
from coldfront.core.department.models import Department, DepartmentMember
from coldfront.core.utils.common import import_from_settings

if ENV.bool('PLUGIN_SFTOCF', default=False):
from coldfront.plugins.sftocf.utils import StarFishRedash, STARFISH_SERVER

MANAGERS = import_from_settings('MANAGERS', ['Manager'])

def home(request):
context = {}
Expand All @@ -41,7 +43,7 @@ def home(request):
Q(project__status__name__in=['Active', 'New']) &
Q(project__projectuser__user=request.user) &
Q(project__projectuser__status__name__in=['Active', ]) &
(Q(project__projectuser__role__name='Manager') |
(Q(project__projectuser__role__name__in=MANAGERS) |
Q(allocationuser__user=request.user) &
Q(allocationuser__status__name='Active'))
).distinct().order_by('-created')
Expand All @@ -51,7 +53,7 @@ def home(request):
& Q(project__status__name__in=['Active', 'New']) & (
Q(project__pi=request.user) | (
Q(project__projectuser__user=request.user)
& Q(project__projectuser__role__name='Manager')
& Q(project__projectuser__role__name__in=MANAGERS)
)
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def handle(self, *args, **options):
for choice in ['Completed', 'Pending', ]:
ProjectReviewStatusChoice.objects.get_or_create(name=choice)

for choice in ['User', 'Manager', ]:
for choice in ['User', 'General Manager', 'Data Manager', 'Access Manager']:
ProjectUserRoleChoice.objects.get_or_create(name=choice)

for choice in ['Active', 'Pending - Add', 'Pending - Remove', 'Denied', 'Removed', ]:
Expand Down
23 changes: 15 additions & 8 deletions coldfront/core/project/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@
from coldfront.core.utils.common import import_from_settings

PROJECT_ENABLE_PROJECT_REVIEW = import_from_settings('PROJECT_ENABLE_PROJECT_REVIEW', False)
DATA_MANAGERS = import_from_settings('DATA_MANAGERS', ['Manager'])
ACCESS_MANAGERS = import_from_settings('ACCESS_MANAGERS', ['Manager'])
MANAGERS = import_from_settings('MANAGERS', ['Manager'])

class ProjectPermission(Enum):
""" A project permission stores the user, manager, pi, and update fields of a project. """

USER = 'user'
MANAGER = 'manager'
DATA_MANAGER = 'data_manager'
ACCESS_MANAGER = 'access_manager'
PI = 'pi'
UPDATE = 'update'

class ProjectStatusChoice(TimeStampedModel):
""" A project status choice indicates the status of the project. Examples include Active, Archived, and New.
Expand Down Expand Up @@ -193,16 +196,20 @@ def user_permissions(self, user):

permissions = [ProjectPermission.USER]

if self.projectuser_set.filter(user_conditions & models.Q(role__name='Manager')).exists():
permissions.append(ProjectPermission.MANAGER)
if (
self.projectuser_set.filter(user_conditions & models.Q(role__name__in=DATA_MANAGERS)).exists()
or self.pi.id == user.id
):
permissions.append(ProjectPermission.DATA_MANAGER)

if (
self.projectuser_set.filter(user_conditions & models.Q(role__name__in=ACCESS_MANAGERS)).exists()
or self.pi.id == user.id
):
permissions.append(ProjectPermission.ACCESS_MANAGER)

if self.pi.id == user.id:
permissions.append(ProjectPermission.PI)

if ProjectPermission.MANAGER in permissions or ProjectPermission.PI in permissions:
permissions.append(ProjectPermission.UPDATE)

return permissions

def has_perm(self, user, perm):
Expand Down
8 changes: 5 additions & 3 deletions coldfront/core/project/templates/project/project_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ <h3 class="d-inline" id="users"><i class="fas fa-users" aria-hidden="true"></i>
name="email_notifications_checkbox"
value="{{ user.enable_notifications }}"
{% if user.enable_notifications %} checked {% endif %}
{% if user.role.name == "Manager" %} disabled {% endif %}
{% if user.role.name == "Access Manager" %} disabled {% endif %}
{% if not request.user.is_superuser and user.role.name == "User" and request.user == user.user %} disabled {% endif %}>
{% elif request.user == user.user %}
<input type="checkbox"
Expand All @@ -372,7 +372,7 @@ <h3 class="d-inline" id="users"><i class="fas fa-users" aria-hidden="true"></i>
{% endif %}
</td>
<td>
{% if is_allowed_to_update_project %}
{% if is_allowed_to_update_users %}
<a href="{% url 'project-user-detail' project.pk user.id %}"><i class="fas fa-user-edit" aria-hidden="true"></i><span class="sr-only">Edit</span></a>
{% endif %}
</td>
Expand All @@ -385,8 +385,8 @@ <h3 class="d-inline" id="users"><i class="fas fa-users" aria-hidden="true"></i>
</div>
<!-- End Project Users -->

{% comment %}
<!-- Start Project Attributes -->
{% if request.user.is_superuser %}
<div class="card mb-3">
<div class="card-header">
<h3 class="d-inline"><i class="fas fa-info-circle" aria-hidden="true"></i> Attributes</h3> <span class="badge badge-secondary">{{attributes.count}}</span>
Expand Down Expand Up @@ -451,9 +451,11 @@ <h4 class="card-title">{{attribute}}</h4>
{% endif %}
</div>
</div>
{% endif %}

<!-- End Project Attributes -->

{% comment %}
<!-- Start Project Grants -->
<div style="display:none" class="card mb-3">
<div class="card-header">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ <h3>Project: {{project.title}}</h3>
{% else %}
<tr>
<th scope="row">Role:</th>
<td>{{project_user_update_form.role}}</td>
<td>{{project_user_update_form.role}}<br/><br/>
<b>Users</b> can view information about their project and the project's related allocations.<br/>
<b>Access Managers</b> have the permissions to manage group membership and permissions.<br/>
<b>Data Managers</b> have the permissions to make allocation requests.<br/>
<b>General Managers</b> have all the permissions of a PI.<br/>
<b>PIs</b> have permissions to manage the project and its related allocations, regardless of their assigned projectuser role.<br/>
</td>
</tr>
<tr>
<th scope="row">Notifications On:</th>
Expand Down
Loading

0 comments on commit 965fc14

Please sign in to comment.