diff --git a/src/api/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts
index fe57880a..6c166f5b 100644
--- a/src/api/middlewares/Authentication.ts
+++ b/src/api/middlewares/Authentication.ts
@@ -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
diff --git a/src/api/middlewares/RateLimit.ts b/src/api/middlewares/RateLimit.ts
index 8a8c17f6..fbf9653f 100644
--- a/src/api/middlewares/RateLimit.ts
+++ b/src/api/middlewares/RateLimit.ts
@@ -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
diff --git a/src/api/routes/-/healthz.ts b/src/api/routes/-/healthz.ts
index 9c91de18..a25dbe92 100644
--- a/src/api/routes/-/healthz.ts
+++ b/src/api/routes/-/healthz.ts
@@ -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;
diff --git a/src/api/routes/-/readyz.ts b/src/api/routes/-/readyz.ts
index 9c91de18..a25dbe92 100644
--- a/src/api/routes/-/readyz.ts
+++ b/src/api/routes/-/readyz.ts
@@ -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;
diff --git a/src/api/routes/auth/fingerprint.ts b/src/api/routes/auth/fingerprint.ts
index d3e3321e..eb4bb9ba 100644
--- a/src/api/routes/auth/fingerprint.ts
+++ b/src/api/routes/auth/fingerprint.ts
@@ -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;
diff --git a/src/api/routes/auth/forgot.ts b/src/api/routes/auth/forgot.ts
index 4ee46ccb..636869a3 100644
--- a/src/api/routes/auth/forgot.ts
+++ b/src/api/routes/auth/forgot.ts
@@ -35,6 +35,7 @@ router.post(
body: "APIErrorOrCaptchaResponse",
},
},
+ authentication: "never",
}),
async (req: Request, res: Response) => {
const { login, captcha_key } = req.body as ForgotPasswordSchema;
diff --git a/src/api/routes/auth/location-metadata.ts b/src/api/routes/auth/location-metadata.ts
index b00298bb..a4c5f481 100644
--- a/src/api/routes/auth/location-metadata.ts
+++ b/src/api/routes/auth/location-metadata.ts
@@ -29,6 +29,7 @@ router.get(
body: "LocationMetadataResponse",
},
},
+ authentication: "never",
}),
async (req: Request, res: Response) => {
//TODO
diff --git a/src/api/routes/auth/login.ts b/src/api/routes/auth/login.ts
index 0c1976f0..3a97323a 100644
--- a/src/api/routes/auth/login.ts
+++ b/src/api/routes/auth/login.ts
@@ -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;
diff --git a/src/api/routes/auth/mfa/totp.ts b/src/api/routes/auth/mfa/totp.ts
index 37cff655..70c993d7 100644
--- a/src/api/routes/auth/mfa/totp.ts
+++ b/src/api/routes/auth/mfa/totp.ts
@@ -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 } =
diff --git a/src/api/routes/auth/mfa/webauthn.ts b/src/api/routes/auth/mfa/webauthn.ts
index 8c107a15..a8c955ff 100644
--- a/src/api/routes/auth/mfa/webauthn.ts
+++ b/src/api/routes/auth/mfa/webauthn.ts
@@ -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) {
diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts
index ba2f6607..62c446c0 100644
--- a/src/api/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -47,6 +47,7 @@ router.post(
200: { body: "TokenOnlyResponse" },
400: { body: "APIErrorOrCaptchaResponse" },
},
+ authentication: "never",
}),
async (req: Request, res: Response) => {
const totalSw = Stopwatch.startNew();
diff --git a/src/api/routes/auth/reset.ts b/src/api/routes/auth/reset.ts
index 0270de90..81bbd8e7 100644
--- a/src/api/routes/auth/reset.ts
+++ b/src/api/routes/auth/reset.ts
@@ -38,6 +38,7 @@ router.post(
body: "APIErrorOrCaptchaResponse",
},
},
+ authentication: "never",
}),
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 7630a77f..8cf75a3f 100644
--- a/src/api/routes/auth/verify/index.ts
+++ b/src/api/routes/auth/verify/index.ts
@@ -47,6 +47,7 @@ router.post(
body: "APIErrorOrCaptchaResponse",
},
},
+ authentication: "never",
}),
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 574254d2..7159d326 100644
--- a/src/api/routes/auth/verify/resend.ts
+++ b/src/api/routes/auth/verify/resend.ts
@@ -37,6 +37,7 @@ router.post(
body: "APIErrorResponse",
},
},
+ authentication: "never",
}),
async (req: Request, res: Response) => {
const user = await User.findOneOrFail({
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 724ab6e8..c3f8dfcd 100644
--- a/src/api/routes/auth/verify/view-backup-codes-challenge.ts
+++ b/src/api/routes/auth/verify/view-backup-codes-challenge.ts
@@ -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;
diff --git a/src/api/routes/connections/#connection_name/callback.ts b/src/api/routes/connections/#connection_name/callback.ts
index 134b0d58..fa618167 100644
--- a/src/api/routes/connections/#connection_name/callback.ts
+++ b/src/api/routes/connections/#connection_name/callback.ts
@@ -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;
diff --git a/src/api/routes/download.ts b/src/api/routes/download.ts
index b6dd3578..22c89575 100644
--- a/src/api/routes/download.ts
+++ b/src/api/routes/download.ts
@@ -32,6 +32,7 @@ router.get(
body: "APIErrorResponse",
},
},
+ authentication: "never",
}),
async (req: Request, res: Response) => {
const { platform } = req.query;
diff --git a/src/api/routes/experiments.ts b/src/api/routes/experiments.ts
index 22e0d832..ccdd2d68 100644
--- a/src/api/routes/experiments.ts
+++ b/src/api/routes/experiments.ts
@@ -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;
diff --git a/src/api/routes/gateway/bot.ts b/src/api/routes/gateway/bot.ts
index 23bb402e..024d1340 100644
--- a/src/api/routes/gateway/bot.ts
+++ b/src/api/routes/gateway/bot.ts
@@ -30,6 +30,7 @@ router.get(
body: "GatewayBotResponse",
},
},
+ authentication: "never",
}),
(req: Request, res: Response) => {
const { endpointPublic } = Config.get().gateway;
diff --git a/src/api/routes/gateway/index.ts b/src/api/routes/gateway/index.ts
index 24efef91..a814fa48 100644
--- a/src/api/routes/gateway/index.ts
+++ b/src/api/routes/gateway/index.ts
@@ -30,6 +30,7 @@ router.get(
body: "GatewayResponse",
},
},
+ authentication: "never",
}),
(req: Request, res: Response) => {
const { endpointPublic } = Config.get().gateway;
diff --git a/src/api/routes/guilds/#guild_id/widget.json.ts b/src/api/routes/guilds/#guild_id/widget.json.ts
index 04f103dc..03b86376 100644
--- a/src/api/routes/guilds/#guild_id/widget.json.ts
+++ b/src/api/routes/guilds/#guild_id/widget.json.ts
@@ -47,6 +47,7 @@ router.get(
body: "APIErrorResponse",
},
},
+ authentication: "never",
}),
async (req: Request, res: Response) => {
const { guild_id } = req.params as { [key: string]: string };
diff --git a/src/api/routes/guilds/#guild_id/widget.png.ts b/src/api/routes/guilds/#guild_id/widget.png.ts
index f808aa99..60ce804c 100644
--- a/src/api/routes/guilds/#guild_id/widget.png.ts
+++ b/src/api/routes/guilds/#guild_id/widget.png.ts
@@ -45,6 +45,7 @@ router.get(
body: "APIErrorResponse",
},
},
+ authentication: "never",
}),
async (req: Request, res: Response) => {
const { guild_id } = req.params as { [key: string]: string };
diff --git a/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts b/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts
index 2de4d3da..a1c643c9 100644
--- a/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts
+++ b/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts
@@ -31,6 +31,7 @@ router.post(
route({
stripNulls: true,
requestBody: "InteractionCallbacksSchema",
+ authentication: "never",
}),
async (req: Request, res: Response) => {
const body = req.body as InteractionCallbacksSchema;
diff --git a/src/api/routes/invites/index.ts b/src/api/routes/invites/index.ts
index 609ffc14..083c4315 100644
--- a/src/api/routes/invites/index.ts
+++ b/src/api/routes/invites/index.ts
@@ -36,6 +36,7 @@ router.get(
body: "APIErrorResponse",
},
},
+ authentication: "never",
}),
async (req: Request, res: Response) => {
const { invite_code } = req.params as { [key: string]: string };
diff --git a/src/api/routes/ping.ts b/src/api/routes/ping.ts
index eea5d9fc..babec1ee 100644
--- a/src/api/routes/ping.ts
+++ b/src/api/routes/ping.ts
@@ -31,6 +31,7 @@ router.get(
},
},
spacebarOnly: true,
+ authentication: "never",
}),
(req: Request, res: Response) => {
const { general } = Config.get();
diff --git a/src/api/routes/policies/instance/config.ts b/src/api/routes/policies/instance/config.ts
index 2b0f1a64..44f71c8e 100755
--- a/src/api/routes/policies/instance/config.ts
+++ b/src/api/routes/policies/instance/config.ts
@@ -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;
diff --git a/src/api/routes/policies/instance/domains.ts b/src/api/routes/policies/instance/domains.ts
index c05f1d18..54a27898 100644
--- a/src/api/routes/policies/instance/domains.ts
+++ b/src/api/routes/policies/instance/domains.ts
@@ -30,6 +30,7 @@ router.get(
},
},
spacebarOnly: true,
+ authentication: "never",
}),
(req: Request, res: Response) => {
const { cdn, gateway, api } = Config.get();
diff --git a/src/api/routes/policies/instance/index.ts b/src/api/routes/policies/instance/index.ts
index 116e3512..13897170 100644
--- a/src/api/routes/policies/instance/index.ts
+++ b/src/api/routes/policies/instance/index.ts
@@ -30,6 +30,7 @@ router.get(
},
},
spacebarOnly: true,
+ authentication: "never",
}),
(req: Request, res: Response) => {
const { general } = Config.get();
diff --git a/src/api/routes/policies/instance/limits.ts b/src/api/routes/policies/instance/limits.ts
index 018be038..7aba9a26 100644
--- a/src/api/routes/policies/instance/limits.ts
+++ b/src/api/routes/policies/instance/limits.ts
@@ -30,9 +30,11 @@ router.get(
},
},
spacebarOnly: true,
+ authentication: "optional",
}),
(req: Request, res: Response) => {
const { limits } = Config.get();
+ // TODO: handle rights
res.json(limits);
},
);
diff --git a/src/api/routes/scheduled-maintenances/upcoming.json.ts b/src/api/routes/scheduled-maintenances/upcoming.json.ts
index 50581c40..035981f7 100644
--- a/src/api/routes/scheduled-maintenances/upcoming.json.ts
+++ b/src/api/routes/scheduled-maintenances/upcoming.json.ts
@@ -24,6 +24,7 @@ router.get(
"/",
route({
spacebarOnly: false, // not part of public openapi
+ authentication: "never",
}),
(req: Request, res: Response) => {
res.json({
diff --git a/src/api/routes/science.ts b/src/api/routes/science.ts
index 2a71d747..34f34288 100644
--- a/src/api/routes/science.ts
+++ b/src/api/routes/science.ts
@@ -27,6 +27,7 @@ router.post(
responses: {
204: {},
},
+ authentication: "never",
}),
(req: Request, res: Response) => {
// TODO:
diff --git a/src/api/routes/track.ts b/src/api/routes/track.ts
index d6cd8b19..b41e342d 100644
--- a/src/api/routes/track.ts
+++ b/src/api/routes/track.ts
@@ -25,6 +25,7 @@ router.post(
"/",
route({
spacebarOnly: false, // Not part of the public OpenAPI schema
+ authentication: "never",
}),
(req: Request, res: Response) => {
// TODO:
diff --git a/src/api/routes/updates.ts b/src/api/routes/updates.ts
index 47e1434a..2918f147 100644
--- a/src/api/routes/updates.ts
+++ b/src/api/routes/updates.ts
@@ -37,6 +37,7 @@ router.get(
body: "APIErrorResponse",
},
},
+ authentication: "never",
}),
async (req: Request, res: Response) => {
const platform = req.query.platform;
diff --git a/src/api/routes/webhooks/#webhook_id/#webhook_token/github.ts b/src/api/routes/webhooks/#webhook_id/#webhook_token/github.ts
index ac0b7c35..9a189876 100644
--- a/src/api/routes/webhooks/#webhook_id/#webhook_token/github.ts
+++ b/src/api/routes/webhooks/#webhook_id/#webhook_token/github.ts
@@ -421,6 +421,7 @@ router.post(
},
404: {},
},
+ authentication: "never",
}),
executeWebhook,
);
diff --git a/src/api/routes/webhooks/#webhook_id/#webhook_token/index.ts b/src/api/routes/webhooks/#webhook_id/#webhook_token/index.ts
index f5f31551..3c2891f2 100644
--- a/src/api/routes/webhooks/#webhook_id/#webhook_token/index.ts
+++ b/src/api/routes/webhooks/#webhook_id/#webhook_token/index.ts
@@ -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 };
diff --git a/src/api/routes/webhooks/#webhook_id/#webhook_token/messages/#message_id.ts b/src/api/routes/webhooks/#webhook_id/#webhook_token/messages/#message_id.ts
index 5ada4aa0..f502a88d 100644
--- a/src/api/routes/webhooks/#webhook_id/#webhook_token/messages/#message_id.ts
+++ b/src/api/routes/webhooks/#webhook_id/#webhook_token/messages/#message_id.ts
@@ -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 };
|