[WEB-2357] fix: update and redefine user roles across the platform (#5466)
* chore: removed viewer role * chore: indentation * chore: remove viewer role * chore: handled user permissions in store * chore: updated the migration file * chore: updated user permissions store * chore: removed the owner key * chore: code refactor * chore: code refactor * chore: code refactor * chore: code refactor * chore: code refactor * fix: build error * chore: updated user permissions store and handled the permissions fetch in workspace and project wrappers * chore: package user enum updated * chore: user permission updated * chore: user permission updated * chore: resolved build errors * chore: resolved build error * chore: resolved build errors * chore: computedFn deep map issue resolved * chore: added back migration * chore: added new field in project table * chore: removed member store in users * chore: private project for admins * chore: workspace notification access validation updated * fix: workspace member edit option * fix: project intake permission validation updated * chore: workspace export settings permission updated * chore: guest_view_all_issues added * chore: guest_view_all_issues added * chore: key changed for guest access * chore: added validation for individual issues * chore: changed the dashboard issues count * chore: added new yarn file * chore: modified yarn file * chore: project page permission updated * chore: project page permission updated * chore: member setting ux updated * chore: build error * fix: yarn lock * fix: build error --------- Co-authored-by: gurusainath <gurusainath007@gmail.com> Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@plane.so>
This commit is contained in:
parent
7013a36629
commit
fdcd9a376c
172 changed files with 2057 additions and 1627 deletions
|
|
@ -16,7 +16,8 @@ import { APITokenSettingsLoader } from "@/components/ui";
|
|||
import { EmptyStateType } from "@/constants/empty-state";
|
||||
import { API_TOKENS_LIST } from "@/constants/fetch-keys";
|
||||
// store hooks
|
||||
import { useUser, useWorkspace } from "@/hooks/store";
|
||||
import { useUserPermissions, useWorkspace } from "@/hooks/store";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
// services
|
||||
import { APITokenService } from "@/services/api_token.service";
|
||||
|
||||
|
|
@ -28,11 +29,10 @@ const ApiTokensPage = observer(() => {
|
|||
// router
|
||||
const { workspaceSlug } = useParams();
|
||||
// store hooks
|
||||
const {
|
||||
canPerformWorkspaceAdminActions,
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
|
||||
// derived values
|
||||
const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
|
||||
|
||||
const { data: tokens } = useSWR(
|
||||
workspaceSlug && canPerformWorkspaceAdminActions ? API_TOKENS_LIST(workspaceSlug.toString()) : null,
|
||||
|
|
@ -42,7 +42,7 @@ const ApiTokensPage = observer(() => {
|
|||
|
||||
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - API Tokens` : undefined;
|
||||
|
||||
if (currentWorkspaceRole && !canPerformWorkspaceAdminActions) {
|
||||
if (workspaceUserInfo && !canPerformWorkspaceAdminActions) {
|
||||
return <NotAuthorizedView section="settings" />;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,21 +5,20 @@ import { observer } from "mobx-react";
|
|||
import { NotAuthorizedView } from "@/components/auth-screens";
|
||||
import { PageHead } from "@/components/core";
|
||||
// hooks
|
||||
import { useUser, useWorkspace } from "@/hooks/store";
|
||||
import { useUserPermissions, useWorkspace } from "@/hooks/store";
|
||||
// plane web components
|
||||
import { BillingRoot } from "@/plane-web/components/workspace";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
|
||||
const BillingSettingsPage = observer(() => {
|
||||
// store hooks
|
||||
const {
|
||||
canPerformWorkspaceAdminActions,
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
// derived values
|
||||
const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
|
||||
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Billing & Plans` : undefined;
|
||||
|
||||
if (currentWorkspaceRole && !canPerformWorkspaceAdminActions) {
|
||||
if (workspaceUserInfo && !canPerformWorkspaceAdminActions) {
|
||||
return <NotAuthorizedView section="settings" />;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,22 +8,23 @@ import ExportGuide from "@/components/exporter/guide";
|
|||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
// hooks
|
||||
import { useUser, useWorkspace } from "@/hooks/store";
|
||||
import { useUserPermissions, useWorkspace } from "@/hooks/store";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
|
||||
const ExportsPage = observer(() => {
|
||||
// store hooks
|
||||
const {
|
||||
canPerformWorkspaceViewerActions,
|
||||
canPerformWorkspaceMemberActions,
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
// derived values
|
||||
const canPerformWorkspaceMemberActions = allowPermissions(
|
||||
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
|
||||
EUserPermissionsLevel.WORKSPACE
|
||||
);
|
||||
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Exports` : undefined;
|
||||
|
||||
// if user is not authorized to view this page
|
||||
if (currentWorkspaceRole && !canPerformWorkspaceViewerActions) {
|
||||
if (workspaceUserInfo && !canPerformWorkspaceMemberActions) {
|
||||
return <NotAuthorizedView section="settings" />;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,20 +4,17 @@ import { observer } from "mobx-react";
|
|||
// components
|
||||
import { PageHead } from "@/components/core";
|
||||
import IntegrationGuide from "@/components/integration/guide";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
||||
// hooks
|
||||
import { useUser, useWorkspace } from "@/hooks/store";
|
||||
import { useUserPermissions, useWorkspace } from "@/hooks/store";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
|
||||
const ImportsPage = observer(() => {
|
||||
// store hooks
|
||||
const {
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
|
||||
// derived values
|
||||
const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN;
|
||||
const isAdmin = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
|
||||
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Imports` : undefined;
|
||||
|
||||
if (!isAdmin)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import { SingleIntegrationCard } from "@/components/integration";
|
|||
import { IntegrationAndImportExportBanner, IntegrationsSettingsLoader } from "@/components/ui";
|
||||
// constants
|
||||
import { APP_INTEGRATIONS } from "@/constants/fetch-keys";
|
||||
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
||||
// hooks
|
||||
import { useUser, useWorkspace } from "@/hooks/store";
|
||||
import { useUserPermissions, useWorkspace } from "@/hooks/store";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
// services
|
||||
import { IntegrationService } from "@/services/integrations";
|
||||
|
||||
|
|
@ -20,13 +20,11 @@ const WorkspaceIntegrationsPage = observer(() => {
|
|||
// router
|
||||
const { workspaceSlug } = useParams();
|
||||
// store hooks
|
||||
const {
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
|
||||
// derived values
|
||||
const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN;
|
||||
const isAdmin = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
|
||||
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Integrations` : undefined;
|
||||
|
||||
if (!isAdmin)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ import { MEMBER_INVITED } from "@/constants/event-tracker";
|
|||
import { cn } from "@/helpers/common.helper";
|
||||
import { getUserRole } from "@/helpers/user.helper";
|
||||
// hooks
|
||||
import { useEventTracker, useMember, useUser, useWorkspace } from "@/hooks/store";
|
||||
import { useEventTracker, useMember, useUserPermissions, useWorkspace } from "@/hooks/store";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
|
||||
const WorkspaceMembersSettingsPage = observer(() => {
|
||||
// states
|
||||
|
|
@ -27,18 +28,20 @@ const WorkspaceMembersSettingsPage = observer(() => {
|
|||
// router
|
||||
const { workspaceSlug } = useParams();
|
||||
// store hooks
|
||||
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
|
||||
const { captureEvent } = useEventTracker();
|
||||
const {
|
||||
canPerformWorkspaceAdminActions,
|
||||
canPerformWorkspaceViewerActions,
|
||||
canPerformWorkspaceMemberActions,
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
const {
|
||||
workspace: { inviteMembersToWorkspace },
|
||||
} = useMember();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
// derived values
|
||||
const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
|
||||
const canPerformWorkspaceMemberActions = allowPermissions(
|
||||
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
|
||||
EUserPermissionsLevel.WORKSPACE
|
||||
);
|
||||
|
||||
const handleWorkspaceInvite = (data: IWorkspaceBulkInviteFormData) => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
|
|
@ -49,7 +52,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
|
|||
emails: [
|
||||
...data.emails.map((email) => ({
|
||||
email: email.email,
|
||||
role: getUserRole(email.role),
|
||||
role: getUserRole(email.role as unknown as EUserPermissions),
|
||||
})),
|
||||
],
|
||||
project_id: undefined,
|
||||
|
|
@ -67,7 +70,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
|
|||
emails: [
|
||||
...data.emails.map((email) => ({
|
||||
email: email.email,
|
||||
role: getUserRole(email.role),
|
||||
role: getUserRole(email.role as unknown as EUserPermissions),
|
||||
})),
|
||||
],
|
||||
project_id: undefined,
|
||||
|
|
@ -86,7 +89,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
|
|||
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Members` : undefined;
|
||||
|
||||
// if user is not authorized to view this page
|
||||
if (currentWorkspaceRole && !canPerformWorkspaceViewerActions) {
|
||||
if (workspaceUserInfo && !canPerformWorkspaceMemberActions) {
|
||||
return <NotAuthorizedView section="settings" />;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import { observer } from "mobx-react";
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
||||
// hooks
|
||||
import { useUser } from "@/hooks/store";
|
||||
import { useUserPermissions } from "@/hooks/store";
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
// plane web constants
|
||||
import { EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
import { WORKSPACE_SETTINGS_LINKS } from "@/plane-web/constants/workspace";
|
||||
// plane web helpers
|
||||
import { shouldRenderSettingLink } from "@/plane-web/helpers/workspace.helper";
|
||||
|
|
@ -15,19 +14,14 @@ export const MobileWorkspaceSettingsTabs = observer(() => {
|
|||
const { workspaceSlug } = useParams();
|
||||
const pathname = usePathname();
|
||||
// mobx store
|
||||
const {
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
|
||||
// derived values
|
||||
const workspaceMemberInfo = currentWorkspaceRole || EUserWorkspaceRoles.GUEST;
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
|
||||
return (
|
||||
<div className="flex-shrink-0 md:hidden sticky inset-0 flex overflow-x-auto bg-custom-background-100 z-10">
|
||||
{WORKSPACE_SETTINGS_LINKS.map(
|
||||
(item, index) =>
|
||||
shouldRenderSettingLink(item.key) &&
|
||||
workspaceMemberInfo >= item.access && (
|
||||
allowPermissions(item.access, EUserPermissionsLevel.WORKSPACE, workspaceSlug.toString()) && (
|
||||
<div
|
||||
className={`${
|
||||
item.highlight(pathname, `/${workspaceSlug}`)
|
||||
|
|
|
|||
|
|
@ -6,11 +6,10 @@ import Link from "next/link";
|
|||
import { useParams, usePathname } from "next/navigation";
|
||||
// components
|
||||
import { SidebarNavItem } from "@/components/sidebar";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
||||
// hooks
|
||||
import { useUser } from "@/hooks/store";
|
||||
import { useUserPermissions } from "@/hooks/store";
|
||||
// plane web constants
|
||||
import { EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
import { WORKSPACE_SETTINGS_LINKS } from "@/plane-web/constants/workspace";
|
||||
// plane web helpers
|
||||
import { shouldRenderSettingLink } from "@/plane-web/helpers/workspace.helper";
|
||||
|
|
@ -20,12 +19,7 @@ export const WorkspaceSettingsSidebar = observer(() => {
|
|||
const { workspaceSlug } = useParams();
|
||||
const pathname = usePathname();
|
||||
// mobx store
|
||||
const {
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
|
||||
// derived values
|
||||
const workspaceMemberInfo = currentWorkspaceRole || EUserWorkspaceRoles.GUEST;
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
|
||||
return (
|
||||
<div className="flex w-[280px] flex-col gap-6">
|
||||
|
|
@ -35,7 +29,7 @@ export const WorkspaceSettingsSidebar = observer(() => {
|
|||
{WORKSPACE_SETTINGS_LINKS.map(
|
||||
(link) =>
|
||||
shouldRenderSettingLink(link.key) &&
|
||||
workspaceMemberInfo >= link.access && (
|
||||
allowPermissions(link.access, EUserPermissionsLevel.WORKSPACE, workspaceSlug.toString()) && (
|
||||
<Link key={link.key} href={`/${workspaceSlug}${link.href}`}>
|
||||
<SidebarNavItem
|
||||
key={link.key}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ import { LogoSpinner } from "@/components/common";
|
|||
import { PageHead } from "@/components/core";
|
||||
import { DeleteWebhookModal, WebhookDeleteSection, WebhookForm } from "@/components/web-hooks";
|
||||
// hooks
|
||||
import { useUser, useWebhook, useWorkspace } from "@/hooks/store";
|
||||
import { useUserPermissions, useWebhook, useWorkspace } from "@/hooks/store";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
|
||||
const WebhookDetailsPage = observer(() => {
|
||||
// states
|
||||
|
|
@ -20,18 +21,17 @@ const WebhookDetailsPage = observer(() => {
|
|||
// router
|
||||
const { workspaceSlug, webhookId } = useParams();
|
||||
// mobx store
|
||||
const {
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
const { currentWebhook, fetchWebhookById, updateWebhook } = useWebhook();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
|
||||
// TODO: fix this error
|
||||
// useEffect(() => {
|
||||
// if (isCreated !== "true") clearSecretKey();
|
||||
// }, [clearSecretKey, isCreated]);
|
||||
|
||||
const isAdmin = currentWorkspaceRole === 20;
|
||||
// derived values
|
||||
const isAdmin = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
|
||||
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Webhook` : undefined;
|
||||
|
||||
useSWR(
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ import { WebhooksList, CreateWebhookModal } from "@/components/web-hooks";
|
|||
// constants
|
||||
import { EmptyStateType } from "@/constants/empty-state";
|
||||
// hooks
|
||||
import { useUser, useWebhook, useWorkspace } from "@/hooks/store";
|
||||
import { useUserPermissions, useWebhook, useWorkspace } from "@/hooks/store";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
|
||||
const WebhooksListPage = observer(() => {
|
||||
// states
|
||||
|
|
@ -23,13 +24,13 @@ const WebhooksListPage = observer(() => {
|
|||
// router
|
||||
const { workspaceSlug } = useParams();
|
||||
// mobx store
|
||||
const {
|
||||
canPerformWorkspaceAdminActions,
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
|
||||
|
||||
const { fetchWebhooks, webhooks, clearSecretKey, webhookSecretKey, createWebhook } = useWebhook();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
|
||||
|
||||
useSWR(
|
||||
workspaceSlug && canPerformWorkspaceAdminActions ? `WEBHOOKS_LIST_${workspaceSlug}` : null,
|
||||
workspaceSlug && canPerformWorkspaceAdminActions ? () => fetchWebhooks(workspaceSlug.toString()) : null
|
||||
|
|
@ -42,7 +43,7 @@ const WebhooksListPage = observer(() => {
|
|||
if (!showCreateWebhookModal && webhookSecretKey) clearSecretKey();
|
||||
}, [showCreateWebhookModal, webhookSecretKey, clearSecretKey]);
|
||||
|
||||
if (currentWorkspaceRole && !canPerformWorkspaceAdminActions) {
|
||||
if (workspaceUserInfo && !canPerformWorkspaceAdminActions) {
|
||||
return <NotAuthorizedView section="settings" />;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue