Skip to content

Commit

Permalink
feat: hide permission section in the workspace create and update page
Browse files Browse the repository at this point in the history
Signed-off-by: Lin Wang <wonglam@amazon.com>
  • Loading branch information
wanglam committed Aug 25, 2023
1 parent 1aae8de commit 8ae4713
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 36 deletions.
23 changes: 19 additions & 4 deletions src/core/public/workspace/workspaces_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,23 @@
*/

import { BehaviorSubject } from 'rxjs';
import { WorkspacePermissionMode } from '..';
import { CoreService, WorkspaceAttribute } from '../../types';
import { InternalApplicationStart } from '../application';
import { HttpSetup } from '../http';

type WorkspacePermissionItem = {
modes: Array<
| WorkspacePermissionMode.LibraryRead
| WorkspacePermissionMode.LibraryWrite
| WorkspacePermissionMode.Management
>;
} & ({ type: 'user'; userId: string } | { type: 'group'; group: string });

interface WorkspaceAttributeWithPermissionItems extends WorkspaceAttribute {
permissions: WorkspacePermissionItem[];
}

type WorkspaceMenuRenderFn = ({
basePath,
getUrlForApp,
Expand All @@ -20,8 +33,8 @@ type WorkspaceMenuRenderFn = ({

export interface WorkspaceObservables {
currentWorkspaceId$: BehaviorSubject<string>;
currentWorkspace$: BehaviorSubject<WorkspaceAttribute | null>;
workspaceList$: BehaviorSubject<WorkspaceAttribute[]>;
currentWorkspace$: BehaviorSubject<WorkspaceAttributeWithPermissionItems | null>;
workspaceList$: BehaviorSubject<WorkspaceAttributeWithPermissionItems[]>;
workspaceEnabled$: BehaviorSubject<boolean>;
hasFetchedWorkspaceList$: BehaviorSubject<boolean>;
}
Expand All @@ -39,8 +52,10 @@ export interface WorkspaceStart extends WorkspaceObservables {

export class WorkspaceService implements CoreService<WorkspaceSetup, WorkspaceStart> {
private currentWorkspaceId$ = new BehaviorSubject<string>('');
private workspaceList$ = new BehaviorSubject<WorkspaceAttribute[]>([]);
private currentWorkspace$ = new BehaviorSubject<WorkspaceAttribute | null>(null);
private workspaceList$ = new BehaviorSubject<WorkspaceAttributeWithPermissionItems[]>([]);
private currentWorkspace$ = new BehaviorSubject<WorkspaceAttributeWithPermissionItems | null>(
null
);
private hasFetchedWorkspaceList$ = new BehaviorSubject<boolean>(false);
private workspaceEnabled$ = new BehaviorSubject<boolean>(false);
private _renderWorkspaceMenu: WorkspaceMenuRenderFn | null = null;
Expand Down
7 changes: 6 additions & 1 deletion src/core/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,12 @@ export {
MetricsServiceStart,
} from './metrics';

export { AppCategory, WorkspaceAttribute } from '../types';
export {
AppCategory,
WorkspaceAttribute,
WorkspaceAttributeWithPermission,
WorkspacePermissionItem,
} from '../types';
export {
DEFAULT_APP_CATEGORIES,
WorkspacePermissionMode,
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/workspace/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ export const WORKSPACE_NAV_CATEGORY: AppCategory = {
euiIconType: 'folderClosed',
order: 2000,
};

export const WORKSPACES_API_BASE_URL = '/api/workspaces';
export const WORKSPACES_SETTING_API_BASE_URL = `${WORKSPACES_API_BASE_URL}-setting`;
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
import React, { useCallback } from 'react';
import { EuiPage, EuiPageBody, EuiPageHeader, EuiPageContent } from '@elastic/eui';
import { i18n } from '@osd/i18n';
import { useObservable } from 'react-use';

import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public';
import { WorkspaceForm, WorkspaceFormData } from './workspace_form';
import { WORKSPACE_OVERVIEW_APP_ID, WORKSPACE_OP_TYPE_CREATE } from '../../../common/constants';
import { formatUrlWithWorkspaceId } from '../../utils';
import { WorkspaceClient } from '../../workspace_client';

export const WorkspaceCreator = () => {
const {
services: { application, notifications, http, workspaceClient },
} = useOpenSearchDashboards<{ workspaceClient: WorkspaceClient }>();
const workspaceSetting = useObservable(workspaceClient.getWorkspaceSetting$());

const handleWorkspaceFormSubmit = useCallback(
async (data: WorkspaceFormData) => {
Expand Down Expand Up @@ -70,11 +72,12 @@ export const WorkspaceCreator = () => {
hasShadow={false}
style={{ width: '100%', maxWidth: 1000 }}
>
{application && (
{application && workspaceSetting && (
<WorkspaceForm
application={application}
onSubmit={handleWorkspaceFormSubmit}
opType={WORKSPACE_OP_TYPE_CREATE}
permissionEnabled={workspaceSetting.permission}
/>
)}
</EuiPageContent>
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, useState, FormEventHandler, useRef, useMemo } from 'react';
import React, { useCallback, useState, FormEventHandler, useRef, useMemo, useEffect } from 'react';
import { groupBy } from 'lodash';
import {
EuiPanel,
Expand Down Expand Up @@ -93,13 +93,15 @@ interface WorkspaceFormProps {
onSubmit?: (formData: WorkspaceFormData) => void;
defaultValues?: WorkspaceFormData;
opType?: string;
permissionEnabled: boolean;
}

export const WorkspaceForm = ({
application,
onSubmit,
defaultValues,
opType,
permissionEnabled,
}: WorkspaceFormProps) => {
const applications = useApplications(application);

Expand Down Expand Up @@ -332,6 +334,16 @@ export const WorkspaceForm = ({
setDefaultVISTheme(options[0]?.value);
}, []);

useEffect(() => {
if (!permissionEnabled) {
setPermissionSettings([]);
return;
}
setPermissionSettings((previousPermissionSettings) =>
previousPermissionSettings.length > 0 ? previousPermissionSettings : [{}]
);
}, [permissionEnabled]);

return (
<EuiForm id={formIdRef.current} onSubmit={handleFormSubmit} component="form">
<EuiPanel>
Expand Down Expand Up @@ -430,17 +442,21 @@ export const WorkspaceForm = ({
})}
</EuiFlexGrid>
</EuiPanel>
<EuiSpacer />
<EuiPanel>
<EuiTitle size="s">
<h2>Members & permissions</h2>
</EuiTitle>
<WorkspacePermissionSettingPanel
errors={formErrors.permissions}
value={permissionSettings}
onChange={setPermissionSettings}
/>
</EuiPanel>
{permissionEnabled && (
<>
<EuiSpacer />
<EuiPanel>
<EuiTitle size="s">
<h2>Members & permissions</h2>
</EuiTitle>
<WorkspacePermissionSettingPanel
errors={formErrors.permissions}
value={permissionSettings}
onChange={setPermissionSettings}
/>
</EuiPanel>
</>
)}
<EuiSpacer />
<EuiText textAlign="right">
{opType === WORKSPACE_OP_TYPE_CREATE && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,38 @@ import { DeleteWorkspaceModal } from '../delete_workspace_modal';
import { formatUrlWithWorkspaceId } from '../../utils';
import { WorkspaceClient } from '../../workspace_client';

const getWorkspaceFormData = (
workspace: (WorkspaceAttribute & Pick<WorkspaceFormData, 'permissions'>) | null | undefined
) => {
if (!workspace) {
return {
features: [],
name: '',
permissions: [],
};
}
const { id, features, ...otherAttributes } = workspace;
return {
features: features ? features : [],
...otherAttributes,
};
};

export const WorkspaceUpdater = () => {
const {
services: { application, workspaces, notifications, http, workspaceClient },
} = useOpenSearchDashboards<{ workspaceClient: WorkspaceClient }>();

const currentWorkspace = useObservable(workspaces ? workspaces.currentWorkspace$ : of(null));

const excludedAttribute = 'id';
const { [excludedAttribute]: removedProperty, ...otherAttributes } =
currentWorkspace || ({} as WorkspaceAttribute);

const workspaceSetting = useObservable(workspaceClient.getWorkspaceSetting$());
const [deleteWorkspaceModalVisible, setDeleteWorkspaceModalVisible] = useState(false);
const [currentWorkspaceFormData, setCurrentWorkspaceFormData] = useState<
Omit<WorkspaceAttribute, 'id'>
>(otherAttributes);
const [currentWorkspaceFormData, setCurrentWorkspaceFormData] = useState<WorkspaceFormData>(() =>
getWorkspaceFormData(currentWorkspace)
);

useEffect(() => {
const { id, ...others } = currentWorkspace || ({} as WorkspaceAttribute);
setCurrentWorkspaceFormData(others);
}, [workspaces, currentWorkspace, excludedAttribute]);
setCurrentWorkspaceFormData(getWorkspaceFormData(currentWorkspace));
}, [currentWorkspace]);

const handleWorkspaceFormSubmit = useCallback(
async (data: WorkspaceFormData) => {
Expand Down Expand Up @@ -204,12 +216,13 @@ export const WorkspaceUpdater = () => {
/>
</EuiPanel>
)}
{application && (
{application && workspaceSetting && (
<WorkspaceForm
application={application}
onSubmit={handleWorkspaceFormSubmit}
defaultValues={currentWorkspaceFormData}
opType={WORKSPACE_OP_TYPE_UPDATE}
permissionEnabled={workspaceSetting.permission}
/>
)}
</EuiPageContent>
Expand Down
26 changes: 23 additions & 3 deletions src/plugins/workspace/public/workspace_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { combineLatest } from 'rxjs';
import { BehaviorSubject, combineLatest } from 'rxjs';
import { isEqual } from 'lodash';

import {
Expand All @@ -13,8 +13,7 @@ import {
WorkspaceSetup,
} from '../../../core/public';
import { WorkspacePermissionMode } from '../../../core/public';

const WORKSPACES_API_BASE_URL = '/api/workspaces';
import { WORKSPACES_API_BASE_URL, WORKSPACES_SETTING_API_BASE_URL } from '../common/constants';

enum WORKSPACE_ERROR_REASON_MAP {
WORKSPACE_STALED = 'WORKSPACE_STALED',
Expand Down Expand Up @@ -53,6 +52,10 @@ interface WorkspaceFindOptions {
sortOrder?: string;
}

interface WorkspaceSetting {
permission: boolean;
}

/**
* Workspaces is OpenSearchDashboards's visualize mechanism allowing admins to
* organize related features
Expand All @@ -62,6 +65,7 @@ interface WorkspaceFindOptions {
export class WorkspaceClient {
private http: HttpSetup;
private workspaces: WorkspaceSetup;
private workspaceSetting$ = new BehaviorSubject<WorkspaceSetting | null>(null);

constructor(http: HttpSetup, workspaces: WorkspaceSetup) {
this.http = http;
Expand Down Expand Up @@ -102,6 +106,9 @@ export class WorkspaceClient {
*/
public init() {
this.updateWorkspaceListAndNotify();
this.getWorkspaceSetting().then((workspaceSetting) => {
this.workspaceSetting$.next(workspaceSetting);
});
}

private findWorkspace(payload: [WorkspaceAttribute[], string]): WorkspaceAttribute | null {
Expand Down Expand Up @@ -329,6 +336,19 @@ export class WorkspaceClient {
return result;
}

/**
* Get workspace related setting
*/
public async getWorkspaceSetting(): Promise<WorkspaceSetting | null> {
const result = await this.safeFetch<WorkspaceSetting>(WORKSPACES_SETTING_API_BASE_URL, {});
if (result.success) {
return result.result;
}
return null;
}

public getWorkspaceSetting$ = () => this.workspaceSetting$;

public stop() {
this.workspaces.workspaceList$.unsubscribe();
this.workspaces.currentWorkspaceId$.unsubscribe();
Expand Down
25 changes: 23 additions & 2 deletions src/plugins/workspace/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
import { schema } from '@osd/config-schema';
import { ensureRawRequest } from '../../../../core/server';
import { WORKSPACES_API_BASE_URL, WORKSPACES_SETTING_API_BASE_URL } from '../../common/constants';

import {
ACL,
Expand All @@ -14,8 +15,6 @@ import {
} from '../../../../core/server';
import { IWorkspaceDBImpl, WorkspaceRoutePermissionItem } from '../types';

const WORKSPACES_API_BASE_URL = '/api/workspaces';

const workspacePermissionMode = schema.oneOf([
schema.literal(WorkspacePermissionMode.LibraryRead),
schema.literal(WorkspacePermissionMode.LibraryWrite),
Expand Down Expand Up @@ -78,6 +77,26 @@ const convertFromACL = (permissions: Permissions) => {
}));
};

const registerWorkspaceSettingRoutes = ({ http }: { http: CoreSetup['http'] }) => {
const router = http.createRouter();
router.get(
{
path: WORKSPACES_SETTING_API_BASE_URL,
validate: {},
},
router.handleLegacyErrors(async (_context, _req, res) => {
return res.ok({
body: {
success: true,
result: {
permission: true,
},
},
});
})
);
};

export function registerRoutes({
client,
logger,
Expand Down Expand Up @@ -255,4 +274,6 @@ export function registerRoutes({
return res.ok({ body: result });
})
);

registerWorkspaceSettingRoutes({ http });
}

0 comments on commit 8ae4713

Please sign in to comment.