[Saved Object Management] Address v1 HTTP API TODOs (#150892)

## Summary

This PR addresses 4 TODOs identified in
https://github.com/elastic/kibana/pull/149495. We address these TODOs by
taking a closer look at actual use of flagged fields in public code:

1. `FindQueryHTTP['namespaceType']`: Probably OK to directly expose this
as it seems highly unlikely this value will change soon... We should
also be able to version it since it is a well known set.
2. `FindQueryHTTP['search']`: looks like it is allowing users to enter
_any_ search value against SO attribs. However, this functionality is
constrained because it only takes a search term and runs it against a
server-side determined search field. The risk is that consumers of the
server-side functionality do not keep their default search field
up-to-date.
3. `FindQueryHTTP['fields']`: Our UI only ever passes in `id` here. We
should consider a follow up PR to add some counter telemetry to track
usage of this option and consider removing it entirely.
4. `FindQueryHTTP['sortField']`: Lock this down to a well known set of
values (probably the riskiest change here).

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Jean-Louis Leysens 2023-02-16 12:11:14 +01:00 committed by GitHub
parent 0581fa3a91
commit ad45020c8e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 20 deletions

View file

@ -75,7 +75,6 @@ export interface SavedObjectInvalidRelation {
export interface SavedObjectManagementTypeInfo {
name: string;
// TODO: Fix. We should not directly expose these values to public code.
namespaceType: SavedObjectsNamespaceType;
hidden: boolean;
displayName: string;
@ -118,15 +117,24 @@ export interface FindQueryHTTP {
perPage?: number;
page?: number;
type: string | string[];
// TODO: Fix. this API allows writing an arbitrary query that is passed straight to our persistence layer, thus leaking SO attributes to the public...
/**
* SO's can register one or more "defaultSearchField"'s against which this query will run using the
* {@link SavedObjectsFindOptions['searchFields'] | search fields} option.
*
* Therefore we are not directly exposing SO attributes to the public here.
*/
search?: string;
defaultSearchOperator?: FindSearchOperatorHTTP;
// TODO: Fix. this API allows sorting by any field, thus leaking SO attributes to the public...
sortField?: string;
sortField?: keyof SavedObjectWithMetadata;
sortOrder?: FindSortOrderHTTP;
hasReference?: ReferenceHTTP | ReferenceHTTP[];
hasReferenceOperator?: FindSearchOperatorHTTP;
// TODO: Fix. This exposes attribute schemas to clients.
/**
* It is not clear who might be using this API option, the SOM UI only ever passes in "id" here.
*
* TODO: Determine use. If not in use we should remove this option. If in use we must deprecate and eventually
* remove.
*/
fields?: string | string[];
}

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import type { HttpStart, SavedObjectsFindOptionsReference } from '@kbn/core/public';
import type { HttpStart } from '@kbn/core/public';
import type { v1 } from '../../common';
export async function getSavedObjectCounts({
@ -16,10 +16,7 @@ export async function getSavedObjectCounts({
references,
}: {
http: HttpStart;
typesToInclude: string[];
searchString?: string;
references?: SavedObjectsFindOptionsReference[];
}): Promise<v1.ScrollCountResponseHTTP> {
} & v1.ScrollCountBodyHTTP): Promise<v1.ScrollCountResponseHTTP> {
return await http.post(`/api/kibana/management/saved_objects/scroll/counts`, {
body: JSON.stringify({ typesToInclude, searchString, references }),
});

View file

@ -13,14 +13,13 @@ import { saveAs } from '@elastic/filesaver';
import { EuiSpacer, Query, CriteriaWithPagination } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { HttpStart, OverlayStart, NotificationsStart, ApplicationStart } from '@kbn/core/public';
import type { SavedObjectsFindOptions } from '@kbn/core-saved-objects-api-server';
import { RedirectAppLinks } from '@kbn/kibana-react-plugin/public';
import { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public';
import { DataViewsContract } from '@kbn/data-views-plugin/public';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { CustomBrandingStart } from '@kbn/core-custom-branding-browser';
import { Subscription } from 'rxjs';
import type { SavedObjectManagementTypeInfo } from '../../../common/types';
import type { SavedObjectManagementTypeInfo, FindQueryHTTP } from '../../../common/types/latest';
import {
parseQuery,
getSavedObjectCounts,
@ -233,17 +232,16 @@ export class SavedObjectsTable extends Component<SavedObjectsTableProps, SavedOb
// "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 = {
const findOptions: FindQueryHTTP = {
search: queryText ? `${queryText}*` : undefined,
perPage,
page: page + 1,
fields: ['id'],
type: searchTypes,
sortField: sort?.field,
sortOrder: sort?.direction,
hasReference: getTagFindReferences({ selectedTags, taggingApi }),
};
findOptions.sortField = sort?.field;
findOptions.sortOrder = sort?.direction;
findOptions.hasReference = getTagFindReferences({ selectedTags, taggingApi });
try {
const resp = await findObjects(http, findOptions);

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { schema } from '@kbn/config-schema';
import { type Type, schema } from '@kbn/config-schema';
import type { IRouter } from '@kbn/core/server';
import type { v1 } from '../../common';
@ -24,6 +24,11 @@ export const registerFindRoute = (
const searchOperatorSchema = schema.oneOf([schema.literal('OR'), schema.literal('AND')], {
defaultValue: 'OR',
});
const sortFieldSchema: Type<keyof v1.SavedObjectWithMetadata> = schema.oneOf([
schema.literal('created_at'),
schema.literal('updated_at'),
schema.literal('type'),
]);
router.get(
{
@ -35,7 +40,7 @@ export const registerFindRoute = (
type: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]),
search: schema.maybe(schema.string()),
defaultSearchOperator: searchOperatorSchema,
sortField: schema.maybe(schema.string()),
sortField: schema.maybe(sortFieldSchema),
sortOrder: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])),
hasReference: schema.maybe(
schema.oneOf([referenceSchema, schema.arrayOf(referenceSchema)])

View file

@ -21,7 +21,6 @@
"@kbn/utility-types",
"@kbn/i18n-react",
"@kbn/test-jest-helpers",
"@kbn/core-saved-objects-api-server",
"@kbn/monaco",
"@kbn/config-schema",
"@kbn/core-custom-branding-browser-mocks",