diff --git a/package-lock.json b/package-lock.json index 5591f4b4..867ebf51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,11 @@ "@node-rs/argon2": "1.8.3", "axios": "1.7.7", "better-sqlite3": "11.3.0", + "cookie-parser": "1.4.6", "cors": "2.8.5", "drizzle-orm": "0.33.0", "express": "4.21.0", + "express-rate-limit": "7.4.0", "helmet": "7.1.0", "http-errors": "2.0.0", "lucia": "3.2.0", @@ -29,6 +31,7 @@ "devDependencies": { "@dotenvx/dotenvx": "1.14.2", "@types/better-sqlite3": "7.6.11", + "@types/cookie-parser": "1.4.7", "@types/cors": "2.8.17", "@types/express": "5.0.0", "@types/node": "^20", @@ -5865,6 +5868,15 @@ "@types/node": "*" } }, + "node_modules/@types/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-Fvuyi354Z+uayxzIGCwYTayFKocfV7TuDYZClCdIP9ckhvAu/ixDtCB6qx2TT0FKjPLf1f3P/J1rgf6lPs64mw==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", @@ -7630,6 +7642,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -9355,6 +9387,20 @@ "node": ">= 0.10.0" } }, + "node_modules/express-rate-limit": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.4.0.tgz", + "integrity": "sha512-v1204w3cXu5gCDmAvgvzI6qjzZzoMWKnyVDk3ACgfswTQLYiGen+r8w0VnXnGMmzEN/g8fwIQ4JrFFd4ZP6ssg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "4 || 5 || ^5.0.0-beta.1" + } + }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", diff --git a/package.json b/package.json index d369bcac..f36ffbba 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "dev": "dotenvx run -- tsx watch server/index.ts", "db:generate": "drizzle-kit generate", - "db:push": "npx tsx scripts/migrate.ts", + "db:push": "npx tsx db/migrate.ts", "db:hydrate": "npx tsx scripts/hydrate.ts", "db:studio": "drizzle-kit studio", "build": "next build && tsc --project tsconfig.server.json && tsc-alias -p tsconfig.server.json", @@ -16,9 +16,11 @@ "@node-rs/argon2": "1.8.3", "axios": "1.7.7", "better-sqlite3": "11.3.0", + "cookie-parser": "1.4.6", "cors": "2.8.5", "drizzle-orm": "0.33.0", "express": "4.21.0", + "express-rate-limit": "7.4.0", "helmet": "7.1.0", "http-errors": "2.0.0", "lucia": "3.2.0", @@ -33,6 +35,7 @@ "devDependencies": { "@dotenvx/dotenvx": "1.14.2", "@types/better-sqlite3": "7.6.11", + "@types/cookie-parser": "1.4.7", "@types/cors": "2.8.17", "@types/express": "5.0.0", "@types/node": "^20", diff --git a/server/auth/index.ts b/server/auth/index.ts index adee29c9..06eb6baa 100644 --- a/server/auth/index.ts +++ b/server/auth/index.ts @@ -9,7 +9,7 @@ const adapter = new DrizzleSQLiteAdapter(db, sessions, users); export const lucia = new Lucia(adapter, { getUserAttributes: (attributes) => { return { - username: attributes.username, + email: attributes.email, }; }, // getSessionAttributes: (attributes) => { @@ -19,7 +19,7 @@ export const lucia = new Lucia(adapter, { // }, sessionCookie: { name: "session", - expires: false, // session cookies have very long lifespan (2 years) + expires: false, attributes: { secure: environment.ENVIRONMENT === "prod", sameSite: "strict", @@ -31,7 +31,6 @@ export const lucia = new Lucia(adapter, { export default lucia; -// IMPORTANT! declare module "lucia" { interface Register { Lucia: typeof lucia; @@ -41,7 +40,7 @@ declare module "lucia" { } interface DatabaseUserAttributes { - username: string; + email: string; passwordHash: string; } diff --git a/scripts/migrate.ts b/server/db/migrate.ts similarity index 100% rename from scripts/migrate.ts rename to server/db/migrate.ts diff --git a/server/index.ts b/server/index.ts index b327d097..d1dae8a9 100644 --- a/server/index.ts +++ b/server/index.ts @@ -5,46 +5,60 @@ import environment from "@server/environment"; import logger from "@server/logger"; import helmet from "helmet"; import cors from "cors"; +import { + errorHandlerMiddleware, + rateLimitMiddleware, +} from "@server/middlewares"; import internal from "@server/routers/internal"; -import external from "@server/routers/external"; -import notFoundMiddleware from "./middlewares/notFound"; -import { errorHandlerMiddleware } from "./middlewares/formatError"; +import { authenticated, unauthenticated } from "@server/routers/external"; +import cookieParser from "cookie-parser"; const dev = environment.ENVIRONMENT !== "prod"; + const app = next({ dev }); const handle = app.getRequestHandler(); -const mainPort = environment.EXTERNAL_PORT; + +const externalPort = environment.EXTERNAL_PORT; const internalPort = environment.INTERNAL_PORT; app.prepare().then(() => { - // Main server - const mainServer = express(); - mainServer.use(helmet()); - mainServer.use(cors()); + // External server + const externalServer = express(); + + externalServer.use(helmet()); + externalServer.use(cors()); + externalServer.use(cookieParser()); + externalServer.use(express.json()); + externalServer.use(rateLimitMiddleware); const prefix = `/api/v1`; - mainServer.use(prefix, express.json(), external); + externalServer.use(prefix, unauthenticated); + externalServer.use(prefix, authenticated); // We are using NEXT from here on - mainServer.all("*", (req: Request, res: Response) => { + externalServer.all("*", (req: Request, res: Response) => { const parsedUrl = parse(req.url!, true); handle(req, res, parsedUrl); }); - mainServer.listen(mainPort, (err?: any) => { + externalServer.listen(externalPort, (err?: any) => { if (err) throw err; - logger.info(`Main server is running on http://localhost:${mainPort}`); + logger.info( + `Main server is running on http://localhost:${externalPort}`, + ); }); - mainServer.use(notFoundMiddleware); - mainServer.use(errorHandlerMiddleware); + externalServer.use(errorHandlerMiddleware); // Internal server const internalServer = express(); + internalServer.use(helmet()); internalServer.use(cors()); + internalServer.use(cookieParser()); + internalServer.use(express.json()); - internalServer.use(prefix, express.json(), internal); + internalServer.use(prefix, internal); internalServer.listen(internalPort, (err?: any) => { if (err) throw err; @@ -53,7 +67,3 @@ app.prepare().then(() => { ); }); }); - -process.on("SIGINT", () => { - process.exit(0); -}); diff --git a/server/middlewares/formatError.ts b/server/middlewares/formatError.ts index f653345a..b59d2c6f 100644 --- a/server/middlewares/formatError.ts +++ b/server/middlewares/formatError.ts @@ -10,7 +10,6 @@ export const errorHandlerMiddleware: ErrorRequestHandler = ( res: Response, next: NextFunction, ) => { - logger.error(error); const statusCode = error.statusCode || HttpCode.INTERNAL_SERVER_ERROR; res?.status(statusCode).send({ data: null, diff --git a/server/middlewares/index.ts b/server/middlewares/index.ts new file mode 100644 index 00000000..fa3d0805 --- /dev/null +++ b/server/middlewares/index.ts @@ -0,0 +1,3 @@ +export * from "./notFound"; +export * from "./rateLimit"; +export * from "./formatError"; diff --git a/server/middlewares/rateLimit.ts b/server/middlewares/rateLimit.ts new file mode 100644 index 00000000..69e3a8cf --- /dev/null +++ b/server/middlewares/rateLimit.ts @@ -0,0 +1,20 @@ +import { rateLimit } from "express-rate-limit"; +import createHttpError from "http-errors"; +import { NextFunction, Request, Response } from "express"; +import logger from "@server/logger"; +import HttpCode from "@server/types/HttpCode"; + +const limit = 100; +const minutes = 1; + +export const rateLimitMiddleware = rateLimit({ + windowMs: minutes * 60 * 1000, + limit, + handler: (req: Request, res: Response, next: NextFunction) => { + const message = `Rate limit exceeded. You can make ${limit} requests every ${minutes} minute(s).`; + logger.warn(`Rate limit exceeded for IP ${req.ip}`); + return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message)); + }, +}); + +export default rateLimitMiddleware; diff --git a/server/routers/auth/index.ts b/server/routers/auth/index.ts new file mode 100644 index 00000000..30490028 --- /dev/null +++ b/server/routers/auth/index.ts @@ -0,0 +1,2 @@ +export * from "./login"; +export * from "./signup"; diff --git a/server/auth/login.ts b/server/routers/auth/login.ts similarity index 78% rename from server/auth/login.ts rename to server/routers/auth/login.ts index 7f5dc763..417b833a 100644 --- a/server/auth/login.ts +++ b/server/routers/auth/login.ts @@ -2,6 +2,7 @@ import { verify } from "@node-rs/argon2"; import lucia from "@server/auth"; import db from "@server/db"; import { users } from "@server/db/schema"; +import logger from "@server/logger"; import HttpCode from "@server/types/HttpCode"; import response from "@server/utils/response"; import { eq } from "drizzle-orm"; @@ -15,7 +16,11 @@ export const loginBodySchema = z.object({ password: z.string(), }); -export async function login(req: Request, res: Response, next: NextFunction) { +export async function login( + req: Request, + res: Response, + next: NextFunction, +): Promise { const parsedBody = loginBodySchema.safeParse(req.body); if (!parsedBody.success) { @@ -29,6 +34,20 @@ export async function login(req: Request, res: Response, next: NextFunction) { const { email, password } = parsedBody.data; + const sessionId = req.cookies[lucia.sessionCookieName]; + const { session: existingSession } = await lucia.validateSession(sessionId); + if (existingSession) { + return res.status(HttpCode.OK).send( + response({ + data: null, + success: true, + error: false, + message: "Already logged in", + status: HttpCode.OK, + }), + ); + } + const existingUserRes = await db .select() .from(users) diff --git a/server/auth/signup.ts b/server/routers/auth/signup.ts similarity index 98% rename from server/auth/signup.ts rename to server/routers/auth/signup.ts index 9fd879aa..2a4a7f35 100644 --- a/server/auth/signup.ts +++ b/server/routers/auth/signup.ts @@ -28,7 +28,7 @@ export const signupBodySchema = z.object({ export type SignUpBody = z.infer; -export async function signup(req: Request, res: Response, next: NextFunction) { +export async function signup(req: Request, res: Response, next: NextFunction): Promise { const parsedBody = signupBodySchema.safeParse(req.body); if (!parsedBody.success) { diff --git a/server/routers/badger/badger.ts b/server/routers/badger/badger.ts deleted file mode 100644 index 33666ae7..00000000 --- a/server/routers/badger/badger.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Router } from "express"; - -const badger = Router(); - -badger.get("/", (_, res) => { - res.status(200).json({ message: "Healthy" }); -}); - -export default badger; diff --git a/server/routers/external.ts b/server/routers/external.ts index 1dfecf8b..edfdd891 100644 --- a/server/routers/external.ts +++ b/server/routers/external.ts @@ -1,17 +1,48 @@ import { Router } from "express"; -import gerbil from "./gerbil/gerbil"; -import pangolin from "./pangolin/pangolin"; -import global from "./global/global"; +import * as site from "./site"; +import * as org from "./org"; +import * as resource from "./resource"; +import * as target from "./target"; +import * as user from "./user"; +import * as auth from "./auth"; +import HttpCode from "@server/types/HttpCode"; -const unauth = Router(); +// Root routes +export const unauthenticated = Router(); -unauth.get("/", (_, res) => { - res.status(200).json({ message: "Healthy" }); +unauthenticated.get("/", (_, res) => { + res.status(HttpCode.OK).json({ message: "Healthy" }); }); -unauth.use("/newt", gerbil); -unauth.use("/pangolin", pangolin); +// Authenticated Root routes +export const authenticated = Router(); -unauth.use("/", global) +authenticated.put("/site", site.createSite); +authenticated.get("/site/:siteId", site.getSite); +authenticated.post("/site/:siteId", site.updateSite); +authenticated.delete("/site/:siteId", site.deleteSite); -export default unauth; +authenticated.put("/org", org.createOrg); +authenticated.get("/org/:orgId", org.getOrg); +authenticated.post("/org/:orgId", org.updateOrg); +authenticated.delete("/org/:orgId", org.deleteOrg); + +authenticated.put("/resource", resource.createResource); +authenticated.get("/resource/:resourceId", resource.getResource); +authenticated.post("/resource/:resourceId", resource.updateResource); +authenticated.delete("/resource/:resourceId", resource.deleteResource); + +authenticated.put("/target", target.createTarget); +authenticated.get("/target/:targetId", target.getTarget); +authenticated.post("/target/:targetId", target.updateTarget); +authenticated.delete("/target/:targetId", target.deleteTarget); + +authenticated.get("/user/:userId", user.getUser); +authenticated.delete("/user/:userId", user.deleteUser); + +// Auth routes +const authRouter = Router(); +unauthenticated.use("/auth", authRouter); + +authRouter.put("/signup", auth.signup); +authRouter.post("/login", auth.login); diff --git a/server/routers/gerbil/gerbil.ts b/server/routers/gerbil/gerbil.ts deleted file mode 100644 index 66af3a2f..00000000 --- a/server/routers/gerbil/gerbil.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Router } from "express"; -import { getConfig } from "./getConfig"; -import { receiveBandwidth } from "./receiveBandwidth"; - -const gerbil = Router(); - -gerbil.get("/", (_, res) => { - res.status(200).json({ message: "Healthy" }); -}); - -gerbil.get("/get-config", getConfig); -gerbil.post("/receive-bandwidth", receiveBandwidth); - -export default gerbil; diff --git a/server/routers/gerbil/index.ts b/server/routers/gerbil/index.ts new file mode 100644 index 00000000..82f82c4c --- /dev/null +++ b/server/routers/gerbil/index.ts @@ -0,0 +1,2 @@ +export * from "./getConfig"; +export * from "./receiveBandwidth"; diff --git a/server/routers/global/global.ts b/server/routers/global/global.ts deleted file mode 100644 index 08c3bb19..00000000 --- a/server/routers/global/global.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Router } from "express"; -import { signup } from "@server/auth/signup"; -import { login } from "@server/auth/login"; -import { getSite } from "./site/getSite"; -import { createSite } from "./site/createSite"; -import { updateSite } from "./site/updateSite"; -import { deleteSite } from "./site/deleteSite"; -import { getOrg } from "./org/getOrg"; -import { createOrg } from "./org/createOrg"; -import { updateOrg } from "./org/updateOrg"; -import { deleteOrg } from "./org/deleteOrg"; -import { getResource } from "./resource/getResource"; -import { createResource } from "./resource/createResource"; -import { updateResource } from "./resource/updateResource"; -import { deleteResource } from "./resource/deleteResource"; -import { getTarget } from "./target/getTarget"; -import { createTarget } from "./target/createTarget"; -import { updateTarget } from "./target/updateTarget"; -import { deleteTarget } from "./target/deleteTarget"; -import { getUser } from "./user/getUser"; -import { createUser } from "./user/createUser"; -import { updateUser } from "./user/updateUser"; -import { deleteUser } from "./user/deleteUser"; - -const global = Router(); - -global.get("/", (_, res) => { - res.status(200).json({ message: "Healthy" }); -}); - -global.put("/site", createSite); -global.get("/site/:siteId", getSite); -global.post("/site/:siteId", updateSite); -global.delete("/site/:siteId", deleteSite); - -global.put("/org", createOrg); -global.get("/org/:orgId", getOrg); -global.post("/org/:orgId", updateOrg); -global.delete("/org/:orgId", deleteOrg); - -global.put("/resource", createResource); -global.get("/resource/resourceId", getResource); -global.post("/resource/resourceId", updateResource); -global.delete("/resource/resourceId", deleteResource); - -global.put("/target", createTarget); -global.get("/target/:targetId", getTarget); -global.post("/target/:targetId", updateTarget); -global.delete("/target/:targetId", deleteTarget); - -global.get("/user/:userId", getUser); -global.delete("/user/:userId", deleteUser); - -// auth -global.post("/signup", signup); -global.post("/login", login); - -export default global; diff --git a/server/routers/internal.ts b/server/routers/internal.ts index d6341b98..63e35dc2 100644 --- a/server/routers/internal.ts +++ b/server/routers/internal.ts @@ -1,17 +1,23 @@ import { Router } from "express"; -import gerbil from "./gerbil/gerbil"; -import badger from "./badger/badger"; -import { traefikConfigProvider } from "@server/traefik-config-provider"; +import * as gerbil from "@server/routers/gerbil"; +import * as traefik from "@server/routers/traefik"; +import HttpCode from "@server/types/HttpCode"; -const unauth = Router(); +// Root routes +const internalRouter = Router(); -unauth.get("/", (_, res) => { - res.status(200).json({ message: "Healthy" }); +internalRouter.get("/", (_, res) => { + res.status(HttpCode.OK).json({ message: "Healthy" }); }); -unauth.use("/badger", badger); -unauth.use("/gerbil", gerbil); +internalRouter.get("/traefik-config", traefik.traefikConfigProvider); -unauth.get("/traefik-config-provider", traefikConfigProvider); +// Gerbil routes +const gerbilRouter = Router(); -export default unauth; +gerbilRouter.get("/get-config", gerbil.getConfig); +gerbilRouter.post("/receive-bandwidth", gerbil.receiveBandwidth); + +internalRouter.use("/gerbil", gerbilRouter); + +export default internalRouter; diff --git a/server/routers/newt/newt.ts b/server/routers/newt/newt.ts deleted file mode 100644 index 71689af2..00000000 --- a/server/routers/newt/newt.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Router } from "express"; - -const newt = Router(); - -newt.get("/", (_, res) => { - res.status(200).json({ message: "Healthy" }); -}); - -export default newt; diff --git a/server/routers/global/org/createOrg.ts b/server/routers/org/createOrg.ts similarity index 97% rename from server/routers/global/org/createOrg.ts rename to server/routers/org/createOrg.ts index ed549d39..ee8ce276 100644 --- a/server/routers/global/org/createOrg.ts +++ b/server/routers/org/createOrg.ts @@ -11,7 +11,7 @@ const createOrgSchema = z.object({ domain: z.string().min(1).max(255), }); -export async function createOrg(req: Request, res: Response, next: NextFunction) { +export async function createOrg(req: Request, res: Response, next: NextFunction): Promise { try { const parsedBody = createOrgSchema.safeParse(req.body); if (!parsedBody.success) { @@ -42,4 +42,4 @@ export async function createOrg(req: Request, res: Response, next: NextFunction) } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/org/deleteOrg.ts b/server/routers/org/deleteOrg.ts similarity index 97% rename from server/routers/global/org/deleteOrg.ts rename to server/routers/org/deleteOrg.ts index 6187b5bd..aea15399 100644 --- a/server/routers/global/org/deleteOrg.ts +++ b/server/routers/org/deleteOrg.ts @@ -11,7 +11,7 @@ const deleteOrgSchema = z.object({ orgId: z.string().transform(Number).pipe(z.number().int().positive()) }); -export async function deleteOrg(req: Request, res: Response, next: NextFunction) { +export async function deleteOrg(req: Request, res: Response, next: NextFunction): Promise { try { const parsedParams = deleteOrgSchema.safeParse(req.params); if (!parsedParams.success) { @@ -50,4 +50,4 @@ export async function deleteOrg(req: Request, res: Response, next: NextFunction) } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/org/getOrg.ts b/server/routers/org/getOrg.ts similarity index 97% rename from server/routers/global/org/getOrg.ts rename to server/routers/org/getOrg.ts index e93b70c8..acd81ef7 100644 --- a/server/routers/global/org/getOrg.ts +++ b/server/routers/org/getOrg.ts @@ -11,7 +11,7 @@ const getOrgSchema = z.object({ orgId: z.string().transform(Number).pipe(z.number().int().positive()) }); -export async function getOrg(req: Request, res: Response, next: NextFunction) { +export async function getOrg(req: Request, res: Response, next: NextFunction): Promise { try { const parsedParams = getOrgSchema.safeParse(req.params); if (!parsedParams.success) { @@ -51,4 +51,4 @@ export async function getOrg(req: Request, res: Response, next: NextFunction) { } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/org/index.ts b/server/routers/org/index.ts new file mode 100644 index 00000000..596fc93e --- /dev/null +++ b/server/routers/org/index.ts @@ -0,0 +1,4 @@ +export * from "./getOrg"; +export * from "./createOrg"; +export * from "./deleteOrg"; +export * from "./updateOrg"; diff --git a/server/routers/global/org/updateOrg.ts b/server/routers/org/updateOrg.ts similarity index 98% rename from server/routers/global/org/updateOrg.ts rename to server/routers/org/updateOrg.ts index 49b3397e..2311b412 100644 --- a/server/routers/global/org/updateOrg.ts +++ b/server/routers/org/updateOrg.ts @@ -18,7 +18,7 @@ const updateOrgBodySchema = z.object({ message: "At least one field must be provided for update" }); -export async function updateOrg(req: Request, res: Response, next: NextFunction) { +export async function updateOrg(req: Request, res: Response, next: NextFunction): Promise { try { const parsedParams = updateOrgParamsSchema.safeParse(req.params); if (!parsedParams.success) { @@ -69,4 +69,4 @@ export async function updateOrg(req: Request, res: Response, next: NextFunction) } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/pangolin/pangolin.ts b/server/routers/pangolin/pangolin.ts deleted file mode 100644 index 072d6f29..00000000 --- a/server/routers/pangolin/pangolin.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Router } from "express"; - -const pangolin = Router(); - -pangolin.get("/", (_, res) => { - res.status(200).json({ message: "Healthy" }); -}); - -export default pangolin; diff --git a/server/routers/global/resource/createResource.ts b/server/routers/resource/createResource.ts similarity index 97% rename from server/routers/global/resource/createResource.ts rename to server/routers/resource/createResource.ts index e3544520..1c45f620 100644 --- a/server/routers/global/resource/createResource.ts +++ b/server/routers/resource/createResource.ts @@ -13,7 +13,7 @@ const createResourceSchema = z.object({ subdomain: z.string().min(1).max(255).optional(), }); -export async function createResource(req: Request, res: Response, next: NextFunction) { +export async function createResource(req: Request, res: Response, next: NextFunction): Promise { try { // Validate request body const parsedBody = createResourceSchema.safeParse(req.body); @@ -51,4 +51,4 @@ export async function createResource(req: Request, res: Response, next: NextFunc } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/resource/deleteResource.ts b/server/routers/resource/deleteResource.ts similarity index 97% rename from server/routers/global/resource/deleteResource.ts rename to server/routers/resource/deleteResource.ts index 186979a1..dbc11c00 100644 --- a/server/routers/global/resource/deleteResource.ts +++ b/server/routers/resource/deleteResource.ts @@ -12,7 +12,7 @@ const deleteResourceSchema = z.object({ resourceId: z.string().uuid() }); -export async function deleteResource(req: Request, res: Response, next: NextFunction) { +export async function deleteResource(req: Request, res: Response, next: NextFunction): Promise { try { // Validate request parameters const parsedParams = deleteResourceSchema.safeParse(req.params); @@ -53,4 +53,4 @@ export async function deleteResource(req: Request, res: Response, next: NextFunc } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/resource/getResource.ts b/server/routers/resource/getResource.ts similarity index 97% rename from server/routers/global/resource/getResource.ts rename to server/routers/resource/getResource.ts index 3473a42c..58decd69 100644 --- a/server/routers/global/resource/getResource.ts +++ b/server/routers/resource/getResource.ts @@ -12,7 +12,7 @@ const getResourceSchema = z.object({ resourceId: z.string().uuid() }); -export async function getResource(req: Request, res: Response, next: NextFunction) { +export async function getResource(req: Request, res: Response, next: NextFunction): Promise { try { // Validate request parameters const parsedParams = getResourceSchema.safeParse(req.params); @@ -54,4 +54,4 @@ export async function getResource(req: Request, res: Response, next: NextFunctio } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/resource/index.ts b/server/routers/resource/index.ts new file mode 100644 index 00000000..2192284f --- /dev/null +++ b/server/routers/resource/index.ts @@ -0,0 +1,4 @@ +export * from "./getResource"; +export * from "./createResource"; +export * from "./deleteResource"; +export * from "./updateResource"; diff --git a/server/routers/global/resource/updateResource.ts b/server/routers/resource/updateResource.ts similarity index 98% rename from server/routers/global/resource/updateResource.ts rename to server/routers/resource/updateResource.ts index 8c30c9da..09b6486f 100644 --- a/server/routers/global/resource/updateResource.ts +++ b/server/routers/resource/updateResource.ts @@ -20,7 +20,7 @@ const updateResourceBodySchema = z.object({ message: "At least one field must be provided for update" }); -export async function updateResource(req: Request, res: Response, next: NextFunction) { +export async function updateResource(req: Request, res: Response, next: NextFunction): Promise { try { // Validate request parameters const parsedParams = updateResourceParamsSchema.safeParse(req.params); @@ -74,4 +74,4 @@ export async function updateResource(req: Request, res: Response, next: NextFunc } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/site/createSite.ts b/server/routers/site/createSite.ts similarity index 93% rename from server/routers/global/site/createSite.ts rename to server/routers/site/createSite.ts index 81a639f9..e0bd06dd 100644 --- a/server/routers/global/site/createSite.ts +++ b/server/routers/site/createSite.ts @@ -4,7 +4,7 @@ import HttpCode from '@server/types/HttpCode'; // define zod type here -export async function createSite(req: Request, res: Response, next: NextFunction) { +export async function createSite(req: Request, res: Response, next: NextFunction): Promise { return res.status(HttpCode.OK).send( response({ data: null, diff --git a/server/routers/global/site/deleteSite.ts b/server/routers/site/deleteSite.ts similarity index 97% rename from server/routers/global/site/deleteSite.ts rename to server/routers/site/deleteSite.ts index 61e6e3a4..a982169d 100644 --- a/server/routers/global/site/deleteSite.ts +++ b/server/routers/site/deleteSite.ts @@ -12,7 +12,7 @@ const deleteSiteSchema = z.object({ siteId: z.string().transform(Number).pipe(z.number().int().positive()) }); -export async function deleteSite(req: Request, res: Response, next: NextFunction) { +export async function deleteSite(req: Request, res: Response, next: NextFunction): Promise { try { // Validate request parameters const parsedParams = deleteSiteSchema.safeParse(req.params); @@ -53,4 +53,4 @@ export async function deleteSite(req: Request, res: Response, next: NextFunction } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/site/getSite.ts b/server/routers/site/getSite.ts similarity index 97% rename from server/routers/global/site/getSite.ts rename to server/routers/site/getSite.ts index 408a8794..2049a888 100644 --- a/server/routers/global/site/getSite.ts +++ b/server/routers/site/getSite.ts @@ -12,7 +12,7 @@ const getSiteSchema = z.object({ siteId: z.string().transform(Number).pipe(z.number().int().positive()) }); -export async function getSite(req: Request, res: Response, next: NextFunction) { +export async function getSite(req: Request, res: Response, next: NextFunction): Promise { try { // Validate request parameters const parsedParams = getSiteSchema.safeParse(req.params); @@ -54,4 +54,4 @@ export async function getSite(req: Request, res: Response, next: NextFunction) { } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/site/index.ts b/server/routers/site/index.ts new file mode 100644 index 00000000..2e7db75c --- /dev/null +++ b/server/routers/site/index.ts @@ -0,0 +1,4 @@ +export * from "./getSite"; +export * from "./createSite"; +export * from "./deleteSite"; +export * from "./updateSite"; diff --git a/server/routers/global/site/updateSite.ts b/server/routers/site/updateSite.ts similarity index 98% rename from server/routers/global/site/updateSite.ts rename to server/routers/site/updateSite.ts index c21e8af8..e32a9d8f 100644 --- a/server/routers/global/site/updateSite.ts +++ b/server/routers/site/updateSite.ts @@ -25,7 +25,7 @@ const updateSiteBodySchema = z.object({ message: "At least one field must be provided for update" }); -export async function updateSite(req: Request, res: Response, next: NextFunction) { +export async function updateSite(req: Request, res: Response, next: NextFunction): Promise { try { // Validate request parameters const parsedParams = updateSiteParamsSchema.safeParse(req.params); @@ -79,4 +79,4 @@ export async function updateSite(req: Request, res: Response, next: NextFunction } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/target/createTarget.ts b/server/routers/target/createTarget.ts similarity index 97% rename from server/routers/global/target/createTarget.ts rename to server/routers/target/createTarget.ts index af6a68d8..c51caf93 100644 --- a/server/routers/global/target/createTarget.ts +++ b/server/routers/target/createTarget.ts @@ -15,7 +15,7 @@ const createTargetSchema = z.object({ enabled: z.boolean().default(true), }); -export async function createTarget(req: Request, res: Response, next: NextFunction) { +export async function createTarget(req: Request, res: Response, next: NextFunction): Promise { try { const parsedBody = createTargetSchema.safeParse(req.body); if (!parsedBody.success) { @@ -43,4 +43,4 @@ export async function createTarget(req: Request, res: Response, next: NextFuncti } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/target/deleteTarget.ts b/server/routers/target/deleteTarget.ts similarity index 97% rename from server/routers/global/target/deleteTarget.ts rename to server/routers/target/deleteTarget.ts index 8150d60c..934a8c00 100644 --- a/server/routers/global/target/deleteTarget.ts +++ b/server/routers/target/deleteTarget.ts @@ -11,7 +11,7 @@ const deleteTargetSchema = z.object({ targetId: z.string().transform(Number).pipe(z.number().int().positive()) }); -export async function deleteTarget(req: Request, res: Response, next: NextFunction) { +export async function deleteTarget(req: Request, res: Response, next: NextFunction): Promise { try { const parsedParams = deleteTargetSchema.safeParse(req.params); if (!parsedParams.success) { @@ -50,4 +50,4 @@ export async function deleteTarget(req: Request, res: Response, next: NextFuncti } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/target/getTarget.ts b/server/routers/target/getTarget.ts similarity index 97% rename from server/routers/global/target/getTarget.ts rename to server/routers/target/getTarget.ts index 14a39a5b..918dc8a7 100644 --- a/server/routers/global/target/getTarget.ts +++ b/server/routers/target/getTarget.ts @@ -11,7 +11,7 @@ const getTargetSchema = z.object({ targetId: z.string().transform(Number).pipe(z.number().int().positive()) }); -export async function getTarget(req: Request, res: Response, next: NextFunction) { +export async function getTarget(req: Request, res: Response, next: NextFunction): Promise { try { const parsedParams = getTargetSchema.safeParse(req.params); if (!parsedParams.success) { @@ -51,4 +51,4 @@ export async function getTarget(req: Request, res: Response, next: NextFunction) } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/target/index.ts b/server/routers/target/index.ts new file mode 100644 index 00000000..020f1e6c --- /dev/null +++ b/server/routers/target/index.ts @@ -0,0 +1,4 @@ +export * from "./getTarget"; +export * from "./createTarget"; +export * from "./deleteTarget"; +export * from "./updateTarget"; diff --git a/server/routers/global/target/updateTarget.ts b/server/routers/target/updateTarget.ts similarity index 98% rename from server/routers/global/target/updateTarget.ts rename to server/routers/target/updateTarget.ts index 5ca809be..6b4d1213 100644 --- a/server/routers/global/target/updateTarget.ts +++ b/server/routers/target/updateTarget.ts @@ -21,7 +21,7 @@ const updateTargetBodySchema = z.object({ message: "At least one field must be provided for update" }); -export async function updateTarget(req: Request, res: Response, next: NextFunction) { +export async function updateTarget(req: Request, res: Response, next: NextFunction): Promise { try { const parsedParams = updateTargetParamsSchema.safeParse(req.params); if (!parsedParams.success) { @@ -72,4 +72,4 @@ export async function updateTarget(req: Request, res: Response, next: NextFuncti } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/traefik-config-provider/configSchema.ts b/server/routers/traefik/configSchema.ts similarity index 100% rename from server/traefik-config-provider/configSchema.ts rename to server/routers/traefik/configSchema.ts diff --git a/server/traefik-config-provider/index.ts b/server/routers/traefik/getTraefikConfig.ts similarity index 100% rename from server/traefik-config-provider/index.ts rename to server/routers/traefik/getTraefikConfig.ts diff --git a/server/routers/traefik/index.ts b/server/routers/traefik/index.ts new file mode 100644 index 00000000..0fc483fa --- /dev/null +++ b/server/routers/traefik/index.ts @@ -0,0 +1 @@ +export * from "./getTraefikConfig"; diff --git a/server/routers/global/user/deleteUser.ts b/server/routers/user/deleteUser.ts similarity index 97% rename from server/routers/global/user/deleteUser.ts rename to server/routers/user/deleteUser.ts index 8a3b446d..8d193312 100644 --- a/server/routers/global/user/deleteUser.ts +++ b/server/routers/user/deleteUser.ts @@ -11,7 +11,7 @@ const deleteUserSchema = z.object({ userId: z.string().uuid() }); -export async function deleteUser(req: Request, res: Response, next: NextFunction) { +export async function deleteUser(req: Request, res: Response, next: NextFunction): Promise { try { const parsedParams = deleteUserSchema.safeParse(req.params); if (!parsedParams.success) { @@ -50,4 +50,4 @@ export async function deleteUser(req: Request, res: Response, next: NextFunction } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/global/user/getUser.ts b/server/routers/user/getUser.ts similarity index 97% rename from server/routers/global/user/getUser.ts rename to server/routers/user/getUser.ts index 1b1b47b2..ff98392c 100644 --- a/server/routers/global/user/getUser.ts +++ b/server/routers/user/getUser.ts @@ -11,7 +11,7 @@ const getUserSchema = z.object({ userId: z.string().uuid() }); -export async function getUser(req: Request, res: Response, next: NextFunction) { +export async function getUser(req: Request, res: Response, next: NextFunction): Promise { try { const parsedParams = getUserSchema.safeParse(req.params); if (!parsedParams.success) { @@ -54,4 +54,4 @@ export async function getUser(req: Request, res: Response, next: NextFunction) { } catch (error) { next(error); } -} \ No newline at end of file +} diff --git a/server/routers/user/index.ts b/server/routers/user/index.ts new file mode 100644 index 00000000..d6610fba --- /dev/null +++ b/server/routers/user/index.ts @@ -0,0 +1,2 @@ +export * from "./getUser"; +export * from "./deleteUser";