mirror of
https://github.com/fosrl/pangolin.git
synced 2025-07-22 19:55:37 +02:00
adjustments to migration after testing
This commit is contained in:
parent
e4789c6b08
commit
de70c62ea8
5 changed files with 139 additions and 62 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue