Skip to content

Commit

Permalink
Assign current user as workspace admin
Browse files Browse the repository at this point in the history
Signed-off-by: Lin Wang <wonglam@amazon.com>
  • Loading branch information
wanglam committed Oct 11, 2024
1 parent f858f71 commit 8255e82
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,14 @@ describe('WorkspaceCreator', () => {
{
dataSources: [],
dataConnections: [],
permissions: {
library_write: {
users: ['%me%'],
},
write: {
users: ['%me%'],
},
},
}
);
await waitFor(() => {
Expand Down Expand Up @@ -371,10 +379,10 @@ describe('WorkspaceCreator', () => {
expect.objectContaining({
name: 'test workspace name',
}),
{
expect.objectContaining({
dataConnections: [],
dataSources: ['id1'],
}
})
);
await waitFor(() => {
expect(notificationToastsAddSuccess).toHaveBeenCalled();
Expand Down Expand Up @@ -421,9 +429,40 @@ describe('WorkspaceCreator', () => {
expect.objectContaining({
name: 'test workspace name',
}),
{
expect.objectContaining({
dataConnections: ['id3'],
dataSources: [],
})
);
await waitFor(() => {
expect(notificationToastsAddSuccess).toHaveBeenCalled();
});
expect(notificationToastsAddDanger).not.toHaveBeenCalled();
});

it('should not include permissions parameter if permissions not enabled', async () => {
const { getByTestId } = render(
<WorkspaceCreator isDashboardAdmin={true} isPermissionEnabled={false} />
);

// Ensure workspace create form rendered
await waitFor(() => {
expect(getByTestId('workspaceForm-bottomBar-createButton')).toBeInTheDocument();
});
const nameInput = getByTestId('workspaceForm-workspaceDetails-nameInputText');
fireEvent.input(nameInput, {
target: { value: 'test workspace name' },
});
fireEvent.click(getByTestId('workspaceUseCase-observability'));

fireEvent.click(getByTestId('workspaceForm-bottomBar-createButton'));
expect(workspaceClientCreate).toHaveBeenCalledWith(
expect.objectContaining({
name: 'test workspace name',
}),
{
dataConnections: [],
dataSources: [],
}
);
await waitFor(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,16 @@ import { BehaviorSubject } from 'rxjs';
import { useLocation } from 'react-router-dom';

import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public';
import { WORKSPACE_DETAIL_APP_ID } from '../../../common/constants';
import { WorkspaceFormSubmitData, WorkspaceOperationType, DetailTab } from '../workspace_form';
import { PermissionModeId } from '../../../../../core/public';
import { CURRENT_USER_PLACEHOLDER, WORKSPACE_DETAIL_APP_ID } from '../../../common/constants';
import {
WorkspaceFormSubmitData,
WorkspaceOperationType,
DetailTab,
WorkspacePermissionItemType,
convertPermissionSettingsToPermissions,
WorkspacePermissionSetting,
} from '../workspace_form';
import { getUseCaseFeatureConfig } from '../../../common/utils';
import { formatUrlWithWorkspaceId } from '../../../../../core/public/utils';
import { WorkspaceClient } from '../../workspace_client';
Expand All @@ -23,6 +31,7 @@ import { NavigationPublicPluginStart } from '../../../../../plugins/navigation/p
import { DataSourceConnectionType } from '../../../common/types';
import { navigateToWorkspaceDetail } from '../utils/workspace';
import { WorkspaceCreatorForm } from './workspace_creator_form';
import { optionIdToWorkspacePermissionModesMap } from '../workspace_form/constants';

export interface WorkspaceCreatorProps {
registeredUseCases$: BehaviorSubject<WorkspaceUseCase[]>;
Expand Down Expand Up @@ -73,8 +82,20 @@ export const WorkspaceCreator = (props: WorkspaceCreatorProps) => {
features: [getUseCaseFeatureConfig(defaultSelectedUseCase.id)],
}
: {}),
...(isPermissionEnabled
? {
permissionSettings: [
{
id: 1,
type: WorkspacePermissionItemType.User,
userId: CURRENT_USER_PLACEHOLDER,
modes: optionIdToWorkspacePermissionModesMap[PermissionModeId.Owner],
},
] as WorkspacePermissionSetting[],
}
: {}),
};
}, [location.search, availableUseCases]);
}, [location.search, availableUseCases, isPermissionEnabled]);

const handleWorkspaceFormSubmit = useCallback(
async (data: WorkspaceFormSubmitData) => {
Expand Down Expand Up @@ -102,6 +123,11 @@ export const WorkspaceCreator = (props: WorkspaceCreatorProps) => {
result = await workspaceClient.create(attributes, {
dataSources: selectedDataSourceIds,
dataConnections: selectedDataConnectionIds,
...(isPermissionEnabled
? {
permissions: convertPermissionSettingsToPermissions(permissionSettings),
}
: {}),
});
if (result?.success) {
notifications?.toasts.addSuccess({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ export { ConnectionTypeIcon } from './connection_type_icon';
export { DataSourceConnectionTable } from './data_source_connection_table';
export { WorkspaceUseCaseFlyout } from './workspace_use_case_flyout';

export { WorkspaceFormSubmitData, WorkspaceFormProps, WorkspaceFormDataState } from './types';
export {
WorkspaceFormSubmitData,
WorkspaceFormProps,
WorkspaceFormDataState,
WorkspacePermissionSetting,
} from './types';
export {
WorkspaceOperationType,
DetailTab,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,14 @@ import {
WorkspacePermissionSetting,
WorkspaceFormDataState,
} from './types';
import {
generatePermissionSettingsState,
getNumberOfChanges,
getNumberOfErrors,
validateWorkspaceForm,
} from './utils';
import { getNumberOfChanges, getNumberOfErrors, validateWorkspaceForm } from './utils';
import { WorkspacePermissionItemType } from './constants';

const workspaceHtmlIdGenerator = htmlIdGenerator();

export const useWorkspaceForm = ({
application,
defaultValues,
operationType,
onSubmit,
permissionEnabled,
onAppLeave,
Expand All @@ -40,17 +34,14 @@ export const useWorkspaceForm = ({
const [color, setColor] = useState(defaultValues?.color);
const defaultValuesRef = useRef(defaultValues);
const [isEditing, setIsEditing] = useState(false);
const initialPermissionSettingsRef = useRef(
generatePermissionSettingsState(operationType, defaultValues?.permissionSettings)
);

const [featureConfigs, setFeatureConfigs] = useState<string[]>(defaultValues?.features ?? []);
const selectedUseCase = useMemo(() => getFirstUseCaseOfFeatureConfigs(featureConfigs), [
featureConfigs,
]);
const [permissionSettings, setPermissionSettings] = useState<
WorkspaceFormDataState['permissionSettings']
>(initialPermissionSettingsRef.current);
>(defaultValues?.permissionSettings ?? []);

const [selectedDataSourceConnections, setSelectedDataSourceConnections] = useState<
DataSourceConnection[]
Expand All @@ -77,11 +68,7 @@ export const useWorkspaceForm = ({
getFormDataRef.current = getFormData;
const formData = getFormData();
const numberOfChanges = defaultValuesRef.current
? getNumberOfChanges(formData, {
...defaultValuesRef.current,
// The user form will insert some empty permission rows, should ignore these rows not treated as user new added.
permissionSettings: initialPermissionSettingsRef.current,
})
? getNumberOfChanges(formData, defaultValuesRef.current)
: 0;

if (!formIdRef.current) {
Expand Down Expand Up @@ -161,7 +148,7 @@ export const useWorkspaceForm = ({
setDescription(resetValues?.description ?? '');
setColor(resetValues?.color);
setFeatureConfigs(resetValues?.features ?? []);
setPermissionSettings(initialPermissionSettingsRef.current);
setPermissionSettings(defaultValuesRef.current?.permissionSettings ?? []);
setFormErrors({});
setIsEditing(false);
}, []);
Expand Down
40 changes: 1 addition & 39 deletions src/plugins/workspace/public/components/workspace_form/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
import { i18n } from '@osd/i18n';

import type { SavedObjectPermissions } from '../../../../../core/types';
import { CURRENT_USER_PLACEHOLDER, WorkspacePermissionMode } from '../../../common/constants';
import { WorkspacePermissionMode } from '../../../common/constants';
import { isUseCaseFeatureConfig } from '../../utils';
import {
optionIdToWorkspacePermissionModesMap,
permissionModeOptions,
WorkspaceOperationType,
WorkspacePermissionItemType,
} from './constants';

Expand Down Expand Up @@ -382,43 +381,6 @@ export const generateNextPermissionSettingsId = (permissionSettings: Array<{ id:
: Math.max(...permissionSettings.map(({ id }) => id)) + 1;
};

/**
*
* Generate permission settings state with provided operation type and permission settings,
* It will always return current user as an Owner and an empty user group permission settings
* when operation type is create or no users and groups in provided permission settings.
* It will append current user to result permission settings if no user in provided permission settings.
* It will append an empty permission group to result permission settings if no user group in provided permission settings.
* It will always return original permission settings if both user or user group in provided permission settings.
*
* @param operationType
* @param permissionSettings
* @returns
*/
export const generatePermissionSettingsState = (
operationType: WorkspaceOperationType,
permissionSettings?: WorkspacePermissionSetting[]
): WorkspacePermissionSetting[] => {
const emptyUserPermission: WorkspaceUserPermissionSetting = {
id: 1,
type: WorkspacePermissionItemType.User,
userId: '',
modes: optionIdToWorkspacePermissionModesMap[PermissionModeId.Owner],
};
const emptyUserGroupPermission: WorkspaceUserGroupPermissionSetting = {
id: 2,
type: WorkspacePermissionItemType.Group,
group: '',
modes: optionIdToWorkspacePermissionModesMap[PermissionModeId.Read],
};

if (operationType === WorkspaceOperationType.Create) {
return [];
}

return [...(permissionSettings ?? [])];
};

interface PermissionSettingLike
extends Omit<Partial<WorkspaceUserPermissionSetting>, 'type'>,
Omit<Partial<WorkspaceUserGroupPermissionSetting>, 'type'> {
Expand Down

0 comments on commit 8255e82

Please sign in to comment.