Remove authentication import from ratelimit

This commit is contained in:
Rory&
2026-07-21 17:01:28 +02:00
parent 8e06df76cb
commit 129c652d29
36 changed files with 113 additions and 89 deletions
+1 -46
View File
@@ -17,53 +17,9 @@
*/
import { NextFunction, Request, Response } from "express";
import { HTTPError } from "lambert-server/HTTPError";
import { Session, User } from "@spacebar/database";
import { Random } from "@spacebar/extensions";
import { checkToken, DiscordApiErrors, Rights, UserTokenData } from "@spacebar/util";
export const NO_AUTHORIZATION_ROUTES = [
// Authentication routes
"POST /auth/login",
"POST /auth/register",
"GET /auth/location-metadata",
"POST /auth/mfa/",
"POST /auth/verify",
"POST /auth/forgot",
"POST /auth/reset",
"POST /auth/fingerprint",
"GET /invites/",
// Routes with a seperate auth system
/^(POST|HEAD|GET|PATCH|DELETE) \/webhooks\/\d+\/[\w-]+\/?/, // no token requires auth
/^POST \/interactions\/\d+\/[A-Za-z0-9_-]+\/callback/,
// Public information endpoints
"GET /ping",
"GET /gateway",
"GET /experiments",
"GET /updates",
"GET /download",
"GET /scheduled-maintenances/upcoming.json",
// Public kubernetes integration
"GET /-/readyz",
"GET /-/healthz",
// Client analytics
"POST /science",
"POST /track",
// Public policy pages
"GET /policies/instance/",
// Oauth callback
"/oauth2/callback",
// Asset delivery
/^(GET|HEAD) \/guilds\/\d+\/widget\.(json|png)/,
/^(GET|HEAD) \/guilds\/\d+\/shield\.svg/,
// Connections
/^(POST|HEAD) \/connections\/\w+\/callback/,
// Image proxy
/^(GET|HEAD) \/imageproxy\/[A-Za-z0-9+/]\/\d+x\d+\/.+/,
];
export const API_PREFIX = /^\/api(\/v\d+)?/;
export const API_PREFIX_TRAILING_SLASH = /^\/api(\/v\d+)?\//;
import { checkToken, Rights, UserTokenData } from "@spacebar/util";
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
@@ -84,7 +40,6 @@ declare global {
export async function Authentication(req: Request, res: Response, next: NextFunction) {
if (req.method === "OPTIONS") return res.sendStatus(204);
const url = req.url.replace(API_PREFIX, "");
if (req.headers.cookie?.split("; ").find((x) => x.startsWith("__sb_sessid=")))
req.fingerprint = req.headers.cookie
+2 -1
View File
@@ -18,7 +18,8 @@
import { Config, getRights, listenEvent, RabbitMQ } from "@spacebar/util";
import { NextFunction, Request, Response, Router } from "express";
import { API_PREFIX_TRAILING_SLASH } from "./Authentication";
export const API_PREFIX_TRAILING_SLASH = /^\/api(\/v\d+)?\//;
// Docs: https://discord.com/developers/docs/topics/rate-limits
+12 -4
View File
@@ -22,10 +22,18 @@ import { getDatabase } from "@spacebar/database";
const router = Router({ mergeParams: true });
router.get("/", route({ deprecated: true, spacebarOnly: true }), (req: Request, res: Response) => {
if (!getDatabase()) return res.sendStatus(503);
router.get(
"/",
route({
deprecated: true,
spacebarOnly: true,
authentication: "never",
}),
(req: Request, res: Response) => {
if (!getDatabase()) return res.sendStatus(503);
return res.sendStatus(200);
});
return res.sendStatus(200);
},
);
export default router;
+12 -4
View File
@@ -22,10 +22,18 @@ import { getDatabase } from "@spacebar/database";
const router = Router({ mergeParams: true });
router.get("/", route({ deprecated: true, spacebarOnly: true }), (req: Request, res: Response) => {
if (!getDatabase()) return res.sendStatus(503);
router.get(
"/",
route({
deprecated: true,
spacebarOnly: true,
authentication: "never",
}),
(req: Request, res: Response) => {
if (!getDatabase()) return res.sendStatus(503);
return res.sendStatus(200);
});
return res.sendStatus(200);
},
);
export default router;
+3
View File
@@ -20,11 +20,13 @@ import { createHash } from "node:crypto";
import { Snowflake } from "@spacebar/util";
import { Request, Response, Router } from "express";
const router = Router({ mergeParams: true });
router.post(
"/",
route({
responses: { 200: { body: "CreateFingerprintResponse" } },
spacebarOnly: false, // not part of public openapi
authentication: "never",
}),
(req: Request, res: Response) => {
const snowflake = Snowflake.generate();
@@ -33,4 +35,5 @@ router.post(
});
},
);
export default router;
+1
View File
@@ -35,6 +35,7 @@ router.post(
body: "APIErrorOrCaptchaResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { login, captcha_key } = req.body as ForgotPasswordSchema;
+1
View File
@@ -29,6 +29,7 @@ router.get(
body: "LocationMetadataResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
//TODO
+1
View File
@@ -39,6 +39,7 @@ router.post(
body: "APIErrorOrCaptchaResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { login, password, captcha_key, undelete } = req.body as LoginSchema;
+1
View File
@@ -39,6 +39,7 @@ router.post(
},
},
spacebarOnly: false, // not part of public openapi
authentication: "never",
}),
async (req: Request, res: Response) => {
// const { code, ticket, gift_code_sku_id, login_source } =
+1
View File
@@ -44,6 +44,7 @@ router.post(
400: { body: "APIErrorResponse" },
},
spacebarOnly: false, // not part of public openapi
authentication: "never",
}),
async (req: Request, res: Response) => {
if (!WebAuthn.fido2) {
+1
View File
@@ -47,6 +47,7 @@ router.post(
200: { body: "TokenOnlyResponse" },
400: { body: "APIErrorOrCaptchaResponse" },
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const totalSw = Stopwatch.startNew();
+1
View File
@@ -38,6 +38,7 @@ router.post(
body: "APIErrorOrCaptchaResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { password, token } = req.body as PasswordResetSchema;
+1
View File
@@ -47,6 +47,7 @@ router.post(
body: "APIErrorOrCaptchaResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { captcha_key, token } = req.body;
+1
View File
@@ -37,6 +37,7 @@ router.post(
body: "APIErrorResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const user = await User.findOneOrFail({
@@ -33,6 +33,7 @@ router.post(
200: { body: "BackupCodesChallengeResponse" },
400: { body: "APIErrorResponse" },
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { password } = req.body as BackupCodesChallengeSchema;
@@ -23,39 +23,46 @@ import { ConnectionCallbackSchema } from "@spacebar/schemas";
const router = Router({ mergeParams: true });
router.post("/", route({ requestBody: "ConnectionCallbackSchema" }), async (req: Request, res: Response) => {
const { connection_name } = req.params as { [key: string]: string };
const connection = ConnectionStore.connections.get(connection_name);
if (!connection)
throw FieldErrors({
provider_id: {
code: "BASE_TYPE_CHOICES",
message: req.t("common:field.BASE_TYPE_CHOICES", {
types: Array.from(ConnectionStore.connections.keys()).join(", "),
}),
},
});
router.post(
"/",
route({
requestBody: "ConnectionCallbackSchema",
authentication: "never",
}),
async (req: Request, res: Response) => {
const { connection_name } = req.params as { [key: string]: string };
const connection = ConnectionStore.connections.get(connection_name);
if (!connection)
throw FieldErrors({
provider_id: {
code: "BASE_TYPE_CHOICES",
message: req.t("common:field.BASE_TYPE_CHOICES", {
types: Array.from(ConnectionStore.connections.keys()).join(", "),
}),
},
});
if (!connection.settings.enabled)
throw FieldErrors({
provider_id: {
message: "This connection has been disabled server-side.",
},
});
if (!connection.settings.enabled)
throw FieldErrors({
provider_id: {
message: "This connection has been disabled server-side.",
},
});
const body = req.body as ConnectionCallbackSchema;
const userId = connection.getUserId(body.state);
const connectedAccnt = await connection.handleCallback(body);
const body = req.body as ConnectionCallbackSchema;
const userId = connection.getUserId(body.state);
const connectedAccnt = await connection.handleCallback(body);
// whether we should emit a connections update event, only used when a connection doesnt already exist
if (connectedAccnt)
await emitEvent({
event: "USER_CONNECTIONS_UPDATE",
data: { ...connectedAccnt, token_data: undefined },
user_id: userId,
});
// whether we should emit a connections update event, only used when a connection doesnt already exist
if (connectedAccnt)
await emitEvent({
event: "USER_CONNECTIONS_UPDATE",
data: { ...connectedAccnt, token_data: undefined },
user_id: userId,
});
res.sendStatus(204);
});
res.sendStatus(204);
},
);
export default router;
+1
View File
@@ -32,6 +32,7 @@ router.get(
body: "APIErrorResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { platform } = req.query;
+10 -4
View File
@@ -21,9 +21,15 @@ import { route } from "@spacebar/api/middlewares";
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
// TODO:
res.send({ fingerprint: "", assignments: [], guild_experiments: [] });
});
router.get(
"/",
route({
authentication: "optional",
}),
(req: Request, res: Response) => {
// TODO:
res.send({ fingerprint: "", assignments: [], guild_experiments: [] });
},
);
export default router;
+1
View File
@@ -30,6 +30,7 @@ router.get(
body: "GatewayBotResponse",
},
},
authentication: "never",
}),
(req: Request, res: Response) => {
const { endpointPublic } = Config.get().gateway;
+1
View File
@@ -30,6 +30,7 @@ router.get(
body: "GatewayResponse",
},
},
authentication: "never",
}),
(req: Request, res: Response) => {
const { endpointPublic } = Config.get().gateway;
@@ -47,6 +47,7 @@ router.get(
body: "APIErrorResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { guild_id } = req.params as { [key: string]: string };
@@ -45,6 +45,7 @@ router.get(
body: "APIErrorResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { guild_id } = req.params as { [key: string]: string };
@@ -31,6 +31,7 @@ router.post(
route({
stripNulls: true,
requestBody: "InteractionCallbacksSchema",
authentication: "never",
}),
async (req: Request, res: Response) => {
const body = req.body as InteractionCallbacksSchema;
+1
View File
@@ -36,6 +36,7 @@ router.get(
body: "APIErrorResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { invite_code } = req.params as { [key: string]: string };
+1
View File
@@ -31,6 +31,7 @@ router.get(
},
},
spacebarOnly: true,
authentication: "never",
}),
(req: Request, res: Response) => {
const { general } = Config.get();
@@ -31,10 +31,12 @@ router.get(
},
},
spacebarOnly: true,
authentication: "optional",
}),
async (req: Request, res: Response) => {
const general = Config.get();
let outputtedConfig;
// TODO: clean up
if (req.user_id) {
const rights = await getRights(req.user_id);
if (rights.has("OPERATOR")) outputtedConfig = general;
@@ -30,6 +30,7 @@ router.get(
},
},
spacebarOnly: true,
authentication: "never",
}),
(req: Request, res: Response) => {
const { cdn, gateway, api } = Config.get();
@@ -30,6 +30,7 @@ router.get(
},
},
spacebarOnly: true,
authentication: "never",
}),
(req: Request, res: Response) => {
const { general } = Config.get();
@@ -30,9 +30,11 @@ router.get(
},
},
spacebarOnly: true,
authentication: "optional",
}),
(req: Request, res: Response) => {
const { limits } = Config.get();
// TODO: handle rights
res.json(limits);
},
);
@@ -24,6 +24,7 @@ router.get(
"/",
route({
spacebarOnly: false, // not part of public openapi
authentication: "never",
}),
(req: Request, res: Response) => {
res.json({
+1
View File
@@ -27,6 +27,7 @@ router.post(
responses: {
204: {},
},
authentication: "never",
}),
(req: Request, res: Response) => {
// TODO:
+1
View File
@@ -25,6 +25,7 @@ router.post(
"/",
route({
spacebarOnly: false, // Not part of the public OpenAPI schema
authentication: "never",
}),
(req: Request, res: Response) => {
// TODO:
+1
View File
@@ -37,6 +37,7 @@ router.get(
body: "APIErrorResponse",
},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const platform = req.query.platform;
@@ -421,6 +421,7 @@ router.post(
},
404: {},
},
authentication: "never",
}),
executeWebhook,
);
@@ -37,6 +37,7 @@ router.get(
},
404: {},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { webhook_id, webhook_token } = req.params as { [key: string]: string };
@@ -109,6 +110,7 @@ router.post(
},
404: {},
},
authentication: "never",
}),
executeWebhook,
);
@@ -123,6 +125,7 @@ router.delete(
},
404: {},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { webhook_id, webhook_token } = req.params as { [key: string]: string };
@@ -166,6 +169,7 @@ router.patch(
403: {},
404: {},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { webhook_id, webhook_token } = req.params as { [key: string]: string };
@@ -63,6 +63,7 @@ router.patch(
403: {},
404: {},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { webhook_id, webhook_token, message_id } = req.params as { [key: string]: string };
@@ -116,6 +117,7 @@ router.get(
403: {},
404: {},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { webhook_id, webhook_token, message_id } = req.params as { [key: string]: string };
@@ -144,6 +146,7 @@ router.delete(
},
404: {},
},
authentication: "never",
}),
async (req: Request, res: Response) => {
const { webhook_id, webhook_token, message_id } = req.params as { [key: string]: string };