Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
12b2110
added the createdBy field to schemas
jloleysens Oct 26, 2022
f3bc75e
update serialize-deserializer
jloleysens Oct 26, 2022
755689c
use the security plugin to get the user ID from the request object
jloleysens Oct 26, 2022
5ea2574
get the user name from request
jloleysens Oct 26, 2022
3462c39
update tests
jloleysens Oct 26, 2022
78559b9
Merge branch 'main' into files-record-created-by
jloleysens Oct 26, 2022
f9075da
Merge branch 'main' into files-record-created-by
jloleysens Oct 31, 2022
2f3d2be
CreatedBy -> owner
jloleysens Oct 31, 2022
ce6954f
make owner field optional
jloleysens Oct 31, 2022
de4fcc6
updated files SO hash
jloleysens Oct 31, 2022
09b3061
record both username and UID
jloleysens Oct 31, 2022
fb4c3e2
actually record profile_uid!
jloleysens Oct 31, 2022
52d63a1
only call getCurrentUser once
jloleysens Oct 31, 2022
41988d9
revert to previous files SO hash
jloleysens Oct 31, 2022
8f24d18
fix expects for update arg and pass through meta argument
jloleysens Oct 31, 2022
0c910e7
Merge branch 'main' into files-record-created-by
jloleysens Oct 31, 2022
2d7b3c1
added user field back to base metadata
jloleysens Nov 1, 2022
46531e2
remove references to FileSystemMetadata
jloleysens Nov 1, 2022
bafc2ec
added user field as flattened
jloleysens Nov 1, 2022
9c1be50
updated files SO
jloleysens Nov 1, 2022
f63bb05
update types and metadata
jloleysens Nov 1, 2022
b5ce91c
update how we record the user on the controller
jloleysens Nov 1, 2022
44ec96a
update tests
jloleysens Nov 1, 2022
1a922aa
remove extra long comment from the Meta field
jloleysens Nov 1, 2022
403b47d
Merge branch 'main' into files-record-created-by
jloleysens Nov 1, 2022
5556d7f
Merge branch 'main' into files-record-created-by
jloleysens Nov 1, 2022
6db3f3e
Merge branch 'main' into files-record-created-by
jloleysens Nov 2, 2022
24d9c72
Merge branch 'main' into files-record-created-by
jloleysens Nov 3, 2022
f6c663e
Merge branch 'main' into files-record-created-by
jloleysens Nov 3, 2022
ddeea1d
Merge branch 'main' into files-record-created-by
jloleysens Nov 4, 2022
aa22298
Merge branch 'main' into files-record-created-by
jloleysens Nov 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
"event_loop_delays_daily": "d2ed39cf669577d90921c176499908b4943fb7bd",
"exception-list": "fe8cc004fd2742177cdb9300f4a67689463faf9c",
"exception-list-agnostic": "49fae8fcd1967cc4be45ba2a2c66c4afbc1e341b",
"file": "70c2a768473057157f6ee5d29a436e5288d22ff4",
"file": "05c14a75e5e20b12ca514a1d7de231f420facf2c",
"file-upload-usage-collection-telemetry": "8478924cf0057bd90df737155b364f98d05420a5",
"fileShare": "3f88784b041bb8728a7f40763a08981828799a75",
"fleet-fleet-server-host": "f00ca963f1bee868806319789cdc33f1f53a97e2",
Expand Down
27 changes: 24 additions & 3 deletions src/plugins/files/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,10 @@ export type BaseFileMetadata = {
* ISO string representing the file creation date
*/
created?: string;

/**
* Size of the file
*/
size?: number;

/**
* Hash of the file's contents
*/
Expand Down Expand Up @@ -107,6 +105,25 @@ export type BaseFileMetadata = {
[hashName: string]: string | undefined;
};

/**
* Data about the user that created the file
*/
user?: {
/**
* The human-friendly user name of the owner of the file
*
* @note this field cannot be used to uniquely ID a user. See {@link BaseFileMetadata['user']['id']}.
*/
name?: string;
/**
* The unique ID of the user who created the file, taken from the user profile
* ID.
*
* See https://www.elastic.co/guide/en/elasticsearch/reference/master/user-profile.html.
*/
id?: string;
};

/**
* The file extension, for example "jpg", "png", "svg" and so forth
*/
Expand Down Expand Up @@ -153,7 +170,7 @@ export type FileMetadata<Meta = unknown> = Required<
FileKind: string;

/**
* User-defined metadata
* User-defined metadata.
*/
Meta?: Meta;
};
Expand Down Expand Up @@ -222,6 +239,10 @@ export interface FileJSON<Meta = unknown> {
* See {@link FileStatus} for more details.
*/
status: FileMetadata['Status'];
/**
* User data associated with this file
*/
user?: FileMetadata['user'];
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import React from 'react';
import { ComponentMeta, ComponentStory } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import type { FileJSON } from '../../../common';
import type { FileJSON, FileImageMetadata } from '../../../common';
import { FilesClient, FilesClientResponses } from '../../types';
import { register } from '../stories_shared';
import { base64dLogo } from '../image/image.constants.stories';
Expand Down Expand Up @@ -59,7 +59,7 @@ export const Empty = Template.bind({});

const d = new Date();
let id = 0;
function createFileJSON(file?: Partial<FileJSON>): FileJSON {
function createFileJSON(file?: Partial<FileJSON<FileImageMetadata>>): FileJSON<FileImageMetadata> {
return {
alt: '',
created: d.toISOString(),
Expand Down
14 changes: 9 additions & 5 deletions src/plugins/files/server/file/to_json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,33 @@
import { pickBy } from 'lodash';
import type { FileMetadata, FileJSON } from '../../common/types';

export function serializeJSON<M = unknown>(attrs: Partial<FileJSON>): Partial<FileMetadata> {
const { name, mimeType, size, created, updated, fileKind, status, alt, extension, meta } = attrs;
export function serializeJSON<M = unknown>(attrs: Partial<FileJSON>): Partial<FileMetadata<M>> {
const { name, mimeType, size, created, updated, fileKind, status, alt, extension, meta, user } =
attrs;
return pickBy(
{
name,
mime_type: mimeType,
size,
user,
created,
extension,
Alt: alt,
Status: status,
Meta: meta as M,
Meta: meta,
Updated: updated,
FileKind: fileKind,
},
(v) => v != null
);
}

export function toJSON<M = unknown>(id: string, attrs: FileMetadata): FileJSON<M> {
export function toJSON<M = unknown>(id: string, attrs: FileMetadata<M>): FileJSON<M> {
const {
name,
mime_type: mimeType,
size,
user,
created,
Updated,
FileKind,
Expand All @@ -44,14 +47,15 @@ export function toJSON<M = unknown>(id: string, attrs: FileMetadata): FileJSON<M
return pickBy<FileJSON<M>>(
{
id,
user,
name,
mimeType,
size,
created,
extension,
alt: Alt,
status: Status,
meta: Meta as M,
meta: Meta,
updated: Updated,
fileKind: FileKind,
},
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/files/server/file_client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ export interface DeleteArgs {
/**
* Args to create a file
*/
export interface CreateArgs {
export interface CreateArgs<Meta = unknown> {
/**
* Unique file ID
*/
id?: string;
/**
* The file's metadata
*/
metadata: Omit<CreateFileArgs, 'fileKind'>;
metadata: Omit<CreateFileArgs<Meta>, 'fileKind'>;
}

/**
Expand Down Expand Up @@ -71,7 +71,7 @@ export interface FileClient {
*
* @param arg - Arg to create a file.
* */
create<M = unknown>(arg: CreateArgs): Promise<File<M>>;
create<M = unknown>(arg: CreateArgs<M>): Promise<File<M>>;

/**
* See {@link FileMetadataClient.get}
Expand Down
6 changes: 5 additions & 1 deletion src/plugins/files/server/file_service/file_action_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Side Public License, v 1.
*/

import type { Pagination, UpdatableFileMetadata } from '../../common/types';
import type { FileMetadata, Pagination, UpdatableFileMetadata } from '../../common/types';

/**
* Arguments to create a new file.
Expand All @@ -32,6 +32,10 @@ export interface CreateFileArgs<Meta = unknown> {
* The MIME type of the file.
*/
mime?: string;
/**
* User data associated with this file
*/
user?: FileMetadata['user'];
}

/**
Expand Down
12 changes: 10 additions & 2 deletions src/plugins/files/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ import {

import { BlobStorageService } from './blob_storage_service';
import { FileServiceFactory } from './file_service';
import type { FilesPluginSetupDependencies, FilesSetup, FilesStart } from './types';
import type {
FilesPluginSetupDependencies,
FilesPluginStartDependencies,
FilesSetup,
FilesStart,
} from './types';

import type { FilesRequestHandlerContext, FilesRouter } from './routes/types';
import { registerRoutes, registerFileKindRoutes } from './routes';
Expand All @@ -33,6 +38,7 @@ export class FilesPlugin implements Plugin<FilesSetup, FilesStart, FilesPluginSe
private readonly logger: Logger;
private fileServiceFactory: undefined | FileServiceFactory;
private securitySetup: FilesPluginSetupDependencies['security'];
private securityStart: FilesPluginStartDependencies['security'];

constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get();
Expand All @@ -50,6 +56,7 @@ export class FilesPlugin implements Plugin<FilesSetup, FilesStart, FilesPluginSe
PLUGIN_ID,
async (ctx, req) => {
return {
security: this.securityStart,
fileService: {
asCurrentUser: () => this.fileServiceFactory!.asScoped(req),
asInternalUser: () => this.fileServiceFactory!.asInternal(),
Expand Down Expand Up @@ -81,8 +88,9 @@ export class FilesPlugin implements Plugin<FilesSetup, FilesStart, FilesPluginSe
};
}

public start(coreStart: CoreStart): FilesStart {
public start(coreStart: CoreStart, { security }: FilesPluginStartDependencies): FilesStart {
const { savedObjects } = coreStart;
this.securityStart = security;
const esClient = coreStart.elasticsearch.client.asInternalUser;
const blobStorageService = new BlobStorageService(
esClient,
Expand Down
14 changes: 10 additions & 4 deletions src/plugins/files/server/routes/file_kind/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,19 @@ const rt = {
export type Endpoint<M = unknown> = CreateRouteDefinition<typeof rt, { file: FileJSON<M> }>;

export const handler: CreateHandler<Endpoint> = async ({ fileKind, files }, req, res) => {
const { fileService } = await files;
const { fileService, security } = await files;
const {
body: { name, alt, meta, mimeType },
} = req;
const file = await fileService
.asCurrentUser()
.create({ fileKind, name, alt, meta, mime: mimeType });
const user = security?.authc.getCurrentUser(req);
const file = await fileService.asCurrentUser().create({
fileKind,
name,
alt,
meta,
user: user ? { name: user.username, id: user.profile_uid } : undefined,
mime: mimeType,
});
const body: Endpoint['output'] = {
file: file.toJSON(),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ describe('File kind HTTP API', () => {
mimeType: 'image/png',
extension: 'png',
meta: {},
user: {
name: expect.any(String),
},
alt: 'a picture of my dog',
});
});
Expand Down Expand Up @@ -81,28 +84,32 @@ describe('File kind HTTP API', () => {
} = await request.get(root, `/api/files/files/${fileKind}/${id}`).expect(200);
expect(file.name).toBe('acoolfilename');

const updatedFileAttrs: UpdatableFileMetadata = {
const updatedFileAttrs: UpdatableFileMetadata<{ something: string }> = {
name: 'anothercoolfilename',
alt: 'a picture of my cat',
meta: {
something: 'new',
},
};

const {
body: { file: updatedFile },
} = await request
.patch(root, `/api/files/files/${fileKind}/${id}`)
.send(updatedFileAttrs)
.expect(200);
{
const {
body: { file: updatedFile },
} = await request
.patch(root, `/api/files/files/${fileKind}/${id}`)
.send(updatedFileAttrs)
.expect(200);

expect(updatedFile).toEqual(expect.objectContaining(updatedFileAttrs));
expect(updatedFile).toMatchObject(updatedFileAttrs);
}

const {
body: { file: file2 },
} = await request.get(root, `/api/files/files/${fileKind}/${id}`).expect(200);
{
const {
body: { file: updatedFile },
} = await request.get(root, `/api/files/files/${fileKind}/${id}`).expect(200);

expect(file2).toEqual(expect.objectContaining(updatedFileAttrs));
expect(updatedFile).toMatchObject(updatedFileAttrs);
}
});

test('list current files', async () => {
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/files/server/routes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ import type {
IKibanaResponse,
Logger,
} from '@kbn/core/server';
import type { SecurityPluginStart } from '@kbn/security-plugin/server';
import type { FileServiceStart } from '../file_service';
import { Counters } from '../usage';
import { AnyEndpoint } from './api_routes';

export interface FilesRequestHandlerContext extends RequestHandlerContext {
files: Promise<{
security?: SecurityPluginStart;
fileService: {
asCurrentUser: () => FileServiceStart;
asInternalUser: () => FileServiceStart;
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/files/server/saved_objects/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ const properties: Properties = {
name: {
type: 'text',
},
user: {
type: 'flattened',
},
Status: {
type: 'keyword',
},
Expand Down
7 changes: 5 additions & 2 deletions src/plugins/files/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import type { SecurityPluginSetup } from '@kbn/security-plugin/server';
import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server';
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
import { FileKind } from '../common';
import { FileServiceFactory } from './file_service/file_service_factory';
Expand All @@ -31,6 +30,10 @@ export interface FilesPluginSetupDependencies {
usageCollection?: UsageCollectionSetup;
}

export interface FilesPluginStartDependencies {
security?: SecurityPluginStart;
}

/**
* Files plugin start contract
*/
Expand Down