Skip to content
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

[Backport workspace-2.9] Feat remove management permission mode in acl permission #203

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -19,7 +19,8 @@ export const WORKSPACES_API_BASE_URL = '/api/workspaces';
const workspacePermissionMode = schema.oneOf([
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 @@ -184,7 +185,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
Loading