Skip to content

Commit

Permalink
Add enabledOperators parameter for workspace name unique check (#306)
Browse files Browse the repository at this point in the history
* Add enabledOperators parameter for workspace name unique check

Signed-off-by: Hailong Cui <ihailong@amazon.com>

* Add test for enabled opeartors

Signed-off-by: Hailong Cui <ihailong@amazon.com>

* Add integration test

Signed-off-by: Hailong Cui <ihailong@amazon.com>

---------

Signed-off-by: Hailong Cui <ihailong@amazon.com>
  • Loading branch information
Hailong-am authored Apr 15, 2024
1 parent d6999ac commit da95876
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/core/public/saved_objects/saved_objects_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ export class SavedObjectsClient {
namespaces: 'namespaces',
preference: 'preference',
workspaces: 'workspaces',
enabledOperators: 'enabledOperators',
};

const renamedQuery = renameKeys<SavedObjectsFindOptions, any>(renameMap, {
Expand Down
2 changes: 2 additions & 0 deletions src/core/server/saved_objects/service/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,7 @@ export class SavedObjectsRepository {
workspaces,
workspacesSearchOperator,
ACLSearchParams,
enabledOperators,
} = options;

if (!type && !typeToNamespacesMap) {
Expand Down Expand Up @@ -877,6 +878,7 @@ export class SavedObjectsRepository {
workspaces,
workspacesSearchOperator,
ACLSearchParams,
enabledOperators,
}),
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,25 @@ describe('#getQueryParams', () => {
);
});
});

describe('`enabledOperators` parameter', () => {
it('does not include flags when `enabledOperators` is not specified', () => {
const result = getQueryParams({
registry,
search,
});
expectResult(result, expect.not.objectContaining({ flags: expect.anything() }));
});

it('includes flags when `enabledOperators` specified', () => {
const result = getQueryParams({
registry,
search,
enabledOperators: 'all',
});
expectResult(result, expect.objectContaining({ flags: expect.stringMatching('all') }));
});
});
});

