From 59cdf2253973e302e0ec602d64a35ee56a287588 Mon Sep 17 00:00:00 2001 From: Jasper Mayone Date: Wed, 26 Feb 2025 03:53:46 -0500 Subject: [PATCH 1/3] remove dependency on bcryptjs --- bun.lock | 5 +++++ bunfig.toml | 0 package.json | 5 ++--- src/middleware/logRequest.ts | 21 +++++++++++++------ src/routes/admin/routes/user.ts | 4 +--- src/routes/user.ts | 37 +++++++++------------------------ src/utils/jwt.ts | 6 ------ 7 files changed, 33 insertions(+), 45 deletions(-) create mode 100644 bunfig.toml diff --git a/bun.lock b/bun.lock index 708c642..b205b0f 100644 --- a/bun.lock +++ b/bun.lock @@ -25,6 +25,7 @@ "devDependencies": { "@flydotio/dockerfile": "^0.6.1", "@types/bcrypt": "^5.0.2", + "@types/bun": "^1.2.3", "@types/express": "^4.17.21", "@types/jsonwebtoken": "^9.0.7", "@types/node": "^20.17.10", @@ -191,6 +192,8 @@ "@types/body-parser": ["@types/body-parser@1.19.5", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg=="], + "@types/bun": ["@types/bun@1.2.3", "", { "dependencies": { "bun-types": "1.2.3" } }, "sha512-054h79ipETRfjtsCW9qJK8Ipof67Pw9bodFWmkfkaUaRiIQ1dIV2VTlheshlBx3mpKr0KeK8VqnMMCtgN9rQtw=="], + "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], @@ -725,6 +728,8 @@ "@sveltejs/kit/cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="], + "@types/bun/bun-types": ["bun-types@1.2.3", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-P7AeyTseLKAvgaZqQrvp3RqFM3yN9PlcLuSTe7SoJOfZkER73mLdT2vEQi8U64S1YvM/ldcNiQjn0Sn7H9lGgg=="], + "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json index 59454a8..0a3ee36 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "@playwright/test": "^1.49.1", "@prisma/client": "6.4.1", "axios": "^1.7.9", - "bcrypt": "^5.1.1", "body-parser": "^1.20.3", "colors": "^1.4.0", "dotenv": "^16.4.7", @@ -37,15 +36,15 @@ "ts-node": "^10.9.2" }, "devDependencies": { - "bun-types": "latest", "@flydotio/dockerfile": "^0.6.1", - "@types/bcrypt": "^5.0.2", + "@types/bun": "^1.2.3", "@types/express": "^4.17.21", "@types/jsonwebtoken": "^9.0.7", "@types/node": "^20.17.10", "@types/node-statsd": "^0.1.6", "@types/request-ip": "^0.0.41", "@types/response-time": "^2.3.8", + "bun-types": "latest", "nodemon": "^3.1.9", "prisma": "^6.4.1", "typescript": "^5.7.2" diff --git a/src/middleware/logRequest.ts b/src/middleware/logRequest.ts index 8af0ad3..34ad84e 100644 --- a/src/middleware/logRequest.ts +++ b/src/middleware/logRequest.ts @@ -49,12 +49,21 @@ export const logRequest = async ( if (req.headers.authorization) { const authHeader = req.headers["authorization"]; - const token = authHeader && authHeader.split(" ")[1]; - - if (token !== null && token !== undefined) { - userinfo = await getUserInfo(req); - if (userinfo) { - usr = userinfo.uuid; + // Check if it's a Bearer token with proper JWT format + if (authHeader && authHeader.startsWith("Bearer ")) { + const token = authHeader.split(" ")[1]; + // Basic validation that it looks like a JWT (has two dots) + if (token && token.split(".").length === 3) { + try { + userinfo = await getUserInfo(req); + // Only set usr if userinfo exists AND has a valid uuid + if (userinfo && userinfo.uuid) { + usr = userinfo.uuid; + } + } catch (error) { + // Just log error but continue processing request without setting user values + console.error("Error validating JWT:", error); + } } } } diff --git a/src/routes/admin/routes/user.ts b/src/routes/admin/routes/user.ts index 3b551b9..af885fe 100644 --- a/src/routes/admin/routes/user.ts +++ b/src/routes/admin/routes/user.ts @@ -1,4 +1,3 @@ -import bcrypt from "bcrypt"; import express from "express"; import { ExtendedData } from "@prisma/client"; @@ -218,8 +217,7 @@ router.post("/user/new", async (req, res) => { return; } - const salt = bcrypt.genSaltSync(saltRounds); - let passHash = await bcrypt.hash(password, salt); + let passHash = await Bun.password.hash(password); // Create the user const newUser = await prisma.user.create({ diff --git a/src/routes/user.ts b/src/routes/user.ts index 4eee6ef..1f4cc28 100644 --- a/src/routes/user.ts +++ b/src/routes/user.ts @@ -1,4 +1,3 @@ -import bcrypt from "bcrypt"; import express from "express"; import { logRequest } from "../middleware/logRequest"; @@ -8,15 +7,12 @@ import { generateAccessToken, getUserInfo, } from "../utils/jwt"; -import { userNeedsExtendedData } from "../utils/userNeedsExtendedData"; const router = express.Router(); router.use(express.json()); router.use(express.urlencoded({ extended: false })); router.use(logRequest); -let saltRounds = 10; - /** * POST /user/signup * @summary Create a new user account @@ -63,15 +59,14 @@ router.post("/signup", async (req, res) => { return; } - const salt = bcrypt.genSaltSync(saltRounds); - let passHash = await bcrypt.hash(password, salt); + let passHash = Bun.hash(password); // Create the user const newUser = await prisma.user.create({ data: { name: name, email: email, - password: passHash, + password: `${passHash}`, }, }); @@ -104,8 +99,6 @@ router.post("/signup", async (req, res) => { router.post("/login", async (req, res) => { // metrics.increment("endpoint.user.login"); - let useExteded = await userNeedsExtendedData(req); - const body = req.body; const { email, password } = body; @@ -124,9 +117,9 @@ router.post("/login", async (req, res) => { return res.status(400).json("Invalid email or password"); } - const match = await bcrypt.compare(password, user.password); + const isMatch = await Bun.password.verify(password, user.password); - if (!match) { + if (!isMatch) { return res.status(400).json("Invalid email or password"); } @@ -140,20 +133,10 @@ router.post("/login", async (req, res) => { let token = await generateAccessToken(user); - let jsonresponsebody = {}; - - if (useExteded) { - jsonresponsebody = { - token: token, - uuid: user.uuid, - }; - } else { - jsonresponsebody = { - token: token, - }; - } - - res.status(200).json(jsonresponsebody); + res.status(200).json({ + token: token, + uuid: user.uuid, + }); }); /** @@ -319,11 +302,11 @@ router.patch("/me", authenticateToken, async (req, res) => { } if (password) { - const valid = await bcrypt.compare(password, userInfo.password); + const valid = await Bun.password.verify(password, userInfo.password); if (!valid) { return res.status(400).json("Invalid password"); } - const hashedPassword = await bcrypt.hash(password, 10); + const hashedPassword = await Bun.password.hash(password); await prisma.user.update({ where: { id: userInfo.id, diff --git a/src/utils/jwt.ts b/src/utils/jwt.ts index 44b0ef5..c20cec1 100644 --- a/src/utils/jwt.ts +++ b/src/utils/jwt.ts @@ -77,12 +77,6 @@ export async function generateAccessToken(user: any) { export async function getUserInfo(req: any) { const tsStart = Date.now(); - // FIXME: - // for some reson, even when we have headers, we still get a error, so this is the temp solution - if (!req.headers) { - return logger.debug("No headers found, but not actually an error"); - } - const authHeader = req.headers.authorization; const token = authHeader && authHeader.split(" ")[1]; if (token == null) return console.error("No token provided"); From 3e165416143708da429a4ac6f516763a4d5ba151 Mon Sep 17 00:00:00 2001 From: Jasper Mayone Date: Wed, 26 Feb 2025 19:51:07 -0500 Subject: [PATCH 2/3] base setup --- {src => OLD-SRC}/app.ts | 0 {src => OLD-SRC}/defs/headers.ts | 0 {src => OLD-SRC}/defs/interfaces.ts | 0 OLD-SRC/index.ts | 96 ++++++++++ {src => OLD-SRC}/metrics.ts | 0 {src => OLD-SRC}/middleware/logRequest.ts | 0 {src => OLD-SRC}/prisma.ts | 0 {src => OLD-SRC}/router.ts | 0 {src => OLD-SRC}/routes/_unimplemented/ip.ts | 0 .../routes/_unimplemented/phoneNumber.ts | 0 {src => OLD-SRC}/routes/admin/router.ts | 0 .../routes/admin/routes/domain.ts | 0 {src => OLD-SRC}/routes/admin/routes/user.ts | 0 .../routes/admin/swaggerOptions.ts | 0 {src => OLD-SRC}/routes/domain.ts | 0 {src => OLD-SRC}/routes/domain/check.ts | 0 {src => OLD-SRC}/routes/domain/classify.ts | 0 {src => OLD-SRC}/routes/domain/report.ts | 0 {src => OLD-SRC}/routes/email.ts | 0 {src => OLD-SRC}/routes/misc.ts | 0 {src => OLD-SRC}/routes/user.ts | 0 {src => OLD-SRC}/server.ts | 0 .../services/GoogleSafebrowsing.ts | 0 {src => OLD-SRC}/services/IpQualityScore.ts | 0 {src => OLD-SRC}/services/PhishObserver.ts | 0 {src => OLD-SRC}/services/PhishReport.ts | 0 {src => OLD-SRC}/services/SecurityTrails.ts | 0 {src => OLD-SRC}/services/SinkingYahts.ts | 0 {src => OLD-SRC}/services/UrlScan.ts | 0 {src => OLD-SRC}/services/VirusTotal.ts | 0 {src => OLD-SRC}/services/Walshy.ts | 0 {src => OLD-SRC}/services/_TEMPLATE.ts | 0 {src => OLD-SRC}/services/_index.ts | 0 {src => OLD-SRC}/swaggerOptions.ts | 0 .../utils/db/findOrCreateDomain.ts | 0 {src => OLD-SRC}/utils/db/getDbDomain.ts | 2 +- {src => OLD-SRC}/utils/db/getDbUser.ts | 0 .../domain/checkAndUpdateDomainStatus.ts | 0 {src => OLD-SRC}/utils/domain/domain.ts | 0 {src => OLD-SRC}/utils/domain/domainReport.ts | 0 {src => OLD-SRC}/utils/domain/parseData.ts | 0 .../utils/domain/prepareResponse.ts | 0 .../utils/domain/reportToAlienVault.ts | 0 .../domain/validateAndExtractDomainParams.ts | 0 {src => OLD-SRC}/utils/getVersion.ts | 0 {src => OLD-SRC}/utils/jwt.ts | 2 +- {src => OLD-SRC}/utils/logger.ts | 0 {src => OLD-SRC}/utils/sanitizeDomain.ts | 0 .../utils/userNeedsExtendedData.ts | 0 {src => OLD-SRC}/utils/validateEmail.ts | 0 {src => OLD-SRC}/utils/validationError.ts | 0 src/index.ts | 170 +++++++++--------- tsconfig.json | 8 +- 53 files changed, 185 insertions(+), 93 deletions(-) rename {src => OLD-SRC}/app.ts (100%) rename {src => OLD-SRC}/defs/headers.ts (100%) rename {src => OLD-SRC}/defs/interfaces.ts (100%) create mode 100644 OLD-SRC/index.ts rename {src => OLD-SRC}/metrics.ts (100%) rename {src => OLD-SRC}/middleware/logRequest.ts (100%) rename {src => OLD-SRC}/prisma.ts (100%) rename {src => OLD-SRC}/router.ts (100%) rename {src => OLD-SRC}/routes/_unimplemented/ip.ts (100%) rename {src => OLD-SRC}/routes/_unimplemented/phoneNumber.ts (100%) rename {src => OLD-SRC}/routes/admin/router.ts (100%) rename {src => OLD-SRC}/routes/admin/routes/domain.ts (100%) rename {src => OLD-SRC}/routes/admin/routes/user.ts (100%) rename {src => OLD-SRC}/routes/admin/swaggerOptions.ts (100%) rename {src => OLD-SRC}/routes/domain.ts (100%) rename {src => OLD-SRC}/routes/domain/check.ts (100%) rename {src => OLD-SRC}/routes/domain/classify.ts (100%) rename {src => OLD-SRC}/routes/domain/report.ts (100%) rename {src => OLD-SRC}/routes/email.ts (100%) rename {src => OLD-SRC}/routes/misc.ts (100%) rename {src => OLD-SRC}/routes/user.ts (100%) rename {src => OLD-SRC}/server.ts (100%) rename {src => OLD-SRC}/services/GoogleSafebrowsing.ts (100%) rename {src => OLD-SRC}/services/IpQualityScore.ts (100%) rename {src => OLD-SRC}/services/PhishObserver.ts (100%) rename {src => OLD-SRC}/services/PhishReport.ts (100%) rename {src => OLD-SRC}/services/SecurityTrails.ts (100%) rename {src => OLD-SRC}/services/SinkingYahts.ts (100%) rename {src => OLD-SRC}/services/UrlScan.ts (100%) rename {src => OLD-SRC}/services/VirusTotal.ts (100%) rename {src => OLD-SRC}/services/Walshy.ts (100%) rename {src => OLD-SRC}/services/_TEMPLATE.ts (100%) rename {src => OLD-SRC}/services/_index.ts (100%) rename {src => OLD-SRC}/swaggerOptions.ts (100%) rename {src => OLD-SRC}/utils/db/findOrCreateDomain.ts (100%) rename {src => OLD-SRC}/utils/db/getDbDomain.ts (86%) rename {src => OLD-SRC}/utils/db/getDbUser.ts (100%) rename {src => OLD-SRC}/utils/domain/checkAndUpdateDomainStatus.ts (100%) rename {src => OLD-SRC}/utils/domain/domain.ts (100%) rename {src => OLD-SRC}/utils/domain/domainReport.ts (100%) rename {src => OLD-SRC}/utils/domain/parseData.ts (100%) rename {src => OLD-SRC}/utils/domain/prepareResponse.ts (100%) rename {src => OLD-SRC}/utils/domain/reportToAlienVault.ts (100%) rename {src => OLD-SRC}/utils/domain/validateAndExtractDomainParams.ts (100%) rename {src => OLD-SRC}/utils/getVersion.ts (100%) rename {src => OLD-SRC}/utils/jwt.ts (98%) rename {src => OLD-SRC}/utils/logger.ts (100%) rename {src => OLD-SRC}/utils/sanitizeDomain.ts (100%) rename {src => OLD-SRC}/utils/userNeedsExtendedData.ts (100%) rename {src => OLD-SRC}/utils/validateEmail.ts (100%) rename {src => OLD-SRC}/utils/validationError.ts (100%) diff --git a/src/app.ts b/OLD-SRC/app.ts similarity index 100% rename from src/app.ts rename to OLD-SRC/app.ts diff --git a/src/defs/headers.ts b/OLD-SRC/defs/headers.ts similarity index 100% rename from src/defs/headers.ts rename to OLD-SRC/defs/headers.ts diff --git a/src/defs/interfaces.ts b/OLD-SRC/defs/interfaces.ts similarity index 100% rename from src/defs/interfaces.ts rename to OLD-SRC/defs/interfaces.ts diff --git a/OLD-SRC/index.ts b/OLD-SRC/index.ts new file mode 100644 index 0000000..99654b6 --- /dev/null +++ b/OLD-SRC/index.ts @@ -0,0 +1,96 @@ +import axios from "axios"; +import * as dotenv from "dotenv"; +import expressJSDocSwagger from "express-jsdoc-swagger"; +import helmet from "helmet"; + +import { app } from "./app"; +import router from "./router"; +import { server } from "./server"; +// import metrics from "./metrics"; +import { swaggerOptions as adminSwagOptions } from "./routes/admin/swaggerOptions"; +import { swaggerOptions as mainSwagOptions } from "./swaggerOptions"; +import * as logger from "./utils/logger"; + +dotenv.config(); + +const port: number = Number(process.env.PORT) || 3000; + +expressJSDocSwagger(app)(mainSwagOptions); +expressJSDocSwagger(app)(adminSwagOptions); + +app.disable("x-powered-by"); + +app.use( + helmet({ + xFrameOptions: { action: "deny" }, + xContentTypeOptions: true, + contentSecurityPolicy: { + directives: { + defaultSrc: ["'self'"], + baseUri: ["'self'"], + fontSrc: ["'self'", "https:", "data:"], + formAction: ["'self'"], + frameAncestors: ["'self'"], + imgSrc: ["'self'", "data:"], + objectSrc: ["'none'"], + scriptSrc: ["'self'"], + scriptSrcAttr: ["'none'"], + styleSrc: ["'self'", "https:", "'unsafe-inline'"], + upgradeInsecureRequests: [], + }, + }, + referrerPolicy: { policy: "strict-origin" }, + strictTransportSecurity: { + maxAge: 63072000, + preload: true, + }, + xPoweredBy: false, + }) +); + +// Add metric interceptors for axios +axios.interceptors.request.use((config: any) => { + config.metadata = { startTs: performance.now() }; + return config; +}); + +axios.interceptors.response.use((res: any) => { + const stat = (res.config.method + "/" + res.config.url?.split("/")[1]) + .toLowerCase() + .replace(/[:.]/g, "") + .replace(/\//g, "_"); + + const httpCode = res.status; + const timingStatKey = `http.request.${stat}`; + const codeStatKey = `http.request.${stat}.${httpCode}`; + // metrics.timing( + // timingStatKey, + // performance.now() - res.config.metadata.startTs + // ); + // metrics.increment(codeStatKey, 1); + + return res; +}); + +app.use("/", router); + +// Heartbeat +// new CronJob( +// "0 * * * * *", +// async function () { +// logger.log("Thump Thump"); +// // metrics.increment("heartbeat"); +// }, +// null, +// true, +// "America/New_York", +// ); +// + +server + .listen(Number(port), "0.0.0.0", () => { + logger.info(`Server is running on port ${port}`); + }) + .on("error", (err) => { + logger.error(`Failed to start server: ${err.message}`); + }); diff --git a/src/metrics.ts b/OLD-SRC/metrics.ts similarity index 100% rename from src/metrics.ts rename to OLD-SRC/metrics.ts diff --git a/src/middleware/logRequest.ts b/OLD-SRC/middleware/logRequest.ts similarity index 100% rename from src/middleware/logRequest.ts rename to OLD-SRC/middleware/logRequest.ts diff --git a/src/prisma.ts b/OLD-SRC/prisma.ts similarity index 100% rename from src/prisma.ts rename to OLD-SRC/prisma.ts diff --git a/src/router.ts b/OLD-SRC/router.ts similarity index 100% rename from src/router.ts rename to OLD-SRC/router.ts diff --git a/src/routes/_unimplemented/ip.ts b/OLD-SRC/routes/_unimplemented/ip.ts similarity index 100% rename from src/routes/_unimplemented/ip.ts rename to OLD-SRC/routes/_unimplemented/ip.ts diff --git a/src/routes/_unimplemented/phoneNumber.ts b/OLD-SRC/routes/_unimplemented/phoneNumber.ts similarity index 100% rename from src/routes/_unimplemented/phoneNumber.ts rename to OLD-SRC/routes/_unimplemented/phoneNumber.ts diff --git a/src/routes/admin/router.ts b/OLD-SRC/routes/admin/router.ts similarity index 100% rename from src/routes/admin/router.ts rename to OLD-SRC/routes/admin/router.ts diff --git a/src/routes/admin/routes/domain.ts b/OLD-SRC/routes/admin/routes/domain.ts similarity index 100% rename from src/routes/admin/routes/domain.ts rename to OLD-SRC/routes/admin/routes/domain.ts diff --git a/src/routes/admin/routes/user.ts b/OLD-SRC/routes/admin/routes/user.ts similarity index 100% rename from src/routes/admin/routes/user.ts rename to OLD-SRC/routes/admin/routes/user.ts diff --git a/src/routes/admin/swaggerOptions.ts b/OLD-SRC/routes/admin/swaggerOptions.ts similarity index 100% rename from src/routes/admin/swaggerOptions.ts rename to OLD-SRC/routes/admin/swaggerOptions.ts diff --git a/src/routes/domain.ts b/OLD-SRC/routes/domain.ts similarity index 100% rename from src/routes/domain.ts rename to OLD-SRC/routes/domain.ts diff --git a/src/routes/domain/check.ts b/OLD-SRC/routes/domain/check.ts similarity index 100% rename from src/routes/domain/check.ts rename to OLD-SRC/routes/domain/check.ts diff --git a/src/routes/domain/classify.ts b/OLD-SRC/routes/domain/classify.ts similarity index 100% rename from src/routes/domain/classify.ts rename to OLD-SRC/routes/domain/classify.ts diff --git a/src/routes/domain/report.ts b/OLD-SRC/routes/domain/report.ts similarity index 100% rename from src/routes/domain/report.ts rename to OLD-SRC/routes/domain/report.ts diff --git a/src/routes/email.ts b/OLD-SRC/routes/email.ts similarity index 100% rename from src/routes/email.ts rename to OLD-SRC/routes/email.ts diff --git a/src/routes/misc.ts b/OLD-SRC/routes/misc.ts similarity index 100% rename from src/routes/misc.ts rename to OLD-SRC/routes/misc.ts diff --git a/src/routes/user.ts b/OLD-SRC/routes/user.ts similarity index 100% rename from src/routes/user.ts rename to OLD-SRC/routes/user.ts diff --git a/src/server.ts b/OLD-SRC/server.ts similarity index 100% rename from src/server.ts rename to OLD-SRC/server.ts diff --git a/src/services/GoogleSafebrowsing.ts b/OLD-SRC/services/GoogleSafebrowsing.ts similarity index 100% rename from src/services/GoogleSafebrowsing.ts rename to OLD-SRC/services/GoogleSafebrowsing.ts diff --git a/src/services/IpQualityScore.ts b/OLD-SRC/services/IpQualityScore.ts similarity index 100% rename from src/services/IpQualityScore.ts rename to OLD-SRC/services/IpQualityScore.ts diff --git a/src/services/PhishObserver.ts b/OLD-SRC/services/PhishObserver.ts similarity index 100% rename from src/services/PhishObserver.ts rename to OLD-SRC/services/PhishObserver.ts diff --git a/src/services/PhishReport.ts b/OLD-SRC/services/PhishReport.ts similarity index 100% rename from src/services/PhishReport.ts rename to OLD-SRC/services/PhishReport.ts diff --git a/src/services/SecurityTrails.ts b/OLD-SRC/services/SecurityTrails.ts similarity index 100% rename from src/services/SecurityTrails.ts rename to OLD-SRC/services/SecurityTrails.ts diff --git a/src/services/SinkingYahts.ts b/OLD-SRC/services/SinkingYahts.ts similarity index 100% rename from src/services/SinkingYahts.ts rename to OLD-SRC/services/SinkingYahts.ts diff --git a/src/services/UrlScan.ts b/OLD-SRC/services/UrlScan.ts similarity index 100% rename from src/services/UrlScan.ts rename to OLD-SRC/services/UrlScan.ts diff --git a/src/services/VirusTotal.ts b/OLD-SRC/services/VirusTotal.ts similarity index 100% rename from src/services/VirusTotal.ts rename to OLD-SRC/services/VirusTotal.ts diff --git a/src/services/Walshy.ts b/OLD-SRC/services/Walshy.ts similarity index 100% rename from src/services/Walshy.ts rename to OLD-SRC/services/Walshy.ts diff --git a/src/services/_TEMPLATE.ts b/OLD-SRC/services/_TEMPLATE.ts similarity index 100% rename from src/services/_TEMPLATE.ts rename to OLD-SRC/services/_TEMPLATE.ts diff --git a/src/services/_index.ts b/OLD-SRC/services/_index.ts similarity index 100% rename from src/services/_index.ts rename to OLD-SRC/services/_index.ts diff --git a/src/swaggerOptions.ts b/OLD-SRC/swaggerOptions.ts similarity index 100% rename from src/swaggerOptions.ts rename to OLD-SRC/swaggerOptions.ts diff --git a/src/utils/db/findOrCreateDomain.ts b/OLD-SRC/utils/db/findOrCreateDomain.ts similarity index 100% rename from src/utils/db/findOrCreateDomain.ts rename to OLD-SRC/utils/db/findOrCreateDomain.ts diff --git a/src/utils/db/getDbDomain.ts b/OLD-SRC/utils/db/getDbDomain.ts similarity index 86% rename from src/utils/db/getDbDomain.ts rename to OLD-SRC/utils/db/getDbDomain.ts index e112d7a..4e245a5 100644 --- a/src/utils/db/getDbDomain.ts +++ b/OLD-SRC/utils/db/getDbDomain.ts @@ -1,5 +1,5 @@ import { prisma } from "../../prisma"; -import { sanitizeDomain } from "../../utils/sanitizeDomain"; +import { sanitizeDomain } from "../sanitizeDomain"; export async function getDbDomain(domain: string) { let sanitizedDomain = sanitizeDomain(domain); diff --git a/src/utils/db/getDbUser.ts b/OLD-SRC/utils/db/getDbUser.ts similarity index 100% rename from src/utils/db/getDbUser.ts rename to OLD-SRC/utils/db/getDbUser.ts diff --git a/src/utils/domain/checkAndUpdateDomainStatus.ts b/OLD-SRC/utils/domain/checkAndUpdateDomainStatus.ts similarity index 100% rename from src/utils/domain/checkAndUpdateDomainStatus.ts rename to OLD-SRC/utils/domain/checkAndUpdateDomainStatus.ts diff --git a/src/utils/domain/domain.ts b/OLD-SRC/utils/domain/domain.ts similarity index 100% rename from src/utils/domain/domain.ts rename to OLD-SRC/utils/domain/domain.ts diff --git a/src/utils/domain/domainReport.ts b/OLD-SRC/utils/domain/domainReport.ts similarity index 100% rename from src/utils/domain/domainReport.ts rename to OLD-SRC/utils/domain/domainReport.ts diff --git a/src/utils/domain/parseData.ts b/OLD-SRC/utils/domain/parseData.ts similarity index 100% rename from src/utils/domain/parseData.ts rename to OLD-SRC/utils/domain/parseData.ts diff --git a/src/utils/domain/prepareResponse.ts b/OLD-SRC/utils/domain/prepareResponse.ts similarity index 100% rename from src/utils/domain/prepareResponse.ts rename to OLD-SRC/utils/domain/prepareResponse.ts diff --git a/src/utils/domain/reportToAlienVault.ts b/OLD-SRC/utils/domain/reportToAlienVault.ts similarity index 100% rename from src/utils/domain/reportToAlienVault.ts rename to OLD-SRC/utils/domain/reportToAlienVault.ts diff --git a/src/utils/domain/validateAndExtractDomainParams.ts b/OLD-SRC/utils/domain/validateAndExtractDomainParams.ts similarity index 100% rename from src/utils/domain/validateAndExtractDomainParams.ts rename to OLD-SRC/utils/domain/validateAndExtractDomainParams.ts diff --git a/src/utils/getVersion.ts b/OLD-SRC/utils/getVersion.ts similarity index 100% rename from src/utils/getVersion.ts rename to OLD-SRC/utils/getVersion.ts diff --git a/src/utils/jwt.ts b/OLD-SRC/utils/jwt.ts similarity index 98% rename from src/utils/jwt.ts rename to OLD-SRC/utils/jwt.ts index c20cec1..5105f51 100644 --- a/src/utils/jwt.ts +++ b/OLD-SRC/utils/jwt.ts @@ -2,7 +2,7 @@ import jwt, { JwtPayload } from "jsonwebtoken"; // import metrics from "../metrics"; import { prisma } from "../prisma"; -import * as logger from "../utils/logger"; +import * as logger from "./logger"; /** * Function to authenticate the token diff --git a/src/utils/logger.ts b/OLD-SRC/utils/logger.ts similarity index 100% rename from src/utils/logger.ts rename to OLD-SRC/utils/logger.ts diff --git a/src/utils/sanitizeDomain.ts b/OLD-SRC/utils/sanitizeDomain.ts similarity index 100% rename from src/utils/sanitizeDomain.ts rename to OLD-SRC/utils/sanitizeDomain.ts diff --git a/src/utils/userNeedsExtendedData.ts b/OLD-SRC/utils/userNeedsExtendedData.ts similarity index 100% rename from src/utils/userNeedsExtendedData.ts rename to OLD-SRC/utils/userNeedsExtendedData.ts diff --git a/src/utils/validateEmail.ts b/OLD-SRC/utils/validateEmail.ts similarity index 100% rename from src/utils/validateEmail.ts rename to OLD-SRC/utils/validateEmail.ts diff --git a/src/utils/validationError.ts b/OLD-SRC/utils/validationError.ts similarity index 100% rename from src/utils/validationError.ts rename to OLD-SRC/utils/validationError.ts diff --git a/src/index.ts b/src/index.ts index 99654b6..e98b344 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,96 +1,90 @@ -import axios from "axios"; -import * as dotenv from "dotenv"; -import expressJSDocSwagger from "express-jsdoc-swagger"; -import helmet from "helmet"; +import { swagger } from "@elysiajs/swagger"; +import { Elysia } from "elysia"; -import { app } from "./app"; -import router from "./router"; -import { server } from "./server"; -// import metrics from "./metrics"; -import { swaggerOptions as adminSwagOptions } from "./routes/admin/swaggerOptions"; -import { swaggerOptions as mainSwagOptions } from "./swaggerOptions"; -import * as logger from "./utils/logger"; +import { prisma } from "../OLD-SRC/prisma"; +import { getVersion } from "../OLD-SRC/utils/getVersion"; -dotenv.config(); +let version = getVersion(); -const port: number = Number(process.env.PORT) || 3000; - -expressJSDocSwagger(app)(mainSwagOptions); -expressJSDocSwagger(app)(adminSwagOptions); - -app.disable("x-powered-by"); - -app.use( - helmet({ - xFrameOptions: { action: "deny" }, - xContentTypeOptions: true, - contentSecurityPolicy: { - directives: { - defaultSrc: ["'self'"], - baseUri: ["'self'"], - fontSrc: ["'self'", "https:", "data:"], - formAction: ["'self'"], - frameAncestors: ["'self'"], - imgSrc: ["'self'", "data:"], - objectSrc: ["'none'"], - scriptSrc: ["'self'"], - scriptSrcAttr: ["'none'"], - styleSrc: ["'self'", "https:", "'unsafe-inline'"], - upgradeInsecureRequests: [], +new Elysia() + .use( + swagger({ + // Basic Swagger configuration + documentation: { + info: { + title: "phish.directory API", + version: version, + description: + "API for phish.directory, a community-driven anti-phishing tool. Helping catch, prevent, and catalog phishing links & attempts", + }, + tags: [ + { name: "Domain", description: "Domain-related operations" }, + { name: "Email", description: "Email-related operations" }, + { name: "User", description: "User management operations" }, + { name: "Admin", description: "[RESTRICTED] Admin operations" }, + ], + components: { + securitySchemes: { + BearerAuth: { + type: "http", + scheme: "bearer", + bearerFormat: "JWT", + }, + }, + }, + security: [ + { + BearerAuth: [], + }, + ], }, - }, - referrerPolicy: { policy: "strict-origin" }, - strictTransportSecurity: { - maxAge: 63072000, - preload: true, - }, - xPoweredBy: false, + // Scalar-specific configuration + provider: "scalar", + scalarConfig: { + hideDownloadButton: true, + hideTestRequestButton: true, + servers: [ + { + url: "https://api.phish.directory", + description: "Production server", + }, + { + url: "http://localhost:3000", + description: "Local server", + }, + ], + forceDarkModeState: "dark", + hideDarkModeToggle: true, + // defaultOpenAllTags: true, + metaData: { + title: "phish.directory API", + description: + "API for phish.directory, a community-driven anti-phishing tool. Helping catch, prevent, and catalog phishing links & attempts", + ogDescription: + "API for phish.directory, a community-driven anti-phishing tool. Helping catch, prevent, and catalog phishing links & attempts", + ogTitle: "phish.directory API", + }, + }, + path: "/docs", + }) + ) + .get("/", async ({ set }) => { + // redirect to docs + set.status = 302; + set.headers = { + Location: "/docs", + }; + return "Redirecting to /docs"; }) -); - -// Add metric interceptors for axios -axios.interceptors.request.use((config: any) => { - config.metadata = { startTs: performance.now() }; - return config; -}); - -axios.interceptors.response.use((res: any) => { - const stat = (res.config.method + "/" + res.config.url?.split("/")[1]) - .toLowerCase() - .replace(/[:.]/g, "") - .replace(/\//g, "_"); - - const httpCode = res.status; - const timingStatKey = `http.request.${stat}`; - const codeStatKey = `http.request.${stat}.${httpCode}`; - // metrics.timing( - // timingStatKey, - // performance.now() - res.config.metadata.startTs - // ); - // metrics.increment(codeStatKey, 1); - - return res; -}); - -app.use("/", router); + .get("/up", async ({}) => { + // Record start time for ping calculation + const startTime = Date.now(); -// Heartbeat -// new CronJob( -// "0 * * * * *", -// async function () { -// logger.log("Thump Thump"); -// // metrics.increment("heartbeat"); -// }, -// null, -// true, -// "America/New_York", -// ); -// + // Check database connectivity with a simple query -server - .listen(Number(port), "0.0.0.0", () => { - logger.info(`Server is running on port ${port}`); + await prisma.$queryRaw`SELECT 1`; + // Calculate ping time + const pingTime = Date.now() - startTime; + // Return success response with database status }) - .on("error", (err) => { - logger.error(`Failed to start server: ${err.message}`); - }); + .listen(3000); diff --git a/tsconfig.json b/tsconfig.json index f75fc48..334169e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,9 +5,11 @@ "strict": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true, - "rootDir": "src", + "rootDir": "OLD-SRC", "outDir": "dist", - "typeRoots": ["node_modules/@types"], + "typeRoots": [ + "node_modules/@types" + ], "esModuleInterop": true, "noImplicitAny": false }, @@ -20,4 +22,4 @@ ".git", "playwright.config.ts" ] -} +} \ No newline at end of file From fd9145a1caf82d94574efe2f8d52ab175c090535 Mon Sep 17 00:00:00 2001 From: Jasper Mayone Date: Tue, 4 Mar 2025 14:27:21 -0500 Subject: [PATCH 3/3] move over all logic code --- OLD-SRC/app.ts | 2 - OLD-SRC/index.ts | 96 ---- .../{logRequest.ts => logRequest.txt} | 2 +- OLD-SRC/{router.ts => router.txt} | 2 +- OLD-SRC/routes/_unimplemented/ip.ts | 0 OLD-SRC/routes/_unimplemented/phoneNumber.ts | 0 OLD-SRC/routes/admin/router.ts | 242 ---------- OLD-SRC/routes/admin/routes/domain.ts | 205 --------- OLD-SRC/routes/admin/routes/user.ts | 419 ------------------ OLD-SRC/routes/admin/swaggerOptions.ts | 80 ---- OLD-SRC/routes/domain.ts | 17 - OLD-SRC/routes/domain/check.ts | 43 -- OLD-SRC/routes/domain/classify.ts | 114 ----- OLD-SRC/routes/domain/report.ts | 69 --- OLD-SRC/routes/email.ts | 64 --- OLD-SRC/routes/misc.ts | 55 --- OLD-SRC/routes/user.ts | 323 -------------- OLD-SRC/server.ts | 3 - OLD-SRC/swaggerOptions.ts | 87 ---- OLD-SRC/utils/getVersion.ts | 9 - OLD-SRC/utils/{jwt.ts => jwt.txt} | 2 +- bun.lock | 111 ++--- package.json | 7 +- {OLD-SRC => src}/defs/headers.ts | 0 {OLD-SRC => src}/defs/interfaces.ts | 0 .../utils => src/defs}/validationError.ts | 0 .../func}/db/findOrCreateDomain.ts | 2 +- {OLD-SRC/utils => src/func}/db/getDbDomain.ts | 4 +- {OLD-SRC/utils => src/func}/db/getDbUser.ts | 2 +- .../domain/checkAndUpdateDomainStatus.ts | 0 {OLD-SRC/utils => src/func}/domain/domain.ts | 0 .../utils => src/func}/domain/domainReport.ts | 4 +- .../utils => src/func}/domain/parseData.ts | 0 .../func}/domain/prepareResponse.ts | 2 +- .../func}/domain/reportToAlienVault.ts | 4 +- .../func/domain}/sanitizeDomain.ts | 0 .../domain/validateAndExtractDomainParams.ts | 2 +- .../func}/userNeedsExtendedData.ts | 0 {OLD-SRC/utils => src/func}/validateEmail.ts | 0 src/index.ts | 71 ++- .../services/GoogleSafebrowsing.ts | 9 +- {OLD-SRC => src}/services/IpQualityScore.ts | 9 +- {OLD-SRC => src}/services/PhishObserver.ts | 10 +- {OLD-SRC => src}/services/PhishReport.ts | 9 +- {OLD-SRC => src}/services/SecurityTrails.ts | 8 +- {OLD-SRC => src}/services/SinkingYahts.ts | 9 +- {OLD-SRC => src}/services/UrlScan.ts | 9 +- {OLD-SRC => src}/services/VirusTotal.ts | 9 +- {OLD-SRC => src}/services/Walshy.ts | 9 +- {OLD-SRC => src}/services/_TEMPLATE.ts | 0 {OLD-SRC => src}/services/_index.ts | 0 src/utils/axios.ts | 27 ++ src/utils/getVersion.ts | 10 + {OLD-SRC => src}/utils/logger.ts | 21 +- {OLD-SRC => src/utils}/metrics.ts | 0 {OLD-SRC => src/utils}/prisma.ts | 0 tsconfig.json | 3 +- 57 files changed, 195 insertions(+), 1990 deletions(-) delete mode 100644 OLD-SRC/app.ts delete mode 100644 OLD-SRC/index.ts rename OLD-SRC/middleware/{logRequest.ts => logRequest.txt} (98%) rename OLD-SRC/{router.ts => router.txt} (98%) delete mode 100644 OLD-SRC/routes/_unimplemented/ip.ts delete mode 100644 OLD-SRC/routes/_unimplemented/phoneNumber.ts delete mode 100644 OLD-SRC/routes/admin/router.ts delete mode 100644 OLD-SRC/routes/admin/routes/domain.ts delete mode 100644 OLD-SRC/routes/admin/routes/user.ts delete mode 100644 OLD-SRC/routes/admin/swaggerOptions.ts delete mode 100644 OLD-SRC/routes/domain.ts delete mode 100644 OLD-SRC/routes/domain/check.ts delete mode 100644 OLD-SRC/routes/domain/classify.ts delete mode 100644 OLD-SRC/routes/domain/report.ts delete mode 100644 OLD-SRC/routes/email.ts delete mode 100644 OLD-SRC/routes/misc.ts delete mode 100644 OLD-SRC/routes/user.ts delete mode 100644 OLD-SRC/server.ts delete mode 100644 OLD-SRC/swaggerOptions.ts delete mode 100644 OLD-SRC/utils/getVersion.ts rename OLD-SRC/utils/{jwt.ts => jwt.txt} (98%) rename {OLD-SRC => src}/defs/headers.ts (100%) rename {OLD-SRC => src}/defs/interfaces.ts (100%) rename {OLD-SRC/utils => src/defs}/validationError.ts (100%) rename {OLD-SRC/utils => src/func}/db/findOrCreateDomain.ts (94%) rename {OLD-SRC/utils => src/func}/db/getDbDomain.ts (77%) rename {OLD-SRC/utils => src/func}/db/getDbUser.ts (77%) rename {OLD-SRC/utils => src/func}/domain/checkAndUpdateDomainStatus.ts (100%) rename {OLD-SRC/utils => src/func}/domain/domain.ts (100%) rename {OLD-SRC/utils => src/func}/domain/domainReport.ts (87%) rename {OLD-SRC/utils => src/func}/domain/parseData.ts (100%) rename {OLD-SRC/utils => src/func}/domain/prepareResponse.ts (94%) rename {OLD-SRC/utils => src/func}/domain/reportToAlienVault.ts (85%) rename {OLD-SRC/utils => src/func/domain}/sanitizeDomain.ts (100%) rename {OLD-SRC/utils => src/func}/domain/validateAndExtractDomainParams.ts (93%) rename {OLD-SRC/utils => src/func}/userNeedsExtendedData.ts (100%) rename {OLD-SRC/utils => src/func}/validateEmail.ts (100%) rename {OLD-SRC => src}/services/GoogleSafebrowsing.ts (88%) rename {OLD-SRC => src}/services/IpQualityScore.ts (92%) rename {OLD-SRC => src}/services/PhishObserver.ts (93%) rename {OLD-SRC => src}/services/PhishReport.ts (88%) rename {OLD-SRC => src}/services/SecurityTrails.ts (90%) rename {OLD-SRC => src}/services/SinkingYahts.ts (85%) rename {OLD-SRC => src}/services/UrlScan.ts (91%) rename {OLD-SRC => src}/services/VirusTotal.ts (93%) rename {OLD-SRC => src}/services/Walshy.ts (89%) rename {OLD-SRC => src}/services/_TEMPLATE.ts (100%) rename {OLD-SRC => src}/services/_index.ts (100%) create mode 100644 src/utils/axios.ts create mode 100644 src/utils/getVersion.ts rename {OLD-SRC => src}/utils/logger.ts (84%) rename {OLD-SRC => src/utils}/metrics.ts (100%) rename {OLD-SRC => src/utils}/prisma.ts (100%) diff --git a/OLD-SRC/app.ts b/OLD-SRC/app.ts deleted file mode 100644 index 9d2d584..0000000 --- a/OLD-SRC/app.ts +++ /dev/null @@ -1,2 +0,0 @@ -import express from "express"; -export const app = express(); diff --git a/OLD-SRC/index.ts b/OLD-SRC/index.ts deleted file mode 100644 index 99654b6..0000000 --- a/OLD-SRC/index.ts +++ /dev/null @@ -1,96 +0,0 @@ -import axios from "axios"; -import * as dotenv from "dotenv"; -import expressJSDocSwagger from "express-jsdoc-swagger"; -import helmet from "helmet"; - -import { app } from "./app"; -import router from "./router"; -import { server } from "./server"; -// import metrics from "./metrics"; -import { swaggerOptions as adminSwagOptions } from "./routes/admin/swaggerOptions"; -import { swaggerOptions as mainSwagOptions } from "./swaggerOptions"; -import * as logger from "./utils/logger"; - -dotenv.config(); - -const port: number = Number(process.env.PORT) || 3000; - -expressJSDocSwagger(app)(mainSwagOptions); -expressJSDocSwagger(app)(adminSwagOptions); - -app.disable("x-powered-by"); - -app.use( - helmet({ - xFrameOptions: { action: "deny" }, - xContentTypeOptions: true, - contentSecurityPolicy: { - directives: { - defaultSrc: ["'self'"], - baseUri: ["'self'"], - fontSrc: ["'self'", "https:", "data:"], - formAction: ["'self'"], - frameAncestors: ["'self'"], - imgSrc: ["'self'", "data:"], - objectSrc: ["'none'"], - scriptSrc: ["'self'"], - scriptSrcAttr: ["'none'"], - styleSrc: ["'self'", "https:", "'unsafe-inline'"], - upgradeInsecureRequests: [], - }, - }, - referrerPolicy: { policy: "strict-origin" }, - strictTransportSecurity: { - maxAge: 63072000, - preload: true, - }, - xPoweredBy: false, - }) -); - -// Add metric interceptors for axios -axios.interceptors.request.use((config: any) => { - config.metadata = { startTs: performance.now() }; - return config; -}); - -axios.interceptors.response.use((res: any) => { - const stat = (res.config.method + "/" + res.config.url?.split("/")[1]) - .toLowerCase() - .replace(/[:.]/g, "") - .replace(/\//g, "_"); - - const httpCode = res.status; - const timingStatKey = `http.request.${stat}`; - const codeStatKey = `http.request.${stat}.${httpCode}`; - // metrics.timing( - // timingStatKey, - // performance.now() - res.config.metadata.startTs - // ); - // metrics.increment(codeStatKey, 1); - - return res; -}); - -app.use("/", router); - -// Heartbeat -// new CronJob( -// "0 * * * * *", -// async function () { -// logger.log("Thump Thump"); -// // metrics.increment("heartbeat"); -// }, -// null, -// true, -// "America/New_York", -// ); -// - -server - .listen(Number(port), "0.0.0.0", () => { - logger.info(`Server is running on port ${port}`); - }) - .on("error", (err) => { - logger.error(`Failed to start server: ${err.message}`); - }); diff --git a/OLD-SRC/middleware/logRequest.ts b/OLD-SRC/middleware/logRequest.txt similarity index 98% rename from OLD-SRC/middleware/logRequest.ts rename to OLD-SRC/middleware/logRequest.txt index 34ad84e..c44e3b3 100644 --- a/OLD-SRC/middleware/logRequest.ts +++ b/OLD-SRC/middleware/logRequest.txt @@ -1,9 +1,9 @@ import { NextFunction, Request, Response } from "express"; import requestIp from "request-ip"; +import { log } from "../../src/utils/logger"; import { prisma } from "../prisma"; import { getUserInfo } from "../utils/jwt"; -import { log } from "../utils/logger"; let monitoringAgents = ["Checkly/", "Uptime-Kuma/"]; diff --git a/OLD-SRC/router.ts b/OLD-SRC/router.txt similarity index 98% rename from OLD-SRC/router.ts rename to OLD-SRC/router.txt index 4c92e8a..b49323f 100644 --- a/OLD-SRC/router.ts +++ b/OLD-SRC/router.txt @@ -3,13 +3,13 @@ import responseTime from "response-time"; // import metrics from "./metrics"; import { logRequest } from "./middleware/logRequest"; // import defaultRateLimiter from "./middleware/rateLimit"; +import * as logger from "../src/utils/logger"; import { prisma } from "./prisma"; import adminRouter from "./routes/admin/router"; import domainRouter from "./routes/domain"; import emailRouter from "./routes/email"; import miscRouter from "./routes/misc"; import userRouter from "./routes/user"; -import * as logger from "./utils/logger"; const router = express.Router(); diff --git a/OLD-SRC/routes/_unimplemented/ip.ts b/OLD-SRC/routes/_unimplemented/ip.ts deleted file mode 100644 index e69de29..0000000 diff --git a/OLD-SRC/routes/_unimplemented/phoneNumber.ts b/OLD-SRC/routes/_unimplemented/phoneNumber.ts deleted file mode 100644 index e69de29..0000000 diff --git a/OLD-SRC/routes/admin/router.ts b/OLD-SRC/routes/admin/router.ts deleted file mode 100644 index 6301cfc..0000000 --- a/OLD-SRC/routes/admin/router.ts +++ /dev/null @@ -1,242 +0,0 @@ -import express from "express"; -import moment from "moment"; -import { logRequest } from "../../middleware/logRequest"; -import { prisma } from "../../prisma"; -import { getPackageVersion, getVersion } from "../../utils/getVersion"; -import { authenticateToken, getUserInfo } from "../../utils/jwt"; -import domainRouter from "./routes/domain"; -import userRouter from "./routes/user"; - -const router = express.Router(); -router.use(express.json()); -router.use(express.urlencoded({ extended: false })); -router.use(authenticateToken); - -// middleware to check if the user is an admin -router.use(async (req, res, next) => { - let user = await getUserInfo(req); - - if (!user) { - res.status(401).json({ - error: "Unauthorized", - }); - return; - } - - if (user.permission !== "admin") { - res.status(403).json({ - error: "You do not have permission to access this endpoint", - }); - return; - } else { - next(); - } -}); - -/** - * GET /admin/metrics - * @summary Get comprehensive system metrics - * @description Provides detailed system information and metrics for administrators including: - * - System status and environment details - * - Runtime information (uptime, start time) - * - Version information for API and all dependencies - * - Usage statistics across different time periods - * - API integration response counts - * @security BearerAuth - * @return {object} 200 - Detailed metrics response - * @return {object} 403 - Permission denied - * @produces application/json - * @example response - 200 - Complete metrics response - * { - * "status": "up", - * "environment": "production", - * "uptime": "48:12:33", - * "dateStarted": "01-09-24 9:45:27 AM +00:00", - * "versions": { - * "api": "2.0.0", - * "node": "v18.17.0", - * "packages": { - * "express": "4.18.2", - * "prisma": "5.4.2", - * "axios": "1.5.0", - * "cron": "2.4.3", - * "helmet": "7.0.0", - * "jsonwebtoken": "9.0.2" - * } - * }, - * "counts": { - * "domains": 1234, - * "users": 567, - * "requests": { - * "lifetime": 50000, - * "today": 1500, - * "24 hours": 1800, - * "week": 12000, - * "month": 45000, - * "year": 500000 - * }, - * "responses": { - * "googleSafebrowsing": 45000, - * "ipQualityScore": 42000, - * "phishObserver": 35000, - * "phishReport": 30000, - * "securityTrails": 25000, - * "sinkingYahts": 20000, - * "urlScan": 15000, - * "virusTotal": 10000, - * "walshy": 5000 - * } - * } - * } - * @example response - 403 - Permission denied - * { - * "error": "You do not have permission to access this endpoint" - * } - */ -router.get("/metrics", logRequest, async (req, res) => { - // metrics.increment("endpoint.misc.metrics"); - - let uptime = process.uptime(); - let uptimeString = new Date(uptime * 1000).toISOString().substr(11, 8); - let dateStarted = new Date(Date.now() - uptime * 1000); - let dateStartedFormatted = moment(dateStarted).format("MM-DD-YY H:m:s A Z"); - - let domainCount = await prisma.domain.count(); - let userCount = await prisma.user.count(); - let requestCount = await prisma.expressRequest.count(); - - let npmVersion = getVersion(); - let expressVersion = getPackageVersion("express"); - let prismaVersion = getPackageVersion("@prisma/client"); - let axiosVersion = getPackageVersion("axios"); - let cronVersion = getPackageVersion("cron"); - let helmetVersion = getPackageVersion("helmet"); - let jsonwebtokenVersion = getPackageVersion("jsonwebtoken"); - let nodeVersion = process.version; - - let environment = process.env.NODE_ENV; - - res.status(200).json({ - status: "up", - environment: environment, - uptime: uptimeString, - dateStarted: dateStartedFormatted, - versions: { - api: npmVersion, - node: nodeVersion, - packages: { - express: expressVersion, - prisma: prismaVersion, - axios: axiosVersion, - cron: cronVersion, - helmet: helmetVersion, - jsonwebtoken: jsonwebtokenVersion, - }, - }, - counts: { - domains: domainCount, - users: userCount, - requests: { - lifetime: requestCount, - today: await prisma.expressRequest.count({ - where: { - createdAt: { - gte: new Date(new Date().setHours(0, 0, 0, 0)), - }, - }, - }), - "24 hours": await prisma.expressRequest.count({ - where: { - createdAt: { - gte: new Date(Date.now() - 24 * 60 * 60 * 1000), - }, - }, - }), - week: await prisma.expressRequest.count({ - where: { - createdAt: { - gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), - }, - }, - }), - month: await prisma.expressRequest.count({ - where: { - createdAt: { - gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), - }, - }, - }), - year: await prisma.expressRequest.count({ - where: { - createdAt: { - gte: new Date(Date.now() - 365 * 24 * 60 * 60 * 1000), - }, - }, - }), - }, - responses: { - googleSafebrowsing: await prisma.rawAPIData.count({ - where: { - sourceAPI: "SafeBrowsing", - }, - }), - ipQualityScore: await prisma.rawAPIData.count({ - where: { - sourceAPI: "IpQualityScore", - }, - }), - phishObserver: await prisma.rawAPIData.count({ - where: { - sourceAPI: "PhishObserver", - }, - }), - phishReport: await prisma.rawAPIData.count({ - where: { - sourceAPI: "PhishReport", - }, - }), - securityTrails: await prisma.rawAPIData.count({ - where: { - sourceAPI: "SecurityTrails", - }, - }), - sinkingYahts: await prisma.rawAPIData.count({ - where: { - sourceAPI: "SinkingYachts", - }, - }), - urlScan: await prisma.rawAPIData.count({ - where: { - sourceAPI: "UrlScan", - }, - }), - virusTotal: await prisma.rawAPIData.count({ - where: { - sourceAPI: "VirusTotal", - }, - }), - walshy: await prisma.rawAPIData.count({ - where: { - sourceAPI: "Walshy", - }, - }), - }, - }, - }); -}); - -/** - * Admin Router Configuration - * @summary Administrative route handler with authentication and permission checks - * @description All routes under /admin require: - * 1. Valid JWT authentication token - * 2. Admin-level permissions - * Sub-routes include: - * - /admin/metrics: System metrics and statistics - * - /admin/domain: Domain management - * - /admin/user: User management - */ -router.use("/domain", logRequest, domainRouter); -router.use("/user", userRouter); - -export default router; diff --git a/OLD-SRC/routes/admin/routes/domain.ts b/OLD-SRC/routes/admin/routes/domain.ts deleted file mode 100644 index e82e9c3..0000000 --- a/OLD-SRC/routes/admin/routes/domain.ts +++ /dev/null @@ -1,205 +0,0 @@ -import axios from "axios"; -import express, { Request, Response } from "express"; - -import { headersWithOTX } from "../../../defs/headers"; -import { prisma } from "../../../prisma"; -import { getDbDomain } from "../../../utils/db/getDbDomain"; -import { domainReport } from "../../../utils/domain/domainReport"; -import { getUserInfo } from "../../../utils/jwt"; - -/* -GET domain - Get all domains -GET domain:id - Get domain by ID -*/ - -const router = express.Router(); - -// Add type for report review request -interface ReportReviewRequest { - approved: boolean; -} - -/** - * GET /admin/domain - * @summary Returns a list of all domains. - * @tags Domain - Domain Ops - * @security BearerAuth - * @return {object} 200 - An array of domain objects. - */ -router.get("/", async (req: Request, res: Response) => { - try { - const domains = await prisma.domain.findMany({ - orderBy: { - id: "asc", - }, - }); - res.status(200).json(domains); - } catch (error) { - res - .status(500) - .json({ error: "An error occurred while fetching domains." }); - } -}); - -/** - * GET /admin/domain/:id - * @summary Returns a domain by its ID. - * @tags Domain - Domain Ops - * @security BearerAuth - * @param {number} id.path - The ID of the domain to retrieve. - * @return {object} 200 - A domain object. - */ -router.get("/:id", async (req: Request, res: Response) => { - try { - let { id } = req.params; - - if (!id) { - return res.status(400).json("Missing parameter: id"); - } - - let dbDomain = getDbDomain(id); - - if (!dbDomain) { - return res.status(400).json("Domain not found"); - } - - res.status(200).json(dbDomain); - } catch (error) { - res - .status(500) - .json({ error: "An error occurred while fetching the domain." }); - } -}); - -/** - * GET /admin/domain/reports - * @summary Get pending domain reports - * @tags Domain - Domain Ops - * @security BearerAuth - */ -router.get("/reports", async (req: Request, res: Response) => { - try { - const reports = await prisma.domainReport.findMany({ - where: { status: "PENDING" }, - include: { - domain: true, - reporter: { - select: { - id: true, - name: true, - email: true, - }, - }, - }, - }); - - res.status(200).json(reports); - } catch (error) { - res - .status(500) - .json({ error: "An error occurred while fetching reports." }); - } -}); - -/** - * POST /admin/domain/reports/:id/review - * @summary Review a domain report - * @tags Domain - Domain Ops - * @security BearerAuth - */ -router.post( - "/reports/:id/review", - async ( - req: Request<{ id: string }, {}, ReportReviewRequest>, - res: Response - ) => { - try { - const { id } = req.params; - const { approved } = req.body; - - if (typeof approved !== "boolean") { - return res - .status(400) - .json({ error: "approved must be a boolean value" }); - } - - if (!id || isNaN(parseInt(id))) { - return res.status(400).json({ error: "Invalid report ID" }); - } - - const user = await getUserInfo(req); - if (!user) { - return res.status(401).json({ error: "Unauthorized" }); - } - - const report = await prisma.domainReport.findUnique({ - where: { id: parseInt(id) }, - include: { domain: true }, - }); - - if (!report) { - return res.status(404).json({ error: "Report not found" }); - } - - try { - await prisma.$transaction(async (tx) => { - // Update report status - await tx.domainReport.update({ - where: { id: report.id }, - data: { - status: approved ? "APPROVED" : "REJECTED", - reviewedAt: new Date(), - reviewer: { connect: { id: user.id } }, - }, - }); - - // If approved, mark domain as malicious and run domainReport - if (approved) { - await tx.domain.update({ - where: { id: report.domain.id }, - data: { malicious: true }, - }); - - await axios.patch( - "https://otx.alienvault.com/api/v1/pulses/6785dccb041b628fde283705", - { - indicators: { - add: [ - { - indicator: `${report.domain.domain}`, - type: "domain", - role: "phishing", - }, - ], - }, - }, - { - headers: headersWithOTX, - } - ); - - // Run domainReport function - await domainReport(report.domain.domain); - } - }); - - return res - .status(200) - .json(`Report ${approved ? "approved" : "rejected"}`); - } catch (txError) { - console.error("Transaction failed:", txError); - return res.status(500).json({ - error: "Failed to process report review", - details: txError instanceof Error ? txError.message : "Unknown error", - }); - } - } catch (error) { - console.error("Error in report review endpoint:", error); - return res - .status(500) - .json({ error: "An error occurred while reviewing the report." }); - } - } -); - -export default router; diff --git a/OLD-SRC/routes/admin/routes/user.ts b/OLD-SRC/routes/admin/routes/user.ts deleted file mode 100644 index af885fe..0000000 --- a/OLD-SRC/routes/admin/routes/user.ts +++ /dev/null @@ -1,419 +0,0 @@ -import express from "express"; - -import { ExtendedData } from "@prisma/client"; -import { prisma } from "../../../prisma"; -import * as logger from "../../../utils/logger"; - -let saltRounds = 10; - -const router = express.Router(); - -/** - * User w/ Name - * @typedef {object} User - * @property {string} name.required - The name of the user - * @property {string} email.required - The email of the user - * @property {string} password.required - The password of the user - */ -export type User = { - name: string; - email: string; - password: string; -}; - -/** - * User login information - * @typedef {object} UserLogin - * @property {string} email.required - The email of the user - * @property {string} password.required - The password of the user - */ -export type UserLogin = { - email: string; - password: string; -}; - -/** - * GET /admin/user - * @summary Returns a list of all users. - * @tags User - User Ops - * @security BearerAuth - * @return {array} 200 - An array of user objects. - * @example response - 200 - An array of user objects. - * [ - * { - * "id": 1, - * "name": "John Doe", - * "email": "john@example.com", - * "role": "basic", - * "createdAt": "2021-08-01T00:00:00.000Z", - * "updatedAt": "2021-08-01T00:00:00.000Z", - * "deleted": false, - * "deletedAt": null, - * "uuid": "123e4567-e89b-12d3-a456-426614174000" - * } - * ] - */ -router.get("/", async (req, res) => { - // metrics.increment("endpoint.admin.users.get"); - try { - const users = await prisma.user.findMany({ - orderBy: { - id: "asc", - }, - }); - res.status(200).json(users); - } catch (error) { - res.status(500).json({ error: "An error occurred while fetching users." }); - } -}); - -/** - * GET /admin/user/:id - * @summary Returns a user by their ID. - * @tags User - User Ops - * @security BearerAuth - * @param {number} id.path - The ID of the user to retrieve. - * @return {object} 200 - A user object. - * @example response - 200 - A user object. - * { - * "id": 1, - * "name": "John Doe", - * "email": "john@example.com", - * "role": "basic", - * "createdAt": "2021-08-01T00:00:00.000Z", - * "updatedAt": "2021-08-01T00:00:00.000Z", - * "deleted": false, - * "deletedAt": null, - * "uuid": "123e4567-e89b-12d3-a456-426614174000" - * } - */ -router.get("/user/:id", async (req, res) => { - // metrics.increment("endpoint.admin.user.get"); - - try { - // Process the user request - const { id } = req.params; - - // Validate ID - const userId = parseInt(id); - if (isNaN(userId) || userId <= 0) { - return res.status(400).json({ - message: "Invalid user ID. Must be a positive integer.", - }); - } - - const user = await prisma.user.findUnique({ - where: { id: userId }, - }); - - if (!user) { - return res.status(404).json({ - message: "User not found.", - }); - } - } catch (error) { - logger.error(error as string); - - return res.status(500).json({ - message: "An error occurred.", - }); - } -}); - -/** - * PATCH /admin/user/:id - * @summary Updates a user by their ID. - * @tags User - User Ops - * @security BearerAuth - * @param {number} id.path - The ID of the user to update. - * @param {object} request.body - User fields to update - * @param {string} [request.body.email] - Updated email - * @param {string} [request.body.password] - Updated password - * @param {string} [request.body.role] - Updated role - * @return {object} 200 - Success message - * @example request - Example request - * { - * "email": "newemail@example.com", - * "role": "trusted" - * } - * @example response - 200 - Success message - * { - * "message": "User updated successfully." - * } - */ -router.patch("/user/:id", async (req, res) => { - // metrics.increment("endpoint.admin.user.patch"); - try { - const { id } = req.params; - const { email, password, permission } = req.body; - - // Build the data object dynamically - const updateData = {}; - // @ts-expect-error - if (email !== undefined) updateData.email = email; - // @ts-expect-error - if (password !== undefined) updateData.password = password; - // @ts-expect-error - if (permission !== undefined) updateData.permission = permission; - - // Update user - await prisma.user.update({ - where: { - id: parseInt(id), - }, - data: updateData, - }); - - res.status(200).json({ - message: "User updated successfully.", - }); - } catch (error) { - res.status(500).json({ - message: "An error occurred.", - }); - } -}); - -/** - * POST /admin/user/new - * @summary Creates a new user. - * @tags User - User Ops - * @security BearerAuth - * @param {object} request.body - User information - * @return {object} 200 - Success response - * @example request - Example request - * { - * "name": "John Doe", - * "email": "john@example.com", - * "password": "securePassword123" - * } - * @example response - 200 - success response - * { - * "message": "User created successfully, please login.", - * "uuid": "123e4567-e89b-12d3-a456-426614174000" - * } - */ -router.post("/user/new", async (req, res) => { - const body = req.body; - - const { name, email, password } = body; - - if (!name || !email || !password) { - res - .status(400) - .json("Invalid arguments. Please provide name, email, and password"); - return; - } - - // Check if the user already exists - const user = await prisma.user.findUnique({ - where: { - email: email, - }, - }); - - if (user) { - res.status(400).json("User with that email already exists"); - return; - } - - let passHash = await Bun.password.hash(password); - - // Create the user - const newUser = await prisma.user.create({ - data: { - name: name, - email: email, - password: passHash, - }, - }); - - res.status(200).json({ - message: "User created successfully, please login.", - uuid: newUser.uuid, - }); -}); - -/** - * DELETE /admin/user/:id - * @summary Deletes a user by their ID. - * @tags User - User Ops - * @security BearerAuth - * @param {number} id.path - The ID of the user to delete. - * @return {object} 200 - Success message - * @example response - 200 - Success message - * { - * "message": "User deleted successfully." - * } - */ -router.delete("/user/:id", async (req, res) => { - // metrics.increment("endpoint.admin.user.delete"); - try { - const { id } = req.params; - - await prisma.user.update({ - where: { - id: parseInt(id), - }, - data: { - deletedAt: new Date(), - deleted: true, - }, - }); - - res.status(200).json({ - message: "User deleted successfully.", - }); - } catch (error) { - res.status(500).json({ - message: "An error occurred.", - }); - } -}); - -/** - * PATCH /admin/user/:id/:role/ - * @summary Updates a user's role by their ID. - * @tags User - User Ops - * @security BearerAuth - * @param {number} id.path - The ID of the user to update. - * @param {string} role.path - The role to update the user to. - * @return {object} 200 - Success message - * @example response - 200 - Success message - * { - * "message": "User role updated to *ROLE* successfully." - * } - */ -router.patch("/role/:id/:role", async (req, res) => { - // metrics.increment("endpoint.admin.user.role.patch"); - - try { - const { id, role } = req.params; - const permission = role; - - if (!id) { - return res.status(400).json({ - message: "User ID is required.", - }); - } - - if (!permission) { - return res.status(400).json({ - message: "Role is required.", - }); - } - - if ( - permission !== "basic" && - permission !== "trusted" && - permission !== "admin" - ) { - return res.status(400).json({ - message: "Invalid role.", - }); - } - - let user = await prisma.user.findUnique({ - where: { - id: parseInt(id), - }, - }); - - if (!user) { - return res.status(404).json({ - message: "User not found.", - }); - } - - await prisma.user - .update({ - where: { - id: parseInt(id), - }, - data: { - permission: permission, - }, - }) - .then(() => { - res.status(200).json({ - message: `User role updated to ${permission} successfully.`, - }); - }); - } catch (error) { - res.status(500).json({ - message: "An error occurred.", - }); - } -}); - -/** - * PATCH /admin/user/:id/:useExtended/ - * @summary Updates a user's useExteded data enum - * @tags User - User Ops - * @security BearerAuth - * @param {number} id.path - The ID of the user to update. - * @param {object} useExtended.path - The useExtended data to update the user to. (off, on, or forced) - */ -router.patch("/useExtended/:id/:useExtended", async (req, res) => { - // metrics.increment("endpoint.admin.user.useExtended.patch"); - - try { - let { id, useExtended } = req.params; - - switch (useExtended) { - case "off": - useExtended = ExtendedData.off; - break; - case "on": - useExtended = ExtendedData.on; - break; - case "forced": - useExtended = ExtendedData.forced; - break; - default: - return res.status(400).json({ - message: "Invalid useExtended data.", - }); - } - - if (!id) { - return res.status(400).json({ - message: "User ID is required.", - }); - } - - let user = await prisma.user.findUnique({ - where: { - id: parseInt(id), - }, - }); - - if (!user) { - return res.status(404).json({ - message: "User not found.", - }); - } - - await prisma.user - .update({ - where: { - id: parseInt(id), - }, - data: { - // @ts-expect-error - useExtendedData: useExtended, - }, - }) - .then(() => { - res.status(200).json({ - message: `User useExtended data updated to ${useExtended} successfully.`, - }); - }); - } catch (error) { - res.status(500).json({ - message: "An error occurred.", - }); - } -}); - -export default router; diff --git a/OLD-SRC/routes/admin/swaggerOptions.ts b/OLD-SRC/routes/admin/swaggerOptions.ts deleted file mode 100644 index 6e6a9ff..0000000 --- a/OLD-SRC/routes/admin/swaggerOptions.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { getVersion } from "../../utils/getVersion"; - -let filePattern; -if (process.env.NODE_ENV === "production") { - filePattern = ["./admin.js", "./routes/*.js"]; -} else { - filePattern = ["./router.{ts,js}", "./routes/*.{ts,js}"]; -} -let version = getVersion(); - -/** - * Swagger Options for Admin API documentation - */ -export const swaggerOptions = { - openapi: "3.0.0", - info: { - title: "phish.directory Admin API", - version: `${version}`, - description: - "Administrative API endpoints for phish.directory. These endpoints require admin-level access and provide advanced functionality for managing users, domains, and system configuration.", - contact: { - name: "phish.directory Admin Support", - url: "phish.directory", - email: "admin@phish.directory", - }, - }, - servers: [ - { - url: "https://api.phish.directory/admin", - description: "Production Admin API", - }, - { - url: "http://localhost:3000/admin", - description: "Development Admin API", - }, - ], - components: { - securitySchemes: { - BearerAuth: { - type: "http", - scheme: "bearer", - bearerFormat: "JWT", - }, - }, - }, - security: { - BearerAuth: { - type: "http", - scheme: "bearer", - }, - }, - tags: [ - { - name: "Users", - description: "User management operations", - }, - { - name: "Domains", - description: "Domain management and classification", - }, - { - name: "Reports", - description: "Domain report management and review", - }, - { - name: "System", - description: "System configuration and monitoring", - }, - ], - filesPattern: filePattern, - basePath: "/admin", - exposeSwaggerUI: true, - swaggerUIPath: "/admin/docs", - exposeApiDocs: true, - apiDocsPath: "/admin/api-docs", - baseDir: __dirname, - swaggerUiOptions: { - persistAuthorization: true, - }, -}; diff --git a/OLD-SRC/routes/domain.ts b/OLD-SRC/routes/domain.ts deleted file mode 100644 index 3fc0efe..0000000 --- a/OLD-SRC/routes/domain.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as express from "express"; - -import { logRequest } from "../middleware/logRequest"; -import checkRouter from "./domain/check"; -import classifyRouter from "./domain/classify"; -import reportRouter from "./domain/report"; - -const router = express.Router(); -router.use(express.json()); -router.use(express.urlencoded({ extended: false })); -router.use(logRequest); - -router.use("/check", checkRouter); -router.use("/classify", classifyRouter); -router.use("/report", reportRouter); - -export default router; diff --git a/OLD-SRC/routes/domain/check.ts b/OLD-SRC/routes/domain/check.ts deleted file mode 100644 index afe4623..0000000 --- a/OLD-SRC/routes/domain/check.ts +++ /dev/null @@ -1,43 +0,0 @@ -import express from "express"; -const router = express.Router(); - -import { findOrCreateDomain } from "../../utils/db/findOrCreateDomain"; -import { prepareResponse } from "../../utils/domain/prepareResponse"; -import { validateAndExtractParams } from "../../utils/domain/validateAndExtractDomainParams"; -import { authenticateToken } from "../../utils/jwt"; -import { ValidationError } from "../../utils/validationError"; - -/** - * GET /domain/check - * @summary Checks if a domain is phishing/malicious. - * @description This endpoint checks if a domain is phishing/malicious. - * It will return a boolean value of true if it is phishing/malicious and false if it is not, and some other data. - * @tags Domain - Endpoints for checking / reporting domains. - * @security BearerAuth - * @param {string} domain.query.required - Domain to check - * @param {boolean} extendData.query.optional - Optionally, request extra information about the domain (MAY HAVE LONGER RESPONSE TIME). You need special permissions to access this. - * @return {object} 200 - Success message - * @return {string} 400 - Error message - */ -router.get("/", authenticateToken, async (req, res) => { - try { - // Validate and extract query parameters - const { domain, extendData } = await validateAndExtractParams(req); - - // Check if domain exists in database - const dbDomain = await findOrCreateDomain(domain); - - // Prepare and send response - const response = await prepareResponse(domain, dbDomain, extendData); - - return res.status(200).json(response); - } catch (error) { - if (error instanceof ValidationError) { - return res.status(400).json(error.message); - } - console.error("Error in domain check:", error); - return res.status(500).json("Internal server error"); - } -}); - -export default router; diff --git a/OLD-SRC/routes/domain/classify.ts b/OLD-SRC/routes/domain/classify.ts deleted file mode 100644 index 6da9749..0000000 --- a/OLD-SRC/routes/domain/classify.ts +++ /dev/null @@ -1,114 +0,0 @@ -import express from "express"; -const router = express.Router(); - -import { Classifications } from "@prisma/client"; -import * as jwt from "jsonwebtoken"; -import { prisma } from "../../prisma"; -import { authenticateToken } from "../../utils/jwt"; - -/** - * PUT /domain/classify - * @summary Classify a domain to specific types (scam, phishing, etc.) - * @description Classify a domain to specific types (scam, phishing, etc.). - The classification parameter should be one of the following: "postal", "banking", "item_scams", or "other". - (Check the ClassificationType enum for more information) (see swagger ui) - - This endpoint requires TRUSTED level access. To check if you have this access run /user/me with your token. - - To request trusted level access or a new classification type, contact Jasper via email at jasper.mayone@phish.directory or via Slack. - * @tags Domain - Endpoints for checking / reporting domains. - * @security BearerAuth - * @param {object} request.body.required - Domain Classification Body - * @return {object} 200 - Success message - * @return {string} 400 - Error message - * @example response - 200 - Success message - * "Domain classified successfully" - */ -router.put("/", authenticateToken, async (req, res) => { - const data = req.body; - const domain = data.domain; - const classification = data.classification; - - if (!domain) { - return res.status(400).json("No domain parameter found"); - } - - if (!classification) { - return res.status(400).json("No classification parameter found"); - } - - // validate classification against enum - if (!Object.values(Classifications).includes(classification)) { - return res.status(400).json("Invalid classification parameter"); - } - - // get authorization header - const authHeader = req.headers["authorization"]; - const token = authHeader && authHeader.split(" ")[1]; - - if (token == null) return res.sendStatus(401); - - // decode the token - let decoded = jwt.decode(token); - - if (!decoded) { - return res.status(400).json("Invalid token"); - } - - let user = await prisma.user.findUnique({ - where: { - // @ts-expect-error - id: decoded.id, - }, - }); - - if (!user) { - return res.status(400).json("User not found"); - } - - let trustedTypes = ["trusted", "admin"]; - - if (user.permission !== "basic" && trustedTypes.includes(user.permission)) { - let dbDomain = await prisma.domain.findFirst({ - where: { - domain: domain, - }, - }); - - let databaseDomain = await prisma.domain.findFirst({ - where: { - domain: domain, - }, - }); - - if (!databaseDomain) { - databaseDomain = await prisma.domain.create({ - data: { - domain: domain, - }, - }); - } - - await prisma.classification.create({ - data: { - domain: { - connect: { - id: databaseDomain.id, - }, - }, - classifier: { - connect: { - id: user.id, - }, - }, - classification: classification, - }, - }); - - return res.status(200).json("Domain classified successfully"); - } else { - return res.status(403).json("Unauthorized"); - } -}); - -export default router; diff --git a/OLD-SRC/routes/domain/report.ts b/OLD-SRC/routes/domain/report.ts deleted file mode 100644 index c357f9f..0000000 --- a/OLD-SRC/routes/domain/report.ts +++ /dev/null @@ -1,69 +0,0 @@ -import express from "express"; -const router = express.Router(); - -import { prisma } from "../../prisma"; -import { getDbDomain } from "../../utils/db/getDbDomain"; -import { domainReport } from "../../utils/domain/domainReport"; -import { authenticateToken, getUserInfo } from "../../utils/jwt"; - -/** - * POST /domain/report - * @summary Report a domain as malicious - * @description Reports a domain as potentially malicious. Submissions will be reviewed by a trusted user before being marked and submitted into our database. - * @tags Domain - Endpoints for checking / reporting domains. - * @security BearerAuth - * @param {object} request.body.required - Domain report details - * @return {object} 200 - Success message - * @return {string} 400 - Error message - * @example request - Domain report - * { - * "domain": "malicious-site.com", - * "notes": "This site is attempting to steal banking credentials" - * } - */ -router.post("/", authenticateToken, async (req, res) => { - const { domain, notes } = req.body; - const user = await getUserInfo(req); - - if (!domain) { - return res.status(400).json("No domain parameter found"); - } - - // Get or create domain record - let dbDomain = await getDbDomain(domain); - - // Create report - const report = await prisma.domainReport.create({ - data: { - domain: { connect: { id: dbDomain.id } }, - reporter: { connect: { id: user!.id } }, - notes, - }, - }); - - // If user is trusted/admin, automatically approve and mark domain as malicious - if (user!.permission === "trusted" || user!.permission === "admin") { - await prisma.$transaction([ - prisma.domainReport.update({ - where: { id: report.id }, - data: { - status: "APPROVED", - reviewedAt: new Date(), - reviewer: { connect: { id: user!.id } }, - }, - }), - prisma.domain.update({ - where: { id: dbDomain.id }, - data: { malicious: true }, - }), - ]); - - await domainReport(domain); - - return res.status(200).json("Domain reported and marked as malicious"); - } - - return res.status(200).json("Domain report submitted for review"); -}); - -export default router; diff --git a/OLD-SRC/routes/email.ts b/OLD-SRC/routes/email.ts deleted file mode 100644 index 5ecd705..0000000 --- a/OLD-SRC/routes/email.ts +++ /dev/null @@ -1,64 +0,0 @@ -import * as express from "express"; -import { logRequest } from "../middleware/logRequest"; -import { ipQualityScoreService } from "../services/_index"; -import { validateEmail } from "../utils/validateEmail"; - -const router = express.Router(); -router.use(express.json()); -router.use(express.urlencoded({ extended: false })); -router.use(logRequest); - -/** - * GET /email/check - * @summary Check email address reputation and validity - * @description Asynchronously validates an email address and checks it against known malicious email databases. - * Performs the following checks: - * - Email format validation - * - Domain validity - * - Disposable email detection - * - Fraud score assessment - * - Recent abuse detection - * @tags Email - Email validation and reputation checking - * @param {string} email.query.required - Email address to check - eg: test@example.com - * @return {object} 200 - Email check results - * @return {object} 400 - Invalid email error - * @produces application/json - * @example response - 200 - Valid email response - * { - * "valid": true, - * "disposable": false, - * "dns_valid": true, - * "fraud_score": 10, - * "recent_abuse": false, - * "suggested_domain": null, - * "first_seen": "2023-01-15", - * "success": true, - * "message": null - * } - * @example response - 400 - Invalid email error - * { - * "message": "Invalid email provided." - * } - * @example response - 400 - Missing email error - * { - * "message": "No email provided." - * } - */ -router.get("/check", async (req, res) => { - const email = req.query.email as string; - if (!email) { - return res.status(400).json({ message: "No email provided." }); - } - - if (!validateEmail(email)) { - return res.status(400).json({ - message: "Invalid email provided.", - code: "INVALID_EMAIL", - }); - } - - const result = await ipQualityScoreService.email.check(email); - res.status(200).json(result); -}); - -export default router; diff --git a/OLD-SRC/routes/misc.ts b/OLD-SRC/routes/misc.ts deleted file mode 100644 index 337f96e..0000000 --- a/OLD-SRC/routes/misc.ts +++ /dev/null @@ -1,55 +0,0 @@ -import * as express from "express"; -import moment from "moment"; -import { logRequest } from "../middleware/logRequest"; -import { prisma } from "../prisma"; -import { getVersion } from "../utils/getVersion"; - -const router = express.Router(); -router.use(express.json()); -router.use(express.urlencoded({ extended: false })); -router.use(logRequest); - -/** - * GET /misc/metrics - * @summary Get API system metrics and status - * @description Returns operational metrics and system information including: - * - Current API status - * - Environment (production/development) - * - System uptime - * - Service start timestamp - * - API version - * - Total number of tracked domains - * @tags Miscellaneous - System information and metrics - * @return {object} 200 - System metrics response - * @produces application/json - * @example response - 200 - Example metrics response - * { - * "status": "up", - * "environment": "production", - * "uptime": "48:12:33", - * "dateStarted": "01-09-24 9:45:27 AM +00:00", - * "version": "2.0.0", - * "domains": 1234 - * } - */ -router.get("/metrics", async (req, res) => { - // metrics.increment("endpoint.misc.metrics"); - let uptime = process.uptime(); - let uptimeString = new Date(uptime * 1000).toISOString().substr(11, 8); - let dateStarted = new Date(Date.now() - uptime * 1000); - let dateStartedFormatted = moment(dateStarted).format("MM-DD-YY H:m:s A Z"); - let domainCount = await prisma.domain.count(); - let npmVersion = getVersion(); - let environment = process.env.NODE_ENV; - - res.status(200).json({ - status: "up", - environment: environment, - uptime: uptimeString, - dateStarted: dateStartedFormatted, - version: npmVersion, - domains: domainCount, - }); -}); - -export default router; diff --git a/OLD-SRC/routes/user.ts b/OLD-SRC/routes/user.ts deleted file mode 100644 index 1f4cc28..0000000 --- a/OLD-SRC/routes/user.ts +++ /dev/null @@ -1,323 +0,0 @@ -import express from "express"; - -import { logRequest } from "../middleware/logRequest"; -import { prisma } from "../prisma"; -import { - authenticateToken, - generateAccessToken, - getUserInfo, -} from "../utils/jwt"; - -const router = express.Router(); -router.use(express.json()); -router.use(express.urlencoded({ extended: false })); -router.use(logRequest); - -/** - * POST /user/signup - * @summary Create a new user account - * @tags User - User Management / Info and Authentication endpoints - * @param {User} request.body.required - User signup information - * @return {object} 200 - Success response with UUID - * @return {object} 400 - Validation error - * @produces application/json - * @example request - Example signup request - * { - * "name": "John Doe", - * "email": "john.doe@example.com", - * "password": "securepassword123", - * } - * @example response - 200 - Success response - * { - * "message": "User created successfully, please login.", - * "uuid": "123e4567-e89b-12d3-a456-426614174000" - * } - */ -router.post("/signup", async (req, res) => { - // metrics.increment("endpoint.user.signup"); - - const body = req.body; - - const { name, email, password } = body; - - if (!name || !email || !password) { - res - .status(400) - .json("Invalid arguments. Please provide name, email, and password"); - return; - } - - // Check if the user already exists - const user = await prisma.user.findUnique({ - where: { - email: email, - }, - }); - - if (user) { - res.status(400).json("User with that email already exists"); - return; - } - - let passHash = Bun.hash(password); - - // Create the user - const newUser = await prisma.user.create({ - data: { - name: name, - email: email, - password: `${passHash}`, - }, - }); - - res.status(200).json({ - message: "User created successfully, please login.", - uuid: newUser.uuid, - }); -}); - -/** - * POST /user/login - * @summary Authenticate user and get JWT token - * @tags User - User Management / Info and Authentication endpoints - * @param {object} request.body.required - User login credentials - * @return {object} 200 - JWT token and user UUID - * @return {object} 400 - Invalid credentials - * @return {object} 403 - Account deleted - * @produces application/json - * @example request - Login request - * { - * "email": "john.doe@example.com", - * "password": "securepassword123" - * } - * @example response - 200 - Successful login - * { - * "token": "eyJhbGciOiJIUzI1NiIs...", - * "uuid": "123e4567-e89b-12d3-a456-426614174000" - * } - */ -router.post("/login", async (req, res) => { - // metrics.increment("endpoint.user.login"); - - const body = req.body; - const { email, password } = body; - - if (!email || !password) { - res.status(400).json("Missing email or password"); - return; - } - - const user = await prisma.user.findUnique({ - where: { - email: email, - }, - }); - - if (!user) { - return res.status(400).json("Invalid email or password"); - } - - const isMatch = await Bun.password.verify(password, user.password); - - if (!isMatch) { - return res.status(400).json("Invalid email or password"); - } - - if (user.deleted === true) { - return res - .status(403) - .json( - "User has been deleted. Please contact support if you believe this is an error or need to reactivate your account." - ); - } - - let token = await generateAccessToken(user); - - res.status(200).json({ - token: token, - uuid: user.uuid, - }); -}); - -/** - * GET /user/me - * @summary Get authenticated user profile and metrics - * @tags User - User Management / Info and Authentication endpoints - * @security BearerAuth - * @return {object} 200 - User profile with usage metrics - * @return {object} 400 - User not found - * @produces application/json - * @example response - 200 - Profile response - * { - * "name": "John Doe", - * "email": "john.doe@example.com", - * "uuid": "123e4567-e89b-12d3-a456-426614174000", - * "permission": "basic", - * "accountType": "user", - * "metrics": { - * "requests": { - * "count": 3, - * "methods": [ - * { - * "method": "GET", - * "count": 3 - * } - * ], - * "urls": [ - * { - * "url": "/user/me", - * "count": 2 - * } - * ] - * } - * }, - * "accountCreated": "2024-08-14T02:11:02.626Z" - * } - */ -router.get("/me", authenticateToken, async (req, res) => { - // metrics.increment("endpoint.user.me"); - - const userInfo = await getUserInfo(req); - - if (!userInfo) { - return res.status(400).json("User not found"); - } - - // Get the count of requests made by the user - const count = await prisma.expressRequest.count({ - where: { - userId: userInfo!.id, - }, - }); - - // Fetch all requests made by the user - const userRequests = await prisma.expressRequest.findMany({ - where: { - userId: userInfo!.id, - }, - }); - - // Normalize the URLs by removing query parameters - const normalizedRequests = userRequests.map((req) => { - const urlWithoutQuery = req.url.split("?")[0]; // Remove query params - return { - ...req, - url: urlWithoutQuery, - }; - }); - - // Group the requests by the normalized URL and count occurrences - const requestCountsByUrl = normalizedRequests.reduce((acc, req) => { - acc[req.url] = (acc[req.url] || 0) + 1; - return acc; - }, {}); - - const requestUrls = Object.keys(requestCountsByUrl).map((url) => ({ - url, - count: requestCountsByUrl[url], - })); - - // Group by request methods using Prisma - const groupByMethod = await prisma.expressRequest.groupBy({ - by: ["method"], - where: { - userId: userInfo!.id, - }, - _count: { - method: true, - }, - }); - - // Transform the data to a more readable format - const requestMethods = groupByMethod.map((methodGroup) => ({ - method: methodGroup.method, - count: methodGroup._count.method, - })); - - res.status(200).json({ - name: userInfo.name, - email: userInfo.email, - uuid: userInfo.uuid, - permission: userInfo.permission, - extendedData: userInfo.useExtendedData, - metrics: { - requests: { - count: count, - methods: requestMethods, - urls: requestUrls, - }, - }, - accountCreated: userInfo.createdAt, - }); -}); - -/** - * PATCH /user/me - * @summary Update authenticated user profile - * @description Update user details (name, password). Email updates require contacting support. - * Only include fields that need updating. Password updates require current password verification. - * @tags User - User Management / Info and Authentication endpoints - * @security BearerAuth - * @param {object} request.body - Fields to update - * @param {string} [request.body.name] - New display name - * @param {string} [request.body.password] - New password (requires verification) - * @return {string} 200 - Update success message - * @return {string} 400 - Update error message - * @produces application/json - * @example request - Name update - * { - * "name": "John Smith" - * } - * @example request - Password update - * { - * "password": "newSecurePassword123" - * } - * @example response - 200 - Success message - * "User updated successfully" - */ -router.patch("/me", authenticateToken, async (req, res) => { - // metrics.increment("endpoint.user.me.patch"); - - const userInfo = await getUserInfo(req); - - if (!userInfo) { - return res.status(400).json("User not found"); - } - - const { name, password } = req.body; - - if (!name && !password) { - return res.status(400).json("No fields to update"); - } - - if (name) { - await prisma.user.update({ - where: { - id: userInfo.id, - }, - data: { - name: name, - }, - }); - } - - if (password) { - const valid = await Bun.password.verify(password, userInfo.password); - if (!valid) { - return res.status(400).json("Invalid password"); - } - const hashedPassword = await Bun.password.hash(password); - await prisma.user.update({ - where: { - id: userInfo.id, - }, - data: { - password: hashedPassword, - }, - }); - } - - res.status(200).json("User updated successfully"); -}); - -export default router; diff --git a/OLD-SRC/server.ts b/OLD-SRC/server.ts deleted file mode 100644 index 0897fc7..0000000 --- a/OLD-SRC/server.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createServer } from "node:http"; -import { app } from "./app"; -export const server = createServer(app); diff --git a/OLD-SRC/swaggerOptions.ts b/OLD-SRC/swaggerOptions.ts deleted file mode 100644 index 09c0afd..0000000 --- a/OLD-SRC/swaggerOptions.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { getVersion } from "./utils/getVersion"; - -let filePattern; -if (process.env.NODE_ENV === "production") { - filePattern = ["./router.js", "./routes/*.js"]; -} else { - filePattern = ["./router.{ts,js}", "./routes/*.{ts,js}"]; -} - -let version = getVersion(); - -/** - * @openapi - * components: - * securitySchemes: - * BearerAuth: - * type: http - * scheme: bearer - * bearerFormat: JWT - * description: JWT token for authentication - * schemas: - * Error: - * type: object - * properties: - * message: - * type: string - * description: Error message - * code: - * type: integer - * description: Error code - * - * security: - * - BearerAuth: [] - */ - -export const swaggerOptions = { - openapi: "3.0.0", - info: { - title: "phish.directory API", - version: `${version}`, - description: - "API for phish.directory, a community-driven anti-phishing tool. Helping catch, prevent, and catalog phishing links & attempts", - contact: { - name: "phish.directory", - url: "phish.directory", - email: "team@phish.directory", - }, - }, - servers: [ - { - url: "https://api.phish.directory", - description: "Production server", - }, - { - url: "http://localhost:3000", - description: "Development server", - }, - ], - tags: [ - { name: "Domain", description: "Domain-related operations" }, - { name: "Email", description: "Email-related operations" }, - { name: "User", description: "User management operations" }, - ], - filesPattern: filePattern, - baseDir: __dirname, - exposeSwaggerUI: true, - exposeApiDocs: true, - swaggerUIPath: "/docs", - apiDocsPath: "/api-docs", - definition: { - openapi: "3.0.0", - components: { - securitySchemes: { - BearerAuth: { - type: "http", - scheme: "bearer", - bearerFormat: "JWT", - }, - }, - }, - security: [ - { - BearerAuth: [], - }, - ], - }, -}; diff --git a/OLD-SRC/utils/getVersion.ts b/OLD-SRC/utils/getVersion.ts deleted file mode 100644 index c8c61ff..0000000 --- a/OLD-SRC/utils/getVersion.ts +++ /dev/null @@ -1,9 +0,0 @@ -export function getVersion() { - const packageJson = require("../../package.json"); - return packageJson.version; -} - -export function getPackageVersion(packageName: string) { - const packageJson = require("../../package.json"); - return packageJson.dependencies[packageName]; -} diff --git a/OLD-SRC/utils/jwt.ts b/OLD-SRC/utils/jwt.txt similarity index 98% rename from OLD-SRC/utils/jwt.ts rename to OLD-SRC/utils/jwt.txt index 5105f51..4c80a08 100644 --- a/OLD-SRC/utils/jwt.ts +++ b/OLD-SRC/utils/jwt.txt @@ -1,8 +1,8 @@ import jwt, { JwtPayload } from "jsonwebtoken"; // import metrics from "../metrics"; +import * as logger from "../../src/utils/logger"; import { prisma } from "../prisma"; -import * as logger from "./logger"; /** * Function to authenticate the token diff --git a/bun.lock b/bun.lock index b205b0f..b4f9d32 100644 --- a/bun.lock +++ b/bun.lock @@ -4,13 +4,17 @@ "": { "name": "phish.directory", "dependencies": { + "@elysiajs/bearer": "^1.2.0", + "@elysiajs/cors": "^1.2.0", + "@elysiajs/cron": "^1.2.0", + "@elysiajs/jwt": "^1.2.0", "@playwright/test": "^1.49.1", "@prisma/client": "6.4.1", "axios": "^1.7.9", - "bcrypt": "^5.1.1", "body-parser": "^1.20.3", "colors": "^1.4.0", "dotenv": "^16.4.7", + "elysia-ip": "^1.0.8", "express": "^4.21.2", "express-jsdoc-swagger": "^1.8.0", "express-rate-limit": "^7.5.0", @@ -24,7 +28,6 @@ }, "devDependencies": { "@flydotio/dockerfile": "^0.6.1", - "@types/bcrypt": "^5.0.2", "@types/bun": "^1.2.3", "@types/express": "^4.17.21", "@types/jsonwebtoken": "^9.0.7", @@ -44,6 +47,14 @@ "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], + "@elysiajs/bearer": ["@elysiajs/bearer@1.2.0", "", { "peerDependencies": { "elysia": ">= 1.2.0" } }, "sha512-orr0XHhc99JgtxQlKhnTPRqRlYrE9MDW+v1IMcs9Uy+bEMbohAkK1zmbi05tO7P2UT9t4Xl6pHF/R0WD71ZpCQ=="], + + "@elysiajs/cors": ["@elysiajs/cors@1.2.0", "", { "peerDependencies": { "elysia": ">= 1.2.0" } }, "sha512-qsJwDAg6WfdQRMfj6uSMcDPSpXvm/zQFeAX1uuJXhIgazH8itSfcDxcH9pMuXVRX1yQNi2pPwNQLJmAcw5mzvw=="], + + "@elysiajs/cron": ["@elysiajs/cron@1.2.0", "", { "dependencies": { "croner": "^6.0.3" }, "peerDependencies": { "elysia": ">= 1.2.0" } }, "sha512-Xg2bUCZNEp2zRzsYeNQ6BUP3uslF5BEPnuLHLnsytiAEqzFTHzS7813XbmHs8xNZKuUAkAnJNTVnQb1Jt5zTwg=="], + + "@elysiajs/jwt": ["@elysiajs/jwt@1.2.0", "", { "dependencies": { "jose": "^4.14.4" }, "peerDependencies": { "elysia": ">= 1.2.0" } }, "sha512-5iMoZucIKNAqPKW3n6RBIyCnDWG3kOcqA4WZKtqEff+IjV6AN3dlMSE2XsS0xjIvusLD0UBXS8cxQ9NwIcj6ew=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], "@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], @@ -106,8 +117,6 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], - "@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@1.0.11", "", { "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", "make-dir": "^3.1.0", "node-fetch": "^2.6.7", "nopt": "^5.0.0", "npmlog": "^5.0.1", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.11" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ=="], - "@playwright/test": ["@playwright/test@1.50.1", "", { "dependencies": { "playwright": "1.50.1" }, "bin": { "playwright": "cli.js" } }, "sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ=="], "@polka/url": ["@polka/url@1.0.0-next.28", "", {}, "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw=="], @@ -172,6 +181,8 @@ "@scarf/scarf": ["@scarf/scarf@1.4.0", "", {}, "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ=="], + "@sinclair/typebox": ["@sinclair/typebox@0.34.28", "", {}, "sha512-e2B9vmvaa5ym5hWgCHw5CstP54au6AOLXrhZErLsOyyRzuWJtXl/8TszKtc5x8rw/b+oY7HKS9m9iRI53RK0WQ=="], + "@sveltejs/adapter-node": ["@sveltejs/adapter-node@5.2.12", "", { "dependencies": { "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.0", "rollup": "^4.9.5" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0" } }, "sha512-0bp4Yb3jKIEcZWVcJC/L1xXp9zzJS4hDwfb4VITAkfT4OVdkspSHsx7YhqJDbb2hgLl6R9Vs7VQR+fqIVOxPUQ=="], "@sveltejs/kit": ["@sveltejs/kit@2.16.1", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", "esm-env": "^1.2.2", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0" }, "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-2pF5sgGJx9brYZ/9nNDYnh5KX0JguPF14dnvvtf/MqrvlWrDj/e7Rk3LBJPecFLLK1GRs6ZniD24gFPqZm/NFw=="], @@ -188,8 +199,6 @@ "@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="], - "@types/bcrypt": ["@types/bcrypt@5.0.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ=="], - "@types/body-parser": ["@types/body-parser@1.19.5", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg=="], "@types/bun": ["@types/bun@1.2.3", "", { "dependencies": { "bun-types": "1.2.3" } }, "sha512-054h79ipETRfjtsCW9qJK8Ipof67Pw9bodFWmkfkaUaRiIQ1dIV2VTlheshlBx3mpKr0KeK8VqnMMCtgN9rQtw=="], @@ -232,8 +241,6 @@ "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], - "abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], - "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], @@ -242,18 +249,12 @@ "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="], - "agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - "aproba": ["aproba@2.0.0", "", {}, "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="], - - "are-we-there-yet": ["are-we-there-yet@2.0.0", "", { "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" } }, "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw=="], - "arg": ["arg@4.1.3", "", {}, "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="], "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], @@ -270,8 +271,6 @@ "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "bcrypt": ["bcrypt@5.1.1", "", { "dependencies": { "@mapbox/node-pre-gyp": "^1.0.11", "node-addon-api": "^5.0.0" } }, "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww=="], - "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], "body-parser": ["body-parser@1.20.3", "", { "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" } }, "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g=="], @@ -294,8 +293,6 @@ "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], - "chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], - "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], @@ -304,8 +301,6 @@ "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - "color-support": ["color-support@1.1.3", "", { "bin": { "color-support": "bin.js" } }, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="], - "colors": ["colors@1.4.0", "", {}, "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="], "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], @@ -314,8 +309,6 @@ "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - "console-control-strings": ["console-control-strings@1.1.0", "", {}, "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="], - "content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -326,20 +319,18 @@ "create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="], + "croner": ["croner@6.0.7", "", {}, "sha512-k3Xx3Rcclfr60Yx4TmvsF3Yscuiql8LSvYLaphTsaq5Hk8La4Z/udmUANMOTKpgGGroI2F6/XOr9cU9OFkYluQ=="], + "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], - "delegates": ["delegates@1.0.0", "", {}, "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="], - "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], - "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], - "devalue": ["devalue@5.1.1", "", {}, "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="], "diff": ["diff@5.2.0", "", {}, "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A=="], @@ -356,6 +347,10 @@ "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], + "elysia": ["elysia@1.2.24", "", { "dependencies": { "@sinclair/typebox": "^0.34.27", "cookie": "^1.0.2", "memoirist": "^0.3.0", "openapi-types": "^12.1.3" }, "peerDependencies": { "typescript": ">= 5.0.0" }, "optionalPeers": ["typescript"] }, "sha512-z849iAFdOCLd/a/ra3dtOmMd9jN4ow1G5Enq5RRRfheu/HEcO61cnwSaj0EScbT91pDiVbozhzqxF/K6b6amEw=="], + + "elysia-ip": ["elysia-ip@1.0.8", "", { "peerDependencies": { "elysia": ">= 1.0.9" } }, "sha512-xzuBMCN+hoM7BTzjB4QDqY6dxTYaK+NrxnVTilNsKW0+T5KTTWBi3vaj3hdRFw06KLNJIlAKR16yU00lPT5IXw=="], + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], @@ -406,16 +401,12 @@ "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], - "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], - "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - "gauge": ["gauge@3.0.2", "", { "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.1", "object-assign": "^4.1.1", "signal-exit": "^3.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.2" } }, "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q=="], - "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], "get-intrinsic": ["get-intrinsic@1.2.7", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", "get-proto": "^1.0.0", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA=="], @@ -432,16 +423,12 @@ "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], - "has-unicode": ["has-unicode@2.0.1", "", {}, "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="], - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], "helmet": ["helmet@7.2.0", "", {}, "sha512-ZRiwvN089JfMXokizgqEPXsl2Guk094yExfoDXR0cBYWxtBbaSww/w+vT4WEJsBW2iTUi1GgZ6swmoug3Oy4Xw=="], "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], - "https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], - "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], "ignore-by-default": ["ignore-by-default@1.0.1", "", {}, "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA=="], @@ -472,6 +459,8 @@ "jake": ["jake@10.9.2", "", { "dependencies": { "async": "^3.2.3", "chalk": "^4.0.2", "filelist": "^1.0.4", "minimatch": "^3.1.2" }, "bin": { "jake": "bin/cli.js" } }, "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA=="], + "jose": ["jose@4.15.9", "", {}, "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA=="], + "jsonwebtoken": ["jsonwebtoken@9.0.2", "", { "dependencies": { "jws": "^3.2.2", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ=="], "jwa": ["jwa@1.4.1", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA=="], @@ -498,14 +487,14 @@ "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], - "make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="], - "make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="], "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], + "memoirist": ["memoirist@0.3.0", "", {}, "sha512-wR+4chMgVPq+T6OOsk40u9Wlpw1Pjx66NMNiYxCQQ4EUJ7jDs3D9kTCeKdBOkvAiqXlHLVJlvYL01PvIJ1MPNg=="], + "merge": ["merge@2.1.1", "", {}, "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w=="], "merge-descriptors": ["merge-descriptors@1.0.3", "", {}, "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="], @@ -520,12 +509,6 @@ "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - "minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], - - "minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], - - "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], - "moment": ["moment@2.30.1", "", {}, "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="], "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], @@ -538,22 +521,12 @@ "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], - "node-addon-api": ["node-addon-api@5.1.0", "", {}, "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA=="], - - "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], - "node-statsd": ["node-statsd@0.1.1", "", {}, "sha512-QDf6R8VXF56QVe1boek8an/Rb3rSNaxoFWb7Elpsv2m1+Noua1yy0F1FpKpK5VluF8oymWM4w764A4KsYL4pDg=="], "nodemon": ["nodemon@3.1.9", "", { "dependencies": { "chokidar": "^3.5.2", "debug": "^4", "ignore-by-default": "^1.0.1", "minimatch": "^3.1.2", "pstree.remy": "^1.1.8", "semver": "^7.5.3", "simple-update-notifier": "^2.0.0", "supports-color": "^5.5.0", "touch": "^3.1.0", "undefsafe": "^2.0.5" }, "bin": { "nodemon": "bin/nodemon.js" } }, "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg=="], - "nopt": ["nopt@5.0.0", "", { "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ=="], - "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], - "npmlog": ["npmlog@5.0.1", "", { "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", "gauge": "^3.0.0", "set-blocking": "^2.0.0" } }, "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw=="], - - "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - "object-inspect": ["object-inspect@1.13.3", "", {}, "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA=="], "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], @@ -562,6 +535,8 @@ "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], @@ -594,8 +569,6 @@ "raw-body": ["raw-body@2.5.2", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA=="], - "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "request-ip": ["request-ip@3.3.0", "", {}, "sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA=="], @@ -606,8 +579,6 @@ "response-time": ["response-time@2.3.3", "", { "dependencies": { "depd": "~2.0.0", "on-headers": "~1.0.1" } }, "sha512-SsjjOPHl/FfrTQNgmc5oen8Hr1Jxpn6LlHNXxCIFdYMHuK1kMeYMobb9XN3mvxaGQm3dbegqYFMX4+GDORfbWg=="], - "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], - "rollup": ["rollup@4.34.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.34.0", "@rollup/rollup-android-arm64": "4.34.0", "@rollup/rollup-darwin-arm64": "4.34.0", "@rollup/rollup-darwin-x64": "4.34.0", "@rollup/rollup-freebsd-arm64": "4.34.0", "@rollup/rollup-freebsd-x64": "4.34.0", "@rollup/rollup-linux-arm-gnueabihf": "4.34.0", "@rollup/rollup-linux-arm-musleabihf": "4.34.0", "@rollup/rollup-linux-arm64-gnu": "4.34.0", "@rollup/rollup-linux-arm64-musl": "4.34.0", "@rollup/rollup-linux-loongarch64-gnu": "4.34.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.0", "@rollup/rollup-linux-riscv64-gnu": "4.34.0", "@rollup/rollup-linux-s390x-gnu": "4.34.0", "@rollup/rollup-linux-x64-gnu": "4.34.0", "@rollup/rollup-linux-x64-musl": "4.34.0", "@rollup/rollup-win32-arm64-msvc": "4.34.0", "@rollup/rollup-win32-ia32-msvc": "4.34.0", "@rollup/rollup-win32-x64-msvc": "4.34.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-+4C/cgJ9w6sudisA0nZz0+O7lTP9a3CzNLsoDwaRumM8QHwghUsu6tqHXiTmNUp/rqNiM14++7dkzHDyCRs0Jg=="], "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], @@ -622,8 +593,6 @@ "serve-static": ["serve-static@1.16.2", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.19.0" } }, "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw=="], - "set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="], - "set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="], "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], @@ -638,8 +607,6 @@ "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], - "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - "simple-update-notifier": ["simple-update-notifier@2.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w=="], "sirv": ["sirv@3.0.0", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg=="], @@ -650,8 +617,6 @@ "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], @@ -664,8 +629,6 @@ "swagger-ui-express": ["swagger-ui-express@4.6.3", "", { "dependencies": { "swagger-ui-dist": ">=4.11.0" }, "peerDependencies": { "express": ">=4.0.0 || >=5.0.0-beta" } }, "sha512-CDje4PndhTD2HkgyKH3pab+LKspDeB/NhPN2OF1j+piYIamQqBYwAXWESOT1Yju2xFg51bRW9sUng2WxDjzArw=="], - "tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], @@ -674,8 +637,6 @@ "touch": ["touch@3.1.1", "", { "bin": { "nodetouch": "bin/nodetouch.js" } }, "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA=="], - "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], - "ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-script": "dist/bin-script-deprecated.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="], "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], @@ -688,8 +649,6 @@ "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], "v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="], @@ -700,20 +659,12 @@ "vitefu": ["vitefu@1.0.5", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["vite"] }, "sha512-h4Vflt9gxODPFNGPwp4zAMZRpZR7eslzwH2c5hn5kNZ5rhnKyRJ50U+yGCdc2IRaBs8O4haIgLNGrV5CrpMsCA=="], - "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], - - "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], - - "wide-align": ["wide-align@1.1.5", "", { "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg=="], - "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], - "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], @@ -734,6 +685,8 @@ "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + "elysia/cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], + "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "express-jsdoc-swagger/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -742,14 +695,8 @@ "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "jake/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "make-dir/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], "readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], diff --git a/package.json b/package.json index 0a3ee36..91ac9c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "phish.directory", - "version": "3.0.0", + "version": "4.0.0", "description": "API for phish.directory, a community-driven anti-phishing tool. Helping catch, prevent, and catalog phishing links & attempts.", "maintainers": [ { @@ -18,12 +18,17 @@ "keywords": [], "author": "Jasper Mayone ", "dependencies": { + "@elysiajs/bearer": "^1.2.0", + "@elysiajs/cors": "^1.2.0", + "@elysiajs/cron": "^1.2.0", + "@elysiajs/jwt": "^1.2.0", "@playwright/test": "^1.49.1", "@prisma/client": "6.4.1", "axios": "^1.7.9", "body-parser": "^1.20.3", "colors": "^1.4.0", "dotenv": "^16.4.7", + "elysia-ip": "^1.0.8", "express": "^4.21.2", "express-jsdoc-swagger": "^1.8.0", "express-rate-limit": "^7.5.0", diff --git a/OLD-SRC/defs/headers.ts b/src/defs/headers.ts similarity index 100% rename from OLD-SRC/defs/headers.ts rename to src/defs/headers.ts diff --git a/OLD-SRC/defs/interfaces.ts b/src/defs/interfaces.ts similarity index 100% rename from OLD-SRC/defs/interfaces.ts rename to src/defs/interfaces.ts diff --git a/OLD-SRC/utils/validationError.ts b/src/defs/validationError.ts similarity index 100% rename from OLD-SRC/utils/validationError.ts rename to src/defs/validationError.ts diff --git a/OLD-SRC/utils/db/findOrCreateDomain.ts b/src/func/db/findOrCreateDomain.ts similarity index 94% rename from OLD-SRC/utils/db/findOrCreateDomain.ts rename to src/func/db/findOrCreateDomain.ts index cc3fc65..5e0b72f 100644 --- a/OLD-SRC/utils/db/findOrCreateDomain.ts +++ b/src/func/db/findOrCreateDomain.ts @@ -1,4 +1,4 @@ -import { prisma } from "../../prisma"; +import { prisma } from "../../utils/prisma"; import { checkAndUpdateDomainStatus } from "../domain/checkAndUpdateDomainStatus"; import { domainCheck } from "../domain/domain"; diff --git a/OLD-SRC/utils/db/getDbDomain.ts b/src/func/db/getDbDomain.ts similarity index 77% rename from OLD-SRC/utils/db/getDbDomain.ts rename to src/func/db/getDbDomain.ts index 4e245a5..f796bc2 100644 --- a/OLD-SRC/utils/db/getDbDomain.ts +++ b/src/func/db/getDbDomain.ts @@ -1,5 +1,5 @@ -import { prisma } from "../../prisma"; -import { sanitizeDomain } from "../sanitizeDomain"; +import { prisma } from "../../utils/prisma"; +import { sanitizeDomain } from "../domain/sanitizeDomain"; export async function getDbDomain(domain: string) { let sanitizedDomain = sanitizeDomain(domain); diff --git a/OLD-SRC/utils/db/getDbUser.ts b/src/func/db/getDbUser.ts similarity index 77% rename from OLD-SRC/utils/db/getDbUser.ts rename to src/func/db/getDbUser.ts index 10d28e4..f6cebdc 100644 --- a/OLD-SRC/utils/db/getDbUser.ts +++ b/src/func/db/getDbUser.ts @@ -1,4 +1,4 @@ -import { prisma } from "../../prisma"; +import { prisma } from "../../utils/prisma"; export async function getDbUser(id: number) { const dbUser = await prisma.user.findUnique({ diff --git a/OLD-SRC/utils/domain/checkAndUpdateDomainStatus.ts b/src/func/domain/checkAndUpdateDomainStatus.ts similarity index 100% rename from OLD-SRC/utils/domain/checkAndUpdateDomainStatus.ts rename to src/func/domain/checkAndUpdateDomainStatus.ts diff --git a/OLD-SRC/utils/domain/domain.ts b/src/func/domain/domain.ts similarity index 100% rename from OLD-SRC/utils/domain/domain.ts rename to src/func/domain/domain.ts diff --git a/OLD-SRC/utils/domain/domainReport.ts b/src/func/domain/domainReport.ts similarity index 87% rename from OLD-SRC/utils/domain/domainReport.ts rename to src/func/domain/domainReport.ts index b19d053..cb6ac22 100644 --- a/OLD-SRC/utils/domain/domainReport.ts +++ b/src/func/domain/domainReport.ts @@ -1,6 +1,6 @@ -import axios from "axios"; +import { axios } from "../../utils/axios"; -import { headersWithOTX } from "../../defs/headers"; +import { headersWithOTX } from "../../../src/defs/headers"; import { virusTotalService, walshyService } from "../../services/_index"; /** diff --git a/OLD-SRC/utils/domain/parseData.ts b/src/func/domain/parseData.ts similarity index 100% rename from OLD-SRC/utils/domain/parseData.ts rename to src/func/domain/parseData.ts diff --git a/OLD-SRC/utils/domain/prepareResponse.ts b/src/func/domain/prepareResponse.ts similarity index 94% rename from OLD-SRC/utils/domain/prepareResponse.ts rename to src/func/domain/prepareResponse.ts index 84ad69c..d3260a3 100644 --- a/OLD-SRC/utils/domain/prepareResponse.ts +++ b/src/func/domain/prepareResponse.ts @@ -1,4 +1,4 @@ -import { DomainCheckResponse } from "../../defs/interfaces"; +import { DomainCheckResponse } from "../../../src/defs/interfaces"; import { prisma } from "../../prisma"; import { reportToAlienVault } from "./reportToAlienVault"; diff --git a/OLD-SRC/utils/domain/reportToAlienVault.ts b/src/func/domain/reportToAlienVault.ts similarity index 85% rename from OLD-SRC/utils/domain/reportToAlienVault.ts rename to src/func/domain/reportToAlienVault.ts index d5a32e6..b987194 100644 --- a/OLD-SRC/utils/domain/reportToAlienVault.ts +++ b/src/func/domain/reportToAlienVault.ts @@ -1,5 +1,5 @@ -import axios from "axios"; -import { headersWithOTX } from "../../defs/headers"; +import { headersWithOTX } from "../../../src/defs/headers"; +import { axios } from "../../utils/axios"; /** * Reports a malicious domain to AlienVault OTX diff --git a/OLD-SRC/utils/sanitizeDomain.ts b/src/func/domain/sanitizeDomain.ts similarity index 100% rename from OLD-SRC/utils/sanitizeDomain.ts rename to src/func/domain/sanitizeDomain.ts diff --git a/OLD-SRC/utils/domain/validateAndExtractDomainParams.ts b/src/func/domain/validateAndExtractDomainParams.ts similarity index 93% rename from OLD-SRC/utils/domain/validateAndExtractDomainParams.ts rename to src/func/domain/validateAndExtractDomainParams.ts index 2ad0bde..560ddfd 100644 --- a/OLD-SRC/utils/domain/validateAndExtractDomainParams.ts +++ b/src/func/domain/validateAndExtractDomainParams.ts @@ -1,5 +1,5 @@ +import { ValidationError } from "../../../src/defs/validationError"; import { userNeedsExtendedData } from "../userNeedsExtendedData"; -import { ValidationError } from "../validationError"; /** * Validates the domain parameter and extracts query parameters diff --git a/OLD-SRC/utils/userNeedsExtendedData.ts b/src/func/userNeedsExtendedData.ts similarity index 100% rename from OLD-SRC/utils/userNeedsExtendedData.ts rename to src/func/userNeedsExtendedData.ts diff --git a/OLD-SRC/utils/validateEmail.ts b/src/func/validateEmail.ts similarity index 100% rename from OLD-SRC/utils/validateEmail.ts rename to src/func/validateEmail.ts diff --git a/src/index.ts b/src/index.ts index e98b344..dddf65d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,53 @@ +import { cors } from "@elysiajs/cors"; import { swagger } from "@elysiajs/swagger"; import { Elysia } from "elysia"; +// import { cron } from "@elysiajs/cron"; +// bun add @elysiajs/jwt +// import { randomUUIDv7 } from "bun"; +import { ip } from "elysia-ip"; -import { prisma } from "../OLD-SRC/prisma"; -import { getVersion } from "../OLD-SRC/utils/getVersion"; +import { getVersion } from "./utils/getVersion"; +// import { prisma } from "./utils/prisma"; +import * as logger from "./utils/logger"; let version = getVersion(); +const port: number = Number(process.env.PORT) || 3000; + new Elysia() + .use( + cors({ + maxAge: 86400, + }) + ) + .use(ip()) + // .use( + // cron({ + // name: "updateState", + // pattern: "*/10 * * * * *", + // run() { + + // }, + // }) + // ) .use( swagger({ - // Basic Swagger configuration + exclude: ["/"], documentation: { info: { title: "phish.directory API", version: version, description: "API for phish.directory, a community-driven anti-phishing tool. Helping catch, prevent, and catalog phishing links & attempts", + contact: { + name: "phish.directory", + url: "mailto:team@phish.directory", + email: "team@phish.directory", + }, + // license: { + // name: "AGPL 3.0", + // url: "", + // }, }, tags: [ { name: "Domain", description: "Domain-related operations" }, @@ -41,8 +73,8 @@ new Elysia() // Scalar-specific configuration provider: "scalar", scalarConfig: { - hideDownloadButton: true, - hideTestRequestButton: true, + hideDownloadButton: false, + hideTestRequestButton: false, servers: [ { url: "https://api.phish.directory", @@ -77,14 +109,25 @@ new Elysia() return "Redirecting to /docs"; }) .get("/up", async ({}) => { - // Record start time for ping calculation - const startTime = Date.now(); + return { + status: "up", + }; + }) + .listen(port); - // Check database connectivity with a simple query +// Heartbeat +// new CronJob( +// "0 * * * * *", +// async function () { +// console.log("Thump Thump"); +// // metrics.increment("heartbeat"); +// }, +// null, +// true, +// "America/New_York", +// ); +// - await prisma.$queryRaw`SELECT 1`; - // Calculate ping time - const pingTime = Date.now() - startTime; - // Return success response with database status - }) - .listen(3000); +logger.log(`Server started on port ${port}`, "ready"); +logger.log("Press Ctrl+C to stop the server", "ready"); +logger.log("----\n", "plain"); diff --git a/OLD-SRC/services/GoogleSafebrowsing.ts b/src/services/GoogleSafebrowsing.ts similarity index 88% rename from OLD-SRC/services/GoogleSafebrowsing.ts rename to src/services/GoogleSafebrowsing.ts index c135988..820a3ce 100644 --- a/OLD-SRC/services/GoogleSafebrowsing.ts +++ b/src/services/GoogleSafebrowsing.ts @@ -1,8 +1,7 @@ -import axios from "axios"; - -import { prisma } from "../prisma"; -import { getDbDomain } from "../utils/db/getDbDomain"; -import { sanitizeDomain } from "../utils/sanitizeDomain"; +import { getDbDomain } from "../func/db/getDbDomain"; +import { sanitizeDomain } from "../func/domain/sanitizeDomain"; +import { axios } from "../utils/axios"; +import { prisma } from "../utils/prisma"; /** * A service that provides access to the Google Safebrowsing for checking and reporting domains. diff --git a/OLD-SRC/services/IpQualityScore.ts b/src/services/IpQualityScore.ts similarity index 92% rename from OLD-SRC/services/IpQualityScore.ts rename to src/services/IpQualityScore.ts index 5a9de2a..853df2b 100644 --- a/OLD-SRC/services/IpQualityScore.ts +++ b/src/services/IpQualityScore.ts @@ -1,9 +1,8 @@ -import axios from "axios"; - import { headers } from "../defs/headers"; -import { prisma } from "../prisma"; -import { getDbDomain } from "../utils/db/getDbDomain"; -import { sanitizeDomain } from "../utils/sanitizeDomain"; +import { getDbDomain } from "../func/db/getDbDomain"; +import { sanitizeDomain } from "../func/domain/sanitizeDomain"; +import { axios } from "../utils/axios"; +import { prisma } from "../utils/prisma"; /** * A service that provides access to the IpQualityScore service for checking and reporting domains. diff --git a/OLD-SRC/services/PhishObserver.ts b/src/services/PhishObserver.ts similarity index 93% rename from OLD-SRC/services/PhishObserver.ts rename to src/services/PhishObserver.ts index 5b1b532..084e79f 100644 --- a/OLD-SRC/services/PhishObserver.ts +++ b/src/services/PhishObserver.ts @@ -1,8 +1,10 @@ -import axios, { AxiosError } from "axios"; +import { AxiosError } from "axios"; + import { headersWithPhishObserver } from "../defs/headers"; -import { prisma } from "../prisma"; -import { getDbDomain } from "../utils/db/getDbDomain"; -import { sanitizeDomain } from "../utils/sanitizeDomain"; +import { getDbDomain } from "../func/db/getDbDomain"; +import { sanitizeDomain } from "../func/domain/sanitizeDomain"; +import { axios } from "../utils/axios"; +import { prisma } from "../utils/prisma"; interface PhishObserverError { error: string; diff --git a/OLD-SRC/services/PhishReport.ts b/src/services/PhishReport.ts similarity index 88% rename from OLD-SRC/services/PhishReport.ts rename to src/services/PhishReport.ts index 1cf9476..41267ca 100644 --- a/OLD-SRC/services/PhishReport.ts +++ b/src/services/PhishReport.ts @@ -1,9 +1,8 @@ -import axios from "axios"; - import { headers } from "../defs/headers"; -import { prisma } from "../prisma"; -import { getDbDomain } from "../utils/db/getDbDomain"; -import { sanitizeDomain } from "../utils/sanitizeDomain"; +import { getDbDomain } from "../func/db/getDbDomain"; +import { sanitizeDomain } from "../func/domain/sanitizeDomain"; +import { axios } from "../utils/axios"; +import { prisma } from "../utils/prisma"; /** * A service that provides access to the PhishReport service for checking and reporting domains. diff --git a/OLD-SRC/services/SecurityTrails.ts b/src/services/SecurityTrails.ts similarity index 90% rename from OLD-SRC/services/SecurityTrails.ts rename to src/services/SecurityTrails.ts index 2298cf0..0bc0444 100644 --- a/OLD-SRC/services/SecurityTrails.ts +++ b/src/services/SecurityTrails.ts @@ -1,8 +1,8 @@ -import axios from "axios"; import { headersWithSecurityTrails } from "../defs/headers"; -import { prisma } from "../prisma"; -import { getDbDomain } from "../utils/db/getDbDomain"; -import { sanitizeDomain } from "../utils/sanitizeDomain"; +import { getDbDomain } from "../func/db/getDbDomain"; +import { sanitizeDomain } from "../func/domain/sanitizeDomain"; +import { axios } from "../utils/axios"; +import { prisma } from "../utils/prisma"; /** * A service that provides access to the SecurityTrails service for checking and reporting domains. diff --git a/OLD-SRC/services/SinkingYahts.ts b/src/services/SinkingYahts.ts similarity index 85% rename from OLD-SRC/services/SinkingYahts.ts rename to src/services/SinkingYahts.ts index 384cca7..d067a9c 100644 --- a/OLD-SRC/services/SinkingYahts.ts +++ b/src/services/SinkingYahts.ts @@ -1,9 +1,8 @@ -import axios from "axios"; - import { headersWithSinkingYahts } from "../defs/headers"; -import { prisma } from "../prisma"; -import { getDbDomain } from "../utils/db/getDbDomain"; -import { sanitizeDomain } from "../utils/sanitizeDomain"; +import { getDbDomain } from "../func/db/getDbDomain"; +import { sanitizeDomain } from "../func/domain/sanitizeDomain"; +import { axios } from "../utils/axios"; +import { prisma } from "../utils/prisma"; /** * A service that provides access to the SinkingYahts service for checking and reporting domains. diff --git a/OLD-SRC/services/UrlScan.ts b/src/services/UrlScan.ts similarity index 91% rename from OLD-SRC/services/UrlScan.ts rename to src/services/UrlScan.ts index cc56695..90e1028 100644 --- a/OLD-SRC/services/UrlScan.ts +++ b/src/services/UrlScan.ts @@ -1,9 +1,8 @@ -import axios from "axios"; - import { headersWithUrlScan } from "../defs/headers"; -import { prisma } from "../prisma"; -import { getDbDomain } from "../utils/db/getDbDomain"; -import { sanitizeDomain } from "../utils/sanitizeDomain"; +import { getDbDomain } from "../func/db/getDbDomain"; +import { sanitizeDomain } from "../func/domain/sanitizeDomain"; +import { axios } from "../utils/axios"; +import { prisma } from "../utils/prisma"; /** * A service that provides access to the UrlScan service for checking and reporting domains. diff --git a/OLD-SRC/services/VirusTotal.ts b/src/services/VirusTotal.ts similarity index 93% rename from OLD-SRC/services/VirusTotal.ts rename to src/services/VirusTotal.ts index f0c43b2..a07a951 100644 --- a/OLD-SRC/services/VirusTotal.ts +++ b/src/services/VirusTotal.ts @@ -1,9 +1,8 @@ -import axios from "axios"; - import { headersWithVirusTotal } from "../defs/headers"; -import { prisma } from "../prisma"; -import { getDbDomain } from "../utils/db/getDbDomain"; -import { sanitizeDomain } from "../utils/sanitizeDomain"; +import { getDbDomain } from "../func/db/getDbDomain"; +import { sanitizeDomain } from "../func/domain/sanitizeDomain"; +import { axios } from "../utils/axios"; +import { prisma } from "../utils/prisma"; /** * A service that provides access to the VirusTotal service for checking and reporting domains. diff --git a/OLD-SRC/services/Walshy.ts b/src/services/Walshy.ts similarity index 89% rename from OLD-SRC/services/Walshy.ts rename to src/services/Walshy.ts index 37c10d5..40e67fc 100644 --- a/OLD-SRC/services/Walshy.ts +++ b/src/services/Walshy.ts @@ -1,9 +1,8 @@ -import axios from "axios"; - import { headers } from "../defs/headers"; -import { prisma } from "../prisma"; -import { getDbDomain } from "../utils/db/getDbDomain"; -import { sanitizeDomain } from "../utils/sanitizeDomain"; +import { getDbDomain } from "../func/db/getDbDomain"; +import { sanitizeDomain } from "../func/domain/sanitizeDomain"; +import { axios } from "../utils/axios"; +import { prisma } from "../utils/prisma"; /** * A service that provides access to the Walshy service for checking and reporting domains. diff --git a/OLD-SRC/services/_TEMPLATE.ts b/src/services/_TEMPLATE.ts similarity index 100% rename from OLD-SRC/services/_TEMPLATE.ts rename to src/services/_TEMPLATE.ts diff --git a/OLD-SRC/services/_index.ts b/src/services/_index.ts similarity index 100% rename from OLD-SRC/services/_index.ts rename to src/services/_index.ts diff --git a/src/utils/axios.ts b/src/utils/axios.ts new file mode 100644 index 0000000..31d19ff --- /dev/null +++ b/src/utils/axios.ts @@ -0,0 +1,27 @@ +import axios from "axios"; + +// Add metric interceptors for axios +axios.interceptors.request.use((config: any) => { + config.metadata = { startTs: performance.now() }; + return config; +}); + +axios.interceptors.response.use((res: any) => { + const stat = (res.config.method + "/" + res.config.url?.split("/")[1]) + .toLowerCase() + .replace(/[:.]/g, "") + .replace(/\//g, "_"); + + const httpCode = res.status; + const timingStatKey = `http.request.${stat}`; + const codeStatKey = `http.request.${stat}.${httpCode}`; + // metrics.timing( + // timingStatKey, + // performance.now() - res.config.metadata.startTs + // ); + // metrics.increment(codeStatKey, 1); + + return res; +}); + +export { axios }; diff --git a/src/utils/getVersion.ts b/src/utils/getVersion.ts new file mode 100644 index 0000000..95e8b26 --- /dev/null +++ b/src/utils/getVersion.ts @@ -0,0 +1,10 @@ +// In Bun, you can use direct JSON imports +import packageJson from "../../package.json"; + +export function getVersion(): string { + return packageJson.version; +} + +export function getPackageVersion(packageName: string): string | undefined { + return packageJson.dependencies?.[packageName]; +} diff --git a/OLD-SRC/utils/logger.ts b/src/utils/logger.ts similarity index 84% rename from OLD-SRC/utils/logger.ts rename to src/utils/logger.ts index 95e85d0..99d7564 100644 --- a/OLD-SRC/utils/logger.ts +++ b/src/utils/logger.ts @@ -16,7 +16,8 @@ export const log = ( | "error" | "debug" | "db" - | "ready" = "log", + | "ready" + | "multicolor" = "log" ) => { const timestamp = `${colors.white(`[${moment().format("DD-MM-YY H:m:s")}]`)}`; @@ -27,30 +28,34 @@ export const log = ( return console.log(`${content}`); case "info": return console.log( - `${colors.cyan("[INFO]")} ${timestamp} ${colors.cyan(content)}`, + `${colors.cyan("[INFO]")} ${timestamp} ${colors.cyan(content)}` ); case "warn": return console.log( - `${colors.yellow("[WARN]")} ${timestamp} ${colors.yellow(content)} `, + `${colors.yellow("[WARN]")} ${timestamp} ${colors.yellow(content)} ` ); case "error": return console.log( - `${colors.red("[ERROR]")} ${timestamp} ${colors.red(content)} `, + `${colors.red("[ERROR]")} ${timestamp} ${colors.red(content)} ` ); case "debug": return console.log( - `${colors.green("[DEBUG]")} ${timestamp} ${colors.green(content)} `, + `${colors.green("[DEBUG]")} ${timestamp} ${colors.green(content)} ` ); case "db": { return console.log( `${colors.magenta("[DATABASE]")} ${timestamp} ${colors.magenta( - content, - )} `, + content + )} ` ); } + case "multicolor": + return console.log( + `${colors.rainbow("[LOG]")} ${timestamp} ${colors.rainbow(content)}` + ); case "ready": return console.log( - `${colors.rainbow("[READY]")} ${timestamp} ${colors.rainbow(content)}`, + `${colors.green("[READY]")} ${timestamp} ${colors.green(content)}` ); default: throw new TypeError("Logger type not correct."); diff --git a/OLD-SRC/metrics.ts b/src/utils/metrics.ts similarity index 100% rename from OLD-SRC/metrics.ts rename to src/utils/metrics.ts diff --git a/OLD-SRC/prisma.ts b/src/utils/prisma.ts similarity index 100% rename from OLD-SRC/prisma.ts rename to src/utils/prisma.ts diff --git a/tsconfig.json b/tsconfig.json index 334169e..00207c3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,11 +5,12 @@ "strict": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true, - "rootDir": "OLD-SRC", + "rootDir": "src", "outDir": "dist", "typeRoots": [ "node_modules/@types" ], + "resolveJsonModule": true, "esModuleInterop": true, "noImplicitAny": false },