chore: Page auth and other improvements (#3011)

* chore: project query optimised

* chore: page permissions changed
This commit is contained in:
Bavisetti Narayan 2023-12-06 19:30:40 +05:30 committed by Aaryan Khandelwal
parent dfb0c49070
commit c40e45528e
5 changed files with 47 additions and 62 deletions

View File

@ -103,7 +103,7 @@ class InboxIssueAPIEndpoint(BaseAPIView):
if inbox is None and not project.inbox_view: if inbox is None and not project.inbox_view:
return Response( return Response(
{ {
"error": "Inbox is not enabled for this project enable it through the project settings" "error": "Inbox is not enabled for this project enable it through the project's api"
}, },
status=status.HTTP_400_BAD_REQUEST, status=status.HTTP_400_BAD_REQUEST,
) )
@ -177,7 +177,7 @@ class InboxIssueAPIEndpoint(BaseAPIView):
if inbox is None and not project.inbox_view: if inbox is None and not project.inbox_view:
return Response( return Response(
{ {
"error": "Inbox is not enabled for this project enable it through the project settings" "error": "Inbox is not enabled for this project enable it through the project's api"
}, },
status=status.HTTP_400_BAD_REQUEST, status=status.HTTP_400_BAD_REQUEST,
) )
@ -311,7 +311,7 @@ class InboxIssueAPIEndpoint(BaseAPIView):
if inbox is None and not project.inbox_view: if inbox is None and not project.inbox_view:
return Response( return Response(
{ {
"error": "Inbox is not enabled for this project enable it through the project settings" "error": "Inbox is not enabled for this project enable it through the project's api"
}, },
status=status.HTTP_400_BAD_REQUEST, status=status.HTTP_400_BAD_REQUEST,
) )

View File

@ -103,16 +103,19 @@ class ProjectListSerializer(DynamicBaseSerializer):
members = serializers.SerializerMethodField() members = serializers.SerializerMethodField()
def get_members(self, obj): def get_members(self, obj):
project_members = ProjectMember.objects.filter( project_members = getattr(obj, "members_list", None)
project_id=obj.id, if project_members is not None:
is_active=True, # Filter members by the project ID
).values( return [
"id", {
"member_id", "id": member.id,
"member__display_name", "member_id": member.member_id,
"member__avatar", "member__display_name": member.member.display_name,
) "member__avatar": member.member.avatar,
return list(project_members) }
for member in project_members
]
return []
class Meta: class Meta:
model = Project model = Project

View File

@ -130,7 +130,6 @@ from .page import (
PageFavoriteViewSet, PageFavoriteViewSet,
PageLogEndpoint, PageLogEndpoint,
SubPagesEndpoint, SubPagesEndpoint,
CreateIssueFromBlockEndpoint,
) )
from .search import GlobalSearchEndpoint, IssueSearchEndpoint from .search import GlobalSearchEndpoint, IssueSearchEndpoint

View File

@ -22,6 +22,7 @@ from plane.db.models import (
IssueAssignee, IssueAssignee,
IssueActivity, IssueActivity,
PageLog, PageLog,
ProjectMember,
) )
from plane.app.serializers import ( from plane.app.serializers import (
PageSerializer, PageSerializer,
@ -140,12 +141,6 @@ class PageViewSet(BaseViewSet):
pk=page_id, workspace__slug=slug, project_id=project_id pk=page_id, workspace__slug=slug, project_id=project_id
).first() ).first()
# only the owner can lock the page
if request.user.id != page.owned_by_id:
return Response(
{"error": "Only the page owner can lock the page"},
)
page.is_locked = True page.is_locked = True
page.save() page.save()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
@ -155,12 +150,6 @@ class PageViewSet(BaseViewSet):
pk=page_id, workspace__slug=slug, project_id=project_id pk=page_id, workspace__slug=slug, project_id=project_id
).first() ).first()
# only the owner can unlock the page
if request.user.id != page.owned_by_id:
return Response(
{"error": "Only the page owner can unlock the page"},
status=status.HTTP_400_BAD_REQUEST,
)
page.is_locked = False page.is_locked = False
page.save() page.save()
@ -175,10 +164,16 @@ class PageViewSet(BaseViewSet):
def archive(self, request, slug, project_id, page_id): def archive(self, request, slug, project_id, page_id):
page = Page.objects.get(pk=page_id, workspace__slug=slug, project_id=project_id) page = Page.objects.get(pk=page_id, workspace__slug=slug, project_id=project_id)
if page.owned_by_id != request.user.id: # only the owner and admin can archive the page
if (
ProjectMember.objects.filter(
project_id=project_id, member=request.user, is_active=True, role__gt=20
).exists()
or request.user.id != page.owned_by_id
):
return Response( return Response(
{"error": "Only the owner of the page can archive a page"}, {"error": "Only the owner and admin can archive the page"},
status=status.HTTP_204_NO_CONTENT, status=status.HTTP_400_BAD_REQUEST,
) )
unarchive_archive_page_and_descendants(page_id, datetime.now()) unarchive_archive_page_and_descendants(page_id, datetime.now())
@ -188,9 +183,15 @@ class PageViewSet(BaseViewSet):
def unarchive(self, request, slug, project_id, page_id): def unarchive(self, request, slug, project_id, page_id):
page = Page.objects.get(pk=page_id, workspace__slug=slug, project_id=project_id) page = Page.objects.get(pk=page_id, workspace__slug=slug, project_id=project_id)
if page.owned_by_id != request.user.id: # only the owner and admin can un archive the page
if (
ProjectMember.objects.filter(
project_id=project_id, member=request.user, is_active=True, role__gt=20
).exists()
or request.user.id != page.owned_by_id
):
return Response( return Response(
{"error": "Only the owner of the page can unarchive a page"}, {"error": "Only the owner and admin can un archive the page"},
status=status.HTTP_400_BAD_REQUEST, status=status.HTTP_400_BAD_REQUEST,
) )
@ -216,6 +217,18 @@ class PageViewSet(BaseViewSet):
def destroy(self, request, slug, project_id, pk): def destroy(self, request, slug, project_id, pk):
page = Page.objects.get(pk=pk, workspace__slug=slug, project_id=project_id) page = Page.objects.get(pk=pk, workspace__slug=slug, project_id=project_id)
# only the owner and admin can delete the page
if (
ProjectMember.objects.filter(
project_id=project_id, member=request.user, is_active=True, role__gt=20
).exists()
or request.user.id != page.owned_by_id
):
return Response(
{"error": "Only the owner and admin can delete the page"},
status=status.HTTP_400_BAD_REQUEST,
)
if page.archived_at is None: if page.archived_at is None:
return Response( return Response(
{"error": "The page should be archived before deleting"}, {"error": "The page should be archived before deleting"},
@ -227,7 +240,6 @@ class PageViewSet(BaseViewSet):
parent_id=pk, project_id=project_id, workspace__slug=slug parent_id=pk, project_id=project_id, workspace__slug=slug
).update(parent=None) ).update(parent=None)
page.delete() page.delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
@ -310,36 +322,6 @@ class PageLogEndpoint(BaseAPIView):
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
class CreateIssueFromBlockEndpoint(BaseAPIView):
permission_classes = [
ProjectEntityPermission,
]
def post(self, request, slug, project_id, page_id):
page = Page.objects.get(
workspace__slug=slug,
project_id=project_id,
pk=page_id,
)
issue = Issue.objects.create(
name=request.data.get("name"),
project_id=project_id,
)
_ = IssueAssignee.objects.create(
issue=issue, assignee=request.user, project_id=project_id
)
_ = IssueActivity.objects.create(
issue=issue,
actor=request.user,
project_id=project_id,
comment=f"created the issue from {page.name} block",
verb="created",
)
return Response(IssueLiteSerializer(issue).data, status=status.HTTP_200_OK)
class SubPagesEndpoint(BaseAPIView): class SubPagesEndpoint(BaseAPIView):
permission_classes = [ permission_classes = [
ProjectEntityPermission, ProjectEntityPermission,

View File

@ -165,6 +165,7 @@ class ProjectViewSet(WebhookMixin, BaseViewSet):
workspace__slug=slug, workspace__slug=slug,
is_active=True, is_active=True,
).select_related("member"), ).select_related("member"),
to_attr='members_list'
) )
) )
.order_by("sort_order", "name") .order_by("sort_order", "name")