diff --git a/src/presentation/http/http-api.ts b/src/presentation/http/http-api.ts index dd1e4985..7beca6c0 100644 --- a/src/presentation/http/http-api.ts +++ b/src/presentation/http/http-api.ts @@ -20,6 +20,7 @@ import EditorToolsRouter from './router/editorTools.js'; import { UserSchema } from './schema/User.js'; import { NoteSchema } from './schema/Note.js'; import { NoteSettingsSchema } from './schema/NoteSettings.js'; +import { OauthSchema } from './schema/OauthSchema.js'; import Policies from './policies/index.js'; import type { RequestParams, Response } from '@presentation/api.interface.js'; import NoteSettingsRouter from './router/noteSettings.js'; @@ -60,9 +61,9 @@ export default class HttpApi implements Api { this.server = fastify({ logger: appServerLogger as FastifyBaseLogger, ajv: { - plugins: [ + plugins: [ /** Allows to validate files in schema */ - ajvFilePlugin + ajvFilePlugin, ], }, }); @@ -300,6 +301,7 @@ export default class HttpApi implements Api { this.server?.addSchema(NoteSettingsSchema); this.server?.addSchema(JoinSchemaParams); this.server?.addSchema(JoinSchemaResponse); + this.server?.addSchema(OauthSchema); this.server?.addSchema(UploadSchema); } diff --git a/src/presentation/http/router/auth.ts b/src/presentation/http/router/auth.ts index d77bc231..724ef80d 100644 --- a/src/presentation/http/router/auth.ts +++ b/src/presentation/http/router/auth.ts @@ -39,27 +39,54 @@ const AuthRouter: FastifyPluginCallback = (fastify, opts, don fastify.post<{ Body: AuthOptions; Reply: AuthSession | ErrorResponse; - }>('/', async (request, reply) => { - const { token } = request.body; - const userSession = await opts.authService.verifyRefreshToken(token); + }>('/', + { + schema: { + body: { + required: [ 'token' ], + properties: { + token: { + type: 'string', + }, + }, + }, - /** - * Check if session is valid - */ - if (!userSession) { - return await reply.unauthorized('Session is not valid'); - } + response: { + '2xx': { + description: 'New auth session generated', + content: { + 'application/json': { + schema: { + accessToken: { type: 'string' }, + refreshToken: { type: 'string' }, + }, + }, + }, + }, + }, + }, + }, + async (request, reply) => { + const { token } = request.body; + const userSession = await opts.authService.verifyRefreshToken(token); - const accessToken = opts.authService.signAccessToken({ id: userSession.userId }); + /** + * Check if session is valid + */ + if (!userSession) { + return await reply.unauthorized('Session is not valid'); + } - await opts.authService.removeSessionByRefreshToken(token); - const refreshToken = await opts.authService.signRefreshToken(userSession.userId); + const accessToken = opts.authService.signAccessToken({ id: userSession.userId }); - return reply.send({ - accessToken, - refreshToken, + await opts.authService.removeSessionByRefreshToken(token); + const refreshToken = await opts.authService.signRefreshToken(userSession.userId); + + return reply.send({ + accessToken, + refreshToken, + }); }); - }); /** * Route for logout, removes session from database by refresh token @@ -67,7 +94,30 @@ const AuthRouter: FastifyPluginCallback = (fastify, opts, don fastify.delete<{ Body: AuthOptions; Reply: { ok: boolean } - }>('/', async (request, reply) => { + }>('/', { + schema: { + body: { + token: { + type: 'string', + }, + }, + + response: { + '2xx': { + description: 'Check for successful deletion of the token', + content: { + 'application/json': { + schema:{ + ok: { + type: 'boolean', + }, + }, + }, + }, + }, + }, + }, + }, async (request, reply) => { await opts.authService.removeSessionByRefreshToken(request.body.token); return reply.status(StatusCodes.OK).send({ diff --git a/src/presentation/http/router/note.ts b/src/presentation/http/router/note.ts index b0c39e3d..0e84f17b 100644 --- a/src/presentation/http/router/note.ts +++ b/src/presentation/http/router/note.ts @@ -101,6 +101,7 @@ const NoteRouter: FastifyPluginCallback = (fastify, opts, don response: { '2xx': { type: 'object', + description: 'Fetch all information of the notePublicId passed', properties: { note: { $ref: 'NoteSchema', @@ -202,6 +203,17 @@ const NoteRouter: FastifyPluginCallback = (fastify, opts, don $ref: 'NoteSchema#/properties/id', }, }, + + response: { + '2xx': { + type: 'object', + properties: { + isDeleted: { + type: 'boolean', + }, + }, + }, + }, }, config: { policy: [ @@ -240,6 +252,30 @@ const NoteRouter: FastifyPluginCallback = (fastify, opts, don 'authRequired', ], }, + schema: { + body: { + content: { + $ref: 'NoteSchema#/properties/content', + }, + parentId: { + $ref: 'NoteSchema#/properties/id', + }, + }, + response: { + '2xx': { + description: 'Note fields response', + content: { + 'application/json':{ + schema: { + id: { + $ref: 'NoteSchema#/properties/id', + }, + }, + }, + }, + }, + }, + }, }, async (request, reply) => { /** * @todo Validate request query @@ -291,6 +327,13 @@ const NoteRouter: FastifyPluginCallback = (fastify, opts, don updatedAt: Note['updatedAt'], } }>('/:notePublicId', { + config: { + policy: [ + 'authRequired', + 'userCanEdit', + ], + }, + schema: { params: { notePublicId: { @@ -299,15 +342,20 @@ const NoteRouter: FastifyPluginCallback = (fastify, opts, don }, body: { content: { - $ref: 'NoteSchema#/properties/content', + type: 'object', + }, + }, + + response: { + '2xx': { + description: 'Updated timestamp', + properties: { + updatedAt: { + type: 'string', + }, + }, }, }, - }, - config: { - policy: [ - 'authRequired', - 'userCanEdit', - ], }, preHandler: [ noteResolver, @@ -352,6 +400,7 @@ const NoteRouter: FastifyPluginCallback = (fastify, opts, don response: { '2xx': { type: 'object', + description: 'Updated note', properties: { isUpdated: { type: 'boolean', @@ -456,9 +505,15 @@ const NoteRouter: FastifyPluginCallback = (fastify, opts, don }| ErrorResponse, }>('/resolve-hostname/:hostname', { schema: { + params: { + hostname: { + type: 'string', + }, + }, response: { '2xx': { type: 'object', + description: 'Custom hostname response', properties: { note: { $ref: 'NoteSchema', diff --git a/src/presentation/http/router/noteList.ts b/src/presentation/http/router/noteList.ts index 7f320b15..1540b57c 100644 --- a/src/presentation/http/router/noteList.ts +++ b/src/presentation/http/router/noteList.ts @@ -45,6 +45,21 @@ const NoteListRouter: FastifyPluginCallback = (fastify, o maximum: 30, }, }, + + response: { + '2xx':{ + description: 'Query notelist', + properties: { + items: { + id: { type: 'string' }, + content: { type: 'string' }, + createdAt: { type: 'string' }, + creatorId: { type: 'string' }, + updatedAt: { type: 'string' }, + }, + }, + }, + }, }, }, async (request, reply) => { const userId = request.userId as number; diff --git a/src/presentation/http/router/noteSettings.ts b/src/presentation/http/router/noteSettings.ts index 4729559c..10719384 100644 --- a/src/presentation/http/router/noteSettings.ts +++ b/src/presentation/http/router/noteSettings.ts @@ -117,6 +117,27 @@ const NoteSettingsRouter: FastifyPluginCallback = (fa $ref: 'NoteSchema#/properties/id', }, }, + body: { + properties: { + userId: { + $ref: 'UserSchema#/properties/id', + }, + newRole:{ + $ref: 'NoteSettingsSchema#/properties/team/items/properties/role', + }, + }, + }, + + response: { + '2xx': { + type: 'number', + properties: { + newRole: { + type: 'number', + }, + }, + }, + }, }, preHandler: [ noteResolver, @@ -134,6 +155,7 @@ const NoteSettingsRouter: FastifyPluginCallback = (fa return reply.notFound('User does not belong to Note\'s team'); } + return reply.send(newRole); }); @@ -196,7 +218,7 @@ const NoteSettingsRouter: FastifyPluginCallback = (fa * Patch noteSettings by note id */ fastify.patch<{ - Body: Partial, + Body: Pick, Params: { notePublicId: NotePublicId; }, @@ -214,6 +236,17 @@ const NoteSettingsRouter: FastifyPluginCallback = (fa $ref: 'NoteSchema#/properties/id', }, }, + body: { + properties: { + customHostname: { + type: 'string', + }, + + isPublic: { + type: 'boolean', + }, + }, + }, response: { '2xx': { $ref: 'NoteSettingsSchema', @@ -266,6 +299,19 @@ const NoteSettingsRouter: FastifyPluginCallback = (fa $ref: 'NoteSchema#/properties/id', }, }, + + response: { + '2xx': { + type: 'array', + description: 'Fetch all teams associated with the notePublicId', + properties: { + id: { type: 'string' }, + noteId: { type: 'string' }, + role: { type: 'string' }, + userId: { type: 'string' }, + }, + }, + }, }, preHandler: [ noteResolver, diff --git a/src/presentation/http/router/oauth.ts b/src/presentation/http/router/oauth.ts index 386486b3..23f56822 100644 --- a/src/presentation/http/router/oauth.ts +++ b/src/presentation/http/router/oauth.ts @@ -34,7 +34,18 @@ const OauthRouter: FastifyPluginCallback = (fastify, opts, d /** * Callback for Google oauth2. Google redirects to this endpoint after user authentication. */ - fastify.get('/google/callback', async (request, reply) => { + fastify.get('/google/callback', { + schema: { + params: { + clientId: { + $ref: 'OauthSchema#/properties/clientId', + }, + clientSecret: { + $ref: 'OauthSchema#/properties/clientSecret', + }, + }, + }, + }, async (request, reply) => { /** * Get referer from request headers */ diff --git a/src/presentation/http/router/upload.ts b/src/presentation/http/router/upload.ts index 2619b1ab..34b6e581 100644 --- a/src/presentation/http/router/upload.ts +++ b/src/presentation/http/router/upload.ts @@ -128,6 +128,15 @@ const UploadRouter: FastifyPluginCallback = async (fastify, $ref: 'UploadSchema#/properties/key', }, }, + + response: { + '2xx': { + description: 'Generated buffer', + properties: { + fileData: { type: 'string' }, + }, + }, + }, }, preHandler: [ noteResolver ], }, async (request, reply) => { diff --git a/src/presentation/http/router/user.ts b/src/presentation/http/router/user.ts index 47a942ef..5e48306c 100644 --- a/src/presentation/http/router/user.ts +++ b/src/presentation/http/router/user.ts @@ -115,8 +115,7 @@ const UserRouter: FastifyPluginCallback = (fastify, opts, don schema: { body: { toolId: { - type: 'string', - description: 'Unique editor tool id', + $ref: 'EditorToolSchema#/properties/id', }, }, response: { @@ -162,8 +161,7 @@ const UserRouter: FastifyPluginCallback = (fastify, opts, don schema: { body: { toolId: { - type: 'string', - description: 'Unique editor tool id', + $ref: 'EditorToolSchema#/properties/id', }, }, response: { @@ -173,7 +171,7 @@ const UserRouter: FastifyPluginCallback = (fastify, opts, don 'application/json': { schema: { removedId: { - type: 'string', + $ref: 'EditorToolSchema#/properties/id', }, }, }, diff --git a/src/presentation/http/schema/Join.ts b/src/presentation/http/schema/Join.ts index 9b5205d8..ad0d1249 100644 --- a/src/presentation/http/schema/Join.ts +++ b/src/presentation/http/schema/Join.ts @@ -1,6 +1,7 @@ export const JoinSchemaParams = { $id: 'JoinSchemaParams', type: 'object', + required: [ 'hash' ], properties: { hash: { type: 'string', diff --git a/src/presentation/http/schema/NoteSettings.ts b/src/presentation/http/schema/NoteSettings.ts index 4aa0a6c4..d87c9a2b 100644 --- a/src/presentation/http/schema/NoteSettings.ts +++ b/src/presentation/http/schema/NoteSettings.ts @@ -52,5 +52,8 @@ export const NoteSettingsSchema = { }, }, }, + role: { + type: 'number', + }, }, }; diff --git a/src/presentation/http/schema/OauthSchema.ts b/src/presentation/http/schema/OauthSchema.ts new file mode 100644 index 00000000..69958fca --- /dev/null +++ b/src/presentation/http/schema/OauthSchema.ts @@ -0,0 +1,30 @@ + +export const OauthSchema = { + $id: 'OauthSchema', + type: 'object', + required: [ + 'clientId', + 'clientSecret', + ], + properties: { + clientId: { + type: 'string', + description: 'Google client id token', + }, + + clientSecret: { + type: 'string', + description: 'Google client secret key', + }, + + accessToken: { + type: 'string', + description: 'The returned access token from Google', + }, + + refreshToken: { + type: 'string', + description: 'The returned refreshtoken from Google', + }, + }, +}; \ No newline at end of file