adjustments to migration after testing

This commit is contained in:
miloschwartz 2025-02-25 22:58:52 -05:00
parent e4789c6b08
commit de70c62ea8
No known key found for this signature in database
5 changed files with 139 additions and 62 deletions

View file

@ -38,13 +38,44 @@ const configSchema = z.object({
save_logs: z.boolean(),
log_failed_attempts: z.boolean().optional()
}),
domains: z.record(
domains: z
.record(
z.string(),
z.object({
base_domain: hostnameSchema.transform((url) => url.toLowerCase()),
base_domain: hostnameSchema.transform((url) =>
url.toLowerCase()
),
cert_resolver: z.string().optional(),
prefer_wildcard_cert: z.boolean().optional()
})
)
.refine(
(domains) => {
const keys = Object.keys(domains);
if (keys.length === 0) {
return false;
}
return true;
},
{
message: "At least one domain must be defined"
}
)
.refine(
(domains) => {
const envBaseDomain = process.env.APP_BASE_DOMAIN;
if (envBaseDomain) {
return hostnameSchema.safeParse(envBaseDomain).success;
}
return true;
},
{
message: "APP_BASE_DOMAIN must be a valid hostname"
}
),
server: z.object({
external_port: portSchema
@ -169,8 +200,6 @@ export class Config {
}
}
public loadEnvironment() {}
public loadConfig() {
const loadConfig = (configPath: string) => {
try {
@ -277,6 +306,17 @@ export class Config {
: "false";
process.env.DASHBOARD_URL = parsedConfig.data.app.dashboard_url;
if (process.env.APP_BASE_DOMAIN) {
console.log(
`DEPRECATED! APP_BASE_DOMAIN is deprecated and will be removed in a future release. Use the domains section in the configuration file instead. See https://docs.fossorial.io/Pangolin/Configuration/config for more information.`
);
parsedConfig.data.domains.domain1 = {
base_domain: process.env.APP_BASE_DOMAIN,
cert_resolver: "letsencrypt"
};
}
this.rawConfig = parsedConfig.data;
}

View file

@ -2,7 +2,7 @@ import path from "path";
import { fileURLToPath } from "url";
// This is a placeholder value replaced by the build process
export const APP_VERSION = "1.0.0-beta.13";
export const APP_VERSION = "1.0.0-beta.15";
export const __FILENAME = fileURLToPath(import.meta.url);
export const __DIRNAME = path.dirname(__FILENAME);

View file

@ -51,6 +51,32 @@ export async function copyInConfig() {
}
}
const allOrgs = await trx.select().from(orgs);
const existingOrgDomains = await trx.select().from(orgDomains);
const existingOrgDomainSet = new Set(
existingOrgDomains.map((od) => `${od.orgId}-${od.domainId}`)
);
const newOrgDomains = [];
for (const org of allOrgs) {
for (const domain of configDomains) {
const key = `${org.orgId}-${domain.domainId}`;
if (!existingOrgDomainSet.has(key)) {
newOrgDomains.push({
orgId: org.orgId,
domainId: domain.domainId
});
}
}
}
if (newOrgDomains.length > 0) {
await trx.insert(orgDomains).values(newOrgDomains).execute();
}
});
await db.transaction(async (trx) => {
const allResources = await trx
.select()
.from(resources)
@ -77,30 +103,6 @@ export async function copyInConfig() {
.set({ fullDomain })
.where(eq(resources.resourceId, resource.resourceId));
}
const allOrgs = await trx.select().from(orgs);
const existingOrgDomains = await trx.select().from(orgDomains);
const existingOrgDomainSet = new Set(
existingOrgDomains.map((od) => `${od.orgId}-${od.domainId}`)
);
const newOrgDomains = [];
for (const org of allOrgs) {
for (const domain of configDomains) {
const key = `${org.orgId}-${domain.domainId}`;
if (!existingOrgDomainSet.has(key)) {
newOrgDomains.push({
orgId: org.orgId,
domainId: domain.domainId
});
}
}
}
if (newOrgDomains.length > 0) {
await trx.insert(orgDomains).values(newOrgDomains).execute();
}
});
// TODO: eventually each exit node could have a different endpoint

View file

@ -15,6 +15,7 @@ import m6 from "./scripts/1.0.0-beta9";
import m7 from "./scripts/1.0.0-beta10";
import m8 from "./scripts/1.0.0-beta12";
import m13 from "./scripts/1.0.0-beta13";
import m15 from "./scripts/1.0.0-beta15";
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
// EXCEPT FOR THE DATABASE AND THE SCHEMA
@ -29,7 +30,8 @@ const migrations = [
{ version: "1.0.0-beta.9", run: m6 },
{ version: "1.0.0-beta.10", run: m7 },
{ version: "1.0.0-beta.12", run: m8 },
{ version: "1.0.0-beta.13", run: m13 }
{ version: "1.0.0-beta.13", run: m13 },
{ version: "1.0.0-beta.15", run: m15 }
// Add new migrations here as they are created
] as const;

View file

@ -3,38 +3,14 @@ import { configFilePath1, configFilePath2 } from "@server/lib/consts";
import fs from "fs";
import yaml from "js-yaml";
import { sql } from "drizzle-orm";
import { domains, orgDomains, resources } from "@server/db/schema";
const version = "1.0.0-beta.15";
export default async function migration() {
console.log(`Running setup script ${version}...`);
try {
db.transaction((trx) => {
trx.run(sql`CREATE TABLE 'domains' (
'domainId' text PRIMARY KEY NOT NULL,
'baseDomain' text NOT NULL,
'configManaged' integer DEFAULT false NOT NULL
);`);
trx.run(sql`CREATE TABLE 'orgDomains' (
'orgId' text NOT NULL,
'domainId' text NOT NULL,
FOREIGN KEY ('orgId') REFERENCES 'orgs'('orgId') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('domainId') REFERENCES 'domains'('domainId') ON UPDATE no action ON DELETE cascade
);`);
trx.run(
sql`ALTER TABLE 'resources' ADD 'domainId' text REFERENCES domains(domainId);`
);
trx.run(sql`ALTER TABLE 'orgs' DROP COLUMN 'domain';`);
});
console.log(`Migrated database schema`);
} catch (e) {
console.log("Unable to migrate database schema");
throw e;
}
let domain = "";
try {
// Determine which config file exists
@ -84,11 +60,68 @@ export default async function migration() {
const updatedYaml = yaml.dump(rawConfig);
fs.writeFileSync(filePath, updatedYaml, "utf8");
domain = baseDomain;
console.log(`Moved base_domain to new domains section`);
} catch (e) {
console.log(
`Unable to migrate config file and move base_domain to domains. Error: ${e}`
);
throw e;
}
try {
db.transaction((trx) => {
trx.run(sql`CREATE TABLE 'domains' (
'domainId' text PRIMARY KEY NOT NULL,
'baseDomain' text NOT NULL,
'configManaged' integer DEFAULT false NOT NULL
);`);
trx.run(sql`CREATE TABLE 'orgDomains' (
'orgId' text NOT NULL,
'domainId' text NOT NULL,
FOREIGN KEY ('orgId') REFERENCES 'orgs'('orgId') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('domainId') REFERENCES 'domains'('domainId') ON UPDATE no action ON DELETE cascade
);`);
trx.run(
sql`ALTER TABLE 'resources' ADD 'domainId' text REFERENCES domains(domainId);`
);
trx.run(sql`ALTER TABLE 'orgs' DROP COLUMN 'domain';`);
});
console.log(`Migrated database schema`);
} catch (e) {
console.log("Unable to migrate database schema");
throw e;
}
try {
await db.transaction(async (trx) => {
await trx
.insert(domains)
.values({
domainId: "domain1",
baseDomain: domain,
configManaged: true
})
.execute();
await trx.update(resources).set({ domainId: "domain1" });
const existingOrgDomains = await trx.select().from(orgDomains);
for (const orgDomain of existingOrgDomains) {
await trx
.insert(orgDomains)
.values({ orgId: orgDomain.orgId, domainId: "domain1" })
.execute();
}
});
console.log(`Updated resources table with new domainId`);
} catch (e) {
console.log(
`Unable to update resources table with new domainId. Error: ${e}`
);
return;
}