diff --git a/apiserver/plane/app/urls/page.py b/apiserver/plane/app/urls/page.py index 8ed0bd18d7..7c1ac5dfee 100644 --- a/apiserver/plane/app/urls/page.py +++ b/apiserver/plane/app/urls/page.py @@ -66,6 +66,16 @@ urlpatterns = [ ), name="project-pages-lock-unlock", ), + # private and public page + path( + "workspaces//projects//pages//access/", + PageViewSet.as_view( + { + "post": "access", + } + ), + name="project-pages-access", + ), path( "workspaces//projects//pages//transactions/", PageLogEndpoint.as_view(), diff --git a/apiserver/plane/app/views/page/base.py b/apiserver/plane/app/views/page/base.py index 1b2944294c..4bcaa8dfc8 100644 --- a/apiserver/plane/app/views/page/base.py +++ b/apiserver/plane/app/views/page/base.py @@ -245,6 +245,28 @@ class PageViewSet(BaseViewSet): return Response(status=status.HTTP_204_NO_CONTENT) + def access(self, request, slug, project_id, pk): + access = request.data.get("access", 0) + page = Page.objects.filter( + pk=pk, workspace__slug=slug, projects__id=project_id + ).first() + + # Only update access if the page owner is the requesting user + if ( + page.access != request.data.get("access", page.access) + and page.owned_by_id != request.user.id + ): + return Response( + { + "error": "Access cannot be updated since this page is owned by someone else" + }, + status=status.HTTP_400_BAD_REQUEST, + ) + + page.access = access + page.save() + return Response(status=status.HTTP_204_NO_CONTENT) + def list(self, request, slug, project_id): queryset = self.get_queryset() pages = PageSerializer(queryset, many=True).data diff --git a/web/core/services/page/project-page.service.ts b/web/core/services/page/project-page.service.ts index 1d82b4ebaf..8439f36ab0 100644 --- a/web/core/services/page/project-page.service.ts +++ b/web/core/services/page/project-page.service.ts @@ -42,6 +42,14 @@ export class ProjectPageService extends APIService { }); } + async updateAccess(workspaceSlug: string, projectId: string, pageId: string, data: Partial): Promise { + return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/access/`, data) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } + async remove(workspaceSlug: string, projectId: string, pageId: string): Promise { return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`) .then((response) => response?.data) diff --git a/web/core/store/pages/page.ts b/web/core/store/pages/page.ts index 7fd8bdf719..2b75b8594e 100644 --- a/web/core/store/pages/page.ts +++ b/web/core/store/pages/page.ts @@ -363,7 +363,7 @@ export class Page implements IPage { runInAction(() => (this.access = EPageAccess.PUBLIC)); try { - await this.pageService.update(workspaceSlug, projectId, this.id, { + await this.pageService.updateAccess(workspaceSlug, projectId, this.id, { access: EPageAccess.PUBLIC, }); } catch (error) { @@ -385,7 +385,7 @@ export class Page implements IPage { runInAction(() => (this.access = EPageAccess.PRIVATE)); try { - await this.pageService.update(workspaceSlug, projectId, this.id, { + await this.pageService.updateAccess (workspaceSlug, projectId, this.id, { access: EPageAccess.PRIVATE, }); } catch (error) {