Skip to content

Commit

Permalink
feat: POC implementation
Browse files Browse the repository at this point in the history
Signed-off-by: SuZhou-Joe <suzhou@amazon.com>
  • Loading branch information
SuZhou-Joe committed Mar 13, 2024
1 parent 0cef35d commit 2c8ce9d
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/plugins/workspace/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ export enum WorkspacePermissionMode {
LibraryRead = 'library_read',
LibraryWrite = 'library_write',
}

export const WORKSPACE_ID_CONSUMER_WRAPPER_ID = 'workspace_id_consumer';
4 changes: 1 addition & 3 deletions src/plugins/workspace/opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
"version": "opensearchDashboards",
"server": true,
"ui": true,
"requiredPlugins": [
"savedObjects"
],
"requiredPlugins": [],
"optionalPlugins": ["savedObjectsManagement"],
"requiredBundles": ["opensearchDashboardsReact"]
}
11 changes: 11 additions & 0 deletions src/plugins/workspace/server/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

/**
* A symbol used for imply the workspace id in original url
*
* @Internal
*/
export const workspaceIdInUrlSymbol = Symbol('workspace_id_in_url');
13 changes: 13 additions & 0 deletions src/plugins/workspace/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
import {
WORKSPACE_SAVED_OBJECTS_CLIENT_WRAPPER_ID,
WORKSPACE_CONFLICT_CONTROL_SAVED_OBJECTS_CLIENT_WRAPPER_ID,
WORKSPACE_ID_CONSUMER_WRAPPER_ID,
} from '../common/constants';
import { IWorkspaceClientImpl } from './types';
import { WorkspaceClient } from './workspace_client';
Expand All @@ -27,6 +28,10 @@ import {
SavedObjectsPermissionControlContract,
} from './permission_control/client';
import { WorkspacePluginConfigType } from '../config';
import { workspaceIdInUrlSymbol } from './constant';
import { WorkspaceIdConsumerWrapper } from './saved_objects/workspace_id_consumer_wrapper';
// eslint-disable-next-line @osd/eslint/no-restricted-paths
import { ensureRawRequest } from '../../../core/server/http/router'; // will be an issue as the ensureRawRequest is an internal implementation

export class WorkspacePlugin implements Plugin<{}, {}> {
private readonly logger: Logger;
Expand All @@ -44,6 +49,8 @@ export class WorkspacePlugin implements Plugin<{}, {}> {
const workspaceId = getWorkspaceIdFromUrl(request.url.toString());

if (workspaceId) {
const rawRequest = ensureRawRequest(request);
rawRequest.headers[workspaceIdInUrlSymbol.toString()] = workspaceId;
const requestUrl = new URL(request.url.toString());
requestUrl.pathname = cleanWorkspaceId(requestUrl.pathname);
return toolkit.rewriteUrl(requestUrl.toString());
Expand Down Expand Up @@ -91,6 +98,12 @@ export class WorkspacePlugin implements Plugin<{}, {}> {
);
}

core.savedObjects.addClientWrapper(
-2,
WORKSPACE_ID_CONSUMER_WRAPPER_ID,
new WorkspaceIdConsumerWrapper().wrapperFactory
);

registerRoutes({
http: core.http,
logger: this.logger,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
SavedObjectsBaseOptions,
SavedObjectsBulkCreateObject,
SavedObjectsClientWrapperFactory,
SavedObjectsCreateOptions,
SavedObjectsCheckConflictsObject,
OpenSearchDashboardsRequest,
SavedObjectsFindOptions,
SavedObjectsUpdateOptions,
SavedObjectsBulkUpdateOptions,
SavedObjectsBulkUpdateObject,
WORKSPACE_TYPE,
} from '../../../../core/server';
import { workspaceIdInUrlSymbol } from '../constant';

type WorkspaceOptions =
| {
workspaces?: string[];
}
| undefined;

export class WorkspaceIdConsumerWrapper {
private typeRelatedToWorkspace(type: string | string[]): boolean {
if (Array.isArray(type)) {
return type.some((item) => item === WORKSPACE_TYPE);
}

return type === WORKSPACE_TYPE;
}
private formatWorkspaceIdParams<T extends WorkspaceOptions>(
request: OpenSearchDashboardsRequest,
options: T
): T {
if (!options) {
return options;
}
const { workspaces, ...others } = options;
const workspaceIdParsedFromUrl = request.headers[workspaceIdInUrlSymbol.toString()] as string;
const workspaceIdInUserOptions = options.workspaces;
let finalWorkspaces: string[] = [];
if (workspaceIdInUserOptions?.length) {
finalWorkspaces = workspaceIdInUserOptions;
} else if (workspaceIdParsedFromUrl) {
finalWorkspaces = [workspaceIdParsedFromUrl];
}

return {
...(others as T),
...(finalWorkspaces.length ? { workspaces: finalWorkspaces } : {}),
};
}
public wrapperFactory: SavedObjectsClientWrapperFactory = (wrapperOptions) => {
return {
...wrapperOptions.client,
create: <T>(type: string, attributes: T, options: SavedObjectsCreateOptions = {}) =>
wrapperOptions.client.create(
type,
attributes,
this.formatWorkspaceIdParams(wrapperOptions.request, options)
),
bulkCreate: <T = unknown>(
objects: Array<SavedObjectsBulkCreateObject<T>>,
options: SavedObjectsCreateOptions = {}
) =>
wrapperOptions.client.bulkCreate(
objects,
this.formatWorkspaceIdParams(wrapperOptions.request, options)
),
checkConflicts: (
objects: SavedObjectsCheckConflictsObject[] = [],
options: SavedObjectsBaseOptions = {}
) =>
wrapperOptions.client.checkConflicts(
objects,
this.formatWorkspaceIdParams(wrapperOptions.request, options)
),
delete: wrapperOptions.client.delete,
find: (options: SavedObjectsFindOptions) =>
wrapperOptions.client.find(
this.typeRelatedToWorkspace(options.type)
? options
: this.formatWorkspaceIdParams(wrapperOptions.request, options)
),
bulkGet: wrapperOptions.client.bulkGet,
get: wrapperOptions.client.get,
update: <T = unknown>(
type: string,
id: string,
attributes: Partial<T>,
options: SavedObjectsUpdateOptions = {}
) =>
wrapperOptions.client.update(
type,
id,
attributes,
this.formatWorkspaceIdParams(wrapperOptions.request, options)
),
bulkUpdate: <T = unknown>(
objects: Array<SavedObjectsBulkUpdateObject<T>>,
options?: SavedObjectsBulkUpdateOptions
) =>
wrapperOptions.client.bulkUpdate(
objects,
this.formatWorkspaceIdParams(wrapperOptions.request, options)
),
addToNamespaces: wrapperOptions.client.addToNamespaces,
deleteFromNamespaces: wrapperOptions.client.deleteFromNamespaces,
};
};

constructor() {}
}
1 change: 1 addition & 0 deletions src/plugins/workspace/server/workspace_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { IWorkspaceClientImpl, WorkspaceFindOptions, IResponse, IRequestDetail }
import { workspace } from './saved_objects';
import { generateRandomId } from './utils';
import {
WORKSPACE_ID_CONSUMER_WRAPPER_ID,
WORKSPACE_OVERVIEW_APP_ID,
WORKSPACE_SAVED_OBJECTS_CLIENT_WRAPPER_ID,
WORKSPACE_UPDATE_APP_ID,
Expand Down

0 comments on commit 2c8ce9d

Please sign in to comment.