Skip to content

Commit

Permalink
feat: make create/find support workspaces
Browse files Browse the repository at this point in the history
Signed-off-by: SuZhoue-Joe <[email protected]>
  • Loading branch information
SuZhou-Joe committed Jun 16, 2023
1 parent 94a67df commit d62f9b7
Show file tree
Hide file tree
Showing 14 changed files with 112 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/core/public/core_system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export class CoreSystem {
const docLinks = this.docLinks.start({ injectedMetadata });
const http = await this.http.start();
const workspaces = await this.workspaces.start();
const savedObjects = await this.savedObjects.start({ http });
const savedObjects = await this.savedObjects.start({ http, workspaces });
const i18n = await this.i18n.start();
const fatalErrors = await this.fatalErrors.start();
await this.integrations.start({ uiSettings });
Expand Down
22 changes: 16 additions & 6 deletions src/core/public/saved_objects/saved_objects_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export interface SavedObjectsCreateOptions {
/** {@inheritDoc SavedObjectsMigrationVersion} */
migrationVersion?: SavedObjectsMigrationVersion;
references?: SavedObjectReference[];
initialNamespaces?: string[];
workspaces?: string[];
}

/**
Expand Down Expand Up @@ -231,13 +231,13 @@ export class SavedObjectsClient {
this.batchQueue = [];
}

private async _getCurrentWorkspace(): Promise<string> {
private async _getCurrentWorkspace(): Promise<string | null> {
const currentWorkspaceIdResp = await this.workspaces.client.getCurrentWorkspaceId();
if (currentWorkspaceIdResp.success && currentWorkspaceIdResp.result) {
return currentWorkspaceIdResp.result;
}

return 'default';
return null;
}

/**
Expand Down Expand Up @@ -270,7 +270,11 @@ export class SavedObjectsClient {
attributes,
migrationVersion: options.migrationVersion,
references: options.references,
initialNamespaces: options.initialNamespaces || [currentWorkspaceId],
...(options.workspaces || currentWorkspaceId
? {
workspaces: options.workspaces || [currentWorkspaceId],
}
: {}),
}),
});

Expand Down Expand Up @@ -343,7 +347,7 @@ export class SavedObjectsClient {
* @property {object} [options.hasReference] - { type, id }
* @returns A find result with objects matching the specified search.
*/
public find = <T = unknown>(
public find = async <T = unknown>(
options: SavedObjectsFindOptions
): Promise<SavedObjectsFindResponsePublic<T>> => {
const path = this.getPath(['_find']);
Expand All @@ -360,9 +364,15 @@ export class SavedObjectsClient {
filter: 'filter',
namespaces: 'namespaces',
preference: 'preference',
workspaces: 'workspaces',
};

const renamedQuery = renameKeys<SavedObjectsFindOptions, any>(renameMap, options);
const workspaces = [...(options.workspaces || [await this._getCurrentWorkspace()]), 'public'];

const renamedQuery = renameKeys<SavedObjectsFindOptions, any>(renameMap, {
...options,
workspaces,
});
const query = pick.apply(null, [renamedQuery, ...Object.values<string>(renameMap)]);

const request: ReturnType<SavedObjectsApi['find']> = this.savedObjectsFetch(path, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ function defaultMapping(): IndexMapping {
},
},
},
workspaces: {
type: 'keyword',
},
},
};
}
Expand Down
12 changes: 10 additions & 2 deletions src/core/server/saved_objects/routes/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,23 @@ export const registerCreateRoute = (router: IRouter) => {
)
),
initialNamespaces: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })),
workspaces: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })),
}),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const { type, id } = req.params;
const { overwrite } = req.query;
const { attributes, migrationVersion, references, initialNamespaces } = req.body;
const { attributes, migrationVersion, references, initialNamespaces, workspaces } = req.body;

const options = { id, overwrite, migrationVersion, references, initialNamespaces };
const options = {
id,
overwrite,
migrationVersion,
references,
initialNamespaces,
workspaces,
};
const result = await context.core.savedObjects.client.create(type, attributes, options);
return res.ok({ body: result });
})
Expand Down
6 changes: 6 additions & 0 deletions src/core/server/saved_objects/routes/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ export const registerFindRoute = (router: IRouter) => {
namespaces: schema.maybe(
schema.oneOf([schema.string(), schema.arrayOf(schema.string())])
),
workspaces: schema.maybe(
schema.oneOf([schema.string(), schema.arrayOf(schema.string())])
),
}),
},
},
Expand All @@ -81,6 +84,9 @@ export const registerFindRoute = (router: IRouter) => {
fields: typeof query.fields === 'string' ? [query.fields] : query.fields,
filter: query.filter,
namespaces,
workspaces: Array.isArray(query.workspaces)
? query.workspaces
: [query.workspaces || ''].filter((item) => item),
});

