Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
a0ed1f3
Django guardian setup
mohamedelabbas1996 Jan 24, 2025
bbd7faa
feat: added object level permissions for Project
mohamedelabbas1996 Jan 27, 2025
bcb2eeb
feat: added object level permissions management to the admin page
mohamedelabbas1996 Jan 27, 2025
aab6000
feat: added signals to auto-assign permissions when a project is crea…
mohamedelabbas1996 Jan 27, 2025
8bb1ac3
Added tests for user permissions
mohamedelabbas1996 Jan 27, 2025
38addf3
cleanup: removed logs
mohamedelabbas1996 Jan 27, 2025
d85b88e
feat: Enforce project_id for project entities & inherit project permi…
mohamedelabbas1996 Jan 31, 2025
3e4f1d8
feat: added roles
mohamedelabbas1996 Feb 4, 2025
ac83301
feat: added custom permission checks
mohamedelabbas1996 Feb 4, 2025
080315b
cleanup: refactored ObjectPermissions to ProjectCRUDPermissions
mohamedelabbas1996 Feb 4, 2025
82f49fc
fix: made project_id param optional
mohamedelabbas1996 Feb 6, 2025
31ff972
feat: added project entities CRUD permissions
mohamedelabbas1996 Feb 6, 2025
1338032
Added tests for basic member and identifier roles
mohamedelabbas1996 Feb 6, 2025
a2a4b67
cleanup: squashed migrations
mohamedelabbas1996 Feb 6, 2025
04e58ed
fix: added CanDeleteIdentification permission to Identifier role
mohamedelabbas1996 Feb 6, 2025
6836bd2
fix: Allow only the user who created an Identification to delete it
mohamedelabbas1996 Feb 6, 2025
01d0c84
fix: Allow Project Manager to delete all Identifications in the project
mohamedelabbas1996 Feb 6, 2025
bddb311
fix: Auto-create roles when a project is created
mohamedelabbas1996 Feb 6, 2025
c28394e
fix: Prevent Project Manager from creating a project
mohamedelabbas1996 Feb 6, 2025
853ecb9
stub out solution for permissions per-collection type
mihow Feb 7, 2025
9a5d12f
Merge branch 'main' into feat/user-permissions
mohamedelabbas1996 Feb 7, 2025
bf7b091
fix: Resolved merge conflict
mohamedelabbas1996 Feb 7, 2025
3c4ec72
fix: resovled merge conflict
mohamedelabbas1996 Feb 7, 2025
670fb5f
fix: check permissions before creating an object
mohamedelabbas1996 Feb 7, 2025
3724e5f
feat: Add identifier and source image collection permissions
mohamedelabbas1996 Feb 11, 2025
0bb0783
fix: Ensure identifier permissions are reflected on the frontend
mohamedelabbas1996 Feb 11, 2025
39ec6cf
cleanup: Removed TODOs
mohamedelabbas1996 Feb 11, 2025
8458f95
fix: renamed storage permission
mohamedelabbas1996 Feb 11, 2025
eccca1f
fix: update frontend logic for entity delete permissions
annavik Feb 12, 2025
5e07ab4
fix: added create permission to the user permissions field at the col…
mohamedelabbas1996 Feb 12, 2025
a5003a6
Merge branch 'feat/user-permissions' of https://github.com/RolnickLab…
mohamedelabbas1996 Feb 12, 2025
8fd64a8
fix: Fixed Identifier role tests
mohamedelabbas1996 Feb 12, 2025
2178095
fix: Resolved migration conflict
mohamedelabbas1996 Feb 12, 2025
a10041f
fix: added algorithm (name,version) unique constraint
mohamedelabbas1996 Feb 13, 2025
b25fa77
fix: removed permissions for machine suggestions
mohamedelabbas1996 Feb 13, 2025
e32b9dd
fix: auto-assign BasicMember and ProjectManager roles for all projects
mohamedelabbas1996 Feb 18, 2025
2a8f326
fix: get the queryset for project members
mohamedelabbas1996 Feb 18, 2025
bdba187
Merge branch 'main' into feat/user-permissions
mohamedelabbas1996 Feb 18, 2025
ee03ed1
merged migrations
mohamedelabbas1996 Feb 18, 2025
964711c
fix: only run create roles once after migrations are completed
mihow Feb 19, 2025
3db5224
feat: added assign_identifiers & assign_roles management commands
mohamedelabbas1996 Feb 20, 2025
11169bd
Merge branch 'feat/user-permissions' of https://github.com/RolnickLab…
mohamedelabbas1996 Feb 20, 2025
b604345
Merge branch 'main' into feat/user-permissions
mohamedelabbas1996 Feb 20, 2025
79a18ce
fix: first, reset all permissions for non-superusers in the assign_ro…
mohamedelabbas1996 Feb 20, 2025
1f8978f
Merge branch 'feat/user-permissions' of https://github.com/RolnickLab…
mohamedelabbas1996 Feb 20, 2025
7a94767
added merge migration
mohamedelabbas1996 Feb 20, 2025
54f70fc
chore: modified doc string
mohamedelabbas1996 Feb 20, 2025
7651004
fix: added frontend permisssion checks for star and populate actions
mohamedelabbas1996 Feb 21, 2025
b1c8725
fix: adjust star button tooltip based on permissions status
annavik Feb 21, 2025
351f079
style: add gap to identification card action buttons when more than o…
annavik Feb 21, 2025
1bdba18
fix: modify create permission check to fall back to object permissions
mohamedelabbas1996 Feb 21, 2025
a45d52c
Merge branch 'feat/user-permissions' of https://github.com/RolnickLab…
mohamedelabbas1996 Feb 21, 2025
c3bca51
test: added tests to make sure that project manager can CRUD project …
mohamedelabbas1996 Feb 21, 2025
1ae6152
feat: refine permissions and role-based access control
mohamedelabbas1996 Feb 23, 2025
577731e
added migration file
mohamedelabbas1996 Feb 23, 2025
55a6dfc
fix: handle underscores in project name
mohamedelabbas1996 Feb 24, 2025
8300905
fix: only show button "Register pipelines" if user is allowed to crea…
annavik Feb 24, 2025
1324fa6
fix: mark prop as optional
annavik Feb 24, 2025
b7e6d42
style: format code
annavik Feb 24, 2025
a5d06e0
fix: Extract role name after the last underscore and check if the gro…
mohamedelabbas1996 Feb 24, 2025
6ae6995
fix: Extract role name after the last underscore and check if the gro…
mohamedelabbas1996 Feb 24, 2025
cfb88a1
Merge branch 'feat/user-permissions' of https://github.com/RolnickLab…
mohamedelabbas1996 Feb 24, 2025
19bc51f
feat: update FE to use custom permissions for jobs
annavik Feb 24, 2025
34f8fcf
fix: removed project update permission from basic member role
mohamedelabbas1996 Feb 24, 2025
73abb4b
fix: removed project update permission from basic member role
mohamedelabbas1996 Feb 24, 2025
6412eba
fix: removed project update permission from basic member role
mohamedelabbas1996 Feb 24, 2025
ff17595
fix: removed project update permission from basic member role
mohamedelabbas1996 Feb 24, 2025
bceab0a
fix: removed project update permission from basic member role
mohamedelabbas1996 Feb 24, 2025
3b7579b
Merge branch 'main' into feat/user-permissions
mohamedelabbas1996 Feb 25, 2025
1d75e9d
cleanup: merged assign_roles & assign_identifiers management commands
mohamedelabbas1996 Feb 25, 2025
44ce97a
Merge branch 'feat/user-permissions' of https://github.com/RolnickLab…
mohamedelabbas1996 Feb 25, 2025
02d9795
fix: show projects in My projetcs based on roles assigned to user
mohamedelabbas1996 Feb 26, 2025
e1c3e17
fix: show projects in My projetcs based on roles assigned to user
mohamedelabbas1996 Feb 26, 2025
b1ba917
fix: Add user to project members when they got assigned a role
mohamedelabbas1996 Feb 27, 2025
963a33b
chore: standardize the generation of the permission group name
mihow Feb 27, 2025
0d67332
chore: Added TODOs for tracking permission group names used to link p…
mohamedelabbas1996 Feb 27, 2025
57e8911
Merge branch 'main' of github.com:RolnickLab/antenna into feat/user-p…
mihow Mar 6, 2025
c7ae632
chore: add type annotation
mihow Mar 6, 2025
0a83d4e
feat: reduce logs & make log level configurable locally
mihow Mar 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions ami/main/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,9 @@ def create_default_research_site(project: "Project") -> "Site":
class ProjectQuerySet(models.QuerySet):
def filter_by_user(self, user):
"""
Filters projects to include only those where the given user has any role.
Filters projects to include only those where the given user is a member.
"""

