Skip to content

Commit

Permalink
feat: update VPNServer entity & add internal endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
cybor97 committed Jan 27, 2024
1 parent b21d0e4 commit 79f29ba
Show file tree
Hide file tree
Showing 14 changed files with 749 additions and 47 deletions.
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"@aws-sdk/client-sqs": "^3.495.0",
"better-sqlite3": "^8.7.0",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.2",
"node-cron": "^3.0.3",
"pkg": "^5.8.1",
"telegraf": "^4.15.3",
Expand All @@ -14,6 +16,8 @@
"devDependencies": {
"@types/node": "^20.10.3",
"@types/node-cron": "^3.0.11",
"@types/express": "^4.17.21",
"@types/jsonwebtoken": "^9.0.5",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.3.3"
Expand All @@ -25,7 +29,9 @@
"dev": "nodemon ./src/index.ts",
"build": "tsc -p tsconfig.json",
"start": "node ./dist/src/index.js",
"db": "typeorm-ts-node-commonjs"
"db": "typeorm-ts-node-commonjs",
"db:migration:run": "yarn db migration:run -d src/orm/dataSource.ts",
"db:migration:generate": "yarn db migration:generate -d src/orm/dataSource.ts src/orm/migrations/migration"
},
"author": "rinfly97",
"license": "ISC",
Expand Down
27 changes: 27 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import express, {
ErrorRequestHandler,
NextFunction,
Request,
Response,
} from "express";
import internal from "./internal";
import logger from "../utils/logger";
import { inspect } from "util";

export function getApi() {
const app = express();

app.use(internal);

app.use(((
err: Error,
_req: Request,
res: Response,
_next: () => NextFunction
) => {
logger.error(`[api] Unexpected error ${err.message} ${inspect(err)}`);
res.status(500).send("Unknown error");
}) as ErrorRequestHandler);

return app;
}
8 changes: 8 additions & 0 deletions src/api/internal/getServers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Request, Response } from "express";
import { VPNServerService } from "../../services/VPNServerService";

export async function getServers(_req: Request, res: Response): Promise<void> {
const vpnServerService = VPNServerService.getService();
const vpnServers = await vpnServerService.getAll();
res.status(200).send(vpnServers);
}
25 changes: 25 additions & 0 deletions src/api/internal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Router } from "express";
import jwt, { JwtPayload } from "jsonwebtoken";
import config from "../../config";
import logger from "../../utils/logger";
import { getServers } from "./getServers";

const router = Router();

router.use((req, res, next) => {
try {
const jwtData = jwt.verify(
req.headers.authorization as string,
config.api.internalJwtSecret
) as JwtPayload;
logger.info(`[Internal] ${req.method} ${req.path} (${jwtData.app})`);
next();
} catch (e) {
res.status(401).send("Unauthorized");
return;
}
});

router.get("/internal/servers", getServers);

export default router;
4 changes: 4 additions & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ export default {
agentQueueUrl: process.env.SQS_AGENT_QUEUE_URL as string,
appQueueUrl: process.env.SQS_APP_QUEUE_URL as string,
},
api: {
internalJwtSecret: process.env.API_INTERNAL_JWT_SECRET as string,
port: process.env.API_PORT ?? "8083",
},
};
12 changes: 12 additions & 0 deletions src/entryPoints/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import logger from "../utils/logger";
import { getApi } from "../api";
import config from "../config";

export async function initAPI(): Promise<void> {
await new Promise<void>((resolve) =>
getApi().listen(config.api.port, resolve)
);
logger.info(
`[api][initAPI] API initialized, listening on port ${config.api.port}`
);
}
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import pkg from "../package.json";
import "dotenv/config";
import pkg from "../package.json";
import { initBot } from "./entryPoints/bot";
import { initCron } from "./entryPoints/cron";
import { initSQS } from "./entryPoints/sqs";
import AppDataSource from "./orm/dataSource";
import logger from "./utils/logger";
import { initAPI } from "./entryPoints/api";

async function main() {
logger.info(`[main] Starting ovpnrental(v${pkg.version})`);
await AppDataSource.initialize();
await initCron();
await initBot();
await initSQS();
await initAPI();
}

main();
15 changes: 15 additions & 0 deletions src/orm/dao/VPNServerDao.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Repository } from "typeorm";
import AppDataSource from "../dataSource";
import { VPNServer } from "../entities/VPNServer";