describe('when using prefix search (query.bool.should)', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ interface QueryParams {
workspaces?: SavedObjectsFindOptions['workspaces'];
workspacesSearchOperator?: 'AND' | 'OR';
ACLSearchParams?: SavedObjectsFindOptions['ACLSearchParams'];
enabledOperators?: SavedObjectsFindOptions['enabledOperators'];
}

export function getClauseForReference(reference: HasReferenceQueryParams) {
Expand Down Expand Up @@ -229,6 +230,7 @@ export function getQueryParams({
workspaces,
workspacesSearchOperator = 'AND',
ACLSearchParams,
enabledOperators,
}: QueryParams) {
const types = getTypes(
registry,
Expand Down Expand Up @@ -261,6 +263,7 @@ export function getQueryParams({
searchFields,
rootSearchFields,
defaultSearchOperator,
enabledOperators,
});

if (useMatchPhrasePrefix) {
Expand Down Expand Up @@ -432,18 +435,21 @@ const getSimpleQueryStringClause = ({
searchFields,
rootSearchFields,
defaultSearchOperator,
enabledOperators,
}: {
search: string;
types: string[];
searchFields?: string[];
rootSearchFields?: string[];
defaultSearchOperator?: string;
enabledOperators?: SavedObjectsFindOptions['enabledOperators'];
}) => {
return {
simple_query_string: {
query: search,
...getSimpleQueryStringTypeFields(types, searchFields, rootSearchFields),
...(defaultSearchOperator ? { default_operator: defaultSearchOperator } : {}),
...(enabledOperators ? { flags: enabledOperators } : {}),
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ interface GetSearchDslOptions {
workspaces?: SavedObjectsFindOptions['workspaces'];
workspacesSearchOperator?: 'AND' | 'OR';
ACLSearchParams?: SavedObjectsFindOptions['ACLSearchParams'];
enabledOperators?: SavedObjectsFindOptions['enabledOperators'];
}

export function getSearchDsl(
Expand All @@ -78,6 +79,7 @@ export function getSearchDsl(
workspaces,
workspacesSearchOperator,
ACLSearchParams,
enabledOperators,
} = options;

if (!type) {
Expand All @@ -103,6 +105,7 @@ export function getSearchDsl(
workspaces,
workspacesSearchOperator,
ACLSearchParams,
enabledOperators,
}),
...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 @@ -92,6 +92,8 @@ export interface SavedObjectsFindOptions {
search?: string;
/** The fields to perform the parsed query against. See OpenSearch Simple Query String `fields` argument for more information */
searchFields?: string[];
/** The enabled operators for OpenSearch Simple Query String. See OpenSearch Simple Query String `flags` argument for more information */
enabledOperators?: string;
/**
* The fields to perform the parsed query against. Unlike the `searchFields` argument, these are expected to be root fields and will not
* be modified. If used in conjunction with `searchFields`, both are concatenated together.
Expand Down
86 changes: 86 additions & 0 deletions src/plugins/workspace/server/integration_tests/routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,42 @@ describe('workspace service api integration test', () => {
expect(result.body.success).toEqual(true);
expect(typeof result.body.result.id).toBe('string');
});
it('create workspace failed when name duplicate', async () => {
let result: any = await osdTestServer.request
.post(root, `/api/workspaces`)
.send({
attributes: omitId(testWorkspace),
})
.expect(200);

expect(result.body.success).toEqual(true);

await opensearchServer.opensearch.getClient().indices.refresh({ index: '.kibana' });

// same name
result = await osdTestServer.request
.post(root, `/api/workspaces`)
.send({
attributes: omitId(testWorkspace),
})
.expect(200);

expect(result.body.success).toEqual(false);
expect(result.body.error).toEqual(
'workspace name has already been used, try with a different name'
);

// verify simple query string flags is NONE
result = await osdTestServer.request
.post(root, `/api/workspaces`)
.send({
attributes: { ...omitId(testWorkspace), name: 'test test_workspace' },
})
.expect(200);

expect(result.body.success).toEqual(true);
});

it('get', async () => {
const result = await osdTestServer.request
.post(root, `/api/workspaces`)
Expand Down Expand Up @@ -128,6 +164,56 @@ describe('workspace service api integration test', () => {
expect(getResult.body.success).toEqual(true);
expect(getResult.body.result.name).toEqual('updated');
});

it('update workspace failed when name is duplicate', async () => {
const result: any = await osdTestServer.request
.post(root, `/api/workspaces`)
.send({
attributes: { ...omitId(testWorkspace), name: 'foo' },
})
.expect(200);

await osdTestServer.request
.post(root, `/api/workspaces`)
.send({
attributes: { ...omitId(testWorkspace), name: 'bar baz' },
})
.expect(200);

const updateResult = await osdTestServer.request
.put(root, `/api/workspaces/${result.body.result.id}`)
.send({
attributes: {
...omitId(testWorkspace),
name: 'bar baz',
},
})
.expect(200);

expect(updateResult.body.success).toEqual(false);
expect(updateResult.body.error).toEqual(
'workspace name has already been used, try with a different name'
);

await osdTestServer.request
.put(root, `/api/workspaces/${result.body.result.id}`)
.send({
attributes: {
...omitId(testWorkspace),
name: 'bar',
},
})
.expect(200);

const getResult = await osdTestServer.request.get(
root,
`/api/workspaces/${result.body.result.id}`
);

expect(getResult.body.success).toEqual(true);
expect(getResult.body.result.name).toEqual('bar');
});

it('delete', async () => {
const result: any = await osdTestServer.request
.post(root, `/api/workspaces`)
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/workspace/server/workspace_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export class WorkspaceClient implements IWorkspaceClientImpl {
type: WORKSPACE_TYPE,
search: attributes.name,
searchFields: ['name'],
enabledOperators: 'NONE', // disable all operators, treat workspace as literal string
}
);
if (existingWorkspaceRes && existingWorkspaceRes.total > 0) {
Expand Down Expand Up @@ -260,6 +261,7 @@ export class WorkspaceClient implements IWorkspaceClientImpl {
search: attributes.name,
searchFields: ['name'],
fields: ['_id'],
enabledOperators: 'NONE', // disable all operators, treat workspace as literal string
});
if (existingWorkspaceRes && existingWorkspaceRes.total > 0) {
throw new Error(DUPLICATE_WORKSPACE_NAME_ERROR);
Expand Down

0 comments on commit da95876

Please sign in to comment.