# To avoid circular import
from ami.users.roles import Role # noqa: F401

# @TODO modify once we have the formal relationship between projects and groups
return self.filter(
id__in=Project.objects.filter(
id__in=[project.id for project in Project.objects.all() if Role.user_has_any_role(user, project)]
)
)
return self.filter(members=user)


class ProjectManager(models.Manager):
Expand Down
7 changes: 2 additions & 5 deletions ami/main/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1341,11 +1341,7 @@ def _test_role_permissions(self, role_class, user, permissions_map):
# Step 5: Unassign Role and Verify Permissions are Revoked
if role_class:
role_class.unassign_user(user, self.project)

# if user is the project manager unassign the basic member role as well
if role_class == ProjectManager:
BasicMember.unassign_user(user, project=self.project)

BasicMember.unassign_user(user, project=self.project)
self.client.force_authenticate(user=user)

for entity, actions in permissions_map.items():
Expand All @@ -1369,6 +1365,7 @@ def _test_role_permissions(self, role_class, user, permissions_map):
response = self.client.post(endpoints["capture_star"])
logger.info(f"star capture response: {response.json()}")
logger.info(f"Testing {role_class} for star capture permission after role unassignment")
logger.info(f"{role_class} {user} user permissions: {get_perms(user, self.project)}")
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

