Merge branch 'dev' of https://github.com/fosrl/pangolin into dev

This commit is contained in:
miloschwartz
2025-07-15 16:24:26 -07:00
5 changed files with 294 additions and 15 deletions

View File

@@ -89,21 +89,22 @@ export async function createOrg(
);
}
// TODO: for now we are making all of the orgs the same subnet
// make sure the subnet is unique
const subnetExists = await db
.select()
.from(orgs)
.where(eq(orgs.subnet, subnet))
.limit(1);
// const subnetExists = await db
// .select()
// .from(orgs)
// .where(eq(orgs.subnet, subnet))
// .limit(1);
if (subnetExists.length > 0) {
return next(
createHttpError(
HttpCode.CONFLICT,
`Subnet ${subnet} already exists`
)
);
}
// if (subnetExists.length > 0) {
// return next(
// createHttpError(
// HttpCode.CONFLICT,
// `Subnet ${subnet} already exists`
// )
// );
// }
// make sure the orgId is unique
const orgExists = await db

View File

@@ -5,13 +5,15 @@ import { versionMigrations } from "../db/pg";
import { __DIRNAME, APP_VERSION } from "@server/lib/consts";
import path from "path";
import m1 from "./scriptsPg/1.6.0";
import m2 from "./scriptsPg/1.7.0";
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
// EXCEPT FOR THE DATABASE AND THE SCHEMA
// Define the migration list with versions and their corresponding functions
const migrations = [
{ version: "1.6.0", run: m1 }
{ version: "1.6.0", run: m1 },
{ version: "1.7.0", run: m2 }
// Add new migrations here as they are created
] as {
version: string;

View File

@@ -22,6 +22,7 @@ import m18 from "./scriptsSqlite/1.2.0";
import m19 from "./scriptsSqlite/1.3.0";
import m20 from "./scriptsSqlite/1.5.0";
import m21 from "./scriptsSqlite/1.6.0";
import m22 from "./scriptsSqlite/1.7.0";
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
// EXCEPT FOR THE DATABASE AND THE SCHEMA
@@ -43,7 +44,8 @@ const migrations = [
{ version: "1.2.0", run: m18 },
{ version: "1.3.0", run: m19 },
{ version: "1.5.0", run: m20 },
{ version: "1.6.0", run: m21 }
{ version: "1.6.0", run: m21 },
{ version: "1.7.0", run: m22 },
// Add new migrations here as they are created
] as const;

View File

@@ -0,0 +1,118 @@
import { db } from "@server/db/pg/driver";
import { sql } from "drizzle-orm";
const version = "1.7.0";
export default async function migration() {
console.log(`Running setup script ${version}...`);
try {
db.execute(sql`
CREATE TABLE "clientSites" (
"clientId" integer NOT NULL,
"siteId" integer NOT NULL,
"isRelayed" boolean DEFAULT false NOT NULL
);
CREATE TABLE "clients" (
"id" serial PRIMARY KEY NOT NULL,
"orgId" varchar NOT NULL,
"exitNode" integer,
"name" varchar NOT NULL,
"pubKey" varchar,
"subnet" varchar NOT NULL,
"bytesIn" integer,
"bytesOut" integer,
"lastBandwidthUpdate" varchar,
"lastPing" varchar,
"type" varchar NOT NULL,
"online" boolean DEFAULT false NOT NULL,
"endpoint" varchar,
"lastHolePunch" integer,
"maxConnections" integer
);
CREATE TABLE "clientSession" (
"id" varchar PRIMARY KEY NOT NULL,
"olmId" varchar NOT NULL,
"expiresAt" integer NOT NULL
);
CREATE TABLE "olms" (
"id" varchar PRIMARY KEY NOT NULL,
"secretHash" varchar NOT NULL,
"dateCreated" varchar NOT NULL,
"clientId" integer
);
CREATE TABLE "roleClients" (
"roleId" integer NOT NULL,
"clientId" integer NOT NULL
);
CREATE TABLE "webauthnCredentials" (
"credentialId" varchar PRIMARY KEY NOT NULL,
"userId" varchar NOT NULL,
"publicKey" varchar NOT NULL,
"signCount" integer NOT NULL,
"transports" varchar,
"name" varchar,
"lastUsed" varchar NOT NULL,
"dateCreated" varchar NOT NULL,
"securityKeyName" varchar
);
CREATE TABLE "userClients" (
"userId" varchar NOT NULL,
"clientId" integer NOT NULL
);
CREATE TABLE "webauthnChallenge" (
"sessionId" varchar PRIMARY KEY NOT NULL,
"challenge" varchar NOT NULL,
"securityKeyName" varchar,
"userId" varchar,
"expiresAt" bigint NOT NULL
);
ALTER TABLE "limits" DISABLE ROW LEVEL SECURITY;
DROP TABLE "limits" CASCADE;
ALTER TABLE "sites" ALTER COLUMN "subnet" DROP NOT NULL;
ALTER TABLE "sites" ALTER COLUMN "bytesIn" SET DEFAULT 0;
ALTER TABLE "sites" ALTER COLUMN "bytesOut" SET DEFAULT 0;
ALTER TABLE "domains" ADD COLUMN "type" varchar;
ALTER TABLE "domains" ADD COLUMN "verified" boolean DEFAULT false NOT NULL;
ALTER TABLE "domains" ADD COLUMN "failed" boolean DEFAULT false NOT NULL;
ALTER TABLE "domains" ADD COLUMN "tries" integer DEFAULT 0 NOT NULL;
ALTER TABLE "exitNodes" ADD COLUMN "maxConnections" integer;
ALTER TABLE "newt" ADD COLUMN "version" varchar;
ALTER TABLE "orgs" ADD COLUMN "subnet" varchar NOT NULL;
ALTER TABLE "sites" ADD COLUMN "address" varchar;
ALTER TABLE "sites" ADD COLUMN "endpoint" varchar;
ALTER TABLE "sites" ADD COLUMN "publicKey" varchar;
ALTER TABLE "sites" ADD COLUMN "lastHolePunch" bigint;
ALTER TABLE "sites" ADD COLUMN "listenPort" integer;
ALTER TABLE "user" ADD COLUMN "twoFactorSetupRequested" boolean DEFAULT false;
ALTER TABLE "clientSites" ADD CONSTRAINT "clientSites_clientId_clients_id_fk" FOREIGN KEY ("clientId") REFERENCES "public"."clients"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "clientSites" ADD CONSTRAINT "clientSites_siteId_sites_siteId_fk" FOREIGN KEY ("siteId") REFERENCES "public"."sites"("siteId") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "clients" ADD CONSTRAINT "clients_orgId_orgs_orgId_fk" FOREIGN KEY ("orgId") REFERENCES "public"."orgs"("orgId") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "clients" ADD CONSTRAINT "clients_exitNode_exitNodes_exitNodeId_fk" FOREIGN KEY ("exitNode") REFERENCES "public"."exitNodes"("exitNodeId") ON DELETE set null ON UPDATE no action;
ALTER TABLE "clientSession" ADD CONSTRAINT "clientSession_olmId_olms_id_fk" FOREIGN KEY ("olmId") REFERENCES "public"."olms"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "olms" ADD CONSTRAINT "olms_clientId_clients_id_fk" FOREIGN KEY ("clientId") REFERENCES "public"."clients"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "roleClients" ADD CONSTRAINT "roleClients_roleId_roles_roleId_fk" FOREIGN KEY ("roleId") REFERENCES "public"."roles"("roleId") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "roleClients" ADD CONSTRAINT "roleClients_clientId_clients_id_fk" FOREIGN KEY ("clientId") REFERENCES "public"."clients"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "webauthnCredentials" ADD CONSTRAINT "webauthnCredentials_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "userClients" ADD CONSTRAINT "userClients_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "userClients" ADD CONSTRAINT "userClients_clientId_clients_id_fk" FOREIGN KEY ("clientId") REFERENCES "public"."clients"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "webauthnChallenge" ADD CONSTRAINT "webauthnChallenge_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "resources" DROP COLUMN "isBaseDomain";
`);
console.log(`Migrated database schema`);
} catch (e) {
console.log("Unable to migrate database schema");
console.log(e);
}
console.log(`${version} migration complete`);
}

View File

@@ -0,0 +1,156 @@
import { APP_PATH } from "@server/lib/consts";
import Database from "better-sqlite3";
import path from "path";
const version = "1.7.0";
export default async function migration() {
console.log(`Running setup script ${version}...`);
const location = path.join(APP_PATH, "db", "db.sqlite");
const db = new Database(location);
try {
db.transaction(() => {
db.exec(`
CREATE TABLE 'clientSites' (
'clientId' integer NOT NULL,
'siteId' integer NOT NULL,
'isRelayed' integer DEFAULT false NOT NULL,
FOREIGN KEY ('clientId') REFERENCES 'clients'('id') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('siteId') REFERENCES 'sites'('siteId') ON UPDATE no action ON DELETE cascade
);
CREATE TABLE 'clients' (
'id' integer PRIMARY KEY AUTOINCREMENT NOT NULL,
'orgId' text NOT NULL,
'exitNode' integer,
'name' text NOT NULL,
'pubKey' text,
'subnet' text NOT NULL,
'bytesIn' integer,
'bytesOut' integer,
'lastBandwidthUpdate' text,
'lastPing' text,
'type' text NOT NULL,
'online' integer DEFAULT false NOT NULL,
'endpoint' text,
'lastHolePunch' integer,
FOREIGN KEY ('orgId') REFERENCES 'orgs'('orgId') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('exitNode') REFERENCES 'exitNodes'('exitNodeId') ON UPDATE no action ON DELETE set null
);
CREATE TABLE 'clientSession' (
'id' text PRIMARY KEY NOT NULL,
'olmId' text NOT NULL,
'expiresAt' integer NOT NULL,
FOREIGN KEY ('olmId') REFERENCES 'olms'('id') ON UPDATE no action ON DELETE cascade
);
CREATE TABLE 'olms' (
'id' text PRIMARY KEY NOT NULL,
'secretHash' text NOT NULL,
'dateCreated' text NOT NULL,
'clientId' integer,
FOREIGN KEY ('clientId') REFERENCES 'clients'('id') ON UPDATE no action ON DELETE cascade
);
CREATE TABLE 'roleClients' (
'roleId' integer NOT NULL,
'clientId' integer NOT NULL,
FOREIGN KEY ('roleId') REFERENCES 'roles'('roleId') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('clientId') REFERENCES 'clients'('id') ON UPDATE no action ON DELETE cascade
);
CREATE TABLE 'webauthnCredentials' (
'credentialId' text PRIMARY KEY NOT NULL,
'userId' text NOT NULL,
'publicKey' text NOT NULL,
'signCount' integer NOT NULL,
'transports' text,
'name' text,
'lastUsed' text NOT NULL,
'dateCreated' text NOT NULL,
FOREIGN KEY ('userId') REFERENCES 'user'('id') ON UPDATE no action ON DELETE cascade
);
CREATE TABLE 'userClients' (
'userId' text NOT NULL,
'clientId' integer NOT NULL,
FOREIGN KEY ('userId') REFERENCES 'user'('id') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('clientId') REFERENCES 'clients'('id') ON UPDATE no action ON DELETE cascade
);
CREATE TABLE 'userDomains' (
'userId' text NOT NULL,
'domainId' text NOT NULL,
FOREIGN KEY ('userId') REFERENCES 'user'('id') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('domainId') REFERENCES 'domains'('domainId') ON UPDATE no action ON DELETE cascade
);
CREATE TABLE 'webauthnChallenge' (
'sessionId' text PRIMARY KEY NOT NULL,
'challenge' text NOT NULL,
'securityKeyName' text,
'userId' text,
'expiresAt' integer NOT NULL,
FOREIGN KEY ('userId') REFERENCES 'user'('id') ON UPDATE no action ON DELETE cascade
);
`);
})(); // <-- executes the transaction immediately
db.pragma("foreign_keys = OFF");
db.transaction(() => {
db.exec(`
CREATE TABLE '__new_sites' (
'siteId' integer PRIMARY KEY AUTOINCREMENT NOT NULL,
'orgId' text NOT NULL,
'niceId' text NOT NULL,
'exitNode' integer,
'name' text NOT NULL,
'pubKey' text,
'subnet' text,
'bytesIn' integer DEFAULT 0,
'bytesOut' integer DEFAULT 0,
'lastBandwidthUpdate' text,
'type' text NOT NULL,
'online' integer DEFAULT false NOT NULL,
'address' text,
'endpoint' text,
'publicKey' text,
'lastHolePunch' integer,
'listenPort' integer,
'dockerSocketEnabled' integer DEFAULT true NOT NULL,
FOREIGN KEY ('orgId') REFERENCES 'orgs'('orgId') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('exitNode') REFERENCES 'exitNodes'('exitNodeId') ON UPDATE no action ON DELETE set null
);
INSERT INTO '__new_sites'("siteId", "orgId", "niceId", "exitNode", "name", "pubKey", "subnet", "bytesIn", "bytesOut", "lastBandwidthUpdate", "type", "online", "address", "endpoint", "publicKey", "lastHolePunch", "listenPort", "dockerSocketEnabled") SELECT "siteId", "orgId", "niceId", "exitNode", "name", "pubKey", "subnet", "bytesIn", "bytesOut", "lastBandwidthUpdate", "type", "online", "address", "endpoint", "publicKey", "lastHolePunch", "listenPort", "dockerSocketEnabled" FROM 'sites';
DROP TABLE 'sites';
ALTER TABLE '__new_sites' RENAME TO 'sites';
`);
})(); // <-- executes the transaction immediately
db.pragma("foreign_keys = ON");
db.transaction(() => {
db.exec(`
ALTER TABLE 'domains' ADD 'type' text;
ALTER TABLE 'domains' ADD 'verified' integer DEFAULT false NOT NULL;
ALTER TABLE 'domains' ADD 'failed' integer DEFAULT false NOT NULL;
ALTER TABLE 'domains' ADD 'tries' integer DEFAULT 0 NOT NULL;
ALTER TABLE 'exitNodes' ADD 'maxConnections' integer;
ALTER TABLE 'newt' ADD 'version' text;
ALTER TABLE 'orgs' ADD 'subnet' text NOT NULL;
ALTER TABLE 'user' ADD 'twoFactorSetupRequested' integer DEFAULT false;
ALTER TABLE 'resources' DROP COLUMN 'isBaseDomain';
`);
})(); // <-- executes the transaction immediately
console.log(`Migrated database schema`);
} catch (e) {
console.log("Unable to migrate database schema");
console.log(e);
}
console.log(`${version} migration complete`);
}