From a567ca3f514b7671da5d523325751a8383885d2c Mon Sep 17 00:00:00 2001 From: Puyodead1 Date: Thu, 23 Mar 2023 10:40:37 -0400 Subject: auth routes --- src/api/routes/auth/forgot.ts | 13 +++++++- .../routes/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 +++++- .../auth/verify/view-backup-codes-challenge.ts | 12 ++++++-- src/api/util/handlers/route.ts | 17 +++++++---- src/util/schemas/index.ts | 1 + .../schemas/responses/APIErrorOrCaptchaResponse.ts | 6 ++++ src/util/schemas/responses/APIErrorResponse.ts | 12 ++++++++ .../responses/BackupCodesChallengeResponse.ts | 4 +++ .../schemas/responses/CaptchaRequiredResponse.ts | 5 ++++ .../GenerateRegistrationTokensResponse.ts | 3 ++ .../schemas/responses/LocationMetadataResponse.ts | 5 ++++ src/util/schemas/responses/TokenResponse.ts | 6 ++++ src/util/schemas/responses/index.ts | 7 +++++ 22 files changed, 201 insertions(+), 46 deletions(-) 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 (limited to 'src') 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"; -- cgit 1.4.1