Skip to content

Commit

Permalink
Feat remove management permission mode in acl permission (#195)
Browse files Browse the repository at this point in the history
* feat: remove management permission mode and clearify library permission mode usage

Signed-off-by: Lin Wang <wonglam@amazon.com>

* address PR comments and add annotations

Signed-off-by: Lin Wang <wonglam@amazon.com>

---------

Signed-off-by: Lin Wang <wonglam@amazon.com>
  • Loading branch information
wanglam authored Sep 25, 2023
1 parent 03b2452 commit 29ccc20
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 124 deletions.
1 change: 0 additions & 1 deletion src/core/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export const WORKSPACE_PATH_PREFIX = '/w';
export enum WorkspacePermissionMode {
Read = 'read',
Write = 'write',
Management = 'management',
LibraryRead = 'library_read',
LibraryWrite = 'library_write',
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useCallback, useMemo, useRef } from 'react';
import React, { useCallback, useMemo } from 'react';
import {
EuiDescribedFormGroup,
EuiFlexGroup,
Expand All @@ -25,57 +25,61 @@ export type WorkspacePermissionSetting = (
type: 'user' | 'group';
userId?: string;
group?: string;
modes: Array<
| WorkspacePermissionMode.LibraryRead
| WorkspacePermissionMode.LibraryWrite
| WorkspacePermissionMode.Management
>;
modes: WorkspacePermissionMode[];
};

enum PermissionModeId {
Read = 'read',
ReadAndWrite = 'read+write',
Admin = 'admin',
}

const permissionModeOptions = [
{
id: WorkspacePermissionMode.LibraryRead,
label: 'View',
id: PermissionModeId.Read,
label: 'Read',
iconType: 'eye',
},
{
id: WorkspacePermissionMode.LibraryWrite,
label: 'Edit',
id: PermissionModeId.ReadAndWrite,
label: 'Read + Write',
iconType: 'pencil',
},
{
id: WorkspacePermissionMode.Management,
id: PermissionModeId.Admin,
label: 'Management',
iconType: 'visTimelion',
},
];

const optionIdToWorkspacePermissionModesMap: {
[key: string]: WorkspacePermissionMode[];
} = {
[PermissionModeId.Read]: [WorkspacePermissionMode.LibraryRead, WorkspacePermissionMode.Read],
[PermissionModeId.ReadAndWrite]: [
WorkspacePermissionMode.LibraryWrite,
WorkspacePermissionMode.Read,
],
[PermissionModeId.Admin]: [WorkspacePermissionMode.LibraryWrite, WorkspacePermissionMode.Write],
};

const permissionTypeOptions = [
{ value: 'user' as const, inputDisplay: 'User' },
{ value: 'group' as const, inputDisplay: 'Group' },
];

const isWorkspacePermissionMode = (
test: string
): test is
| WorkspacePermissionMode.LibraryRead
| WorkspacePermissionMode.LibraryWrite
| WorkspacePermissionMode.Management =>
test === WorkspacePermissionMode.LibraryRead ||
test === WorkspacePermissionMode.LibraryWrite ||
test === WorkspacePermissionMode.Management;
const generateWorkspacePermissionItemKey = (
item: Partial<WorkspacePermissionSetting>,
index?: number
) => [item.type, item.userId, item.group, ...(item.modes ?? []), index].filter(Boolean).join('-');

interface WorkspacePermissionSettingInputProps {
index: number;
deletable: boolean;
type?: 'user' | 'group';
userId?: string;
group?: string;
modes?: Array<
| WorkspacePermissionMode.LibraryRead
| WorkspacePermissionMode.LibraryWrite
| WorkspacePermissionMode.Management
>;
modes?: WorkspacePermissionMode[];
onTypeChange: (type: 'user' | 'group', index: number) => void;
onGroupOrUserIdChange: (
groupOrUserId:
Expand All @@ -85,11 +89,7 @@ interface WorkspacePermissionSettingInputProps {
index: number
) => void;
onPermissionModesChange: (
WorkspacePermissionMode: Array<
| WorkspacePermissionMode.LibraryRead
| WorkspacePermissionMode.LibraryWrite
| WorkspacePermissionMode.Management
>,
WorkspacePermissionMode: WorkspacePermissionMode[],
index: number
) => void;
onDelete: (index: number) => void;
Expand All @@ -111,16 +111,16 @@ const WorkspacePermissionSettingInput = ({
() => (group || userId ? [{ label: (group || userId) as string }] : []),
[group, userId]
);
const permissionModesIdToSelectMap = useMemo(
() => ({
[WorkspacePermissionMode.LibraryRead]: !!modes?.includes(WorkspacePermissionMode.LibraryRead),
[WorkspacePermissionMode.LibraryWrite]: !!modes?.includes(
WorkspacePermissionMode.LibraryWrite
),
[WorkspacePermissionMode.Management]: !!modes?.includes(WorkspacePermissionMode.Management),
}),
[modes]
);
const permissionModesSelectedId = useMemo(() => {
if (!modes) {
return undefined;
}
for (const key in optionIdToWorkspacePermissionModesMap) {
if (optionIdToWorkspacePermissionModesMap[key].every((mode) => modes?.includes(mode))) {
return key;
}
}
}, [modes]);

const handleTypeChange = useCallback(
(newType: 'user' | 'group') => {
Expand Down Expand Up @@ -154,16 +154,13 @@ const WorkspacePermissionSettingInput = ({
[index, type, onGroupOrUserIdChange]
);

const handlePermissionStateChange = useCallback(
const handlePermissionModeOptionChange = useCallback(
(id: string) => {
if (isWorkspacePermissionMode(id)) {
onPermissionModesChange(
modes?.includes(id) ? modes.filter((value) => value !== id) : [...(modes ?? []), id],
index
);
if (optionIdToWorkspacePermissionModesMap[id]) {
onPermissionModesChange([...optionIdToWorkspacePermissionModesMap[id]], index);
}
},
[index, modes, onPermissionModesChange]
[index, onPermissionModesChange]
);

const handleDelete = useCallback(() => {
Expand Down Expand Up @@ -195,11 +192,11 @@ const WorkspacePermissionSettingInput = ({
<EuiFlexItem grow={false}>
<EuiButtonGroup
legend="Permission Modes"
type="multi"
type="single"
options={permissionModeOptions}
onChange={handlePermissionStateChange}
isIconOnly
idToSelectedMap={permissionModesIdToSelectMap}
idSelected={permissionModesSelectedId}
onChange={handlePermissionModeOptionChange}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
Expand Down Expand Up @@ -227,63 +224,99 @@ export const WorkspacePermissionSettingPanel = ({
onChange,
firstRowDeletable,
}: WorkspacePermissionSettingPanelProps) => {
const valueRef = useRef(value);
valueRef.current = value;
const transformedValue = useMemo(() => {
if (!value) {
return [];
}
const result: Array<Partial<WorkspacePermissionSetting>> = [];
/**
* One workspace permission setting may includes multi setting options,
* for loop the workspace permission setting array to separate it to multi rows.
**/
for (let i = 0; i < value.length; i++) {
const valueItem = value[i];
// Incomplete workspace permission setting don't need to separate to multi rows
if (
!valueItem.modes ||
!valueItem.type ||
(valueItem.type === 'user' && !valueItem.userId) ||
(valueItem.type === 'group' && !valueItem.group)
) {
result.push(valueItem);
continue;
}
/**
* For loop the option id to workspace permission modes map,
* if one settings includes all permission modes in a specific option,
* add these permission modes to the result array.
*/
for (const key in optionIdToWorkspacePermissionModesMap) {
if (!Object.prototype.hasOwnProperty.call(optionIdToWorkspacePermissionModesMap, key)) {
continue;
}
const modesForCertainPermissionId = optionIdToWorkspacePermissionModesMap[key];
if (modesForCertainPermissionId.every((mode) => valueItem.modes?.includes(mode))) {
result.push({ ...valueItem, modes: modesForCertainPermissionId });
}
}
}
return result;
}, [value]);

const handleAddNewOne = useCallback(() => {
onChange?.([...(valueRef.current ?? []), {}]);
}, [onChange]);
onChange?.([...(transformedValue ?? []), {}]);
}, [onChange, transformedValue]);

const handleDelete = useCallback(
(index: number) => {
onChange?.((valueRef.current ?? []).filter((_item, itemIndex) => itemIndex !== index));
onChange?.((transformedValue ?? []).filter((_item, itemIndex) => itemIndex !== index));
},
[onChange]
[onChange, transformedValue]
);

const handlePermissionModesChange = useCallback<
WorkspacePermissionSettingInputProps['onPermissionModesChange']
>(
(modes, index) => {
onChange?.(
(valueRef.current ?? []).map((item, itemIndex) =>
(transformedValue ?? []).map((item, itemIndex) =>
index === itemIndex ? { ...item, modes } : item
)
);
},
[onChange]
[onChange, transformedValue]
);

const handleTypeChange = useCallback<WorkspacePermissionSettingInputProps['onTypeChange']>(
(type, index) => {
onChange?.(
(valueRef.current ?? []).map((item, itemIndex) =>
(transformedValue ?? []).map((item, itemIndex) =>
index === itemIndex ? { ...item, type } : item
)
);
},
[onChange]
[onChange, transformedValue]
);

const handleGroupOrUserIdChange = useCallback<
WorkspacePermissionSettingInputProps['onGroupOrUserIdChange']
>(
(userOrGroupIdWithType, index) => {
onChange?.(
(valueRef.current ?? []).map((item, itemIndex) =>
(transformedValue ?? []).map((item, itemIndex) =>
index === itemIndex
? { ...userOrGroupIdWithType, ...(item.modes ? { modes: item.modes } : {}) }
: item
)
);
},
[onChange]
[onChange, transformedValue]
);

return (
<EuiDescribedFormGroup title={<h3>Users, User Groups & Groups</h3>}>
{value?.map((item, index) => (
<React.Fragment key={index}>
{transformedValue?.map((item, index) => (
<React.Fragment key={generateWorkspacePermissionItemKey(item, index)}>
<EuiFormRow isInvalid={!!errors?.[index]} error={errors?.[index]}>
<WorkspacePermissionSettingInput
{...item}
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/workspace/public/workspace_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ type WorkspaceRoutePermissionItem = {
modes: Array<
| WorkspacePermissionMode.LibraryRead
| WorkspacePermissionMode.LibraryWrite
| WorkspacePermissionMode.Management
| WorkspacePermissionMode.Read
| WorkspacePermissionMode.Write
>;
} & ({ type: 'user'; userId: string } | { type: 'group'; group: string });

Expand Down
10 changes: 8 additions & 2 deletions src/plugins/workspace/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const workspacePermissionMode = schema.oneOf([
schema.literal(WorkspacePermissionMode.Write),
schema.literal(WorkspacePermissionMode.LibraryRead),
schema.literal(WorkspacePermissionMode.LibraryWrite),
schema.literal(WorkspacePermissionMode.Management),
schema.literal(WorkspacePermissionMode.Read),
schema.literal(WorkspacePermissionMode.Write),
]);

const workspacePermission = schema.oneOf([
Expand Down Expand Up @@ -187,7 +188,12 @@ export function registerRoutes({
permissions.push({
type: 'user',
userId: authInfo.user_name,
modes: [WorkspacePermissionMode.Management],
modes: [WorkspacePermissionMode.LibraryWrite],
});
permissions.push({
type: 'user',
userId: authInfo.user_name,
modes: [WorkspacePermissionMode.Write],
});
}

Expand Down
Loading

0 comments on commit 29ccc20

Please sign in to comment.