Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
{
"extends": [
"@bonadocs"
]
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
"@typescript-eslint/no-explicit-any": "warn",
"prefer-const": "error",
"no-var": "error"
},
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"env": {
"node": true,
"es6": true
}
}
3,413 changes: 566 additions & 2,847 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"type": "private",
"url": "https://github.com/bonadocs/api"
},
"prettier": "@bonadocs/prettier-config",
"prettier": {},
"scripts": {
"build": "rm -rf dist/ && tsc -p tsconfig.build.json",
"watch:build": "tsc -p tsconfig.build.json -w",
Expand All @@ -27,8 +27,6 @@
"lint": "prettier -c \"src/**/*.ts{,x}\" && eslint src --ext .ts"
},
"dependencies": {
"@bonadocs/di": "^1.0.0",
"@bonadocs/logger": "^1.0.0",
"@paddle/paddle-node-sdk": "^2.7.0",
"axios": "^1.7.9",
"body-parser": "^1.20.3",
Expand All @@ -53,7 +51,6 @@
"typedi": "^0.10.0"
},
"devDependencies": {
"@bonadocs/eslint-config": "latest",
"@jest/globals": "^29.7.0",
"@types/cors": "^2.8.17",
"@types/node": "^22.5.4",
Expand All @@ -62,8 +59,11 @@
"@types/randomstring": "^1.3.0",
"@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.7",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"class-validator-jsonschema": "^5.0.1",
"dotenv": "^16.4.5",
"eslint": "^8.57.1",
"husky": "^9.1.7",
"jest": "^29.7.0",
"prettier": "^3.4.2",
Expand Down
40 changes: 20 additions & 20 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { validationMetadatasToSchemas } from 'class-validator-jsonschema';
import express from 'express';
import helmet from 'helmet';
import { getMetadataArgsStorage, useExpressServer } from 'routing-controllers';
import { routingControllersToSpec } from 'routing-controllers-openapi';
import swaggerUi from 'swagger-ui-express';
import { validationMetadatasToSchemas } from "class-validator-jsonschema";
import express from "express";
import helmet from "helmet";
import { getMetadataArgsStorage, useExpressServer } from "routing-controllers";
import { routingControllersToSpec } from "routing-controllers-openapi";
import swaggerUi from "swagger-ui-express";

import { diMiddleware, useScopedContainer } from '@bonadocs/di';
import { rootLoggerMiddleware } from '@bonadocs/logger';
import { diMiddleware, useScopedContainer } from "@bonadocs/di";
import { rootLoggerMiddleware } from "@bonadocs/logger";

import {
AdminMiddleware,
Expand All @@ -16,7 +16,7 @@ import {
healthcheckMiddleware,
useCors,
webhookMiddleware,
} from './middleware';
} from "./middleware";
import {
AuthController,
BillingController,
Expand All @@ -26,29 +26,29 @@ import {
ProjectController,
SubscriptionController,
TenderlyController,
} from './modules';
} from "./modules";
import {
MonitorPaymentStatus,
SubscriptionExpirationCheck,
SubscriptionRenewalSetup,
} from './modules/cron';
} from "./modules/cron";

const app = express();
const configService = getConfigService();

// add middleware
app.use(helmet());
useCors(app);
app.use('/v1/billing/webhook', express.raw({ type: '*/*' }));
app.use("/v1/billing/webhook", express.raw({ type: "*/*" }));
app.use(webhookMiddleware);
app.use(express.json({ limit: '300kb' }));
app.use(express.json({ limit: "300kb" }));

// add this before the logger to avoid unnecessary healthcheck
// request logs
app.use(healthcheckMiddleware);

const schemas = validationMetadatasToSchemas({
refPointerPrefix: '#/components/schemas/',
refPointerPrefix: "#/components/schemas/",
});

const spec = routingControllersToSpec(
Expand All @@ -59,13 +59,13 @@ const spec = routingControllersToSpec(
schemas: schemas as any,
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
type: "http",
scheme: "bearer",
bearerFormat: "JWT",
},
},
},
info: { title: 'API Docs', version: '1.0.0' },
info: { title: "API Docs", version: "1.0.0" },
security: [{ bearerAuth: [] }],
},
);
Expand All @@ -78,7 +78,7 @@ app.use(diMiddleware);
// use the scoped container for routing-controllers
useScopedContainer();

