From a567ca3f514b7671da5d523325751a8383885d2c Mon Sep 17 00:00:00 2001 From: Puyodead1 Date: Thu, 23 Mar 2023 10:40:37 -0400 Subject: [PATCH] auth routes --- assets/openapi.json | Bin 253823 -> 0 bytes assets/schemas.json | Bin 1549271 -> 2417674 bytes scripts/openapi.js | 57 +++++++++--------- src/api/routes/auth/forgot.ts | 13 +++- .../auth/generate-registration-tokens.ts | 7 ++- src/api/routes/auth/location-metadata.ts | 35 +++++++---- src/api/routes/auth/login.ts | 12 +++- src/api/routes/auth/logout.ts | 33 ++++++---- src/api/routes/auth/mfa/totp.ts | 18 ++++-- src/api/routes/auth/mfa/webauthn.ts | 8 ++- src/api/routes/auth/register.ts | 8 ++- src/api/routes/auth/reset.ts | 13 +++- src/api/routes/auth/verify/index.ts | 13 +++- src/api/routes/auth/verify/resend.ts | 9 ++- .../verify/view-backup-codes-challenge.ts | 12 +++- src/api/util/handlers/route.ts | 17 ++++-- src/util/schemas/index.ts | 1 + .../responses/APIErrorOrCaptchaResponse.ts | 6 ++ .../schemas/responses/APIErrorResponse.ts | 12 ++++ .../responses/BackupCodesChallengeResponse.ts | 4 ++ .../responses/CaptchaRequiredResponse.ts | 5 ++ .../GenerateRegistrationTokensResponse.ts | 3 + .../responses/LocationMetadataResponse.ts | 5 ++ src/util/schemas/responses/TokenResponse.ts | 6 ++ src/util/schemas/responses/index.ts | 7 +++ 25 files changed, 230 insertions(+), 74 deletions(-) delete mode 100644 assets/openapi.json create mode 100644 src/util/schemas/responses/APIErrorOrCaptchaResponse.ts create mode 100644 src/util/schemas/responses/APIErrorResponse.ts create mode 100644 src/util/schemas/responses/BackupCodesChallengeResponse.ts create mode 100644 src/util/schemas/responses/CaptchaRequiredResponse.ts create mode 100644 src/util/schemas/responses/GenerateRegistrationTokensResponse.ts create mode 100644 src/util/schemas/responses/LocationMetadataResponse.ts create mode 100644 src/util/schemas/responses/TokenResponse.ts create mode 100644 src/util/schemas/responses/index.ts diff --git a/assets/openapi.json b/assets/openapi.json deleted file mode 100644 index 4e4d50a8b1d71770b655e2cfa774a45d66990369..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 253823 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 QU<8bS5tlG>ixRr;55S@?H~;_u delta 3004 zcmb7FUr19?80X%*ySwe~&LVZ{<~H4;QK;2JHOQ8mmeWmaqD7Efas88lSV9yM1qD%0 zg%7778kiJ@gn!Ua7$bX#7E&n&HyHIIm=t6}APt7yB|Rtx-+4a2Ki_x0-*?X4WIv<4 zX&o_Mgr7k^p@D5voT43j@>n9?8rDQ+EsUP@wDNj#Dy<<z zRF0DZo_?J_kB+ho9|Pu23U&W`bC}{bA2k(xq9~?MDewl+w+XMJg&p|E3o4chdr_~) z-;WxGx{Dq(;)|(WEBb4E;zvH`r@L=&E zMS3!B+X`NtsBj%*hHbkkEXw!Uk5IsSC+t-e@VLj}rkKFAzeIqQmyRU9X;3*W_)rry z)FQZNO3vZ8vVYQNf#Jqd2Q$8RYPAv{@%VgcHA}_mf?p?{-)Mc_rJRejoPmg|9X-f1 Htl`=pW2}S7 diff --git a/scripts/openapi.js b/scripts/openapi.js index 49d5dfde..86527ada 100644 --- a/scripts/openapi.js +++ b/scripts/openapi.js @@ -147,36 +147,37 @@ function apiRoutes() { }.merge(obj.requestBody); } - if (route.test?.response) { - const status = route.test.response.status || 200; - let schema = { - allOf: [ - { - $ref: `#/components/schemas/${route.test.response.body}`, - }, - { - example: route.test.body, - }, - ], - }; - if (!route.test.body) schema = schema.allOf[0]; + if (route.responses) { + for (const [k, v] of Object.entries(route.responses)) { + let schema = { + allOf: [ + { + $ref: `#/components/schemas/${v.body}`, + }, + { + example: v.body, + }, + ], + }; + if (!v.body) schema = schema.allOf[0]; - obj.responses = { - [status]: { - ...(route.test.response.body - ? { - description: - obj?.responses?.[status]?.description || "", - content: { - "application/json": { - schema: schema, + obj.responses = { + [k]: { + ...(v.body + ? { + description: + obj?.responses?.[k]?.description || "", + content: { + "application/json": { + schema: schema, + }, }, - }, - } - : {}), - }, - }.merge(obj.responses); - delete obj.responses.default; + } + : {}), + }, + }.merge(obj.responses); + delete obj.responses.default; + } } if (p.includes(":")) { obj.parameters = p.match(/:\w+/g)?.map((x) => ({ diff --git a/src/api/routes/auth/forgot.ts b/src/api/routes/auth/forgot.ts index e240dff2..7e1ba65a 100644 --- a/src/api/routes/auth/forgot.ts +++ b/src/api/routes/auth/forgot.ts @@ -30,7 +30,18 @@ const router = Router(); router.post( "/", - route({ body: "ForgotPasswordSchema" }), + route({ + body: "ForgotPasswordSchema", + responses: { + 204: {}, + 400: { + body: "APIErrorResponse", + }, + 500: { + body: "APIErrorResponse", + }, + }, + }), async (req: Request, res: Response) => { const { login, captcha_key } = req.body as ForgotPasswordSchema; diff --git a/src/api/routes/auth/generate-registration-tokens.ts b/src/api/routes/auth/generate-registration-tokens.ts index 723875f8..48fe6421 100644 --- a/src/api/routes/auth/generate-registration-tokens.ts +++ b/src/api/routes/auth/generate-registration-tokens.ts @@ -16,7 +16,7 @@ along with this program. If not, see . */ -import { route, random } from "@spacebar/api"; +import { random, route } from "@spacebar/api"; import { Config, ValidRegistrationToken } from "@spacebar/util"; import { Request, Response, Router } from "express"; @@ -25,7 +25,10 @@ export default router; router.get( "/", - route({ right: "OPERATOR" }), + route({ + right: "OPERATOR", + responses: { 200: { body: "GenerateRegistrationTokensResponse" } }, + }), async (req: Request, res: Response) => { const count = req.query.count ? parseInt(req.query.count as string) : 1; const length = req.query.length diff --git a/src/api/routes/auth/location-metadata.ts b/src/api/routes/auth/location-metadata.ts index 52a45c67..28293e59 100644 --- a/src/api/routes/auth/location-metadata.ts +++ b/src/api/routes/auth/location-metadata.ts @@ -16,20 +16,29 @@ along with this program. If not, see . */ -import { Router, Request, Response } from "express"; -import { route } from "@spacebar/api"; -import { getIpAdress, IPAnalysis } from "@spacebar/api"; +import { IPAnalysis, getIpAdress, route } from "@spacebar/api"; +import { Request, Response, Router } from "express"; const router = Router(); -router.get("/", route({}), async (req: Request, res: Response) => { - //TODO - //Note: It's most likely related to legal. At the moment Discord hasn't finished this too - const country_code = (await IPAnalysis(getIpAdress(req))).country_code; - res.json({ - consent_required: false, - country_code: country_code, - promotional_email_opt_in: { required: true, pre_checked: false }, - }); -}); +router.get( + "/", + route({ + responses: { + 200: { + body: "LocationMetadataResponse", + }, + }, + }), + async (req: Request, res: Response) => { + //TODO + //Note: It's most likely related to legal. At the moment Discord hasn't finished this too + const country_code = (await IPAnalysis(getIpAdress(req))).country_code; + res.json({ + consent_required: false, + country_code: country_code, + promotional_email_opt_in: { required: true, pre_checked: false }, + }); + }, +); export default router; diff --git a/src/api/routes/auth/login.ts b/src/api/routes/auth/login.ts index fe0b4f99..729bd1cb 100644 --- a/src/api/routes/auth/login.ts +++ b/src/api/routes/auth/login.ts @@ -36,7 +36,17 @@ export default router; router.post( "/", - route({ body: "LoginSchema" }), + route({ + body: "LoginSchema", + responses: { + 200: { + body: "TokenResponse", + }, + 400: { + body: "APIErrorOrCaptchaResponse", + }, + }, + }), async (req: Request, res: Response) => { const { login, password, captcha_key, undelete } = req.body as LoginSchema; diff --git a/src/api/routes/auth/logout.ts b/src/api/routes/auth/logout.ts index 51909afa..94a3e474 100644 --- a/src/api/routes/auth/logout.ts +++ b/src/api/routes/auth/logout.ts @@ -22,14 +22,25 @@ import { Request, Response, Router } from "express"; const router: Router = Router(); export default router; -router.post("/", route({}), async (req: Request, res: Response) => { - if (req.body.provider != null || req.body.voip_provider != null) { - console.log(`[LOGOUT]: provider or voip provider not null!`, req.body); - } else { - delete req.body.provider; - delete req.body.voip_provider; - if (Object.keys(req.body).length != 0) - console.log(`[LOGOUT]: Extra fields sent in logout!`, req.body); - } - res.status(204).send(); -}); +router.post( + "/", + route({ + responses: { + 204: {}, + }, + }), + async (req: Request, res: Response) => { + if (req.body.provider != null || req.body.voip_provider != null) { + console.log( + `[LOGOUT]: provider or voip provider not null!`, + req.body, + ); + } else { + delete req.body.provider; + delete req.body.voip_provider; + if (Object.keys(req.body).length != 0) + console.log(`[LOGOUT]: Extra fields sent in logout!`, req.body); + } + res.status(204).send(); + }, +); diff --git a/src/api/routes/auth/mfa/totp.ts b/src/api/routes/auth/mfa/totp.ts index 2396443d..0bfc2c52 100644 --- a/src/api/routes/auth/mfa/totp.ts +++ b/src/api/routes/auth/mfa/totp.ts @@ -16,16 +16,26 @@ along with this program. If not, see . */ -import { Router, Request, Response } from "express"; import { route } from "@spacebar/api"; -import { BackupCode, generateToken, User, TotpSchema } from "@spacebar/util"; -import { verifyToken } from "node-2fa"; +import { BackupCode, TotpSchema, User, generateToken } from "@spacebar/util"; +import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; +import { verifyToken } from "node-2fa"; const router = Router(); router.post( "/", - route({ body: "TotpSchema" }), + route({ + body: "TotpSchema", + responses: { + 200: { + body: "TokenResponse", + }, + 400: { + body: "APIErrorResponse", + }, + }, + }), async (req: Request, res: Response) => { // const { code, ticket, gift_code_sku_id, login_source } = const { code, ticket } = req.body as TotpSchema; diff --git a/src/api/routes/auth/mfa/webauthn.ts b/src/api/routes/auth/mfa/webauthn.ts index 1b387411..e7278047 100644 --- a/src/api/routes/auth/mfa/webauthn.ts +++ b/src/api/routes/auth/mfa/webauthn.ts @@ -41,7 +41,13 @@ function toArrayBuffer(buf: Buffer) { router.post( "/", - route({ body: "WebAuthnTotpSchema" }), + route({ + body: "WebAuthnTotpSchema", + responses: { + 200: { body: "TokenResponse" }, + 400: { body: "APIErrorResponse" }, + }, + }), async (req: Request, res: Response) => { if (!WebAuthn.fido2) { // TODO: I did this for typescript and I can't use ! diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts index 430c9532..70acedcd 100644 --- a/src/api/routes/auth/register.ts +++ b/src/api/routes/auth/register.ts @@ -42,7 +42,13 @@ const router: Router = Router(); router.post( "/", - route({ body: "RegisterSchema" }), + route({ + body: "RegisterSchema", + responses: { + 200: { body: "TokenResponse" }, + 400: { body: "APIErrorOrCaptchaResponse" }, + }, + }), async (req: Request, res: Response) => { const body = req.body as RegisterSchema; const { register, security, limits } = Config.get(); diff --git a/src/api/routes/auth/reset.ts b/src/api/routes/auth/reset.ts index 852a43c7..9c17d2b0 100644 --- a/src/api/routes/auth/reset.ts +++ b/src/api/routes/auth/reset.ts @@ -31,9 +31,20 @@ import { Request, Response, Router } from "express"; const router = Router(); +// TODO: the response interface also returns settings, but this route doesn't actually return that. router.post( "/", - route({ body: "PasswordResetSchema" }), + route({ + body: "PasswordResetSchema", + responses: { + 200: { + body: "TokenResponse", + }, + 400: { + body: "APIErrorOrCaptchaResponse", + }, + }, + }), async (req: Request, res: Response) => { const { password, token } = req.body as PasswordResetSchema; diff --git a/src/api/routes/auth/verify/index.ts b/src/api/routes/auth/verify/index.ts index c1afcde9..da92f256 100644 --- a/src/api/routes/auth/verify/index.ts +++ b/src/api/routes/auth/verify/index.ts @@ -37,9 +37,20 @@ async function getToken(user: User) { return { token }; } +// TODO: the response interface also returns settings, but this route doesn't actually return that. router.post( "/", - route({ body: "VerifyEmailSchema" }), + route({ + body: "VerifyEmailSchema", + responses: { + 200: { + body: "TokenResponse", + }, + 400: { + body: "APIErrorOrCaptchaResponse", + }, + }, + }), async (req: Request, res: Response) => { const { captcha_key, token } = req.body; diff --git a/src/api/routes/auth/verify/resend.ts b/src/api/routes/auth/verify/resend.ts index f2727abd..215308ec 100644 --- a/src/api/routes/auth/verify/resend.ts +++ b/src/api/routes/auth/verify/resend.ts @@ -24,7 +24,14 @@ const router = Router(); router.post( "/", - route({ right: "RESEND_VERIFICATION_EMAIL" }), + route({ + right: "RESEND_VERIFICATION_EMAIL", + responses: { + 204: {}, + 400: {}, + 500: {}, + }, + }), async (req: Request, res: Response) => { const user = await User.findOneOrFail({ where: { id: req.user_id }, diff --git a/src/api/routes/auth/verify/view-backup-codes-challenge.ts b/src/api/routes/auth/verify/view-backup-codes-challenge.ts index b12719ff..63158d9d 100644 --- a/src/api/routes/auth/verify/view-backup-codes-challenge.ts +++ b/src/api/routes/auth/verify/view-backup-codes-challenge.ts @@ -16,15 +16,21 @@ along with this program. If not, see . */ -import { Router, Request, Response } from "express"; import { route } from "@spacebar/api"; -import { FieldErrors, User, BackupCodesChallengeSchema } from "@spacebar/util"; +import { BackupCodesChallengeSchema, FieldErrors, User } from "@spacebar/util"; import bcrypt from "bcrypt"; +import { Request, Response, Router } from "express"; const router = Router(); router.post( "/", - route({ body: "BackupCodesChallengeSchema" }), + route({ + body: "BackupCodesChallengeSchema", + responses: { + 200: { body: "BackupCodesChallengeResponse" }, + 400: { body: "APIErrorResponse" }, + }, + }), async (req: Request, res: Response) => { const { password } = req.body as BackupCodesChallengeSchema; diff --git a/src/api/util/handlers/route.ts b/src/api/util/handlers/route.ts index 604df4e9..66bd2890 100644 --- a/src/api/util/handlers/route.ts +++ b/src/api/util/handlers/route.ts @@ -17,21 +17,21 @@ */ import { - ajv, DiscordApiErrors, EVENT, FieldErrors, - SpacebarApiErrors, - getPermission, - getRights, - normalizeBody, PermissionResolvable, Permissions, RightResolvable, Rights, + SpacebarApiErrors, + ajv, + getPermission, + getRights, + normalizeBody, } from "@spacebar/util"; -import { NextFunction, Request, Response } from "express"; import { AnyValidateFunction } from "ajv/dist/core"; +import { NextFunction, Request, Response } from "express"; declare global { // TODO: fix this @@ -53,6 +53,11 @@ export interface RouteOptions { permission?: PermissionResolvable; right?: RightResolvable; body?: `${string}Schema`; // typescript interface name + responses?: { + [status: number]: { + body?: `${string}Response`; + }; + }; test?: { response?: RouteResponse; body?: unknown; diff --git a/src/util/schemas/index.ts b/src/util/schemas/index.ts index 2d254752..22927146 100644 --- a/src/util/schemas/index.ts +++ b/src/util/schemas/index.ts @@ -58,6 +58,7 @@ export * from "./PurgeSchema"; export * from "./RegisterSchema"; export * from "./RelationshipPostSchema"; export * from "./RelationshipPutSchema"; +export * from "./responses"; export * from "./RoleModifySchema"; export * from "./RolePositionUpdateSchema"; export * from "./SelectProtocolSchema"; diff --git a/src/util/schemas/responses/APIErrorOrCaptchaResponse.ts b/src/util/schemas/responses/APIErrorOrCaptchaResponse.ts new file mode 100644 index 00000000..c9a0e5be --- /dev/null +++ b/src/util/schemas/responses/APIErrorOrCaptchaResponse.ts @@ -0,0 +1,6 @@ +import { APIErrorResponse } from "./APIErrorResponse"; +import { CaptchaRequiredResponse } from "./CaptchaRequiredResponse"; + +export type APIErrorOrCaptchaResponse = + | CaptchaRequiredResponse + | APIErrorResponse; diff --git a/src/util/schemas/responses/APIErrorResponse.ts b/src/util/schemas/responses/APIErrorResponse.ts new file mode 100644 index 00000000..25bb9504 --- /dev/null +++ b/src/util/schemas/responses/APIErrorResponse.ts @@ -0,0 +1,12 @@ +export interface APIErrorResponse { + code: number; + message: string; + errors: { + [key: string]: { + _errors: { + message: string; + code: string; + }[]; + }; + }; +} diff --git a/src/util/schemas/responses/BackupCodesChallengeResponse.ts b/src/util/schemas/responses/BackupCodesChallengeResponse.ts new file mode 100644 index 00000000..5473ad1f --- /dev/null +++ b/src/util/schemas/responses/BackupCodesChallengeResponse.ts @@ -0,0 +1,4 @@ +export interface BackupCodesChallengeResponse { + nonce: string; + regenerate_nonce: string; +} diff --git a/src/util/schemas/responses/CaptchaRequiredResponse.ts b/src/util/schemas/responses/CaptchaRequiredResponse.ts new file mode 100644 index 00000000..9f7f02ff --- /dev/null +++ b/src/util/schemas/responses/CaptchaRequiredResponse.ts @@ -0,0 +1,5 @@ +export interface CaptchaRequiredResponse { + captcha_key: string; + captcha_sitekey: string; + captcha_service: string; +} diff --git a/src/util/schemas/responses/GenerateRegistrationTokensResponse.ts b/src/util/schemas/responses/GenerateRegistrationTokensResponse.ts new file mode 100644 index 00000000..8816eabf --- /dev/null +++ b/src/util/schemas/responses/GenerateRegistrationTokensResponse.ts @@ -0,0 +1,3 @@ +export interface GenerateRegistrationTokensResponse { + tokens: string[]; +} diff --git a/src/util/schemas/responses/LocationMetadataResponse.ts b/src/util/schemas/responses/LocationMetadataResponse.ts new file mode 100644 index 00000000..55337557 --- /dev/null +++ b/src/util/schemas/responses/LocationMetadataResponse.ts @@ -0,0 +1,5 @@ +export interface LocationMetadataResponse { + consent_required: boolean; + country_code: string; + promotional_email_opt_in: { required: true; pre_checked: false }; +} diff --git a/src/util/schemas/responses/TokenResponse.ts b/src/util/schemas/responses/TokenResponse.ts new file mode 100644 index 00000000..c811632f --- /dev/null +++ b/src/util/schemas/responses/TokenResponse.ts @@ -0,0 +1,6 @@ +import { UserSettings } from "../../entities"; + +export interface TokenResponse { + token: string; + settings: UserSettings; +} diff --git a/src/util/schemas/responses/index.ts b/src/util/schemas/responses/index.ts new file mode 100644 index 00000000..ed91b866 --- /dev/null +++ b/src/util/schemas/responses/index.ts @@ -0,0 +1,7 @@ +export * from "./APIErrorOrCaptchaResponse"; +export * from "./APIErrorResponse"; +export * from "./BackupCodesChallengeResponse"; +export * from "./CaptchaRequiredResponse"; +export * from "./GenerateRegistrationTokensResponse"; +export * from "./LocationMetadataResponse"; +export * from "./TokenResponse";