mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: guest user profile access-related problem (#3089)
* fix: resolve guest user profile access-related problem * chore: header and app sidebar permission validation added
This commit is contained in:
parent
2605b938f0
commit
6c61fbd102
@ -16,6 +16,7 @@ import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOption
|
|||||||
// constants
|
// constants
|
||||||
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
|
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
|
||||||
import { EFilterType } from "store/issues/types";
|
import { EFilterType } from "store/issues/types";
|
||||||
|
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||||
|
|
||||||
const GLOBAL_VIEW_LAYOUTS = [
|
const GLOBAL_VIEW_LAYOUTS = [
|
||||||
{ key: "list", title: "List", link: "/workspace-views", icon: List },
|
{ key: "list", title: "List", link: "/workspace-views", icon: List },
|
||||||
@ -38,7 +39,7 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
|
|||||||
workspace: { workspaceLabels },
|
workspace: { workspaceLabels },
|
||||||
workspaceMember: { workspaceMembers },
|
workspaceMember: { workspaceMembers },
|
||||||
project: { workspaceProjects },
|
project: { workspaceProjects },
|
||||||
|
user: { currentWorkspaceRole },
|
||||||
workspaceGlobalIssuesFilter: { issueFilters, updateFilters },
|
workspaceGlobalIssuesFilter: { issueFilters, updateFilters },
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
@ -77,6 +78,8 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
|
|||||||
[workspaceSlug, updateFilters]
|
[workspaceSlug, updateFilters]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
|
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
|
||||||
@ -142,10 +145,11 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
|
|||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{isAuthorizedUser && (
|
||||||
<Button variant="primary" size="sm" prependIcon={<PlusIcon />} onClick={() => setCreateViewModal(true)}>
|
<Button variant="primary" size="sm" prependIcon={<PlusIcon />} onClick={() => setCreateViewModal(true)}>
|
||||||
New View
|
New View
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -5,6 +5,8 @@ import { Breadcrumbs, Button } from "@plane/ui";
|
|||||||
// hooks
|
// hooks
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
// constants
|
||||||
|
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||||
|
|
||||||
export const ProjectsHeader = observer(() => {
|
export const ProjectsHeader = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -15,10 +17,13 @@ export const ProjectsHeader = observer(() => {
|
|||||||
project: projectStore,
|
project: projectStore,
|
||||||
commandPalette: commandPaletteStore,
|
commandPalette: commandPaletteStore,
|
||||||
trackEvent: { setTrackElement },
|
trackEvent: { setTrackElement },
|
||||||
|
user: { currentWorkspaceRole },
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
const projectsList = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : [];
|
const projectsList = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : [];
|
||||||
|
|
||||||
|
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
|
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
|
||||||
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
|
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
|
||||||
@ -44,17 +49,18 @@ export const ProjectsHeader = observer(() => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{isAuthorizedUser && (
|
||||||
<Button
|
<Button
|
||||||
prependIcon={<Plus />}
|
prependIcon={<Plus />}
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTrackElement("PROJECTS_PAGE_HEADER");
|
setTrackElement("PROJECTS_PAGE_HEADER");
|
||||||
commandPaletteStore.toggleCreateProjectModal(true);
|
commandPaletteStore.toggleCreateProjectModal(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Add Project
|
Add Project
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -17,6 +17,8 @@ import { orderArrayBy } from "helpers/array.helper";
|
|||||||
import { IProject } from "types";
|
import { IProject } from "types";
|
||||||
// mobx store
|
// mobx store
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
|
// constants
|
||||||
|
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||||
|
|
||||||
export const ProjectSidebarList: FC = observer(() => {
|
export const ProjectSidebarList: FC = observer(() => {
|
||||||
// states
|
// states
|
||||||
@ -31,6 +33,7 @@ export const ProjectSidebarList: FC = observer(() => {
|
|||||||
project: { joinedProjects, favoriteProjects, orderProjectsWithSortOrder, updateProjectView },
|
project: { joinedProjects, favoriteProjects, orderProjectsWithSortOrder, updateProjectView },
|
||||||
commandPalette: { toggleCreateProjectModal },
|
commandPalette: { toggleCreateProjectModal },
|
||||||
trackEvent: { setTrackElement },
|
trackEvent: { setTrackElement },
|
||||||
|
user: { currentWorkspaceRole },
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -39,6 +42,8 @@ export const ProjectSidebarList: FC = observer(() => {
|
|||||||
// toast
|
// toast
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
|
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
const orderedJoinedProjects: IProject[] | undefined = joinedProjects
|
const orderedJoinedProjects: IProject[] | undefined = joinedProjects
|
||||||
? orderArrayBy(joinedProjects, "sort_order", "ascending")
|
? orderArrayBy(joinedProjects, "sort_order", "ascending")
|
||||||
: undefined;
|
: undefined;
|
||||||
@ -138,16 +143,18 @@ export const ProjectSidebarList: FC = observer(() => {
|
|||||||
<ChevronRight className="h-3 w-3 opacity-0 group-hover:opacity-100" />
|
<ChevronRight className="h-3 w-3 opacity-0 group-hover:opacity-100" />
|
||||||
)}
|
)}
|
||||||
</Disclosure.Button>
|
</Disclosure.Button>
|
||||||
<button
|
{isAuthorizedUser && (
|
||||||
className="opacity-0 group-hover:opacity-100"
|
<button
|
||||||
onClick={() => {
|
className="opacity-0 group-hover:opacity-100"
|
||||||
setTrackElement("APP_SIDEBAR_FAVORITES_BLOCK");
|
onClick={() => {
|
||||||
setIsFavoriteProjectCreate(true);
|
setTrackElement("APP_SIDEBAR_FAVORITES_BLOCK");
|
||||||
setIsProjectModalOpen(true);
|
setIsFavoriteProjectCreate(true);
|
||||||
}}
|
setIsProjectModalOpen(true);
|
||||||
>
|
}}
|
||||||
<Plus className="h-3 w-3" />
|
>
|
||||||
</button>
|
<Plus className="h-3 w-3" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Transition
|
<Transition
|
||||||
@ -213,15 +220,17 @@ export const ProjectSidebarList: FC = observer(() => {
|
|||||||
<ChevronRight className="h-3 w-3 opacity-0 group-hover:opacity-100" />
|
<ChevronRight className="h-3 w-3 opacity-0 group-hover:opacity-100" />
|
||||||
)}
|
)}
|
||||||
</Disclosure.Button>
|
</Disclosure.Button>
|
||||||
<button
|
{isAuthorizedUser && (
|
||||||
className="opacity-0 group-hover:opacity-100"
|
<button
|
||||||
onClick={() => {
|
className="opacity-0 group-hover:opacity-100"
|
||||||
setIsFavoriteProjectCreate(false);
|
onClick={() => {
|
||||||
setIsProjectModalOpen(true);
|
setIsFavoriteProjectCreate(false);
|
||||||
}}
|
setIsProjectModalOpen(true);
|
||||||
>
|
}}
|
||||||
<Plus className="h-3 w-3" />
|
>
|
||||||
</button>
|
<Plus className="h-3 w-3" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Transition
|
<Transition
|
||||||
@ -260,7 +269,7 @@ export const ProjectSidebarList: FC = observer(() => {
|
|||||||
</Droppable>
|
</Droppable>
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
|
|
||||||
{joinedProjects && joinedProjects.length === 0 && (
|
{isAuthorizedUser && joinedProjects && joinedProjects.length === 0 && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="flex w-full items-center gap-2 px-3 text-sm text-custom-sidebar-text-200"
|
className="flex w-full items-center gap-2 px-3 text-sm text-custom-sidebar-text-200"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
// mobx store
|
// mobx store
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// components
|
// components
|
||||||
@ -14,6 +15,7 @@ const AUTHORIZED_ROLES = [20, 15, 10];
|
|||||||
|
|
||||||
export const ProfileAuthWrapper: React.FC<Props> = observer((props) => {
|
export const ProfileAuthWrapper: React.FC<Props> = observer((props) => {
|
||||||
const { children, className, showProfileIssuesFilter } = props;
|
const { children, className, showProfileIssuesFilter } = props;
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
user: { currentWorkspaceRole },
|
user: { currentWorkspaceRole },
|
||||||
@ -23,12 +25,14 @@ export const ProfileAuthWrapper: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
const isAuthorized = AUTHORIZED_ROLES.includes(currentWorkspaceRole);
|
const isAuthorized = AUTHORIZED_ROLES.includes(currentWorkspaceRole);
|
||||||
|
|
||||||
|
const isAuthorizedPath = router.pathname.includes("assigned" || "created" || "subscribed");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-full md:flex md:flex-row-reverse md:overflow-hidden">
|
<div className="h-full w-full md:flex md:flex-row-reverse md:overflow-hidden">
|
||||||
<ProfileSidebar />
|
<ProfileSidebar />
|
||||||
<div className="flex w-full flex-col md:h-full md:overflow-hidden">
|
<div className="flex w-full flex-col md:h-full md:overflow-hidden">
|
||||||
<ProfileNavbar isAuthorized={isAuthorized} showProfileIssuesFilter={showProfileIssuesFilter} />
|
<ProfileNavbar isAuthorized={isAuthorized} showProfileIssuesFilter={showProfileIssuesFilter} />
|
||||||
{isAuthorized ? (
|
{isAuthorized || !isAuthorizedPath ? (
|
||||||
<div className={`w-full overflow-hidden md:h-full ${className}`}>{children}</div>
|
<div className={`w-full overflow-hidden md:h-full ${className}`}>{children}</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="grid h-full w-full place-items-center text-custom-text-200">
|
<div className="grid h-full w-full place-items-center text-custom-text-200">
|
||||||
|
Loading…
Reference in New Issue
Block a user