export class VPNServerDao {
private vpnServerRepository: Repository<VPNServer>;

public constructor() {
this.vpnServerRepository = AppDataSource.getRepository(VPNServer);
}

public async getServers(): Promise<VPNServer[]> {
return await this.vpnServerRepository.find();
}
}
10 changes: 7 additions & 3 deletions src/orm/dao/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import { User } from "../entities/User";
import { UserKey } from "../entities/UserKey";
import { UserRent } from "../entities/UserRent";
import { VPNServer } from "../entities/VPNServer";
import { UserDao } from "./UserDao";
import { UserKeyDao } from "./UserKeyDao";
import { UserRentDao } from "./UserRentDao";
import { VPNServerDao } from "./VPNServerDao";

export abstract class Dao {
public static async getDao<T extends Dao | null>(
type: typeof User | typeof UserKey | typeof UserRent
): Promise<T> {
public static getDao<T extends Dao | null>(
type: typeof User | typeof UserKey | typeof UserRent | typeof VPNServer
): T {
switch (type) {
case UserKey:
return new UserKeyDao() as Dao as T;
case UserRent:
return new UserRentDao() as Dao as T;
case User:
return new UserDao() as Dao as T;
case VPNServer:
return new VPNServerDao() as Dao as T;
default:
return null as T;
}
Expand Down
2 changes: 2 additions & 0 deletions src/orm/dataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { existsSync, mkdirSync } from "fs";
import logger from "../utils/logger";
import { UpdateUserKey1705184832393 } from "./migrations/1705184832393-UpdateUserKey";
import { AddCreatedAt1705958731396 } from "./migrations/1705958731396-AddCreatedAt";
import { UpdateVPNServer1706360105938 } from "./migrations/1706360105938-UpdateVPNServer";

const dbDir = join(homedir(), ".config/vpnrental");
const dbPath = join(dbDir, "vpnrental.sqlite");
Expand All @@ -26,6 +27,7 @@ const AppDataSource = new DataSource({
AddServer1702326435123,
UpdateUserKey1705184832393,
AddCreatedAt1705958731396,
UpdateVPNServer1706360105938
],
});

Expand Down
19 changes: 8 additions & 11 deletions src/orm/entities/VPNServer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ export class VPNServer {
@PrimaryGeneratedColumn()
id: number;

@Column('varchar')
ipAddress: string;
@Column("varchar")
host: string;

@Column('integer')
name: string;
@Column("varchar")
countryIsoCode: string;

@Column('varchar')
region: string;
@Column("varchar")
agentQueueName: string;

@Column('varchar')
agentVersionInstalled: number;

@Column('varchar')
agentInstalledAt: number;
@Column("json")
tags: string[];

@OneToMany(() => UserKey, (userKey) => userKey.vpnServer)
userKeys: UserKey[];
Expand Down
19 changes: 19 additions & 0 deletions src/orm/migrations/1706360105938-UpdateVPNServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from "typeorm";

export class UpdateVPNServer1706360105938 implements MigrationInterface {
name = "UpdateVPNServer1706360105938";

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "vpn_server"`);
await queryRunner.query(
`CREATE TABLE "vpn_server" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "host" varchar NOT NULL, "countryIsoCode" varchar NOT NULL, "agentQueueName" varchar NOT NULL, "tags" json NOT NULL)`
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "vpn_server"`);
await queryRunner.query(
`CREATE TABLE "vpn_server" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "ipAddress" varchar NOT NULL, "name" integer NOT NULL, "region" varchar NOT NULL, "agentVersionInstalled" varchar NOT NULL, "agentInstalledAt" varchar NOT NULL)`
);
}
}
19 changes: 19 additions & 0 deletions src/services/VPNServerService/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Dao } from "../../orm/dao";
import { VPNServerDao } from "../../orm/dao/VPNServerDao";
import { VPNServer } from "../../orm/entities/VPNServer";

export class VPNServerService {
private vpnServerDao: VPNServerDao;
constructor(vpnServerDao: VPNServerDao) {
this.vpnServerDao = vpnServerDao;
}

public static getService(): VPNServerService {
const vpnServerDao = Dao.getDao<VPNServerDao>(VPNServer);
return new VPNServerService(vpnServerDao);
}

public async getAll(): Promise<Array<VPNServer>> {
return this.vpnServerDao.getServers();
}
}
Loading

0 comments on commit 79f29ba

Please sign in to comment.