feat: add api prefix option

This commit is contained in:
Dragory 2024-04-06 11:54:31 +00:00
parent 899f743ed6
commit b40ed5ce49
No known key found for this signature in database
9 changed files with 27 additions and 22 deletions

View file

@ -81,3 +81,6 @@ LIGHTWEIGHT_DB_PORT=
LIGHTWEIGHT_DB_USER= LIGHTWEIGHT_DB_USER=
LIGHTWEIGHT_DB_PASSWORD= LIGHTWEIGHT_DB_PASSWORD=
LIGHTWEIGHT_DB_DATABASE= LIGHTWEIGHT_DB_DATABASE=
# If you want to add a prefix to API paths, such as /api, you can set that here
LIGHTWEIGHT_API_PATH_PREFIX=

View file

@ -3,15 +3,15 @@ import moment from "moment-timezone";
import { GuildArchives } from "../data/GuildArchives"; import { GuildArchives } from "../data/GuildArchives";
import { notFound } from "./responses"; import { notFound } from "./responses";
export function initArchives(app: express.Express) { export function initArchives(router: express.Router) {
const archives = new GuildArchives(null); const archives = new GuildArchives(null);
// Legacy redirect // Legacy redirect
app.get("/spam-logs/:id", (req: Request, res: Response) => { router.get("/spam-logs/:id", (req: Request, res: Response) => {
res.redirect("/archives/" + req.params.id); res.redirect("/archives/" + req.params.id);
}); });
app.get("/archives/:id", async (req: Request, res: Response) => { router.get("/archives/:id", async (req: Request, res: Response) => {
const archive = await archives.find(req.params.id); const archive = await archives.find(req.params.id);
if (!archive) return notFound(res); if (!archive) return notFound(res);

View file

@ -51,8 +51,8 @@ function simpleDiscordAPIRequest(bearerToken, path): Promise<any> {
}); });
} }
export function initAuth(app: express.Express) { export function initAuth(router: express.Router) {
app.use(passport.initialize()); router.use(passport.initialize());
passport.serializeUser((user, done) => done(null, user)); passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user as IPassportApiUser)); passport.deserializeUser((user, done) => done(null, user as IPassportApiUser));
@ -110,8 +110,8 @@ export function initAuth(app: express.Express) {
), ),
); );
app.get("/auth/login", passport.authenticate("oauth2")); router.get("/auth/login", passport.authenticate("oauth2"));
app.get( router.get(
"/auth/oauth-callback", "/auth/oauth-callback",
passport.authenticate("oauth2", { failureRedirect: "/", session: false }), passport.authenticate("oauth2", { failureRedirect: "/", session: false }),
(req: Request, res: Response) => { (req: Request, res: Response) => {
@ -122,7 +122,7 @@ export function initAuth(app: express.Express) {
} }
}, },
); );
app.post("/auth/validate-key", async (req: Request, res: Response) => { router.post("/auth/validate-key", async (req: Request, res: Response) => {
const key = req.body.key; const key = req.body.key;
if (!key) { if (!key) {
return res.status(400).json({ error: "No key supplied" }); return res.status(400).json({ error: "No key supplied" });
@ -135,14 +135,14 @@ export function initAuth(app: express.Express) {
res.json({ valid: true, userId }); res.json({ valid: true, userId });
}); });
app.post("/auth/logout", ...apiTokenAuthHandlers(), async (req: Request, res: Response) => { router.post("/auth/logout", ...apiTokenAuthHandlers(), async (req: Request, res: Response) => {
await apiLogins.expireApiKey(req.user!.apiKey); await apiLogins.expireApiKey(req.user!.apiKey);
return ok(res); return ok(res);
}); });
// API route to refresh the given API token's expiry time // API route to refresh the given API token's expiry time
// The actual refreshing happens in the api-token passport strategy above, so we just return 200 OK here // The actual refreshing happens in the api-token passport strategy above, so we just return 200 OK here
app.post("/auth/refresh", ...apiTokenAuthHandlers(), (req, res) => { router.post("/auth/refresh", ...apiTokenAuthHandlers(), (req, res) => {
return ok(res); return ok(res);
}); });
} }

View file

@ -97,10 +97,10 @@ function formatZodConfigSchema(schema: z.ZodTypeAny) {
return "unknown"; return "unknown";
} }
export function initDocs(app: express.Express) { export function initDocs(router: express.Router) {
const docsPluginNames = Object.keys(guildPluginInfo).filter((k) => guildPluginInfo[k].showInDocs); const docsPluginNames = Object.keys(guildPluginInfo).filter((k) => guildPluginInfo[k].showInDocs);
app.get("/docs/plugins", (req: express.Request, res: express.Response) => { router.get("/docs/plugins", (req: express.Request, res: express.Response) => {
res.json( res.json(
docsPluginNames.map((pluginName) => { docsPluginNames.map((pluginName) => {
const info = guildPluginInfo[pluginName]; const info = guildPluginInfo[pluginName];
@ -113,7 +113,7 @@ export function initDocs(app: express.Express) {
); );
}); });
app.get("/docs/plugins/:pluginName", (req: express.Request, res: express.Response) => { router.get("/docs/plugins/:pluginName", (req: express.Request, res: express.Response) => {
const name = req.params.pluginName; const name = req.params.pluginName;
const baseInfo = guildPluginInfo[name]; const baseInfo = guildPluginInfo[name];
if (!baseInfo) { if (!baseInfo) {

View file

@ -3,12 +3,12 @@ import { apiTokenAuthHandlers } from "../auth";
import { initGuildsImportExportAPI } from "./importExport"; import { initGuildsImportExportAPI } from "./importExport";
import { initGuildsMiscAPI } from "./misc"; import { initGuildsMiscAPI } from "./misc";
export function initGuildsAPI(app: express.Express) { export function initGuildsAPI(router: express.Router) {
const guildRouter = express.Router(); const guildRouter = express.Router();
guildRouter.use(...apiTokenAuthHandlers()); guildRouter.use(...apiTokenAuthHandlers());
initGuildsMiscAPI(guildRouter); initGuildsMiscAPI(guildRouter);
initGuildsImportExportAPI(guildRouter); initGuildsImportExportAPI(guildRouter);
app.use("/guilds", guildRouter); router.use("/guilds", guildRouter);
} }

View file

@ -10,6 +10,8 @@ import { initGuildsAPI } from "./guilds/index";
import { clientError, error, notFound } from "./responses"; import { clientError, error, notFound } from "./responses";
import { startBackgroundTasks } from "./tasks"; import { startBackgroundTasks } from "./tasks";
const apiPathPrefix = env.HOST_MODE === "lightweight" ? env.LIGHTWEIGHT_API_PATH_PREFIX || "" : "/api";
const app = express(); const app = express();
app.use( app.use(
@ -24,16 +26,20 @@ app.use(
); );
app.use(multer().none()); app.use(multer().none());
const rootRouter = express.Router();
initAuth(app); initAuth(app);
initGuildsAPI(app); initGuildsAPI(app);
initArchives(app); initArchives(app);
initDocs(app); initDocs(app);
// Default route // Default route
app.get("/", (req, res) => { rootRouter.get("/", (req, res) => {
res.json({ status: "cookies", with: "milk" }); res.json({ status: "cookies", with: "milk" });
}); });
app.use(apiPathPrefix, rootRouter);
// Error response // Error response
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
app.use((err, req, res, next) => { app.use((err, req, res, next) => {

View file

@ -47,6 +47,8 @@ const envType = z.object({
LIGHTWEIGHT_DB_PASSWORD: z.string().optional(), LIGHTWEIGHT_DB_PASSWORD: z.string().optional(),
LIGHTWEIGHT_DB_DATABASE: z.string().optional(), LIGHTWEIGHT_DB_DATABASE: z.string().optional(),
LIGHTWEIGHT_API_PATH_PREFIX: z.string().optional(),
HOST_MODE: z.enum(["development", "standalone", "lightweight"]).optional().default("lightweight"), HOST_MODE: z.enum(["development", "standalone", "lightweight"]).optional().default("lightweight"),
DEBUG: z DEBUG: z
.string() .string()

View file

@ -15,9 +15,6 @@ server {
} }
location /api { location /api {
# Remove /api/ from the beginning when passing the path to the API process
rewrite /api(/.*)$ $1 break;
resolver 127.0.0.11; resolver 127.0.0.11;
proxy_pass $backend_upstream$uri$is_args$args; proxy_pass $backend_upstream$uri$is_args$args;
proxy_redirect off; proxy_redirect off;

View file

@ -15,9 +15,6 @@ server {
} }
location /api { location /api {
# Remove /api/ from the beginning when passing the path to the API process
rewrite /api(/.*)$ $1 break;
resolver 127.0.0.11; resolver 127.0.0.11;
proxy_pass $backend_upstream$uri$is_args$args; proxy_pass $backend_upstream$uri$is_args$args;
proxy_redirect off; proxy_redirect off;