mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-28 13:48:13 +02:00
rename auth and start work separating config
This commit is contained in:
parent
d447de9e8a
commit
b199595100
15 changed files with 153 additions and 120 deletions
|
@ -12,12 +12,12 @@ import { eq } from "drizzle-orm";
|
||||||
import config from "@server/config";
|
import config from "@server/config";
|
||||||
import type { RandomReader } from "@oslojs/crypto/random";
|
import type { RandomReader } from "@oslojs/crypto/random";
|
||||||
import { generateRandomString } from "@oslojs/crypto/random";
|
import { generateRandomString } from "@oslojs/crypto/random";
|
||||||
|
import { extractBaseDomain } from "@server/utils/extractBaseDomain";
|
||||||
|
|
||||||
export const SESSION_COOKIE_NAME = config.server.session_cookie_name;
|
export const SESSION_COOKIE_NAME = config.server.session_cookie_name;
|
||||||
export const SESSION_COOKIE_EXPIRES = 1000 * 60 * 60 * 24 * 30;
|
export const SESSION_COOKIE_EXPIRES = 1000 * 60 * 60 * 24 * 30;
|
||||||
export const SECURE_COOKIES = config.server.secure_cookies;
|
export const SECURE_COOKIES = config.server.secure_cookies;
|
||||||
export const COOKIE_DOMAIN =
|
export const COOKIE_DOMAIN = "." + extractBaseDomain(config.app.base_url);
|
||||||
"." + new URL(config.app.base_url).hostname.split(".").slice(-2).join(".");
|
|
||||||
|
|
||||||
export function generateSessionToken(): string {
|
export function generateSessionToken(): string {
|
||||||
const bytes = new Uint8Array(20);
|
const bytes = new Uint8Array(20);
|
||||||
|
|
|
@ -9,12 +9,12 @@ import { Newt, newts, newtSessions, NewtSession } from "@server/db/schema";
|
||||||
import db from "@server/db";
|
import db from "@server/db";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import config from "@server/config";
|
import config from "@server/config";
|
||||||
|
import { extractBaseDomain } from "@server/utils/extractBaseDomain";
|
||||||
|
|
||||||
export const SESSION_COOKIE_NAME = "session";
|
export const SESSION_COOKIE_NAME = "session";
|
||||||
export const SESSION_COOKIE_EXPIRES = 1000 * 60 * 60 * 24 * 30;
|
export const SESSION_COOKIE_EXPIRES = 1000 * 60 * 60 * 24 * 30;
|
||||||
export const SECURE_COOKIES = config.server.secure_cookies;
|
export const SECURE_COOKIES = config.server.secure_cookies;
|
||||||
export const COOKIE_DOMAIN =
|
export const COOKIE_DOMAIN = "." + extractBaseDomain(config.app.base_url);
|
||||||
"." + new URL(config.app.base_url).hostname.split(".").slice(-2).join(".");
|
|
||||||
|
|
||||||
export async function createNewtSession(
|
export async function createNewtSession(
|
||||||
token: string,
|
token: string,
|
||||||
|
|
|
@ -8,12 +8,12 @@ import {
|
||||||
import db from "@server/db";
|
import db from "@server/db";
|
||||||
import { eq, and } from "drizzle-orm";
|
import { eq, and } from "drizzle-orm";
|
||||||
import config from "@server/config";
|
import config from "@server/config";
|
||||||
|
import { extractBaseDomain } from "@server/utils/extractBaseDomain";
|
||||||
|
|
||||||
export const SESSION_COOKIE_NAME = "resource_session";
|
export const SESSION_COOKIE_NAME = "resource_session";
|
||||||
export const SESSION_COOKIE_EXPIRES = 1000 * 60 * 60 * 24 * 30;
|
export const SESSION_COOKIE_EXPIRES = 1000 * 60 * 60 * 24 * 30;
|
||||||
export const SECURE_COOKIES = config.server.secure_cookies;
|
export const SECURE_COOKIES = config.server.secure_cookies;
|
||||||
export const COOKIE_DOMAIN =
|
export const COOKIE_DOMAIN = "." + extractBaseDomain(config.app.base_url);
|
||||||
"." + new URL(config.app.base_url).hostname.split(".").slice(-2).join(".");
|
|
||||||
|
|
||||||
export async function createResourceSession(opts: {
|
export async function createResourceSession(opts: {
|
||||||
token: string;
|
token: string;
|
||||||
|
|
193
server/config.ts
193
server/config.ts
|
@ -1,9 +1,9 @@
|
||||||
import { z } from "zod";
|
|
||||||
import { fromError } from "zod-validation-error";
|
|
||||||
import path from "path";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
|
import path from "path";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { fromError } from "zod-validation-error";
|
||||||
|
|
||||||
export const __FILENAME = fileURLToPath(import.meta.url);
|
export const __FILENAME = fileURLToPath(import.meta.url);
|
||||||
export const __DIRNAME = path.dirname(__FILENAME);
|
export const __DIRNAME = path.dirname(__FILENAME);
|
||||||
|
@ -79,102 +79,125 @@ const environmentSchema = z.object({
|
||||||
.optional()
|
.optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export function getConfig() {
|
export class Config {
|
||||||
const loadConfig = (configPath: string) => {
|
private rawConfig!: z.infer<typeof environmentSchema>;
|
||||||
try {
|
|
||||||
const yamlContent = fs.readFileSync(configPath, "utf8");
|
|
||||||
const config = yaml.load(yamlContent);
|
|
||||||
return config;
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof Error) {
|
|
||||||
throw new Error(
|
|
||||||
`Error loading configuration file: ${error.message}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const configFilePath1 = path.join(APP_PATH, "config.yml");
|
constructor() {
|
||||||
const configFilePath2 = path.join(APP_PATH, "config.yaml");
|
this.loadConfig();
|
||||||
|
|
||||||
let environment: any;
|
|
||||||
if (fs.existsSync(configFilePath1)) {
|
|
||||||
environment = loadConfig(configFilePath1);
|
|
||||||
} else if (fs.existsSync(configFilePath2)) {
|
|
||||||
environment = loadConfig(configFilePath2);
|
|
||||||
}
|
}
|
||||||
if (!environment) {
|
|
||||||
const exampleConfigPath = path.join(__DIRNAME, "config.example.yml");
|
public getRawConfig() {
|
||||||
if (fs.existsSync(exampleConfigPath)) {
|
return this.rawConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public loadConfig() {
|
||||||
|
const loadConfig = (configPath: string) => {
|
||||||
try {
|
try {
|
||||||
const exampleConfigContent = fs.readFileSync(
|
const yamlContent = fs.readFileSync(configPath, "utf8");
|
||||||
exampleConfigPath,
|
const config = yaml.load(yamlContent);
|
||||||
"utf8"
|
return config;
|
||||||
);
|
|
||||||
fs.writeFileSync(configFilePath1, exampleConfigContent, "utf8");
|
|
||||||
environment = loadConfig(configFilePath1);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Error creating configuration file from example: ${error.message}`
|
`Error loading configuration file: ${error.message}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
} else {
|
};
|
||||||
throw new Error(
|
|
||||||
"No configuration file found and no example configuration available"
|
const configFilePath1 = path.join(APP_PATH, "config.yml");
|
||||||
|
const configFilePath2 = path.join(APP_PATH, "config.yaml");
|
||||||
|
|
||||||
|
let environment: any;
|
||||||
|
if (fs.existsSync(configFilePath1)) {
|
||||||
|
environment = loadConfig(configFilePath1);
|
||||||
|
} else if (fs.existsSync(configFilePath2)) {
|
||||||
|
environment = loadConfig(configFilePath2);
|
||||||
|
}
|
||||||
|
if (!environment) {
|
||||||
|
const exampleConfigPath = path.join(
|
||||||
|
__DIRNAME,
|
||||||
|
"config.example.yml"
|
||||||
);
|
);
|
||||||
|
if (fs.existsSync(exampleConfigPath)) {
|
||||||
|
try {
|
||||||
|
const exampleConfigContent = fs.readFileSync(
|
||||||
|
exampleConfigPath,
|
||||||
|
"utf8"
|
||||||
|
);
|
||||||
|
fs.writeFileSync(
|
||||||
|
configFilePath1,
|
||||||
|
exampleConfigContent,
|
||||||
|
"utf8"
|
||||||
|
);
|
||||||
|
environment = loadConfig(configFilePath1);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
throw new Error(
|
||||||
|
`Error creating configuration file from example: ${
|
||||||
|
error.message
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"No configuration file found and no example configuration available"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!environment) {
|
if (!environment) {
|
||||||
throw new Error("No configuration file found");
|
throw new Error("No configuration file found");
|
||||||
}
|
|
||||||
|
|
||||||
const parsedConfig = environmentSchema.safeParse(environment);
|
|
||||||
|
|
||||||
if (!parsedConfig.success) {
|
|
||||||
const errors = fromError(parsedConfig.error);
|
|
||||||
throw new Error(`Invalid configuration file: ${errors}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const packageJsonPath = path.join(__DIRNAME, "..", "package.json");
|
|
||||||
let packageJson: any;
|
|
||||||
if (fs.existsSync && fs.existsSync(packageJsonPath)) {
|
|
||||||
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf8");
|
|
||||||
packageJson = JSON.parse(packageJsonContent);
|
|
||||||
|
|
||||||
if (packageJson.version) {
|
|
||||||
process.env.APP_VERSION = packageJson.version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const parsedConfig = environmentSchema.safeParse(environment);
|
||||||
|
|
||||||
|
if (!parsedConfig.success) {
|
||||||
|
const errors = fromError(parsedConfig.error);
|
||||||
|
throw new Error(`Invalid configuration file: ${errors}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const packageJsonPath = path.join(__DIRNAME, "..", "package.json");
|
||||||
|
let packageJson: any;
|
||||||
|
if (fs.existsSync && fs.existsSync(packageJsonPath)) {
|
||||||
|
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf8");
|
||||||
|
packageJson = JSON.parse(packageJsonContent);
|
||||||
|
|
||||||
|
if (packageJson.version) {
|
||||||
|
process.env.APP_VERSION = packageJson.version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.env.NEXT_PORT = parsedConfig.data.server.next_port.toString();
|
||||||
|
process.env.SERVER_EXTERNAL_PORT =
|
||||||
|
parsedConfig.data.server.external_port.toString();
|
||||||
|
process.env.SERVER_INTERNAL_PORT =
|
||||||
|
parsedConfig.data.server.internal_port.toString();
|
||||||
|
process.env.FLAGS_EMAIL_VERIFICATION_REQUIRED = parsedConfig.data.flags
|
||||||
|
?.require_email_verification
|
||||||
|
? "true"
|
||||||
|
: "false";
|
||||||
|
process.env.SESSION_COOKIE_NAME =
|
||||||
|
parsedConfig.data.server.session_cookie_name;
|
||||||
|
process.env.RESOURCE_SESSION_COOKIE_NAME =
|
||||||
|
parsedConfig.data.server.resource_session_cookie_name;
|
||||||
|
process.env.EMAIL_ENABLED = parsedConfig.data.email ? "true" : "false";
|
||||||
|
process.env.DISABLE_SIGNUP_WITHOUT_INVITE = parsedConfig.data.flags
|
||||||
|
?.disable_signup_without_invite
|
||||||
|
? "true"
|
||||||
|
: "false";
|
||||||
|
process.env.DISABLE_USER_CREATE_ORG = parsedConfig.data.flags
|
||||||
|
?.disable_user_create_org
|
||||||
|
? "true"
|
||||||
|
: "false";
|
||||||
|
|
||||||
|
this.rawConfig = parsedConfig.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
process.env.NEXT_PORT = parsedConfig.data.server.next_port.toString();
|
|
||||||
process.env.SERVER_EXTERNAL_PORT =
|
|
||||||
parsedConfig.data.server.external_port.toString();
|
|
||||||
process.env.SERVER_INTERNAL_PORT =
|
|
||||||
parsedConfig.data.server.internal_port.toString();
|
|
||||||
process.env.FLAGS_EMAIL_VERIFICATION_REQUIRED = parsedConfig.data.flags
|
|
||||||
?.require_email_verification
|
|
||||||
? "true"
|
|
||||||
: "false";
|
|
||||||
process.env.SESSION_COOKIE_NAME =
|
|
||||||
parsedConfig.data.server.session_cookie_name;
|
|
||||||
process.env.RESOURCE_SESSION_COOKIE_NAME =
|
|
||||||
parsedConfig.data.server.resource_session_cookie_name;
|
|
||||||
process.env.EMAIL_ENABLED = parsedConfig.data.email ? "true" : "false";
|
|
||||||
process.env.DISABLE_SIGNUP_WITHOUT_INVITE = parsedConfig.data.flags
|
|
||||||
?.disable_signup_without_invite
|
|
||||||
? "true"
|
|
||||||
: "false";
|
|
||||||
process.env.DISABLE_USER_CREATE_ORG = parsedConfig.data.flags
|
|
||||||
?.disable_user_create_org
|
|
||||||
? "true"
|
|
||||||
: "false";
|
|
||||||
|
|
||||||
return parsedConfig.data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getConfig();
|
export const config = new Config();
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import logger from "@server/logger";
|
||||||
export async function sendEmail(
|
export async function sendEmail(
|
||||||
template: ReactElement,
|
template: ReactElement,
|
||||||
opts: {
|
opts: {
|
||||||
name: string | undefined;
|
name?: string;
|
||||||
from: string | undefined;
|
from: string | undefined;
|
||||||
to: string | undefined;
|
to: string | undefined;
|
||||||
subject: string;
|
subject: string;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { createAdminRole } from "@server/setup/ensureActions";
|
||||||
import config from "@server/config";
|
import config from "@server/config";
|
||||||
import { fromError } from "zod-validation-error";
|
import { fromError } from "zod-validation-error";
|
||||||
import { defaultRoleAllowedActions } from "../role";
|
import { defaultRoleAllowedActions } from "../role";
|
||||||
|
import { extractBaseDomain } from "@server/utils/extractBaseDomain";
|
||||||
|
|
||||||
const createOrgSchema = z
|
const createOrgSchema = z
|
||||||
.object({
|
.object({
|
||||||
|
@ -83,7 +84,7 @@ export async function createOrg(
|
||||||
|
|
||||||
await db.transaction(async (trx) => {
|
await db.transaction(async (trx) => {
|
||||||
// create a url from config.app.base_url and get the hostname
|
// create a url from config.app.base_url and get the hostname
|
||||||
const domain = new URL(config.app.base_url).hostname;
|
const domain = extractBaseDomain(config.app.base_url);
|
||||||
|
|
||||||
const newOrg = await trx
|
const newOrg = await trx
|
||||||
.insert(orgs)
|
.insert(orgs)
|
||||||
|
|
|
@ -53,8 +53,6 @@ export async function createResource(
|
||||||
|
|
||||||
let { name, subdomain } = parsedBody.data;
|
let { name, subdomain } = parsedBody.data;
|
||||||
|
|
||||||
subdomain = subdomain.toLowerCase(); // always to lower case
|
|
||||||
|
|
||||||
// Validate request params
|
// Validate request params
|
||||||
const parsedParams = createResourceParamsSchema.safeParse(req.params);
|
const parsedParams = createResourceParamsSchema.safeParse(req.params);
|
||||||
if (!parsedParams.success) {
|
if (!parsedParams.success) {
|
||||||
|
|
|
@ -41,8 +41,6 @@ export async function traefikConfigProvider(
|
||||||
const badgerMiddlewareName = "badger";
|
const badgerMiddlewareName = "badger";
|
||||||
const redirectMiddlewareName = "redirect-to-https";
|
const redirectMiddlewareName = "redirect-to-https";
|
||||||
|
|
||||||
// const baseDomain = new URL(config.app.base_url).hostname;
|
|
||||||
|
|
||||||
const http: any = {
|
const http: any = {
|
||||||
routers: {},
|
routers: {},
|
||||||
services: {},
|
services: {},
|
||||||
|
|
|
@ -3,10 +3,11 @@ import { orgs } from "../db/schema";
|
||||||
import config from "@server/config";
|
import config from "@server/config";
|
||||||
import { ne } from "drizzle-orm";
|
import { ne } from "drizzle-orm";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
|
import { extractBaseDomain } from "@server/utils/extractBaseDomain";
|
||||||
|
|
||||||
export async function copyInConfig() {
|
export async function copyInConfig() {
|
||||||
// create a url from config.app.base_url and get the hostname
|
// create a url from config.app.base_url and get the hostname
|
||||||
const domain = new URL(config.app.base_url).hostname;
|
const domain = extractBaseDomain(config.app.base_url);
|
||||||
|
|
||||||
// update the domain on all of the orgs where the domain is not equal to the new domain
|
// update the domain on all of the orgs where the domain is not equal to the new domain
|
||||||
// TODO: eventually each org could have a unique domain that we do not want to overwrite, so this will be unnecessary
|
// TODO: eventually each org could have a unique domain that we do not want to overwrite, so this will be unnecessary
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
import { ensureActions } from "./ensureActions";
|
import { ensureActions } from "./ensureActions";
|
||||||
import { copyInConfig } from "./copyInConfig";
|
import { copyInConfig } from "./copyInConfig";
|
||||||
import logger from "@server/logger";
|
|
||||||
import { runMigrations } from "./migrations";
|
import { runMigrations } from "./migrations";
|
||||||
import { setupServerAdmin } from "./setupServerAdmin";
|
import { setupServerAdmin } from "./setupServerAdmin";
|
||||||
|
import { loadConfig } from "@server/config";
|
||||||
|
|
||||||
export async function runSetupFunctions() {
|
export async function runSetupFunctions() {
|
||||||
try {
|
try {
|
||||||
logger.info(`Setup for version ${process.env.APP_VERSION}`);
|
|
||||||
await runMigrations(); // run the migrations
|
await runMigrations(); // run the migrations
|
||||||
|
|
||||||
|
console.log("Migrations completed successfully.")
|
||||||
|
|
||||||
|
// ANYTHING BEFORE THIS LINE CANNOT USE THE CONFIG
|
||||||
|
loadConfig();
|
||||||
|
|
||||||
await copyInConfig(); // copy in the config to the db as needed
|
await copyInConfig(); // copy in the config to the db as needed
|
||||||
await setupServerAdmin();
|
await setupServerAdmin();
|
||||||
await ensureActions(); // make sure all of the actions are in the db and the roles
|
await ensureActions(); // make sure all of the actions are in the db and the roles
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("Error running setup functions", error);
|
console.error("Error running setup functions:", error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import logger from "@server/logger";
|
|
||||||
import { __DIRNAME } from "@server/config";
|
import { __DIRNAME } from "@server/config";
|
||||||
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
||||||
import db, { exists } from "@server/db";
|
import db, { exists } from "@server/db";
|
||||||
|
@ -8,12 +7,12 @@ import { versionMigrations } from "@server/db/schema";
|
||||||
import { desc } from "drizzle-orm";
|
import { desc } from "drizzle-orm";
|
||||||
|
|
||||||
// Import all migrations explicitly
|
// Import all migrations explicitly
|
||||||
import migration100beta1 from "./scripts/1.0.0-beta1";
|
import m1 from "./scripts/1.0.0-beta1";
|
||||||
// Add new migration imports here as they are created
|
// Add new migration imports here as they are created
|
||||||
|
|
||||||
// Define the migration list with versions and their corresponding functions
|
// Define the migration list with versions and their corresponding functions
|
||||||
const migrations = [
|
const migrations = [
|
||||||
{ version: "1.0.0-beta.1", run: migration100beta1 }
|
{ version: "1.0.0-beta.1", run: m1 }
|
||||||
// Add new migrations here as they are created
|
// Add new migrations here as they are created
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
@ -23,21 +22,21 @@ export async function runMigrations() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.ENVIRONMENT !== "prod") {
|
if (process.env.ENVIRONMENT !== "prod") {
|
||||||
logger.info("Skipping migrations in non-prod environment");
|
console.info("Skipping migrations in non-prod environment");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists) {
|
if (exists) {
|
||||||
await executeScripts();
|
await executeScripts();
|
||||||
} else {
|
} else {
|
||||||
logger.info("Running migrations...");
|
console.info("Running migrations...");
|
||||||
try {
|
try {
|
||||||
migrate(db, {
|
migrate(db, {
|
||||||
migrationsFolder: path.join(__DIRNAME, "init") // put here during the docker build
|
migrationsFolder: path.join(__DIRNAME, "init") // put here during the docker build
|
||||||
});
|
});
|
||||||
logger.info("Migrations completed successfully.");
|
console.info("Migrations completed successfully.");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("Error running migrations:", error);
|
console.error("Error running migrations:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert process.env.APP_VERSION into the versionMigrations table
|
// insert process.env.APP_VERSION into the versionMigrations table
|
||||||
|
@ -61,7 +60,7 @@ async function executeScripts() {
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
const startVersion = lastExecuted[0]?.version ?? "0.0.0";
|
const startVersion = lastExecuted[0]?.version ?? "0.0.0";
|
||||||
logger.info(`Starting migrations from version ${startVersion}`);
|
console.info(`Starting migrations from version ${startVersion}`);
|
||||||
|
|
||||||
// Filter and sort migrations
|
// Filter and sort migrations
|
||||||
const pendingMigrations = migrations
|
const pendingMigrations = migrations
|
||||||
|
@ -70,7 +69,7 @@ async function executeScripts() {
|
||||||
|
|
||||||
// Run migrations in order
|
// Run migrations in order
|
||||||
for (const migration of pendingMigrations) {
|
for (const migration of pendingMigrations) {
|
||||||
logger.info(`Running migration ${migration.version}`);
|
console.info(`Running migration ${migration.version}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await migration.run();
|
await migration.run();
|
||||||
|
@ -84,11 +83,11 @@ async function executeScripts() {
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
logger.info(
|
console.info(
|
||||||
`Successfully completed migration ${migration.version}`
|
`Successfully completed migration ${migration.version}`
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(
|
console.error(
|
||||||
`Failed to run migration ${migration.version}:`,
|
`Failed to run migration ${migration.version}:`,
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
|
@ -96,9 +95,9 @@ async function executeScripts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("All migrations completed successfully");
|
console.info("All migrations completed successfully");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("Migration process failed:", error);
|
console.error("Migration process failed:", error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
|
|
||||||
export default async function migration100beta1() {
|
export default async function migration() {
|
||||||
logger.info("Running setup script 1.0.0-beta.1");
|
logger.info("Running setup script 1.0.0-beta.1");
|
||||||
// SQL operations would go here in ts format
|
// SQL operations would go here in ts format
|
||||||
logger.info("Done...");
|
logger.info("Done...");
|
||||||
|
|
11
server/utils/extractBaseDomain.ts
Normal file
11
server/utils/extractBaseDomain.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
export function extractBaseDomain(url: string): string {
|
||||||
|
const newUrl = new URL(url);
|
||||||
|
const hostname = newUrl.hostname;
|
||||||
|
const parts = hostname.split(".");
|
||||||
|
|
||||||
|
if (parts.length <= 2) {
|
||||||
|
return parts.join(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.slice(1).join(".");
|
||||||
|
}
|
|
@ -398,7 +398,7 @@ export default function ResourceAuthenticationPage() {
|
||||||
onCheckedChange={(val) => setSsoEnabled(val)}
|
onCheckedChange={(val) => setSsoEnabled(val)}
|
||||||
/>
|
/>
|
||||||
<Label htmlFor="sso-toggle">
|
<Label htmlFor="sso-toggle">
|
||||||
Allow Unified Login
|
Use Platform SSO
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-muted-foreground text-sm">
|
<span className="text-muted-foreground text-sm">
|
||||||
|
|
|
@ -44,7 +44,6 @@ export default async function InvitePage(props: {
|
||||||
await authCookieHeader()
|
await authCookieHeader()
|
||||||
)
|
)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error(e);
|
|
||||||
error = formatAxiosError(e);
|
error = formatAxiosError(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -68,8 +67,6 @@ export default async function InvitePage(props: {
|
||||||
|
|
||||||
const type = cardType();
|
const type = cardType();
|
||||||
|
|
||||||
console.log("card type is", type, error)
|
|
||||||
|
|
||||||
if (!user && type === "user_does_not_exist") {
|
if (!user && type === "user_does_not_exist") {
|
||||||
redirect(`/auth/signup?redirect=/invite?token=${params.token}`);
|
redirect(`/auth/signup?redirect=/invite?token=${params.token}`);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue