Skip to content

Commit

Permalink
Merge pull request #32 from HF6-PROJECT/ara-31
Browse files Browse the repository at this point in the history
feat: Added Item endpoints
  • Loading branch information
Anders164a authored Oct 17, 2023
2 parents 8019a33 + c5c5563 commit 87e7406
Show file tree
Hide file tree
Showing 8 changed files with 374 additions and 13 deletions.
206 changes: 206 additions & 0 deletions src/modules/item/__test__/item.read.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ describe('GET /api/item/:parentId', () => {
deletedAt: null,
updatedAt: expect.any(String),
isStarred: false,
linkedItemId: blob.id,
},
]);
});
Expand Down Expand Up @@ -228,3 +229,208 @@ describe('GET /api/item/:parentId', () => {
});
});
});

describe('GET /api/item/:id/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: '[email protected]',
password: '1234',
});
otherUser = await userService.createUser({
name: 'Joe Biden the 3rd',
email: '[email protected]',
password: '4321',
});
});

it('Should return status 200 and folder 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 responseFolder = await global.fastify.inject({
method: 'GET',
url: '/api/item/' + folder.id + '/single',
headers: {
authorization: 'Bearer ' + accessToken,
},
});

expect(responseFolder.statusCode).toBe(200);
expect(responseFolder.json()).toEqual({
id: expect.any(Number),
name: 'Folder1',
color: '#123456',
parentId: null,
ownerId: user.id,
mimeType: 'application/vnd.cloudstore.folder',
createdAt: expect.any(String),
deletedAt: null,
updatedAt: expect.any(String),
isStarred: false,
});
});

it('Should return status 200 and blob item from id', async () => {
const { accessToken } = await authService.createTokens(user.id);

const blob = await blobService.createBlob({
mimeType: 'text/plain',
name: 'test1.txt',
ownerId: user.id,
parentId: null,
blobUrl: 'https://example.com/test1.txt',
});

const responseBlob = await global.fastify.inject({
method: 'GET',
url: '/api/item/' + blob.id + '/single',
headers: {
authorization: 'Bearer ' + accessToken,
},
});

expect(responseBlob.statusCode).toBe(200);
expect(responseBlob.json()).toEqual({
id: expect.any(Number),
name: 'test1.txt',
blobUrl: 'https://example.com/test1.txt',
parentId: null,
ownerId: user.id,
mimeType: 'text/plain',
createdAt: expect.any(String),
deletedAt: null,
updatedAt: expect.any(String),
isStarred: false,
});
});

it('Should return status 200 and docs item from id', async () => {
const { accessToken } = await authService.createTokens(user.id);

const docs = await docsService.createDocs({
name: 'Docser',
ownerId: user.id,
parentId: null,
text: 'Docs text here!',
});

const responseDocs = await global.fastify.inject({
method: 'GET',
url: '/api/item/' + docs.id + '/single',
headers: {
authorization: 'Bearer ' + accessToken,
},
});

expect(responseDocs.statusCode).toBe(200);
expect(responseDocs.json()).toEqual({
id: expect.any(Number),
name: 'Docser',
text: 'Docs text here!',
parentId: null,
ownerId: user.id,
mimeType: 'application/vnd.cloudstore.docs',
createdAt: expect.any(String),
deletedAt: null,
updatedAt: expect.any(String),
isStarred: false,
});
});

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,
});
});
});
1 change: 1 addition & 0 deletions src/modules/item/__test__/item.root.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ describe('GET /api/item', () => {
deletedAt: null,
updatedAt: expect.any(String),
isStarred: false,
linkedItemId: folder.id,
},
]);
});
Expand Down
6 changes: 6 additions & 0 deletions src/modules/item/__test__/item.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,4 +400,10 @@ describe('ItemService', () => {
await expect(itemService.getItemByIdWithSharingsAndOwner(1234)).rejects.toThrow();
});
});

describe('getItemByIdWithInclude()', () => {
it("should throw error, when item doesn't exist", async () => {
await expect(itemService.getItemByIdWithInclude(1234, user.id)).rejects.toThrow();
});
});
});
1 change: 1 addition & 0 deletions src/modules/item/__test__/item.shared.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
28 changes: 27 additions & 1 deletion src/modules/item/item.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FastifyReply, FastifyRequest } from 'fastify';
import ItemService from './item.service';
import { ReadInput, itemSharingsInput } from './item.schema';
import { ReadInput, itemSharingsInput, itemReadInput } from './item.schema';
import AccessService from './sharing/access.service';

export default class ItemController {
Expand Down Expand Up @@ -68,6 +68,32 @@ export default class ItemController {
}
}

public async readHandler(
request: FastifyRequest<{
Params: itemReadInput;
}>,
reply: FastifyReply,
) {
try {
const id = Number.parseInt(request.params.id);

if (!(await this.accessService.hasAccessToItem(id, request.user.sub))) {
return reply.unauthorized();
}

const item = await this.itemService.getItemByIdWithInclude(id, request.user.sub);

return reply.code(200).send(item);
} catch (e) {
if (e instanceof Error) {
return reply.badRequest(request.i18n.t(e.message));
}

/* istanbul ignore next */
return reply.badRequest();
}
}

public async sharingsHandler(
request: FastifyRequest<{
Params: itemSharingsInput;
Expand Down
19 changes: 19 additions & 0 deletions src/modules/item/item.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ export default async (fastify: FastifyInstance) => {
itemController.itemRootHandler.bind(itemController),
);

fastify.get(
'/:id/single',
{
schema: {
tags: ['Item'],
response: {
200: { $ref: 'itemResponseSchema' },
},
security: [
{
bearerAuth: [],
},
],
},
onRequest: [fastify.authenticate],
},
itemController.readHandler.bind(itemController),
);

fastify.get(
'/:parentId',
{
Expand Down
Loading

0 comments on commit 87e7406

Please sign in to comment.