From af222cbdd20ece23b382d2652ab546ead44f09ae Mon Sep 17 00:00:00 2001 From: Praveen Yadav Date: Sat, 9 Sep 2023 16:54:26 +0530 Subject: [PATCH] feat: support check permission for workspace actions --- .../general/general.workspace.tsx | 30 +++-- .../components/organization/general/index.tsx | 106 ++++++++++++++---- sdks/js/packages/core/utils/index.ts | 29 +++++ 3 files changed, 133 insertions(+), 32 deletions(-) diff --git a/sdks/js/packages/core/react/components/organization/general/general.workspace.tsx b/sdks/js/packages/core/react/components/organization/general/general.workspace.tsx index afdc32b12..53ddcc0d5 100644 --- a/sdks/js/packages/core/react/components/organization/general/general.workspace.tsx +++ b/sdks/js/packages/core/react/components/organization/general/general.workspace.tsx @@ -14,6 +14,7 @@ import { toast } from 'sonner'; import * as yup from 'yup'; import { useFrontier } from '~/react/contexts/FrontierContext'; import { V1Beta1Organization } from '~/src'; +import { PERMISSIONS } from '~/utils'; const generalSchema = yup .object({ @@ -24,10 +25,14 @@ const generalSchema = yup export const GeneralOrganization = ({ organization, - isLoading + isLoading, + organizationPermissions, + permissionMap }: { organization?: V1Beta1Organization; isLoading?: boolean; + organizationPermissions?: Record; + permissionMap?: Record; }) => { const { client } = useFrontier(); const { @@ -111,15 +116,20 @@ export const GeneralOrganization = ({ - + {organizationPermissions && + organizationPermissions[ + `${PERMISSIONS.PUT}::${permissionMap?.Organization}` + ] ? ( + + ) : null} ); diff --git a/sdks/js/packages/core/react/components/organization/general/index.tsx b/sdks/js/packages/core/react/components/organization/general/index.tsx index 7de8aa38b..4a67b9c87 100644 --- a/sdks/js/packages/core/react/components/organization/general/index.tsx +++ b/sdks/js/packages/core/react/components/organization/general/index.tsx @@ -2,16 +2,66 @@ import { Button, Flex, Separator, Text } from '@raystack/apsara'; import { Outlet, useNavigate } from '@tanstack/react-router'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useFrontier } from '~/react/contexts/FrontierContext'; +import { PERMISSIONS, formatPermissions } from '~/utils'; import { styles } from '../styles'; import { GeneralProfile } from './general.profile'; import { GeneralOrganization } from './general.workspace'; export default function GeneralSetting() { - const { - activeOrganization: organization, - isActiveOrganizationLoading: isLoading - } = useFrontier(); + const [permisionValues, setPermisionValues] = useState([]); + const [fetchingOrgPermissions, setFetchingOrgPermissions] = useState(true); + + const { client, activeOrganization: organization } = useFrontier(); + const isLoading = fetchingOrgPermissions; + + const PERMISSIONS_MAP = { + Organization: `app/organization:${organization?.id}` + }; + + const permisions = [ + { + permission: PERMISSIONS.GET, + resource: PERMISSIONS_MAP.Organization + }, + { + permission: PERMISSIONS.DELETE, + resource: PERMISSIONS_MAP.Organization + } + ]; + + const fetchOrganizationPermissions = useCallback(async () => { + try { + const { + // @ts-ignore + data: { pairs } + } = await client?.frontierServiceBatchCheckPermission({ + bodies: permisions + }); + setPermisionValues(pairs); + } catch (err) { + console.error(err); + } finally { + setFetchingOrgPermissions(false); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [client]); + + useEffect(() => { + if (organization?.id) { + fetchOrganizationPermissions(); + } + }, [fetchOrganizationPermissions, organization?.id]); + + const organizationPermissions = useMemo(() => { + if (permisionValues.length) { + return formatPermissions(permisionValues); + } else { + return {}; + } + }, [permisionValues]); + return ( @@ -22,11 +72,17 @@ export default function GeneralSetting() { - - + {organizationPermissions && + organizationPermissions[ + `${PERMISSIONS.DELETE}::${PERMISSIONS_MAP.Organization}` + ] ? ( + + ) : null} ); @@ -39,21 +95,27 @@ export const GeneralDeleteOrganization = ({ }) => { const navigate = useNavigate({ from: '/' }); return ( - - - If you want to permanently delete this organization and all of its data. - - - - - + <> + + + If you want to permanently delete this organization and all of its + data. + + + + + + + ); }; + + diff --git a/sdks/js/packages/core/utils/index.ts b/sdks/js/packages/core/utils/index.ts index a94ed0374..5322471f1 100644 --- a/sdks/js/packages/core/utils/index.ts +++ b/sdks/js/packages/core/utils/index.ts @@ -23,3 +23,32 @@ export const filterUsersfromUsers = ( const excludeIds = exclude.map(e => e.id); return arr.filter(user => !excludeIds.includes(user.id)); }; + + +export const PERMISSIONS = { + ADMINISTER: 'administer', + GROUPCREATE: 'groupcreate', + GROUPLIST: 'grouplist', + INVITATIONCREATE: 'invitationcreate', + INVITATIONLIST: 'invitationlist', + POLICYMANAGE: 'policymanage', + PROJECTCREATE: 'projectcreate', + PROJECTLIST: 'projectlist', + RESOURCELIST: 'resourcelist', + ROLEMANAGE: 'rolemanage', + SERVICEUSERMANAGE: 'serviceusermanage', + GET: 'get', + PUT: 'put', + POST: 'post', + UPDATE: 'update', + DELETE: 'delete' +}; + +export const formatPermissions = ( + permisions: { body: any; status: boolean }[] = [] +): Record => + permisions.reduce((acc: any, p: any) => { + const { body, status } = p; + acc[`${body.permission}::${body.resource}`] = status; + return acc; + }, {}); \ No newline at end of file