From 944651e021dadc058887694c668c6d2f218b374c Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Thu, 28 Apr 2022 09:15:05 -0300 Subject: [PATCH] feat: update listTasks flow Signed-off-by: Rogerio Angeliski --- .../src/scaffolder/tasks/DatabaseTaskStore.ts | 16 +++-- .../tasks/StorageTaskBroker.test.ts | 26 ++++++++ .../src/scaffolder/tasks/StorageTaskBroker.ts | 6 +- .../src/service/router.test.ts | 61 +++++++++++++++++++ .../scaffolder-backend/src/service/router.ts | 9 +-- 5 files changed, 99 insertions(+), 19 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index 6752972244..1c4b9b5210 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -86,12 +86,15 @@ export class DatabaseTaskStore implements TaskStore { } async list(options: Partial): Promise { - const results = await this.db('tasks') - .where({ + const queryBuilder = this.db('tasks'); + + if (options.createdBy) { + queryBuilder.where({ created_by: options.createdBy, - }) - .orderBy('created_at', 'desc') - .select(); + }); + } + + const results = await queryBuilder.orderBy('created_at', 'desc').select(); return results.map(result => ({ id: result.id, @@ -153,7 +156,8 @@ export class DatabaseTaskStore implements TaskStore { secrets: options.secrets ? JSON.stringify(options.secrets) : undefined, created_by: options.createdBy ?? null, status: 'open', - created_by: ('createdBy' in spec && spec.createdBy) || null, + created_by: + ('createdBy' in options.spec && options.spec.createdBy) || null, }); return { taskId }; } diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts index bb375e5a0f..7ed2eb620a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts @@ -202,4 +202,30 @@ describe('StorageTaskBroker', () => { expect(task.done).toBe(true); }); + + it('should list all tasks', async () => { + const broker = new StorageTaskBroker(storage, logger); + const { taskId } = await broker.dispatch({ spec: {} as TaskSpec }); + + const promise = broker.list(); + await expect(promise).resolves.toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: taskId, + }), + ]), + ); + }); + + it('should list only tasks createdBy a specific user', async () => { + const broker = new StorageTaskBroker(storage, logger); + const { taskId } = await broker.dispatch({ + spec: { createdBy: 'user:default/foo' } as TaskSpec, + }); + + const task = await storage.getTask(taskId); + + const promise = broker.list({ createdBy: 'user:default/foo' }); + await expect(promise).resolves.toEqual([task]); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 927bbf6842..8e3dadd844 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -152,11 +152,7 @@ export class StorageTaskBroker implements TaskBroker { ) {} async list(options?: Partial): Promise { - if (!options || !options.createdBy) { - throw new Error('Method not implemented.'); - } - - return await this.storage.list({ createdBy: options.createdBy }); + return await this.storage.list({ createdBy: options?.createdBy }); } private deferredDispatch = defer(); diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 14c543249e..52f11357a6 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -131,6 +131,7 @@ describe('createRouter', () => { jest.spyOn(taskBroker, 'dispatch'); jest.spyOn(taskBroker, 'get'); + jest.spyOn(taskBroker, 'list'); jest.spyOn(taskBroker, 'event$'); const router = await createRouter({ @@ -294,6 +295,65 @@ describe('createRouter', () => { }); }); + describe('GET /v2/tasks', () => { + it('return all tasks', async () => { + (taskBroker.list as jest.Mocked['list']).mockResolvedValue([ + { + id: 'a-random-id', + spec: {} as any, + status: 'completed', + createdAt: '', + createdBy: '', + }, + ]); + + const response = await request(app).get(`/v2/tasks`); + expect(taskBroker.list).toBeCalledWith({ + createdBy: undefined, + }); + expect(response.status).toEqual(200); + expect(response.body).toStrictEqual([ + { + id: 'a-random-id', + spec: {} as any, + status: 'completed', + createdAt: '', + createdBy: '', + }, + ]); + }); + + it('return filtered tasks', async () => { + (taskBroker.list as jest.Mocked['list']).mockResolvedValue([ + { + id: 'a-random-id', + spec: {} as any, + status: 'completed', + createdAt: '', + createdBy: 'user:default/foo', + }, + ]); + + const response = await request(app).get( + `/v2/tasks?createdBy=user:default/foo`, + ); + expect(taskBroker.list).toBeCalledWith({ + createdBy: 'user:default/foo', + }); + + expect(response.status).toEqual(200); + expect(response.body).toStrictEqual([ + { + id: 'a-random-id', + spec: {} as any, + status: 'completed', + createdAt: '', + createdBy: 'user:default/foo', + }, + ]); + }); + }); + describe('GET /v2/tasks/:taskId', () => { it('does not divulge secrets', async () => { (taskBroker.get as jest.Mocked['get']).mockResolvedValue({ @@ -302,6 +362,7 @@ describe('createRouter', () => { status: 'completed', createdAt: '', secrets: { backstageToken: 'secret' }, + createdBy: '', }); const response = await request(app).get(`/v2/tasks/a-random-id`); diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 58bb2e831a..61fbe74b8b 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -258,14 +258,7 @@ export async function createRouter( res.status(201).json({ id: result.taskId }); }) .get('/v2/tasks', async (req, res) => { - const token = getBearerToken(req.headers.authorization); - const userEntityRef = token && getUserEntityRefFromToken(token); - - if (!userEntityRef) { - throw new InputError( - 'Could not find a valid user entity ref in the request', - ); - } + const userEntityRef = req.query.createdBy?.toString(); const tasks = await taskBroker.list({ createdBy: userEntityRef,