return res.ok({ body: result });
Expand Down
5 changes: 4 additions & 1 deletion src/core/server/saved_objects/serialization/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export class SavedObjectsSerializer {
*/
public rawToSavedObject(doc: SavedObjectsRawDoc): SavedObjectSanitizedDoc {
const { _id, _source, _seq_no, _primary_term } = doc;
const { type, namespace, namespaces, originId } = _source;
const { type, namespace, namespaces, originId, workspaces } = _source;

const version =
_seq_no != null || _primary_term != null
Expand All @@ -91,6 +91,7 @@ export class SavedObjectsSerializer {
...(_source.migrationVersion && { migrationVersion: _source.migrationVersion }),
...(_source.updated_at && { updated_at: _source.updated_at }),
...(version && { version }),
...(workspaces && { workspaces }),
};
}

Expand All @@ -112,6 +113,7 @@ export class SavedObjectsSerializer {
updated_at,
version,
references,
workspaces,
} = savedObj;
const source = {
[type]: attributes,
Expand All @@ -122,6 +124,7 @@ export class SavedObjectsSerializer {
...(originId && { originId }),
...(migrationVersion && { migrationVersion }),
...(updated_at && { updated_at }),
...(workspaces && { workspaces }),
};

return {
Expand Down
1 change: 1 addition & 0 deletions src/core/server/saved_objects/serialization/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ interface SavedObjectDoc<T = unknown> {
version?: string;
updated_at?: string;
originId?: string;
workspaces?: string[];
}

interface Referencable {
Expand Down
4 changes: 4 additions & 0 deletions src/core/server/saved_objects/service/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ export class SavedObjectsRepository {
originId,
initialNamespaces,
version,
workspaces,
} = options;
const namespace = normalizeNamespace(options.namespace);

Expand Down Expand Up @@ -289,6 +290,7 @@ export class SavedObjectsRepository {
migrationVersion,
updated_at: time,
...(Array.isArray(references) && { references }),
...(Array.isArray(workspaces) && { workspaces }),
});

const raw = this._serializer.savedObjectToRaw(migrated as SavedObjectSanitizedDoc);
Expand Down Expand Up @@ -736,6 +738,7 @@ export class SavedObjectsRepository {
typeToNamespacesMap,
filter,
preference,
workspaces,
} = options;

if (!type && !typeToNamespacesMap) {
Expand Down Expand Up @@ -809,6 +812,7 @@ export class SavedObjectsRepository {
typeToNamespacesMap,
hasReference,
kueryNode,
workspaces,
}),
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,35 @@ function getClauseForType(
};
}

/**
* Gets the clause that will filter for the workspace.
*/
function getClauseForWorkspace(workspace: string) {
if (workspace === '*') {
return {
bool: {
must: {
match_all: {},
},
},
};
}

if (workspace === 'public') {
return {
bool: {
must_not: [{ exists: { field: 'workspaces' } }],
},
};
}

return {
bool: {
must: [{ term: { workspaces: workspace } }],
},
};
}

interface HasReferenceQueryParams {
type: string;
id: string;
Expand All @@ -144,6 +173,7 @@ interface QueryParams {
defaultSearchOperator?: string;
hasReference?: HasReferenceQueryParams;
kueryNode?: KueryNode;
workspaces?: string[];
}

export function getClauseForReference(reference: HasReferenceQueryParams) {
Expand Down Expand Up @@ -200,6 +230,7 @@ export function getQueryParams({
defaultSearchOperator,
hasReference,
kueryNode,
workspaces,
}: QueryParams) {
const types = getTypes(
registry,
Expand All @@ -224,6 +255,17 @@ export function getQueryParams({
],
};

if (workspaces) {
bool.filter.push({
bool: {
should: workspaces.map((workspace) => {
return getClauseForWorkspace(workspace);
}),
minimum_should_match: 1,
},
});
}

if (search) {
const useMatchPhrasePrefix = shouldUseMatchPhrasePrefix(search);
const simpleQueryStringClause = getSimpleQueryStringClause({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ interface GetSearchDslOptions {
id: string;
};
kueryNode?: KueryNode;
workspaces?: string[];
}

export function getSearchDsl(
Expand All @@ -71,6 +72,7 @@ export function getSearchDsl(
typeToNamespacesMap,
hasReference,
kueryNode,
workspaces,
} = options;

if (!type) {
Expand All @@ -93,6 +95,7 @@ export function getSearchDsl(
defaultSearchOperator,
hasReference,
kueryNode,
workspaces,
}),
...getSortingParams(mappings, type, sortField, sortOrder),
};
Expand Down
2 changes: 2 additions & 0 deletions src/core/server/saved_objects/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export interface SavedObjectsFindOptions {
typeToNamespacesMap?: Map<string, string[] | undefined>;
/** An optional OpenSearch preference value to be used for the query **/
preference?: string;
workspaces?: string[];
}

/**
Expand All @@ -119,6 +120,7 @@ export interface SavedObjectsFindOptions {
export interface SavedObjectsBaseOptions {
/** Specify the namespace for this operation */
namespace?: string;
workspaces?: string[];
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import {
OverlayStart,
NotificationsStart,
ApplicationStart,
WorkspacesStart,
} from 'src/core/public';
import { RedirectAppLinks } from '../../../../opensearch_dashboards_react/public';
import { IndexPatternsContract } from '../../../../data/public';
Expand Down Expand Up @@ -114,6 +115,7 @@ export interface SavedObjectsTableProps {
goInspectObject: (obj: SavedObjectWithMetadata) => void;
canGoInApp: (obj: SavedObjectWithMetadata) => boolean;
dateFormat: string;
workspaces: WorkspacesStart;
}

export interface SavedObjectsTableState {
Expand Down Expand Up @@ -250,9 +252,11 @@ export class SavedObjectsTable extends Component<SavedObjectsTableProps, SavedOb

debouncedFetchObjects = debounce(async () => {
const { activeQuery: query, page, perPage } = this.state;
const { notifications, http, allowedTypes, namespaceRegistry } = this.props;
const { notifications, http, allowedTypes, namespaceRegistry, workspaces } = this.props;
const { queryText, visibleTypes, visibleNamespaces } = parseQuery(query);
const filteredTypes = filterQuery(allowedTypes, visibleTypes);
const currentWorkspaceIdResp = await workspaces.client.getCurrentWorkspaceId();
const currentWorkspaceId = currentWorkspaceIdResp.success ? currentWorkspaceIdResp.result : '';
// "searchFields" is missing from the "findOptions" but gets injected via the API.
// The API extracts the fields from each uiExports.savedObjectsManagement "defaultSearchField" attribute
const findOptions: SavedObjectsFindOptions = {
Expand All @@ -261,6 +265,7 @@ export class SavedObjectsTable extends Component<SavedObjectsTableProps, SavedOb
page: page + 1,
fields: ['id'],
type: filteredTypes,
workspaces: ['public', ...(currentWorkspaceId ? [currentWorkspaceId] : [])],
};

const availableNamespaces = namespaceRegistry.getAll()?.map((ns) => ns.id) || [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const SavedObjectsTablePage = ({
overlays={coreStart.overlays}
notifications={coreStart.notifications}
applications={coreStart.application}
workspaces={coreStart.workspaces}
perPageConfig={itemsPerPage}
goInspectObject={(savedObject) => {
const { editUrl } = savedObject.meta;
Expand Down
13 changes: 13 additions & 0 deletions src/plugins/saved_objects_management/server/routes/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ export const registerFindRoute = (
fields: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], {
defaultValue: [],
}),
workspaces: schema.maybe(
schema.oneOf([schema.string(), schema.arrayOf(schema.string())])
),
}),
},
},
Expand Down Expand Up @@ -94,6 +97,16 @@ export const registerFindRoute = (
...req.query,
fields: undefined,
searchFields: [...searchFields],
namespaces: req.query.namespaces
? Array.isArray(req.query.namespaces)
? req.query.namespaces
: [req.query.namespaces]
: undefined,
workspaces: req.query.workspaces
? Array.isArray(req.query.workspaces)
? req.query.workspaces
: [req.query.workspaces]
: undefined,
});

const savedObjects = await Promise.all(
Expand Down

0 comments on commit d62f9b7

Please sign in to comment.