auth routes
This commit is contained in:
parent
174d34c376
commit
a567ca3f51
7992
assets/openapi.json
7992
assets/openapi.json
File diff suppressed because it is too large
Load Diff
27130
assets/schemas.json
27130
assets/schemas.json
File diff suppressed because it is too large
Load Diff
@ -147,36 +147,37 @@ function apiRoutes() {
|
|||||||
}.merge(obj.requestBody);
|
}.merge(obj.requestBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route.test?.response) {
|
if (route.responses) {
|
||||||
const status = route.test.response.status || 200;
|
for (const [k, v] of Object.entries(route.responses)) {
|
||||||
let schema = {
|
let schema = {
|
||||||
allOf: [
|
allOf: [
|
||||||
{
|
{
|
||||||
$ref: `#/components/schemas/${route.test.response.body}`,
|
$ref: `#/components/schemas/${v.body}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
example: route.test.body,
|
example: v.body,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
if (!route.test.body) schema = schema.allOf[0];
|
if (!v.body) schema = schema.allOf[0];
|
||||||
|
|
||||||
obj.responses = {
|
obj.responses = {
|
||||||
[status]: {
|
[k]: {
|
||||||
...(route.test.response.body
|
...(v.body
|
||||||
? {
|
? {
|
||||||
description:
|
description:
|
||||||
obj?.responses?.[status]?.description || "",
|
obj?.responses?.[k]?.description || "",
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: schema,
|
schema: schema,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
: {}),
|
||||||
: {}),
|
},
|
||||||
},
|
}.merge(obj.responses);
|
||||||
}.merge(obj.responses);
|
delete obj.responses.default;
|
||||||
delete obj.responses.default;
|
}
|
||||||
}
|
}
|
||||||
if (p.includes(":")) {
|
if (p.includes(":")) {
|
||||||
obj.parameters = p.match(/:\w+/g)?.map((x) => ({
|
obj.parameters = p.match(/:\w+/g)?.map((x) => ({
|
||||||
|
@ -30,7 +30,18 @@ const router = Router();
|
|||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
route({ body: "ForgotPasswordSchema" }),
|
route({
|
||||||
|
body: "ForgotPasswordSchema",
|
||||||
|
responses: {
|
||||||
|
204: {},
|
||||||
|
400: {
|
||||||
|
body: "APIErrorResponse",
|
||||||
|
},
|
||||||
|
500: {
|
||||||
|
body: "APIErrorResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
const { login, captcha_key } = req.body as ForgotPasswordSchema;
|
const { login, captcha_key } = req.body as ForgotPasswordSchema;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { route, random } from "@spacebar/api";
|
import { random, route } from "@spacebar/api";
|
||||||
import { Config, ValidRegistrationToken } from "@spacebar/util";
|
import { Config, ValidRegistrationToken } from "@spacebar/util";
|
||||||
import { Request, Response, Router } from "express";
|
import { Request, Response, Router } from "express";
|
||||||
|
|
||||||
@ -25,7 +25,10 @@ export default router;
|
|||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
"/",
|
"/",
|
||||||
route({ right: "OPERATOR" }),
|
route({
|
||||||
|
right: "OPERATOR",
|
||||||
|
responses: { 200: { body: "GenerateRegistrationTokensResponse" } },
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
const count = req.query.count ? parseInt(req.query.count as string) : 1;
|
const count = req.query.count ? parseInt(req.query.count as string) : 1;
|
||||||
const length = req.query.length
|
const length = req.query.length
|
||||||
|
@ -16,20 +16,29 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Router, Request, Response } from "express";
|
import { IPAnalysis, getIpAdress, route } from "@spacebar/api";
|
||||||
import { route } from "@spacebar/api";
|
import { Request, Response, Router } from "express";
|
||||||
import { getIpAdress, IPAnalysis } from "@spacebar/api";
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
router.get(
|
||||||
//TODO
|
"/",
|
||||||
//Note: It's most likely related to legal. At the moment Discord hasn't finished this too
|
route({
|
||||||
const country_code = (await IPAnalysis(getIpAdress(req))).country_code;
|
responses: {
|
||||||
res.json({
|
200: {
|
||||||
consent_required: false,
|
body: "LocationMetadataResponse",
|
||||||
country_code: country_code,
|
},
|
||||||
promotional_email_opt_in: { required: true, pre_checked: false },
|
},
|
||||||
});
|
}),
|
||||||
});
|
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;
|
export default router;
|
||||||
|
@ -36,7 +36,17 @@ export default router;
|
|||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
route({ body: "LoginSchema" }),
|
route({
|
||||||
|
body: "LoginSchema",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
body: "TokenResponse",
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
body: "APIErrorOrCaptchaResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
const { login, password, captcha_key, undelete } =
|
const { login, password, captcha_key, undelete } =
|
||||||
req.body as LoginSchema;
|
req.body as LoginSchema;
|
||||||
|
@ -22,14 +22,25 @@ import { Request, Response, Router } from "express";
|
|||||||
const router: Router = Router();
|
const router: Router = Router();
|
||||||
export default router;
|
export default router;
|
||||||
|
|
||||||
router.post("/", route({}), async (req: Request, res: Response) => {
|
router.post(
|
||||||
if (req.body.provider != null || req.body.voip_provider != null) {
|
"/",
|
||||||
console.log(`[LOGOUT]: provider or voip provider not null!`, req.body);
|
route({
|
||||||
} else {
|
responses: {
|
||||||
delete req.body.provider;
|
204: {},
|
||||||
delete req.body.voip_provider;
|
},
|
||||||
if (Object.keys(req.body).length != 0)
|
}),
|
||||||
console.log(`[LOGOUT]: Extra fields sent in logout!`, req.body);
|
async (req: Request, res: Response) => {
|
||||||
}
|
if (req.body.provider != null || req.body.voip_provider != null) {
|
||||||
res.status(204).send();
|
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();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
@ -16,16 +16,26 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Router, Request, Response } from "express";
|
|
||||||
import { route } from "@spacebar/api";
|
import { route } from "@spacebar/api";
|
||||||
import { BackupCode, generateToken, User, TotpSchema } from "@spacebar/util";
|
import { BackupCode, TotpSchema, User, generateToken } from "@spacebar/util";
|
||||||
import { verifyToken } from "node-2fa";
|
import { Request, Response, Router } from "express";
|
||||||
import { HTTPError } from "lambert-server";
|
import { HTTPError } from "lambert-server";
|
||||||
|
import { verifyToken } from "node-2fa";
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
route({ body: "TotpSchema" }),
|
route({
|
||||||
|
body: "TotpSchema",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
body: "TokenResponse",
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
body: "APIErrorResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
// const { code, ticket, gift_code_sku_id, login_source } =
|
// const { code, ticket, gift_code_sku_id, login_source } =
|
||||||
const { code, ticket } = req.body as TotpSchema;
|
const { code, ticket } = req.body as TotpSchema;
|
||||||
|
@ -41,7 +41,13 @@ function toArrayBuffer(buf: Buffer) {
|
|||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
route({ body: "WebAuthnTotpSchema" }),
|
route({
|
||||||
|
body: "WebAuthnTotpSchema",
|
||||||
|
responses: {
|
||||||
|
200: { body: "TokenResponse" },
|
||||||
|
400: { body: "APIErrorResponse" },
|
||||||
|
},
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
if (!WebAuthn.fido2) {
|
if (!WebAuthn.fido2) {
|
||||||
// TODO: I did this for typescript and I can't use !
|
// TODO: I did this for typescript and I can't use !
|
||||||
|
@ -42,7 +42,13 @@ const router: Router = Router();
|
|||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
route({ body: "RegisterSchema" }),
|
route({
|
||||||
|
body: "RegisterSchema",
|
||||||
|
responses: {
|
||||||
|
200: { body: "TokenResponse" },
|
||||||
|
400: { body: "APIErrorOrCaptchaResponse" },
|
||||||
|
},
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
const body = req.body as RegisterSchema;
|
const body = req.body as RegisterSchema;
|
||||||
const { register, security, limits } = Config.get();
|
const { register, security, limits } = Config.get();
|
||||||
|
@ -31,9 +31,20 @@ import { Request, Response, Router } from "express";
|
|||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
|
// TODO: the response interface also returns settings, but this route doesn't actually return that.
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
route({ body: "PasswordResetSchema" }),
|
route({
|
||||||
|
body: "PasswordResetSchema",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
body: "TokenResponse",
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
body: "APIErrorOrCaptchaResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
const { password, token } = req.body as PasswordResetSchema;
|
const { password, token } = req.body as PasswordResetSchema;
|
||||||
|
|
||||||
|
@ -37,9 +37,20 @@ async function getToken(user: User) {
|
|||||||
return { token };
|
return { token };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: the response interface also returns settings, but this route doesn't actually return that.
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
route({ body: "VerifyEmailSchema" }),
|
route({
|
||||||
|
body: "VerifyEmailSchema",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
body: "TokenResponse",
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
body: "APIErrorOrCaptchaResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
const { captcha_key, token } = req.body;
|
const { captcha_key, token } = req.body;
|
||||||
|
|
||||||
|
@ -24,7 +24,14 @@ const router = Router();
|
|||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
route({ right: "RESEND_VERIFICATION_EMAIL" }),
|
route({
|
||||||
|
right: "RESEND_VERIFICATION_EMAIL",
|
||||||
|
responses: {
|
||||||
|
204: {},
|
||||||
|
400: {},
|
||||||
|
500: {},
|
||||||
|
},
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
const user = await User.findOneOrFail({
|
const user = await User.findOneOrFail({
|
||||||
where: { id: req.user_id },
|
where: { id: req.user_id },
|
||||||
|
@ -16,15 +16,21 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Router, Request, Response } from "express";
|
|
||||||
import { route } from "@spacebar/api";
|
import { route } from "@spacebar/api";
|
||||||
import { FieldErrors, User, BackupCodesChallengeSchema } from "@spacebar/util";
|
import { BackupCodesChallengeSchema, FieldErrors, User } from "@spacebar/util";
|
||||||
import bcrypt from "bcrypt";
|
import bcrypt from "bcrypt";
|
||||||
|
import { Request, Response, Router } from "express";
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
route({ body: "BackupCodesChallengeSchema" }),
|
route({
|
||||||
|
body: "BackupCodesChallengeSchema",
|
||||||
|
responses: {
|
||||||
|
200: { body: "BackupCodesChallengeResponse" },
|
||||||
|
400: { body: "APIErrorResponse" },
|
||||||
|
},
|
||||||
|
}),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
const { password } = req.body as BackupCodesChallengeSchema;
|
const { password } = req.body as BackupCodesChallengeSchema;
|
||||||
|
|
||||||
|
@ -17,21 +17,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ajv,
|
|
||||||
DiscordApiErrors,
|
DiscordApiErrors,
|
||||||
EVENT,
|
EVENT,
|
||||||
FieldErrors,
|
FieldErrors,
|
||||||
SpacebarApiErrors,
|
|
||||||
getPermission,
|
|
||||||
getRights,
|
|
||||||
normalizeBody,
|
|
||||||
PermissionResolvable,
|
PermissionResolvable,
|
||||||
Permissions,
|
Permissions,
|
||||||
RightResolvable,
|
RightResolvable,
|
||||||
Rights,
|
Rights,
|
||||||
|
SpacebarApiErrors,
|
||||||
|
ajv,
|
||||||
|
getPermission,
|
||||||
|
getRights,
|
||||||
|
normalizeBody,
|
||||||
} from "@spacebar/util";
|
} from "@spacebar/util";
|
||||||
import { NextFunction, Request, Response } from "express";
|
|
||||||
import { AnyValidateFunction } from "ajv/dist/core";
|
import { AnyValidateFunction } from "ajv/dist/core";
|
||||||
|
import { NextFunction, Request, Response } from "express";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// TODO: fix this
|
// TODO: fix this
|
||||||
@ -53,6 +53,11 @@ export interface RouteOptions {
|
|||||||
permission?: PermissionResolvable;
|
permission?: PermissionResolvable;
|
||||||
right?: RightResolvable;
|
right?: RightResolvable;
|
||||||
body?: `${string}Schema`; // typescript interface name
|
body?: `${string}Schema`; // typescript interface name
|
||||||
|
responses?: {
|
||||||
|
[status: number]: {
|
||||||
|
body?: `${string}Response`;
|
||||||
|
};
|
||||||
|
};
|
||||||
test?: {
|
test?: {
|
||||||
response?: RouteResponse;
|
response?: RouteResponse;
|
||||||
body?: unknown;
|
body?: unknown;
|
||||||
|
@ -58,6 +58,7 @@ export * from "./PurgeSchema";
|
|||||||
export * from "./RegisterSchema";
|
export * from "./RegisterSchema";
|
||||||
export * from "./RelationshipPostSchema";
|
export * from "./RelationshipPostSchema";
|
||||||
export * from "./RelationshipPutSchema";
|
export * from "./RelationshipPutSchema";
|
||||||
|
export * from "./responses";
|
||||||
export * from "./RoleModifySchema";
|
export * from "./RoleModifySchema";
|
||||||
export * from "./RolePositionUpdateSchema";
|
export * from "./RolePositionUpdateSchema";
|
||||||
export * from "./SelectProtocolSchema";
|
export * from "./SelectProtocolSchema";
|
||||||
|
6
src/util/schemas/responses/APIErrorOrCaptchaResponse.ts
Normal file
6
src/util/schemas/responses/APIErrorOrCaptchaResponse.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { APIErrorResponse } from "./APIErrorResponse";
|
||||||
|
import { CaptchaRequiredResponse } from "./CaptchaRequiredResponse";
|
||||||
|
|
||||||
|
export type APIErrorOrCaptchaResponse =
|
||||||
|
| CaptchaRequiredResponse
|
||||||
|
| APIErrorResponse;
|
12
src/util/schemas/responses/APIErrorResponse.ts
Normal file
12
src/util/schemas/responses/APIErrorResponse.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export interface APIErrorResponse {
|
||||||
|
code: number;
|
||||||
|
message: string;
|
||||||
|
errors: {
|
||||||
|
[key: string]: {
|
||||||
|
_errors: {
|
||||||
|
message: string;
|
||||||
|
code: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
export interface BackupCodesChallengeResponse {
|
||||||
|
nonce: string;
|
||||||
|
regenerate_nonce: string;
|
||||||
|
}
|
5
src/util/schemas/responses/CaptchaRequiredResponse.ts
Normal file
5
src/util/schemas/responses/CaptchaRequiredResponse.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface CaptchaRequiredResponse {
|
||||||
|
captcha_key: string;
|
||||||
|
captcha_sitekey: string;
|
||||||
|
captcha_service: string;
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
export interface GenerateRegistrationTokensResponse {
|
||||||
|
tokens: string[];
|
||||||
|
}
|
5
src/util/schemas/responses/LocationMetadataResponse.ts
Normal file
5
src/util/schemas/responses/LocationMetadataResponse.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface LocationMetadataResponse {
|
||||||
|
consent_required: boolean;
|
||||||
|
country_code: string;
|
||||||
|
promotional_email_opt_in: { required: true; pre_checked: false };
|
||||||
|
}
|
6
src/util/schemas/responses/TokenResponse.ts
Normal file
6
src/util/schemas/responses/TokenResponse.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { UserSettings } from "../../entities";
|
||||||
|
|
||||||
|
export interface TokenResponse {
|
||||||
|
token: string;
|
||||||
|
settings: UserSettings;
|
||||||
|
}
|
7
src/util/schemas/responses/index.ts
Normal file
7
src/util/schemas/responses/index.ts
Normal file
@ -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";
|
Loading…
x
Reference in New Issue
Block a user