[Files] Mime-type and extension filtering on client side (#159588)

## Summary

This PR makes sure that, both, `.list()` and `.find()` client side
methods support filtering by mime type as well as by file extension.

Closes https://github.com/elastic/kibana/issues/155379


### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

### For maintainers

- [x] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Vadim Kibana 2023-06-15 13:18:56 +02:00 committed by GitHub
parent 2f1c2fa3e7
commit 232c3a247a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 152 additions and 2 deletions

View file

@ -30,6 +30,7 @@ export interface BaseFilesClient<M = unknown> {
kindToExclude?: string | string[];
status?: string | string[];
extension?: string | string[];
mimeType?: string | string[];
name?: string | string[];
meta?: M;
} & Pagination &
@ -73,6 +74,7 @@ export interface BaseFilesClient<M = unknown> {
kind: string;
status?: string | string[];
extension?: string | string[];
mimeType?: string | string[];
name?: string | string[];
meta?: M;
} & Pagination &

View file

@ -132,6 +132,86 @@ describe('File kind HTTP API', () => {
expect(files2).toHaveLength(5);
});
test('can filter by mime type', async () => {
await createFile({ name: 'test', mimeType: 'image/png' });
await createFile({ name: 'test 2', mimeType: 'text/html' });
const {
body: { files },
} = await request
.post(root, `/api/files/files/${fileKind}/list`)
.send({
mimeType: 'image/png',
})
.expect(200);
expect(files.length).toBe(1);
expect(files[0]).toMatchObject({ name: 'test' });
const {
body: { files: files2 },
} = await request
.post(root, `/api/files/files/${fileKind}/list`)
.send({
mimeType: 'text/html',
})
.expect(200);
expect(files2.length).toBe(1);
expect(files2[0]).toMatchObject({ name: 'test 2' });
const {
body: { files: files3 },
} = await request
.post(root, `/api/files/files/${fileKind}/list`)
.send({
mimeType: ['text/html', 'image/png'],
})
.expect(200);
expect(files3.length).toBe(2);
});
test('can filter by file extension', async () => {
await createFile({ name: 'test', mimeType: 'image/png' });
await createFile({ name: 'test 2', mimeType: 'text/html' });
const {
body: { files },
} = await request
.post(root, `/api/files/files/${fileKind}/list`)
.send({
extension: 'png',
})
.expect(200);
expect(files.length).toBe(1);
expect(files[0]).toMatchObject({ name: 'test' });
const {
body: { files: files2 },
} = await request
.post(root, `/api/files/files/${fileKind}/list`)
.send({
extension: 'html',
})
.expect(200);
expect(files2.length).toBe(1);
expect(files2[0]).toMatchObject({ name: 'test 2' });
const {
body: { files: files3 },
} = await request
.post(root, `/api/files/files/${fileKind}/list`)
.send({
extension: ['html', 'png'],
})
.expect(200);
expect(files3.length).toBe(2);
});
const twoDaysFromNow = (): number => Date.now() + 2 * (1000 * 60 * 60 * 24);
test('gets a single share object', async () => {

View file

@ -25,6 +25,7 @@ const rt = {
body: schema.object({
status: schema.maybe(stringOrArrayOfStrings),
extension: schema.maybe(stringOrArrayOfStrings),
mimeType: schema.maybe(stringOrArrayOfStrings),
name: schema.maybe(nameStringOrArrayOfNameStrings),
meta: commonSchemas.fileMeta,
}),
@ -42,7 +43,7 @@ export type Endpoint<M = unknown> = CreateRouteDefinition<
export const handler: CreateHandler<Endpoint> = async ({ files, fileKind }, req, res) => {
const {
body: { name, status, extension, meta },
body: { name, status, extension, mimeType, meta },
query: { page, perPage },
} = req;
const { fileService } = await files;
@ -51,6 +52,7 @@ export const handler: CreateHandler<Endpoint> = async ({ files, fileKind }, req,
name: toArrayOrUndefined(name),
status: toArrayOrUndefined(status),
extension: toArrayOrUndefined(extension),
mimeType: toArrayOrUndefined(mimeType),
page,
perPage,
meta: meta as Record<string, string>,

View file

@ -33,6 +33,7 @@ const rt = {
kindToExclude: schema.maybe(stringOrArrayOfStrings),
status: schema.maybe(stringOrArrayOfStrings),
extension: schema.maybe(stringOrArrayOfStrings),
mimeType: schema.maybe(stringOrArrayOfStrings),
name: schema.maybe(nameStringOrArrayOfNameStrings),
meta: fileMeta,
}),
@ -51,7 +52,7 @@ export type Endpoint = CreateRouteDefinition<
const handler: CreateHandler<Endpoint> = async ({ files }, req, res) => {
const { fileService } = await files;
const {
body: { meta, extension, kind, name, status, kindToExclude },
body: { meta, extension, mimeType, kind, name, status, kindToExclude },
query,
} = req;
@ -61,6 +62,7 @@ const handler: CreateHandler<Endpoint> = async ({ files }, req, res) => {
name: toArrayOrUndefined(name),
status: toArrayOrUndefined(status),
extension: toArrayOrUndefined(extension),
mimeType: toArrayOrUndefined(mimeType),
meta: meta as Record<string, string>,
...query,
});

View file

@ -122,6 +122,70 @@ describe('File HTTP API', () => {
.expect(200);
expect(result.body.files).toHaveLength(1);
});
test('extension', async () => {
const result = await request
.post(root, '/api/files/find')
.send({
kind: testHarness.fileKind,
extension: 'png',
})
.expect(200);
expect(result.body.files).toHaveLength(2);
const result2 = await request
.post(root, '/api/files/find')
.send({
kind: testHarness.fileKind,
extension: 'pdf',
})
.expect(200);
expect(result2.body.files).toHaveLength(1);
const result3 = await request
.post(root, '/api/files/find')
.send({
kind: testHarness.fileKind,
extension: 'txt',
})
.expect(200);
expect(result3.body.files).toHaveLength(0);
});
test('mime type', async () => {
const result = await request
.post(root, '/api/files/find')
.send({
kind: testHarness.fileKind,
mimeType: 'image/png',
})
.expect(200);
expect(result.body.files).toHaveLength(2);
const result2 = await request
.post(root, '/api/files/find')
.send({
kind: testHarness.fileKind,
mimeType: 'application/pdf',
})
.expect(200);
expect(result2.body.files).toHaveLength(1);
const result3 = await request
.post(root, '/api/files/find')
.send({
kind: testHarness.fileKind,
mimeType: 'text/plain',
})
.expect(200);
expect(result3.body.files).toHaveLength(0);
});
});
describe('metrics', () => {