const routePrefix = '/v1';
const routePrefix = "/v1";
spec.paths = Object.keys(spec.paths).reduce(
(paths, path) => {
paths[`${routePrefix}${path}`] = spec.paths[path];
Expand All @@ -87,7 +87,7 @@ spec.paths = Object.keys(spec.paths).reduce(
{} as Record<string, any>,
);

app.use('/docs', ...swaggerUi.serve, swaggerUi.setup(spec));
app.use("/docs", ...swaggerUi.serve, swaggerUi.setup(spec));

useExpressServer(app, {
routePrefix,
Expand Down
2 changes: 1 addition & 1 deletion src/env.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { validateEnvVars } from './modules/configuration';
import { validateEnvVars } from "./modules/configuration";
// This is run on startup to ensure that all required environment variables are
// set before the application starts

Expand Down
4 changes: 2 additions & 2 deletions src/localserver.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import 'dotenv/config';
import './server';
import "dotenv/config";
import "./server";
42 changes: 25 additions & 17 deletions src/middleware/admin.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,44 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Request, Response } from 'express';
import { ExpressMiddlewareInterface, Middleware } from 'routing-controllers';
import { Inject, Service } from 'typedi';
import { Request, Response } from "express";
import { ExpressMiddlewareInterface, Middleware } from "routing-controllers";
import { Inject, Service } from "typedi";

import { diConstants } from '@bonadocs/di';
import { BonadocsLogger } from '@bonadocs/logger';
import { diConstants } from "@bonadocs/di";
import { BonadocsLogger } from "@bonadocs/logger";

@Service()
@Middleware({ type: 'before' })
@Middleware({ type: "before" })
export class AdminMiddleware implements ExpressMiddlewareInterface {
constructor(@Inject(diConstants.logger) private readonly logger: BonadocsLogger) {}
constructor(
@Inject(diConstants.logger) private readonly logger: BonadocsLogger,
) {}

async use(request: Request, response: Response, next: (err?: any) => any): Promise<any> {
async use(
request: Request,
response: Response,
next: (err?: any) => any,
): Promise<any> {
// todo : find a better fix for this
const adminPaths = ['/coupons'];
const isAdminPath = adminPaths.some((path) => request.path.startsWith(path));
const adminPaths = ["/coupons"];
const isAdminPath = adminPaths.some((path) =>
request.path.startsWith(path),
);
if (!isAdminPath) {
return next();
}
const token = request.headers.authorization?.split(' ')[1];
const token = request.headers.authorization?.split(" ")[1];
if (!token) {
this.logger.error('Admin token is missing');
this.logger.error("Admin token is missing");
return response.status(401).json({
message: 'Admin token is missing',
status: 'error',
message: "Admin token is missing",
status: "error",
});
}
if (token !== process.env.ADMIN_TOKEN) {
this.logger.error('Invalid admin token');
this.logger.error("Invalid admin token");
return response.status(403).json({
message: 'Invalid admin token',
status: 'error',
message: "Invalid admin token",
status: "error",
});
}
return next();
Expand Down
45 changes: 27 additions & 18 deletions src/middleware/auth.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,56 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { Request, Response } from 'express';
import { ExpressMiddlewareInterface, Middleware } from 'routing-controllers';
import { Inject, Service } from 'typedi';
import { Request, Response } from "express";
import { ExpressMiddlewareInterface, Middleware } from "routing-controllers";
import { Inject, Service } from "typedi";

import { diConstants } from '@bonadocs/di';
import type { BonadocsLogger } from '@bonadocs/logger';
import { diConstants } from "@bonadocs/di";
import type { BonadocsLogger } from "@bonadocs/logger";

import { AuthService } from '../modules/auth/auth.service';
import { ApplicationError, applicationErrorCodes } from '../modules/errors/ApplicationError';
import { AuthService } from "../modules/auth/auth.service";
import {
ApplicationError,
applicationErrorCodes,
} from "../modules/errors/ApplicationError";

@Service()
@Middleware({ type: 'before' })
@Middleware({ type: "before" })
export class AuthMiddleware implements ExpressMiddlewareInterface {
constructor(
@Inject(diConstants.logger) private readonly logger: BonadocsLogger,
@Inject() private readonly authService: AuthService,
) {}

async use(request: Request, response: Response, next: (err?: any) => any): Promise<any> {
async use(
request: Request,
response: Response,
next: (err?: any) => any,
): Promise<any> {
// todo : find a better fix for this
const exemptPaths = [
'/auth/login',
'/auth/register',
'/auth/refresh',
'/billing/webhook',
'/coupons',
"/auth/login",
"/auth/register",
"/auth/refresh",
"/billing/webhook",
"/coupons",
];
const isExemptPath = exemptPaths.some((path) => request.path.startsWith(path));
const isExemptPath = exemptPaths.some((path) =>
request.path.startsWith(path),
);
if (isExemptPath) {
return next();
}
const token = request.headers.authorization?.split(' ')[1];
const token = request.headers.authorization?.split(" ")[1];
try {
const authData = await this.authService.getCurrentUser(token!);
request.auth = authData;
} catch (error) {
this.logger.error(`An error occurred while validating token, ${error}`);
throw new ApplicationError({
message: 'Invalid token',
message: "Invalid token",
logger: request.logger,
errorCode: applicationErrorCodes.unauthenticated,
userFriendlyMessage: 'Invalid Token',
userFriendlyMessage: "Invalid Token",
statusCode: 401,
});
}
Expand Down
12 changes: 6 additions & 6 deletions src/middleware/cors.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import cors from 'cors';
import { Application } from 'express';
import cors from "cors";
import { Application } from "express";

import { getConfigService } from '../modules';
import { getConfigService } from "../modules";

export function useCors(app: Application): void {
const configService = getConfigService();
app.use(
cors({
origin: configService.getTransformed('corsOrigins'),
origin: configService.getTransformed("corsOrigins"),
maxAge: 3600,
methods: '*',
allowedHeaders: 'Content-Type, Authorization',
methods: "*",
allowedHeaders: "Content-Type, Authorization",
}),
);
}
Loading
Loading