SECURITY - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: ограничение создания проектов
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
ADMIN_ROLE = 20
|
||||
AUTO_ADMIN_COMMENT = "nodedc:workspace-admin"
|
||||
AUTO_ADMIN_CREATED_COMMENT = f"{AUTO_ADMIN_COMMENT}:created"
|
||||
AUTO_ADMIN_PREVIOUS_PREFIX = f"{AUTO_ADMIN_COMMENT}:previous:"
|
||||
|
||||
|
||||
def get_auto_admin_previous_role(comment):
|
||||
if not isinstance(comment, str) or not comment.startswith(AUTO_ADMIN_PREVIOUS_PREFIX):
|
||||
return None
|
||||
|
||||
try:
|
||||
previous_role = int(comment.replace(AUTO_ADMIN_PREVIOUS_PREFIX, "", 1))
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
return previous_role if previous_role in {5, 15, ADMIN_ROLE} else None
|
||||
|
||||
|
||||
def ensure_project_admin_membership(project, user):
|
||||
from plane.db.models import ProjectMember
|
||||
|
||||
project_member = ProjectMember.objects.filter(
|
||||
project=project,
|
||||
member=user,
|
||||
deleted_at__isnull=True,
|
||||
).first()
|
||||
|
||||
if project_member is None:
|
||||
ProjectMember.objects.create(
|
||||
workspace=project.workspace,
|
||||
project=project,
|
||||
member=user,
|
||||
role=ADMIN_ROLE,
|
||||
is_active=True,
|
||||
comment=AUTO_ADMIN_CREATED_COMMENT,
|
||||
)
|
||||
return 1
|
||||
|
||||
update_fields = []
|
||||
if project_member.role != ADMIN_ROLE:
|
||||
project_member.comment = f"{AUTO_ADMIN_PREVIOUS_PREFIX}{project_member.role}"
|
||||
project_member.role = ADMIN_ROLE
|
||||
update_fields.extend(["comment", "role"])
|
||||
if not project_member.is_active:
|
||||
project_member.is_active = True
|
||||
update_fields.append("is_active")
|
||||
|
||||
if update_fields:
|
||||
update_fields.append("updated_at")
|
||||
project_member.save(update_fields=update_fields)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def revoke_auto_project_admin_memberships(workspace, user):
|
||||
from plane.db.models import ProjectMember
|
||||
|
||||
revoked = 0
|
||||
project_memberships = ProjectMember.objects.filter(
|
||||
project__workspace=workspace,
|
||||
member=user,
|
||||
role=ADMIN_ROLE,
|
||||
deleted_at__isnull=True,
|
||||
comment__startswith=AUTO_ADMIN_COMMENT,
|
||||
)
|
||||
|
||||
for project_member in project_memberships:
|
||||
previous_role = get_auto_admin_previous_role(project_member.comment)
|
||||
if project_member.comment == AUTO_ADMIN_CREATED_COMMENT or previous_role is None:
|
||||
project_member.is_active = False
|
||||
project_member.save(update_fields=["is_active", "updated_at"])
|
||||
else:
|
||||
project_member.role = previous_role
|
||||
project_member.comment = None
|
||||
project_member.is_active = True
|
||||
project_member.save(update_fields=["role", "comment", "is_active", "updated_at"])
|
||||
revoked += 1
|
||||
|
||||
return revoked
|
||||
|
||||
|
||||
def ensure_user_admin_project_memberships(workspace, user):
|
||||
from plane.db.models import Project
|
||||
|
||||
restored = 0
|
||||
for project in Project.objects.filter(workspace=workspace, deleted_at__isnull=True).select_related("workspace"):
|
||||
restored += ensure_project_admin_membership(project, user)
|
||||
return restored
|
||||
|
||||
|
||||
def ensure_workspace_admin_project_memberships(workspace, project=None):
|
||||
from plane.db.models import WorkspaceMember
|
||||
|
||||
admin_memberships = (
|
||||
WorkspaceMember.objects.filter(
|
||||
workspace=workspace,
|
||||
role=ADMIN_ROLE,
|
||||
is_active=True,
|
||||
deleted_at__isnull=True,
|
||||
member__is_bot=False,
|
||||
)
|
||||
.select_related("member")
|
||||
.order_by("created_at")
|
||||
)
|
||||
|
||||
restored = 0
|
||||
for workspace_member in admin_memberships:
|
||||
if project is not None:
|
||||
restored += ensure_project_admin_membership(project, workspace_member.member)
|
||||
else:
|
||||
restored += ensure_user_admin_project_memberships(workspace, workspace_member.member)
|
||||
return restored
|
||||
Reference in New Issue
Block a user