diff --git a/config.example.yml b/config.example.yml index 5dcab23d..16fd5031 100644 --- a/config.example.yml +++ b/config.example.yml @@ -1,5 +1,4 @@ app: - name: Pangolin base_url: http://localhost:3000 log_level: warning save_logs: false diff --git a/package.json b/package.json index 7e7c4202..bbf562fd 100644 --- a/package.json +++ b/package.json @@ -1,100 +1,100 @@ { - "name": "@fossorial/pangolin", - "version": "0.1.0", - "private": true, - "type": "module", - "scripts": { - "dev": "ENVIRONMENT=dev tsx watch server/index.ts", - "db:generate": "drizzle-kit generate", - "db:push": "npx tsx server/db/migrate.ts", - "db:hydrate": "npx tsx scripts/hydrate.ts", - "db:studio": "drizzle-kit studio", - "build": "mkdir -p dist && next build && node scripts/esbuild.mjs -e server/index.ts -o dist/server.mjs", - "start": "ENVIRONMENT=prod node dist/server.mjs", - "email": "email dev --dir server/emails/templates --port 3002" - }, - "dependencies": { - "@esbuild-plugins/tsconfig-paths": "0.1.2", - "@hookform/resolvers": "3.9.0", - "@node-rs/argon2": "1.8.3", - "@oslojs/crypto": "1.0.1", - "@oslojs/encoding": "1.1.0", - "@radix-ui/react-avatar": "1.1.1", - "@radix-ui/react-checkbox": "1.1.2", - "@radix-ui/react-dialog": "1.1.2", - "@radix-ui/react-dropdown-menu": "2.1.2", - "@radix-ui/react-icons": "1.3.0", - "@radix-ui/react-label": "2.1.0", - "@radix-ui/react-popover": "1.1.2", - "@radix-ui/react-radio-group": "1.2.1", - "@radix-ui/react-select": "2.1.2", - "@radix-ui/react-separator": "1.1.0", - "@radix-ui/react-slot": "1.1.0", - "@radix-ui/react-switch": "1.1.1", - "@radix-ui/react-toast": "1.2.2", - "@react-email/components": "0.0.25", - "@react-email/tailwind": "0.1.0", - "@tanstack/react-table": "8.20.5", - "axios": "1.7.7", - "better-sqlite3": "11.3.0", - "class-variance-authority": "0.7.0", - "clsx": "2.1.1", - "cmdk": "1.0.0", - "cookie-parser": "1.4.6", - "cors": "2.8.5", - "drizzle-orm": "0.33.0", - "esbuild": "0.20.1", - "esbuild-node-externals": "1.13.0", - "express": "4.21.0", - "express-rate-limit": "7.4.0", - "glob": "11.0.0", - "helmet": "7.1.0", - "http-errors": "2.0.0", - "input-otp": "1.2.4", - "js-yaml": "4.1.0", - "lucide-react": "0.447.0", - "moment": "2.30.1", - "next": "15.0.1", - "next-themes": "0.3.0", - "node-fetch": "3.3.2", - "nodemailer": "6.9.15", - "oslo": "1.2.1", - "react": "19.0.0-rc-69d4b800-20241021", - "react-dom": "19.0.0-rc-69d4b800-20241021", - "react-hook-form": "7.53.0", - "rebuild": "0.1.2", - "tailwind-merge": "2.5.3", - "tailwindcss-animate": "1.0.7", - "winston": "3.14.2", - "winston-daily-rotate-file": "5.0.0", - "yargs": "17.7.2", - "zod": "3.23.8", - "zod-validation-error": "3.4.0" - }, - "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/js-yaml": "4.0.9", - "@types/node": "^20", - "@types/nodemailer": "6.4.16", - "@types/react": "npm:types-react@19.0.0-rc.1", - "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", - "@types/yargs": "17.0.33", - "drizzle-kit": "0.24.2", - "eslint": "^8", - "eslint-config-next": "15.0.1", - "postcss": "^8", - "react-email": "3.0.1", - "tailwindcss": "^3.4.1", - "tsc-alias": "1.8.10", - "tsx": "4.19.1", - "typescript": "^5" - }, - "overrides": { - "@types/react": "npm:types-react@19.0.0-rc.1", - "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" - } + "name": "@fossorial/pangolin", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "ENVIRONMENT=dev tsx watch server/index.ts", + "db:generate": "drizzle-kit generate", + "db:push": "npx tsx server/db/migrate.ts", + "db:hydrate": "npx tsx scripts/hydrate.ts", + "db:studio": "drizzle-kit studio", + "build": "mkdir -p dist && next build && node scripts/esbuild.mjs -e server/index.ts -o dist/server.mjs", + "start": "ENVIRONMENT=prod node dist/server.mjs", + "email": "email dev --dir server/emails/templates --port 3002" + }, + "dependencies": { + "@hookform/resolvers": "3.9.0", + "@node-rs/argon2": "1.8.3", + "@oslojs/crypto": "1.0.1", + "@oslojs/encoding": "1.1.0", + "@radix-ui/react-avatar": "1.1.1", + "@radix-ui/react-checkbox": "1.1.2", + "@radix-ui/react-dialog": "1.1.2", + "@radix-ui/react-dropdown-menu": "2.1.2", + "@radix-ui/react-icons": "1.3.0", + "@radix-ui/react-label": "2.1.0", + "@radix-ui/react-popover": "1.1.2", + "@radix-ui/react-radio-group": "1.2.1", + "@radix-ui/react-select": "2.1.2", + "@radix-ui/react-separator": "1.1.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-switch": "1.1.1", + "@radix-ui/react-toast": "1.2.2", + "@react-email/components": "0.0.25", + "@react-email/tailwind": "0.1.0", + "@tanstack/react-table": "8.20.5", + "axios": "1.7.7", + "better-sqlite3": "11.3.0", + "class-variance-authority": "0.7.0", + "clsx": "2.1.1", + "cmdk": "1.0.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", + "glob": "11.0.0", + "helmet": "7.1.0", + "http-errors": "2.0.0", + "input-otp": "1.2.4", + "js-yaml": "4.1.0", + "lucide-react": "0.447.0", + "moment": "2.30.1", + "next": "15.0.1", + "next-themes": "0.3.0", + "node-fetch": "3.3.2", + "nodemailer": "6.9.15", + "oslo": "1.2.1", + "react": "19.0.0-rc-69d4b800-20241021", + "react-dom": "19.0.0-rc-69d4b800-20241021", + "react-hook-form": "7.53.0", + "rebuild": "0.1.2", + "tailwind-merge": "2.5.3", + "tailwindcss-animate": "1.0.7", + "winston": "3.14.2", + "winston-daily-rotate-file": "5.0.0", + "zod": "3.23.8", + "zod-validation-error": "3.4.0" + }, + "devDependencies": { + "esbuild": "0.20.1", + "esbuild-node-externals": "1.13.0", + "yargs": "17.7.2", + "@esbuild-plugins/tsconfig-paths": "0.1.2", + "@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/js-yaml": "4.0.9", + "@types/node": "^20", + "@types/nodemailer": "6.4.16", + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", + "@types/yargs": "17.0.33", + "drizzle-kit": "0.24.2", + "eslint": "^8", + "eslint-config-next": "15.0.1", + "postcss": "^8", + "react-email": "3.0.1", + "tailwindcss": "^3.4.1", + "tsc-alias": "1.8.10", + "tsx": "4.19.1", + "typescript": "^5" + }, + "overrides": { + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" + } } diff --git a/server/index.ts b/server/index.ts index 9bfd1ccc..a327740d 100644 --- a/server/index.ts +++ b/server/index.ts @@ -15,6 +15,7 @@ import { authenticated, unauthenticated } from "@server/routers/external"; import cookieParser from "cookie-parser"; import { User } from "@server/db/schema"; import { ensureActions } from "./db/ensureActions"; +import { logIncomingMiddleware } from "./middlewares/logIncoming"; const dev = process.env.ENVIRONMENT !== "prod"; @@ -25,7 +26,6 @@ const externalPort = config.server.external_port; const internalPort = config.server.internal_port; app.prepare().then(() => { - ensureActions(); // This loads the actions into the database // External server @@ -42,15 +42,18 @@ app.prepare().then(() => { windowMin: config.rate_limit.window_minutes, max: config.rate_limit.max_requests, type: "IP_ONLY", - }), + }) ); } const prefix = `/api/v1`; + if (dev) { + externalServer.use(logIncomingMiddleware); + } externalServer.use(prefix, unauthenticated); externalServer.use(prefix, authenticated); - externalServer.use(notFoundMiddleware) + externalServer.use(notFoundMiddleware); // We are using NEXT from here on externalServer.all("*", (req: Request, res: Response) => { @@ -61,7 +64,7 @@ app.prepare().then(() => { externalServer.listen(externalPort, (err?: any) => { if (err) throw err; logger.info( - `Main server is running on http://localhost:${externalPort}`, + `Main server is running on http://localhost:${externalPort}` ); }); @@ -80,15 +83,16 @@ app.prepare().then(() => { internalServer.listen(internalPort, (err?: any) => { if (err) throw err; logger.info( - `Internal server is running on http://localhost:${internalPort}`, + `Internal server is running on http://localhost:${internalPort}` ); }); - internalServer.use(notFoundMiddleware) + internalServer.use(notFoundMiddleware); internalServer.use(errorHandlerMiddleware); }); -declare global { // TODO: eventually make seperate types that extend express.Request +declare global { + // TODO: eventually make seperate types that extend express.Request namespace Express { interface Request { user?: User; @@ -97,4 +101,4 @@ declare global { // TODO: eventually make seperate types that extend express.Req userOrgIds?: string[]; } } -} \ No newline at end of file +} diff --git a/server/middlewares/logIncoming.ts b/server/middlewares/logIncoming.ts new file mode 100644 index 00000000..f7284c10 --- /dev/null +++ b/server/middlewares/logIncoming.ts @@ -0,0 +1,14 @@ +import logger from "@server/logger"; +import { NextFunction, Request, Response } from "express"; + +export function logIncomingMiddleware( + req: Request, + res: Response, + next: NextFunction +) { + const { method, url, headers, body } = req; + if (url.includes("/api/v1")) { + logger.debug(`${method} ${url}`); + } + next(); +} diff --git a/server/routers/resource/listResources.ts b/server/routers/resource/listResources.ts index 0fe9de3e..9711327c 100644 --- a/server/routers/resource/listResources.ts +++ b/server/routers/resource/listResources.ts @@ -91,8 +91,6 @@ export async function listResources( next: NextFunction, ): Promise { try { - logger.info(JSON.stringify(req.query, null, 2)); - logger.info(JSON.stringify(req.params, null, 2)); const parsedQuery = listResourcesSchema.safeParse(req.query); if (!parsedQuery.success) { return next(