diff --git a/package.json b/package.json index 4d9180f1..bb1e6a8d 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "dev": "dotenvx run -- tsx watch server/index.ts", "db:generate": "drizzle-kit generate", - "db:push": "drizzle-kit push", + "db:push": "npx tsx scripts/runMigrations.ts", "db:studio": "drizzle-kit studio" }, "dependencies": { diff --git a/scripts/runMigrations.ts b/scripts/runMigrations.ts new file mode 100644 index 00000000..67d9172d --- /dev/null +++ b/scripts/runMigrations.ts @@ -0,0 +1,27 @@ +import { drizzle } from 'drizzle-orm/better-sqlite3'; +import { migrate } from 'drizzle-orm/better-sqlite3/migrator'; +import Database from 'better-sqlite3'; + +const runMigrations = async () => { + // Create a new SQLite database connection + const sqlite = new Database('./config/db/db.sqlite'); + + // Create a Drizzle instance + const db = drizzle(sqlite); + + console.log('Running migrations...'); + + try { + // Run the migrations + await migrate(db, { migrationsFolder: './server/migrations' }); + console.log('Migrations completed successfully.'); + } catch (error) { + console.error('Error running migrations:', error); + process.exit(1); + } finally { + // Close the database connection + sqlite.close(); + } +}; + +runMigrations(); \ No newline at end of file diff --git a/server/db/schema.ts b/server/db/schema.ts index 4880ba77..7f326ade 100644 --- a/server/db/schema.ts +++ b/server/db/schema.ts @@ -1,61 +1,70 @@ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core"; import { InferSelectModel } from "drizzle-orm"; -// Org table -export const org = sqliteTable("org", { +// Orgs table +export const orgs = sqliteTable("orgs", { orgId: integer("orgId").primaryKey({ autoIncrement: true }), name: text("name").notNull(), + domain: text("domain").notNull(), }); // Users table export const users = sqliteTable("users", { - uid: integer("uid").primaryKey({ autoIncrement: true }), - orgId: integer("orgId").references(() => org.orgId), - name: text("name"), - email: text("email"), + userId: integer("userId").primaryKey({ autoIncrement: true }), + orgId: integer("orgId").references(() => orgs.orgId), + name: text("name").notNull(), + email: text("email").notNull(), groups: text("groups"), }); // Sites table export const sites = sqliteTable("sites", { siteId: integer("siteId").primaryKey({ autoIncrement: true }), - orgId: integer("orgId").references(() => org.orgId), - name: text("name"), - autoSubdomain: text("autoSubdomain"), - pubKey: integer("pubKey"), - subnet: text("subnet"), + orgId: integer("orgId").references(() => orgs.orgId), exitNode: integer("exitNode").references(() => exitNodes.exitNodeId), + name: text("name").notNull(), + subdomain: text("subdomain"), + pubKey: text("pubKey"), + subnet: text("subnet"), }); // Resources table export const resources = sqliteTable("resources", { resourceId: integer("resourceId").primaryKey({ autoIncrement: true }), siteId: integer("siteId").references(() => sites.siteId), - name: text("name"), - targetIp: text("targetIp"), - method: text("method"), - port: integer("port"), - proto: text("proto"), + name: text("name").notNull(), + subdomain: text("subdomain"), }); // Exit Nodes table export const exitNodes = sqliteTable("exitNodes", { exitNodeId: integer("exitNodeId").primaryKey({ autoIncrement: true }), - name: text("name"), - address: integer("address"), + name: text("name").notNull(), + address: text("address").notNull(), }); // Routes table export const routes = sqliteTable("routes", { routeId: integer("routeId").primaryKey({ autoIncrement: true }), - subnet: integer("subnet"), exitNodeId: integer("exitNodeId").references(() => exitNodes.exitNodeId), + subnet: text("subnet").notNull(), +}); + +// Targets table +export const targets = sqliteTable("targets", { + targetId: integer("targetId").primaryKey({ autoIncrement: true }), + resourceId: integer("resourceId").references(() => resources.resourceId), + ip: text("ip").notNull(), + method: text("method"), + port: integer("port"), + protocol: text("protocol"), }); // Define the model types for type inference -export type Org = InferSelectModel; +export type Org = InferSelectModel; export type User = InferSelectModel; export type Site = InferSelectModel; export type Resource = InferSelectModel; export type ExitNode = InferSelectModel; export type Route = InferSelectModel; +export type Target = InferSelectModel; \ No newline at end of file diff --git a/server/index.ts b/server/index.ts index 1d014ea5..23c8516f 100644 --- a/server/index.ts +++ b/server/index.ts @@ -19,7 +19,8 @@ let db: Database.Database; app.prepare().then(() => { // Open the SQLite database connection - const sqlite = new Database(`${environment.CONFIG_PATH}/db/db.sqlite`, { verbose: console.log }); + // const sqlite = new Database(`${environment.CONFIG_PATH}/db/db.sqlite`, { verbose: console.log }); + const sqlite = new Database(`${environment.CONFIG_PATH}/db/db.sqlite`); const db = drizzle(sqlite); // Main server diff --git a/server/migrations/0000_lowly_robin_chapel.sql b/server/migrations/0000_short_ulik.sql similarity index 55% rename from server/migrations/0000_lowly_robin_chapel.sql rename to server/migrations/0000_short_ulik.sql index 2cf9334a..84c95510 100644 --- a/server/migrations/0000_lowly_robin_chapel.sql +++ b/server/migrations/0000_short_ulik.sql @@ -1,49 +1,57 @@ CREATE TABLE `exitNodes` ( `exitNodeId` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `name` text, - `address` integer + `name` text NOT NULL, + `address` text NOT NULL ); --> statement-breakpoint -CREATE TABLE `org` ( +CREATE TABLE `orgs` ( `orgId` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `name` text NOT NULL + `name` text NOT NULL, + `domain` text NOT NULL ); --> statement-breakpoint CREATE TABLE `resources` ( `resourceId` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `siteId` integer, - `name` text, - `targetIp` text, - `method` text, - `port` integer, - `proto` text, + `name` text NOT NULL, + `subdomain` text, FOREIGN KEY (`siteId`) REFERENCES `sites`(`siteId`) ON UPDATE no action ON DELETE no action ); --> statement-breakpoint CREATE TABLE `routes` ( `routeId` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `subnet` integer, `exitNodeId` integer, + `subnet` text NOT NULL, FOREIGN KEY (`exitNodeId`) REFERENCES `exitNodes`(`exitNodeId`) ON UPDATE no action ON DELETE no action ); --> statement-breakpoint CREATE TABLE `sites` ( `siteId` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `orgId` integer, - `name` text, - `autoSubdomain` text, - `pubKey` integer, - `subnet` text, `exitNode` integer, - FOREIGN KEY (`orgId`) REFERENCES `org`(`orgId`) ON UPDATE no action ON DELETE no action, + `name` text NOT NULL, + `subdomain` text, + `pubKey` text, + `subnet` text, + FOREIGN KEY (`orgId`) REFERENCES `orgs`(`orgId`) ON UPDATE no action ON DELETE no action, FOREIGN KEY (`exitNode`) REFERENCES `exitNodes`(`exitNodeId`) ON UPDATE no action ON DELETE no action ); --> statement-breakpoint -CREATE TABLE `users` ( - `uid` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `orgId` integer, - `name` text, - `email` text, - `groups` text, - FOREIGN KEY (`orgId`) REFERENCES `org`(`orgId`) ON UPDATE no action ON DELETE no action +CREATE TABLE `targets` ( + `targetId` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `resourceId` integer, + `ip` text NOT NULL, + `method` text, + `port` integer, + `protocol` text, + FOREIGN KEY (`resourceId`) REFERENCES `resources`(`resourceId`) ON UPDATE no action ON DELETE no action +); +--> statement-breakpoint +CREATE TABLE `users` ( + `userId` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `orgId` integer, + `name` text NOT NULL, + `email` text NOT NULL, + `groups` text, + FOREIGN KEY (`orgId`) REFERENCES `orgs`(`orgId`) ON UPDATE no action ON DELETE no action ); diff --git a/server/migrations/meta/0000_snapshot.json b/server/migrations/meta/0000_snapshot.json index 11e8a859..5a16c25d 100644 --- a/server/migrations/meta/0000_snapshot.json +++ b/server/migrations/meta/0000_snapshot.json @@ -1,7 +1,7 @@ { "version": "6", "dialect": "sqlite", - "id": "a06283ff-bd4b-4994-988c-4db3279f73dd", + "id": "9b039f4c-6867-4b08-8aa9-bc184c37b910", "prevId": "00000000-0000-0000-0000-000000000000", "tables": { "exitNodes": { @@ -18,14 +18,14 @@ "name": "name", "type": "text", "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false }, "address": { "name": "address", - "type": "integer", + "type": "text", "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false } }, @@ -34,8 +34,8 @@ "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "org": { - "name": "org", + "orgs": { + "name": "orgs", "columns": { "orgId": { "name": "orgId", @@ -50,6 +50,13 @@ "primaryKey": false, "notNull": true, "autoincrement": false + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false } }, "indexes": {}, @@ -78,32 +85,11 @@ "name": "name", "type": "text", "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false }, - "targetIp": { - "name": "targetIp", - "type": "text", - "primaryKey": false, - "notNull": false, - "autoincrement": false - }, - "method": { - "name": "method", - "type": "text", - "primaryKey": false, - "notNull": false, - "autoincrement": false - }, - "port": { - "name": "port", - "type": "integer", - "primaryKey": false, - "notNull": false, - "autoincrement": false - }, - "proto": { - "name": "proto", + "subdomain": { + "name": "subdomain", "type": "text", "primaryKey": false, "notNull": false, @@ -139,19 +125,19 @@ "notNull": true, "autoincrement": true }, - "subnet": { - "name": "subnet", - "type": "integer", - "primaryKey": false, - "notNull": false, - "autoincrement": false - }, "exitNodeId": { "name": "exitNodeId", "type": "integer", "primaryKey": false, "notNull": false, "autoincrement": false + }, + "subnet": { + "name": "subnet", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false } }, "indexes": {}, @@ -190,15 +176,22 @@ "notNull": false, "autoincrement": false }, - "name": { - "name": "name", - "type": "text", + "exitNode": { + "name": "exitNode", + "type": "integer", "primaryKey": false, "notNull": false, "autoincrement": false }, - "autoSubdomain": { - "name": "autoSubdomain", + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subdomain": { + "name": "subdomain", "type": "text", "primaryKey": false, "notNull": false, @@ -206,7 +199,7 @@ }, "pubKey": { "name": "pubKey", - "type": "integer", + "type": "text", "primaryKey": false, "notNull": false, "autoincrement": false @@ -217,21 +210,14 @@ "primaryKey": false, "notNull": false, "autoincrement": false - }, - "exitNode": { - "name": "exitNode", - "type": "integer", - "primaryKey": false, - "notNull": false, - "autoincrement": false } }, "indexes": {}, "foreignKeys": { - "sites_orgId_org_orgId_fk": { - "name": "sites_orgId_org_orgId_fk", + "sites_orgId_orgs_orgId_fk": { + "name": "sites_orgId_orgs_orgId_fk", "tableFrom": "sites", - "tableTo": "org", + "tableTo": "orgs", "columnsFrom": [ "orgId" ], @@ -258,11 +244,76 @@ "compositePrimaryKeys": {}, "uniqueConstraints": {} }, + "targets": { + "name": "targets", + "columns": { + "targetId": { + "name": "targetId", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "resourceId": { + "name": "resourceId", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "protocol": { + "name": "protocol", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "targets_resourceId_resources_resourceId_fk": { + "name": "targets_resourceId_resources_resourceId_fk", + "tableFrom": "targets", + "tableTo": "resources", + "columnsFrom": [ + "resourceId" + ], + "columnsTo": [ + "resourceId" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, "users": { "name": "users", "columns": { - "uid": { - "name": "uid", + "userId": { + "name": "userId", "type": "integer", "primaryKey": true, "notNull": true, @@ -279,14 +330,14 @@ "name": "name", "type": "text", "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false }, "email": { "name": "email", "type": "text", "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false }, "groups": { @@ -299,10 +350,10 @@ }, "indexes": {}, "foreignKeys": { - "users_orgId_org_orgId_fk": { - "name": "users_orgId_org_orgId_fk", + "users_orgId_orgs_orgId_fk": { + "name": "users_orgId_orgs_orgId_fk", "tableFrom": "users", - "tableTo": "org", + "tableTo": "orgs", "columnsFrom": [ "orgId" ], diff --git a/server/migrations/meta/_journal.json b/server/migrations/meta/_journal.json index 604bb4c3..abe1f447 100644 --- a/server/migrations/meta/_journal.json +++ b/server/migrations/meta/_journal.json @@ -5,8 +5,8 @@ { "idx": 0, "version": "6", - "when": 1727538753952, - "tag": "0000_lowly_robin_chapel", + "when": 1727544220529, + "tag": "0000_short_ulik", "breakpoints": true } ]