diff --git a/src/modules/item/__test__/item.read.test.ts b/src/modules/item/__test__/item.read.test.ts index c6c863f..e1ec8b9 100644 --- a/src/modules/item/__test__/item.read.test.ts +++ b/src/modules/item/__test__/item.read.test.ts @@ -137,6 +137,7 @@ describe('GET /api/item/:parentId', () => { deletedAt: null, updatedAt: expect.any(String), isStarred: false, + linkedItemId: blob.id, }, ]); }); @@ -228,3 +229,212 @@ describe('GET /api/item/:parentId', () => { }); }); }); + +describe('GET /api/item/:parentId/single', () => { + let userService: UserService; + let folderService: FolderService; + let authService: AuthService; + let blobService: BlobService; + let docsService: DocsService; + + let user: User; + let otherUser: User; + + beforeAll(async () => { + userService = UserServiceFactory.make(); + folderService = FolderServiceFactory.make(); + authService = AuthServiceFactory.make(); + blobService = BlobServiceFactory.make(); + docsService = DocsServiceFactory.make(); + + user = await userService.createUser({ + name: 'Joe Biden the 4th', + email: 'joe3@biden.com', + password: '1234', + }); + otherUser = await userService.createUser({ + name: 'Joe Biden the 3rd', + email: 'joe4@biden.com', + password: '4321', + }); + }); + + it('Should return status 200 and item from id', async () => { + const { accessToken } = await authService.createTokens(user.id); + + const folder = await folderService.createFolder({ + name: 'Folder1', + color: '#123456', + ownerId: user.id, + parentId: null, + }); + + const blob = await blobService.createBlob({ + mimeType: 'text/plain', + name: 'test1.txt', + ownerId: user.id, + parentId: null, + blobUrl: 'https://example.com/test1.txt', + }); + + const docs = await docsService.createDocs({ + name: 'Docser', + ownerId: user.id, + parentId: null, + text: 'Docs text here!', + }); + + const responseFolder = await global.fastify.inject({ + method: 'GET', + url: '/api/item/' + folder.id + '/single', + headers: { + authorization: 'Bearer ' + accessToken, + }, + }); + + const responseBlob = await global.fastify.inject({ + method: 'GET', + url: '/api/item/' + blob.id + '/single', + headers: { + authorization: 'Bearer ' + accessToken, + }, + }); + + const responseDocs = await global.fastify.inject({ + method: 'GET', + url: '/api/item/' + docs.id + '/single', + headers: { + authorization: 'Bearer ' + accessToken, + }, + }); + + expect(responseFolder.statusCode).toBe(200); + expect(responseFolder.json()).toEqual({ + id: expect.any(Number), + name: 'Folder1', + parentId: null, + ownerId: user.id, + mimeType: 'application/vnd.cloudstore.folder', + createdAt: expect.any(String), + deletedAt: null, + updatedAt: expect.any(String), + ItemBlob: null, + ItemFolder: { + id: expect.any(Number), + color: '#123456', + }, + ItemDocs: null, + }); + + expect(responseBlob.statusCode).toBe(200); + expect(responseBlob.json()).toEqual({ + id: expect.any(Number), + name: 'test1.txt', + parentId: null, + ownerId: user.id, + mimeType: 'text/plain', + createdAt: expect.any(String), + deletedAt: null, + updatedAt: expect.any(String), + ItemBlob: { + id: expect.any(Number), + blobUrl: 'https://example.com/test1.txt', + }, + ItemFolder: null, + ItemDocs: null, + }); + + expect(responseDocs.statusCode).toBe(200); + expect(responseDocs.json()).toEqual({ + id: expect.any(Number), + name: 'Docser', + parentId: null, + ownerId: user.id, + mimeType: 'application/vnd.cloudstore.docs', + createdAt: expect.any(String), + deletedAt: null, + updatedAt: expect.any(String), + ItemBlob: null, + ItemFolder: null, + ItemDocs: { + id: expect.any(Number), + text: 'Docs text here!', + }, + }); + }); + + it('Should return status 400, when item not found', async () => { + const { accessToken } = await authService.createTokens(user.id); + + const response = await global.fastify.inject({ + method: 'GET', + url: '/api/item/1234/single', + headers: { + authorization: 'Bearer ' + accessToken, + }, + }); + + expect(response.statusCode).toBe(400); + expect(response.json()).toEqual({ + error: 'BadRequestError', + errors: { + _: ['Item not found'], + }, + statusCode: 400, + }); + }); + + it('Should return status 401, when unauthorized', async () => { + const folder = await folderService.createFolder({ + name: 'Folder1', + color: '#123456', + ownerId: user.id, + parentId: null, + }); + + const response = await global.fastify.inject({ + method: 'GET', + url: '/api/item/' + folder.id + '/single', + headers: { + authorization: 'WrongAuth!', + }, + }); + + expect(response.statusCode).toBe(401); + expect(response.json()).toEqual({ + error: 'UnauthorizedError', + errors: { + _: ['Unauthorized'], + }, + statusCode: 401, + }); + }); + + it('Should return status 401, when no access to file', async () => { + const { accessToken } = await authService.createTokens(user.id); + + const folder = await folderService.createFolder({ + name: 'Folder1', + color: '#123456', + ownerId: otherUser.id, + parentId: null, + }); + + const response = await global.fastify.inject({ + method: 'GET', + url: '/api/item/' + folder.id + '/single', + headers: { + authorization: 'Bearer ' + accessToken, + }, + }); + + expect(response.statusCode).toBe(401); + expect(response.json()).toEqual({ + error: 'UnauthorizedError', + errors: { + _: ['Unauthorized'], + }, + statusCode: 401, + }); + }); +}); diff --git a/src/modules/item/__test__/item.root.test.ts b/src/modules/item/__test__/item.root.test.ts index a19a8b0..4dea284 100644 --- a/src/modules/item/__test__/item.root.test.ts +++ b/src/modules/item/__test__/item.root.test.ts @@ -142,6 +142,7 @@ describe('GET /api/item', () => { deletedAt: null, updatedAt: expect.any(String), isStarred: false, + linkedItemId: folder.id, }, ]); }); diff --git a/src/modules/item/__test__/item.shared.test.ts b/src/modules/item/__test__/item.shared.test.ts index ef21a9d..19f104e 100644 --- a/src/modules/item/__test__/item.shared.test.ts +++ b/src/modules/item/__test__/item.shared.test.ts @@ -136,6 +136,7 @@ describe('GET /api/item/shared', () => { createdAt: expect.any(String), deletedAt: null, updatedAt: expect.any(String), + linkedItemId: blob.id, }, { id: expect.any(Number), diff --git a/src/modules/item/item.controller.ts b/src/modules/item/item.controller.ts index 66e94fb..64577a0 100644 --- a/src/modules/item/item.controller.ts +++ b/src/modules/item/item.controller.ts @@ -23,17 +23,6 @@ export default class ItemController { } } - public async browseHandler(request: FastifyRequest, reply: FastifyReply) { - try { - const items = await this.itemService.getByOwnerId(request.user.sub); - - return reply.code(200).send(items); - } catch (e) { - /* istanbul ignore next */ - return reply.badRequest(); - } - } - public async itemRootHandler(request: FastifyRequest, reply: FastifyReply) { try { const items = await this.itemService.getByOwnerIdAndParentId(request.user.sub, null); diff --git a/src/modules/item/item.route.ts b/src/modules/item/item.route.ts index 789d976..6d7650c 100644 --- a/src/modules/item/item.route.ts +++ b/src/modules/item/item.route.ts @@ -61,25 +61,6 @@ export default async (fastify: FastifyInstance) => { itemController.readHandler.bind(itemController), ); - fastify.get( - '/folders', - { - schema: { - tags: ['Item'], - response: { - 200: { $ref: 'itemsResponseSchema' }, - }, - security: [ - { - bearerAuth: [], - }, - ], - }, - onRequest: [fastify.authenticate], - }, - itemController.browseHandler.bind(itemController), - ); - fastify.get( '/:parentId', { diff --git a/src/modules/item/item.schema.ts b/src/modules/item/item.schema.ts index bd41dbb..4881cf6 100644 --- a/src/modules/item/item.schema.ts +++ b/src/modules/item/item.schema.ts @@ -240,7 +240,7 @@ const itemFolderDocsBlobResponseSchema = { type: 'string', }, ownerId: { - type: 'string', + type: 'number', }, parentId: { type: ['number', 'null'], @@ -258,26 +258,23 @@ const itemFolderDocsBlobResponseSchema = { }, ItemBlob: { type: ['object', 'null'], - properties: { - id: { - type: 'number', - }, - blobUrl: { - type: 'string', - }, - }, + properties: { + id: { + type: 'number', + }, + blobUrl: { + type: 'string', + }, + }, }, ItemDocs: { type: ['object', 'null'], - items: { - type: 'object', - properties: { - id: { - type: 'number', - }, - text: { - type: 'string', - }, + properties: { + id: { + type: 'number', + }, + text: { + type: 'string', }, }, }, @@ -297,4 +294,9 @@ export type itemSharingsInput = FromSchema; export type itemReadInput = FromSchema; export type ReadInput = FromSchema; -export const itemSchemas = [readItemsSchema, itemsResponseSchema, itemSharingsResponseSchema, itemFolderDocsBlobResponseSchema]; +export const itemSchemas = [ + readItemsSchema, + itemsResponseSchema, + itemSharingsResponseSchema, + itemFolderDocsBlobResponseSchema, +]; diff --git a/src/modules/item/item.service.ts b/src/modules/item/item.service.ts index ea7d05d..11ee829 100644 --- a/src/modules/item/item.service.ts +++ b/src/modules/item/item.service.ts @@ -54,29 +54,6 @@ export default class ItemService { return this.formatItems(items); } - public async getByOwnerId( - ownerId: number, - ): Promise { - const items = await prisma.item.findMany({ - where: { - ownerId: ownerId, - }, - include: { - ItemBlob: true, - ItemFolder: true, - ItemDocs: true, - ItemShortcut: true, - ItemStarred: { - where: { - userId: ownerId, - }, - }, - }, - }); - - return this.formatItems(items); - } - public async getAllOwnedAndSharredItemsByParentIdAndUserIdRecursively( userId: number, parentId: number | null, @@ -226,10 +203,6 @@ export default class ItemService { }, }); - if (!item) { - throw new Error('item.notFound'); - } - return item; }