-
Notifications
You must be signed in to change notification settings - Fork 3.6k
dev: revamp pages authorization #6094
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+101
to
+111
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add null safety checks and improve error handling While the implementation aligns with the PR objectives, consider these improvements for better robustness:
Consider this safer implementation: get canCurrentUserCreatePage() {
const { workspaceSlug, projectId } = this.store.router;
+ if (!workspaceSlug || !projectId) return false;
const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
- workspaceSlug?.toString() || "",
- projectId?.toString() || ""
+ workspaceSlug.toString(),
+ projectId.toString()
);
- return !!currentUserProjectRole && currentUserProjectRole >= EUserPermissions.MEMBER;
+ try {
+ return typeof currentUserProjectRole === 'number' && currentUserProjectRole >= EUserPermissions.MEMBER;
+ } catch (error) {
+ console.error('Error checking page creation permission:', error);
+ return false;
+ }
}📝 Committable suggestion
Suggested change
💡 Codebase verification Additional permission checks required for page operations The implementation shows that lock/unlock and archive/restore operations are restricted to page owners and admin users only (
These permission checks should be updated to consistently allow members and above for all operations, as per the PR objectives. 🔗 Analysis chainVerify coverage of all PR objectives While this implementation correctly handles the page creation permission requirements, the PR objectives also mention restrictions for lock/unlock, archive/restore, and access change operations. These operations should be implemented with similar permission checks. Let's verify if these operations are implemented elsewhere: Let's search specifically for permission checks related to page operations. Let's check the permission levels required for lock/unlock and archive/restore operations. Let's get the implementation details of these permission checks. Let's try a different approach to get the implementation details. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Search for lock/unlock, archive/restore implementations
rg -l "lock|unlock|archive|restore" --type ts
# Search for permission checks in those files
ast-grep --pattern 'permission.$$$' --lang ts
Length of output: 26076 Script: #!/bin/bash
# Search for page-related permission checks in service and store files
rg -A 5 "lock|unlock|archive|restore" web/core/services/page/project-page.service.ts web/core/store/pages/page.ts
# Search for page permission implementations
ast-grep --pattern 'canCurrentUser$_' --lang ts
Length of output: 11550 Script: #!/bin/bash
# Search for permission checks related to page operations
rg -B 5 "canCurrentUser(Lock|Archive)Page" web/core/store/pages/page.ts
Length of output: 1025 Script: #!/bin/bash
# Get the implementation of permission check methods
ast-grep --pattern 'get canCurrentUser(Lock|Archive)Page() {
$$$
}' --lang ts
Length of output: 552 Script: #!/bin/bash
# Get the implementation of permission check methods
rg -A 10 "get canCurrentUserLockPage\(\)" web/core/store/pages/page.ts
rg -A 10 "get canCurrentUserArchivePage\(\)" web/core/store/pages/page.ts
Length of output: 1091 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @description get the current project page ids based on the pageType | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param {TPageNavigationTabs} pageType | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider allowing admins to edit private pages
The current implementation might be too restrictive as it prevents admins from editing private pages unless they're the owner. Consider updating the logic to:
return ( (isPagePublic && !!currentUserProjectRole && currentUserProjectRole >= EUserPermissions.MEMBER) || - (!isPagePublic && this.isCurrentUserOwner) + (!isPagePublic && (this.isCurrentUserOwner || currentUserProjectRole === EUserPermissions.ADMIN)) );📝 Committable suggestion