Skip to content

Commit

Permalink
dev: revamp pages authorization
Browse files Browse the repository at this point in the history
  • Loading branch information
aaryan610 committed Nov 26, 2024
1 parent 1cb16bf commit e856c91
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 30 deletions.
16 changes: 8 additions & 8 deletions apiserver/plane/app/views/page/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def get_queryset(self):
.distinct()
)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def create(self, request, slug, project_id):
serializer = PageSerializer(
data=request.data,
Expand All @@ -134,7 +134,7 @@ def create(self, request, slug, project_id):
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def partial_update(self, request, slug, project_id, pk):
try:
page = Page.objects.get(
Expand Down Expand Up @@ -234,7 +234,7 @@ def retrieve(self, request, slug, project_id, pk=None):
)
return Response(data, status=status.HTTP_200_OK)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
@allow_permission([ROLE.ADMIN], model=Page, creator=True)
def lock(self, request, slug, project_id, pk):
page = Page.objects.filter(
pk=pk, workspace__slug=slug, projects__id=project_id
Expand All @@ -244,7 +244,7 @@ def lock(self, request, slug, project_id, pk):
page.save()
return Response(status=status.HTTP_204_NO_CONTENT)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
@allow_permission([ROLE.ADMIN], model=Page, creator=True)
def unlock(self, request, slug, project_id, pk):
page = Page.objects.filter(
pk=pk, workspace__slug=slug, projects__id=project_id
Expand All @@ -255,7 +255,7 @@ def unlock(self, request, slug, project_id, pk):

return Response(status=status.HTTP_204_NO_CONTENT)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
@allow_permission([ROLE.ADMIN], model=Page, creator=True)
def access(self, request, slug, project_id, pk):
access = request.data.get("access", 0)
page = Page.objects.filter(
Expand Down Expand Up @@ -296,7 +296,7 @@ def list(self, request, slug, project_id):
pages = PageSerializer(queryset, many=True).data
return Response(pages, status=status.HTTP_200_OK)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
@allow_permission([ROLE.ADMIN], model=Page, creator=True)
def archive(self, request, slug, project_id, pk):
page = Page.objects.get(pk=pk, workspace__slug=slug, projects__id=project_id)

Expand All @@ -323,7 +323,7 @@ def archive(self, request, slug, project_id, pk):

return Response({"archived_at": str(datetime.now())}, status=status.HTTP_200_OK)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
@allow_permission([ROLE.ADMIN], model=Page, creator=True)
def unarchive(self, request, slug, project_id, pk):
page = Page.objects.get(pk=pk, workspace__slug=slug, projects__id=project_id)

Expand All @@ -348,7 +348,7 @@ def unarchive(self, request, slug, project_id, pk):

return Response(status=status.HTTP_204_NO_CONTENT)

@allow_permission([ROLE.ADMIN], creator=True, model=Page)
@allow_permission([ROLE.ADMIN], model=Page, creator=True)
def destroy(self, request, slug, project_id, pk):
page = Page.objects.get(pk=pk, workspace__slug=slug, projects__id=project_id)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import { BreadcrumbLink, Logo } from "@/components/common";
// constants
import { EPageAccess } from "@/constants/page";
// hooks
import { useEventTracker, useProject, useProjectPages, useUserPermissions } from "@/hooks/store";
// plane web hooks
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
import { useEventTracker, useProject, useProjectPages } from "@/hooks/store";

export const PagesListHeader = observer(() => {
// states
Expand All @@ -26,16 +24,9 @@ export const PagesListHeader = observer(() => {
const searchParams = useSearchParams();
const pageType = searchParams.get("type");
// store hooks
const { allowPermissions } = useUserPermissions();

const { currentProjectDetails, loader } = useProject();
const { createPage } = useProjectPages();
const { canCurrentUserCreatePage, createPage } = useProjectPages();
const { setTrackElement } = useEventTracker();
// auth
const canUserCreatePage = allowPermissions(
[EUserPermissions.ADMIN, EUserPermissions.MEMBER, EUserPermissions.GUEST],
EUserPermissionsLevel.PROJECT
);
// handle page create
const handleCreatePage = async () => {
setIsCreatingPage(true);
Expand Down Expand Up @@ -88,7 +79,7 @@ export const PagesListHeader = observer(() => {
</Breadcrumbs>
</div>
</Header.LeftItem>
{canUserCreatePage ? (
{canCurrentUserCreatePage ? (
<Header.RightItem>
<Button variant="primary" size="sm" onClick={handleCreatePage} loading={isCreatingPage}>
{isCreatingPage ? "Adding" : "Add page"}
Expand Down
27 changes: 18 additions & 9 deletions web/core/store/pages/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,47 +215,58 @@ export class Page implements IPage {
*/
get canCurrentUserEditPage() {
const { workspaceSlug, projectId } = this.store.router;

const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
workspaceSlug?.toString() || "",
projectId?.toString() || ""
);
return this.isCurrentUserOwner || (!!currentUserProjectRole && currentUserProjectRole >= EUserPermissions.MEMBER);
const isPagePublic = this.access === EPageAccess.PUBLIC;
return (
(isPagePublic && !!currentUserProjectRole && currentUserProjectRole >= EUserPermissions.MEMBER) ||
(!isPagePublic && this.isCurrentUserOwner)
);
}

/**
* @description returns true if the current logged in user can create a duplicate the page
*/
get canCurrentUserDuplicatePage() {
const { workspaceSlug, projectId } = this.store.router;

const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
workspaceSlug?.toString() || "",
projectId?.toString() || ""
);
return this.isCurrentUserOwner || (!!currentUserProjectRole && currentUserProjectRole >= EUserPermissions.MEMBER);
return !!currentUserProjectRole && currentUserProjectRole >= EUserPermissions.MEMBER;
}

/**
* @description returns true if the current logged in user can lock the page
*/
get canCurrentUserLockPage() {
return this.isCurrentUserOwner;
const { workspaceSlug, projectId } = this.store.router;
const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
workspaceSlug?.toString() || "",
projectId?.toString() || ""
);
return this.isCurrentUserOwner || currentUserProjectRole === EUserPermissions.ADMIN;
}

/**
* @description returns true if the current logged in user can change the access of the page
*/
get canCurrentUserChangeAccess() {
return this.isCurrentUserOwner;
const { workspaceSlug, projectId } = this.store.router;
const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
workspaceSlug?.toString() || "",
projectId?.toString() || ""
);
return this.isCurrentUserOwner || currentUserProjectRole === EUserPermissions.ADMIN;
}

/**
* @description returns true if the current logged in user can archive the page
*/
get canCurrentUserArchivePage() {
const { workspaceSlug, projectId } = this.store.router;

const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
workspaceSlug?.toString() || "",
projectId?.toString() || ""
Expand All @@ -268,7 +279,6 @@ export class Page implements IPage {
*/
get canCurrentUserDeletePage() {
const { workspaceSlug, projectId } = this.store.router;

const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
workspaceSlug?.toString() || "",
projectId?.toString() || ""
Expand All @@ -281,7 +291,6 @@ export class Page implements IPage {
*/
get canCurrentUserFavoritePage() {
const { workspaceSlug, projectId } = this.store.router;

const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
workspaceSlug?.toString() || "",
projectId?.toString() || ""
Expand Down
20 changes: 19 additions & 1 deletion web/core/store/pages/project-page.store.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import set from "lodash/set";
import unset from "lodash/unset";
import { makeObservable, observable, runInAction, action, reaction } from "mobx";
import { makeObservable, observable, runInAction, action, reaction, computed } from "mobx";
import { computedFn } from "mobx-utils";
// types
import { TPage, TPageFilters, TPageNavigationTabs } from "@plane/types";
// helpers
import { filterPagesByPageType, getPageName, orderPages, shouldFilterPage } from "@/helpers/page.helper";
// plane web constants
import { EUserPermissions } from "@/plane-web/constants";
// services
import { ProjectPageService } from "@/services/page";
// store
Expand All @@ -24,6 +26,7 @@ export interface IProjectPageStore {
filters: TPageFilters;
// computed
isAnyPageAvailable: boolean;
canCurrentUserCreatePage: boolean;
// helper actions
getCurrentProjectPageIds: (pageType: TPageNavigationTabs) => string[] | undefined;
getCurrentProjectFilteredPageIds: (pageType: TPageNavigationTabs) => string[] | undefined;
Expand Down Expand Up @@ -62,6 +65,9 @@ export class ProjectPageStore implements IProjectPageStore {
data: observable,
error: observable,
filters: observable,
// computed
isAnyPageAvailable: computed,
canCurrentUserCreatePage: computed,
// helper actions
updateFilters: action,
clearAllFilters: action,
Expand Down Expand Up @@ -92,6 +98,18 @@ export class ProjectPageStore implements IProjectPageStore {
return Object.keys(this.data).length > 0;
}

/**
* @description returns true if the current logged in user can create a page
*/
get canCurrentUserCreatePage() {
const { workspaceSlug, projectId } = this.store.router;
const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
workspaceSlug?.toString() || "",
projectId?.toString() || ""
);
return !!currentUserProjectRole && currentUserProjectRole >= EUserPermissions.MEMBER;
}

/**
* @description get the current project page ids based on the pageType
* @param {TPageNavigationTabs} pageType
Expand Down

0 comments on commit e856c91

Please sign in to comment.