From ee6b1c8bfa7afa3926d25d5a7c2b0484903117a6 Mon Sep 17 00:00:00 2001 From: Guillaume Libersat Date: Thu, 6 Feb 2025 12:02:23 +0100 Subject: [PATCH 1/3] [projects] Draft to assign permissions to project owner in case they want to administrate their project from another site --- recoco/apps/crm/views.py | 1 + recoco/apps/projects/models.py | 2 +- recoco/apps/projects/views/__init__.py | 3 +++ recoco/apps/projects/views/rest.py | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/recoco/apps/crm/views.py b/recoco/apps/crm/views.py index 320835b05..7e06df74f 100644 --- a/recoco/apps/crm/views.py +++ b/recoco/apps/crm/views.py @@ -1347,6 +1347,7 @@ def project_site_handover(request, project_id): is_origin=False, status="DRAFT", ) + onboarding_utils.notify_new_project( site=site, project=project, owner=project.owner ) diff --git a/recoco/apps/projects/models.py b/recoco/apps/projects/models.py index c916406a8..a85d27eeb 100644 --- a/recoco/apps/projects/models.py +++ b/recoco/apps/projects/models.py @@ -259,7 +259,7 @@ def origin(self): def moderated(self): """Filter out sites where this project is not yet validated""" - return self.exclude(status="DRAFT") + return self.exclude(status__in=["DRAFT", "REJECTED"]) def to_moderate(self): """List only sites where this project needs moderation""" diff --git a/recoco/apps/projects/views/__init__.py b/recoco/apps/projects/views/__init__.py index 8069476cf..a5f622067 100644 --- a/recoco/apps/projects/views/__init__.py +++ b/recoco/apps/projects/views/__init__.py @@ -159,6 +159,9 @@ def project_moderation_accept(request, project_pk): # Invite her to fill in a new form # Send an email to the project owner + # TODO: We should iterate over the collaborator list to assign them the + # project permission for this site (permisssion = COLLABORATOR) + params = { "project": digests.make_project_digest(project, owner), "site": digests.make_site_digest( diff --git a/recoco/apps/projects/views/rest.py b/recoco/apps/projects/views/rest.py index 26b1ffba4..475c3f6ed 100644 --- a/recoco/apps/projects/views/rest.py +++ b/recoco/apps/projects/views/rest.py @@ -349,7 +349,7 @@ def fetch_the_site_project_statuses_for_user(site, user): """ project_statuses = models.UserProjectStatus.objects.filter( user=user, project__deleted=None, project__sites=site - ) + ).exclude(project__projectsites__status__in=["DRAFT", "REJECTED"]) # create missing user project status create_missing_user_project_statuses(site, user, project_statuses) From 2db43935eb63181798eb87b28d2ad8b7180f8ab5 Mon Sep 17 00:00:00 2001 From: Guillaume Libersat Date: Mon, 10 Feb 2025 15:22:26 +0100 Subject: [PATCH 2/3] [multisites] Enahnce behaviour for members - Assign permissions on new site once the project is moderated - Allow a collaborator to access the new site and handle their project --- .../management/commands/update_permissions.py | 10 ++++------ recoco/apps/projects/utils.py | 16 +++++++++++++--- recoco/apps/projects/views/__init__.py | 7 +++++-- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/recoco/apps/home/management/commands/update_permissions.py b/recoco/apps/home/management/commands/update_permissions.py index 06d710329..27930c6ee 100644 --- a/recoco/apps/home/management/commands/update_permissions.py +++ b/recoco/apps/home/management/commands/update_permissions.py @@ -16,23 +16,21 @@ from recoco.apps.projects.models import Project, ProjectSwitchtender from recoco.apps.projects.utils import ( assign_advisor, - assign_collaborator, + assign_collaborator_permissions, assign_observer, ) from recoco.utils import get_group_for_site def assign_user_permissions_by_projects(): - """Per project permission for user""" + """Per project permission for user.""" for project in Project.objects.all(): print("Updating perms for project:", project.name) for site in project.sites.all(): print("\t* Updating permissions for collaborators...") with settings.SITE_ID.override(site.id): for membership in project.projectmember_set.all(): - assign_collaborator( - membership.member, project, is_owner=membership.is_owner - ) + assign_collaborator_permissions(membership.member, project) print("\t* Updating permissions for advisors/observers...") print(f"\t== On site {site} ==") @@ -63,7 +61,7 @@ def assign_user_permissions_by_projects(): def assign_group_permissions_by_sites(): - """Per site permissions for Group""" + """Per site permissions for Group.""" for site in Site.objects.all(): print("site:", site) with settings.SITE_ID.override(site.id): diff --git a/recoco/apps/projects/utils.py b/recoco/apps/projects/utils.py index 4c217a4d6..7ff52d3f7 100644 --- a/recoco/apps/projects/utils.py +++ b/recoco/apps/projects/utils.py @@ -25,11 +25,14 @@ @transaction.atomic -def assign_collaborator(user, project, is_owner=False): - """Make someone becomes a project collaborator and assign permissions""" +def assign_collaborator_permissions(user, project): + """ + Assign permissions to project collaborator. + If the project is still in draft (not accepted by moderators) + """ permissions = models.COLLABORATOR_DRAFT_PERMISSIONS - if project.project_sites.origin().status != "DRAFT": + if project.project_sites.current().status != "DRAFT": permissions += models.COLLABORATOR_PERMISSIONS for perm in permissions: @@ -39,6 +42,13 @@ def assign_collaborator(user, project, is_owner=False): print(f"Unable to find permission <{perm}>, aborting.") raise e + +@transaction.atomic +def assign_collaborator(user, project, is_owner=False): + """Make someone becomes a project collaborator and assign permissions""" + + assign_collaborator_permissions(user, project) + # if we already have an owner, don't allow her to be replaced if is_owner: if ( diff --git a/recoco/apps/projects/views/__init__.py b/recoco/apps/projects/views/__init__.py index a5f622067..71385029d 100644 --- a/recoco/apps/projects/views/__init__.py +++ b/recoco/apps/projects/views/__init__.py @@ -37,6 +37,7 @@ from ..utils import ( assign_advisor, assign_collaborator, + assign_collaborator_permissions, assign_observer, can_administrate_project, is_advisor_for_project, @@ -159,8 +160,10 @@ def project_moderation_accept(request, project_pk): # Invite her to fill in a new form # Send an email to the project owner - # TODO: We should iterate over the collaborator list to assign them the - # project permission for this site (permisssion = COLLABORATOR) + # We assign permissions to use their project on this website in + # case of multiplication + for membership in project.projectmember_set.all(): + assign_collaborator_permissions(membership.member, project) params = { "project": digests.make_project_digest(project, owner), From 04e07e7544c068cb9c9b035f89753f4ac1ab59e0 Mon Sep 17 00:00:00 2001 From: Guillaume Libersat Date: Mon, 10 Feb 2025 15:44:35 +0100 Subject: [PATCH 3/3] [projects] fix exclude directive for userprojectstatuses --- recoco/apps/projects/views/rest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recoco/apps/projects/views/rest.py b/recoco/apps/projects/views/rest.py index 475c3f6ed..3e0ae38fb 100644 --- a/recoco/apps/projects/views/rest.py +++ b/recoco/apps/projects/views/rest.py @@ -349,7 +349,7 @@ def fetch_the_site_project_statuses_for_user(site, user): """ project_statuses = models.UserProjectStatus.objects.filter( user=user, project__deleted=None, project__sites=site - ).exclude(project__projectsites__status__in=["DRAFT", "REJECTED"]) + ).exclude(project__project_sites__status__in=["DRAFT", "REJECTED"]) # create missing user project status create_missing_user_project_statuses(site, user, project_statuses)