response = self.client.post(endpoints["capture_unstar"])
Expand Down
51 changes: 50 additions & 1 deletion ami/users/signals.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import logging

from django.contrib.auth.models import Group
from django.db import transaction
from django.db.models.signals import m2m_changed
from django.dispatch import receiver

from ami.main.models import Project
from ami.users.roles import create_roles_for_project
from ami.users.roles import Role, create_roles_for_project

logger = logging.getLogger(__name__)

Expand All @@ -12,3 +17,47 @@ def create_roles(sender, **kwargs):
logger.info("Creating roles")
for project in Project.objects.all():
create_roles_for_project(project)


@receiver(m2m_changed, sender=Group.user_set.through)
def manage_project_membership(sender, instance, action, reverse, model, pk_set, **kwargs):
"""
When a user is added/removed from a permissions group, update project members accordingly.

"""
if action not in ["post_add", "post_remove"]:
return # Only handle add and remove actions

# Temporarily disconnect the signal before updating project.members to prevent infinite recursion.
m2m_changed.disconnect(manage_project_membership, sender=Group.user_set.through)
logger.info("Disconnecting signal to prevent infinite recursion.")
try:
with transaction.atomic(): # Ensure DB consistency
for group in Group.objects.filter(pk__in=pk_set):
parts = group.name.split("_") # Expected format: {project_id}_{project_name}_{Role}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will you keep track of any function that is using the group name to relate to projects? So we can refactor at the same time


try:
project_id = int(parts[0])
project = Project.objects.get(id=project_id)
except (ValueError, Project.DoesNotExist):
logger.warning(f"Skipping invalid group or missing project: {group.name}")
continue

user = instance
if action == "post_add":
# Add user to project members if not already in
if not project.members.filter(id=user.id).exists():
project.members.add(user)
logger.info(f"Added {user.email} to project {project.name} members.")

elif action == "post_remove":
# Check if user still has any role in this project and they exist in the project members
has_any_role = Role.user_has_any_role(user, project)
if not has_any_role and project.members.filter(id=user.id).exists():
project.members.remove(user)
logger.info(f"Removed {user.email} from project {project.name} members (no remaining roles).")

finally:
# Reconnect the signal after updating members
m2m_changed.connect(manage_project_membership, sender=Group.user_set.through)
logger.info("Reconnecting signal after updating project members.")