diff --git a/package.json b/package.json index aeb4303..e658fde 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@odit/lfk-backend", - "version": "0.4.2", + "version": "0.4.3", "main": "src/app.ts", "repository": "https://git.odit.services/lfk/backend", "author": { diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts index 29511a3..de5ed39 100644 --- a/src/controllers/AuthController.ts +++ b/src/controllers/AuthController.ts @@ -1,111 +1,110 @@ -import { Body, CookieParam, JsonController, Param, Post, Req, Res } from 'routing-controllers'; -import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; -import { IllegalJWTError, InvalidCredentialsError, JwtNotProvidedError, PasswordNeededError, RefreshTokenCountInvalidError, UsernameOrEmailNeededError } from '../errors/AuthError'; -import { UserNotFoundError } from '../errors/UserErrors'; -import { Mailer } from '../mailer'; -import { CreateAuth } from '../models/actions/create/CreateAuth'; -import { CreateResetToken } from '../models/actions/create/CreateResetToken'; -import { HandleLogout } from '../models/actions/HandleLogout'; -import { RefreshAuth } from '../models/actions/RefreshAuth'; -import { ResetPassword } from '../models/actions/ResetPassword'; -import { ResponseAuth } from '../models/responses/ResponseAuth'; -import { ResponseEmpty } from '../models/responses/ResponseEmpty'; -import { Logout } from '../models/responses/ResponseLogout'; - -@JsonController('/auth') -export class AuthController { - - private mailer: Mailer; - - constructor() { - this.mailer = new Mailer(); - } - - @Post("/login") - @ResponseSchema(ResponseAuth) - @ResponseSchema(InvalidCredentialsError) - @ResponseSchema(UserNotFoundError) - @ResponseSchema(UsernameOrEmailNeededError) - @ResponseSchema(PasswordNeededError) - @ResponseSchema(InvalidCredentialsError) - @OpenAPI({ description: 'Login with your username/email and password.
You will receive: \n * access token (use it as a bearer token) \n * refresh token (will also be sent as a cookie)' }) - async login(@Body({ validate: true }) createAuth: CreateAuth, @Res() response: any) { - let auth; - console.log(createAuth) - try { - auth = await createAuth.toAuth(); - response.cookie('lfk_backend__refresh_token', auth.refresh_token, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); - response.cookie('lfk_backend__refresh_token_expires_at', auth.refresh_token_expires_at, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); - return response.send(auth) - } catch (error) { - throw error; - } - } - - @Post("/logout") - @ResponseSchema(Logout) - @ResponseSchema(InvalidCredentialsError) - @ResponseSchema(UserNotFoundError) - @ResponseSchema(UsernameOrEmailNeededError) - @ResponseSchema(PasswordNeededError) - @ResponseSchema(InvalidCredentialsError) - @OpenAPI({ description: 'Logout using your refresh token.
This instantly invalidates all your access and refresh tokens.', security: [{ "RefreshTokenCookie": [] }] }) - async logout(@Body({ validate: true }) handleLogout: HandleLogout, @CookieParam("lfk_backend__refresh_token") refresh_token: string, @Res() response: any) { - if (refresh_token && refresh_token.length != 0 && handleLogout.token == undefined) { - handleLogout.token = refresh_token; - } - - let logout; - try { - logout = await handleLogout.logout() - await response.cookie('lfk_backend__refresh_token', "expired", { expires: new Date(Date.now()), httpOnly: true }); - response.cookie('lfk_backend__refresh_token_expires_at', "expired", { expires: new Date(Date.now()), httpOnly: true }); - } catch (error) { - throw error; - } - return response.send(logout) - } - - @Post("/refresh") - @ResponseSchema(ResponseAuth) - @ResponseSchema(JwtNotProvidedError) - @ResponseSchema(IllegalJWTError) - @ResponseSchema(UserNotFoundError) - @ResponseSchema(RefreshTokenCountInvalidError) - @OpenAPI({ description: 'Refresh your access and refresh tokens using a valid refresh token.
You will receive: \n * access token (use it as a bearer token) \n * refresh token (will also be sent as a cookie)', security: [{ "RefreshTokenCookie": [] }] }) - async refresh(@Body({ validate: true }) refreshAuth: RefreshAuth, @CookieParam("lfk_backend__refresh_token") refresh_token: string, @Res() response: any, @Req() req: any) { - if (refresh_token && refresh_token.length != 0 && refreshAuth.token == undefined) { - refreshAuth.token = refresh_token; - } - let auth; - try { - auth = await refreshAuth.toAuth(); - response.cookie('lfk_backend__refresh_token', auth.refresh_token, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); - response.cookie('lfk_backend__refresh_token_expires_at', auth.refresh_token_expires_at, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); - } catch (error) { - throw error; - } - return response.send(auth) - } - - @Post("/reset") - @ResponseSchema(ResponseEmpty, { statusCode: 200 }) - @ResponseSchema(UserNotFoundError, { statusCode: 404 }) - @ResponseSchema(UsernameOrEmailNeededError, { statusCode: 406 }) - @OpenAPI({ description: "Request a password reset token.
This will provide you with a reset token that you can use by posting to /api/auth/reset/{token}." }) - async getResetToken(@Body({ validate: true }) passwordReset: CreateResetToken) { - const reset_token: string = await passwordReset.toResetToken(); - await this.mailer.sendResetMail(passwordReset.email, reset_token); - return new ResponseEmpty(); - } - - @Post("/reset/:token") - @ResponseSchema(ResponseAuth) - @ResponseSchema(UserNotFoundError) - @ResponseSchema(UsernameOrEmailNeededError) - @OpenAPI({ description: "Reset a user's utilising a valid password reset token.
This will set the user's password to the one you provided in the body.
To get a reset token post to /api/auth/reset with your username." }) - async resetPassword(@Param("token") token: string, @Body({ validate: true }) passwordReset: ResetPassword) { - passwordReset.resetToken = token; - return await passwordReset.resetPassword(); - } -} +import { Body, CookieParam, JsonController, Param, Post, Req, Res } from 'routing-controllers'; +import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; +import { IllegalJWTError, InvalidCredentialsError, JwtNotProvidedError, PasswordNeededError, RefreshTokenCountInvalidError, UsernameOrEmailNeededError } from '../errors/AuthError'; +import { UserNotFoundError } from '../errors/UserErrors'; +import { Mailer } from '../mailer'; +import { CreateAuth } from '../models/actions/create/CreateAuth'; +import { CreateResetToken } from '../models/actions/create/CreateResetToken'; +import { HandleLogout } from '../models/actions/HandleLogout'; +import { RefreshAuth } from '../models/actions/RefreshAuth'; +import { ResetPassword } from '../models/actions/ResetPassword'; +import { ResponseAuth } from '../models/responses/ResponseAuth'; +import { ResponseEmpty } from '../models/responses/ResponseEmpty'; +import { Logout } from '../models/responses/ResponseLogout'; + +@JsonController('/auth') +export class AuthController { + + private mailer: Mailer; + + constructor() { + this.mailer = new Mailer(); + } + + @Post("/login") + @ResponseSchema(ResponseAuth) + @ResponseSchema(InvalidCredentialsError) + @ResponseSchema(UserNotFoundError) + @ResponseSchema(UsernameOrEmailNeededError) + @ResponseSchema(PasswordNeededError) + @ResponseSchema(InvalidCredentialsError) + @OpenAPI({ description: 'Login with your username/email and password.
You will receive: \n * access token (use it as a bearer token) \n * refresh token (will also be sent as a cookie)' }) + async login(@Body({ validate: true }) createAuth: CreateAuth, @Res() response: any) { + let auth; + try { + auth = await createAuth.toAuth(); + response.cookie('lfk_backend__refresh_token', auth.refresh_token, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); + response.cookie('lfk_backend__refresh_token_expires_at', auth.refresh_token_expires_at, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); + return response.send(auth) + } catch (error) { + throw error; + } + } + + @Post("/logout") + @ResponseSchema(Logout) + @ResponseSchema(InvalidCredentialsError) + @ResponseSchema(UserNotFoundError) + @ResponseSchema(UsernameOrEmailNeededError) + @ResponseSchema(PasswordNeededError) + @ResponseSchema(InvalidCredentialsError) + @OpenAPI({ description: 'Logout using your refresh token.
This instantly invalidates all your access and refresh tokens.', security: [{ "RefreshTokenCookie": [] }] }) + async logout(@Body({ validate: true }) handleLogout: HandleLogout, @CookieParam("lfk_backend__refresh_token") refresh_token: string, @Res() response: any) { + if (refresh_token && refresh_token.length != 0 && handleLogout.token == undefined) { + handleLogout.token = refresh_token; + } + + let logout; + try { + logout = await handleLogout.logout() + await response.cookie('lfk_backend__refresh_token', "expired", { expires: new Date(Date.now()), httpOnly: true }); + response.cookie('lfk_backend__refresh_token_expires_at', "expired", { expires: new Date(Date.now()), httpOnly: true }); + } catch (error) { + throw error; + } + return response.send(logout) + } + + @Post("/refresh") + @ResponseSchema(ResponseAuth) + @ResponseSchema(JwtNotProvidedError) + @ResponseSchema(IllegalJWTError) + @ResponseSchema(UserNotFoundError) + @ResponseSchema(RefreshTokenCountInvalidError) + @OpenAPI({ description: 'Refresh your access and refresh tokens using a valid refresh token.
You will receive: \n * access token (use it as a bearer token) \n * refresh token (will also be sent as a cookie)', security: [{ "RefreshTokenCookie": [] }] }) + async refresh(@Body({ validate: true }) refreshAuth: RefreshAuth, @CookieParam("lfk_backend__refresh_token") refresh_token: string, @Res() response: any, @Req() req: any) { + if (refresh_token && refresh_token.length != 0 && refreshAuth.token == undefined) { + refreshAuth.token = refresh_token; + } + let auth; + try { + auth = await refreshAuth.toAuth(); + response.cookie('lfk_backend__refresh_token', auth.refresh_token, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); + response.cookie('lfk_backend__refresh_token_expires_at', auth.refresh_token_expires_at, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); + } catch (error) { + throw error; + } + return response.send(auth) + } + + @Post("/reset") + @ResponseSchema(ResponseEmpty, { statusCode: 200 }) + @ResponseSchema(UserNotFoundError, { statusCode: 404 }) + @ResponseSchema(UsernameOrEmailNeededError, { statusCode: 406 }) + @OpenAPI({ description: "Request a password reset token.
This will provide you with a reset token that you can use by posting to /api/auth/reset/{token}." }) + async getResetToken(@Body({ validate: true }) passwordReset: CreateResetToken) { + const reset_token: string = await passwordReset.toResetToken(); + await this.mailer.sendResetMail(passwordReset.email, reset_token); + return new ResponseEmpty(); + } + + @Post("/reset/:token") + @ResponseSchema(ResponseAuth) + @ResponseSchema(UserNotFoundError) + @ResponseSchema(UsernameOrEmailNeededError) + @OpenAPI({ description: "Reset a user's utilising a valid password reset token.
This will set the user's password to the one you provided in the body.
To get a reset token post to /api/auth/reset with your username." }) + async resetPassword(@Param("token") token: string, @Body({ validate: true }) passwordReset: ResetPassword) { + passwordReset.resetToken = token; + return await passwordReset.resetPassword(); + } +}