mirror of
https://github.com/fosrl/pangolin.git
synced 2025-07-28 14:44:55 +02:00
Merge branch 'dev' into clients-pops
This commit is contained in:
commit
acf25e8ad7
20 changed files with 14219 additions and 14178 deletions
105
package-lock.json
generated
105
package-lock.json
generated
|
@ -14041,111 +14041,6 @@
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"zod": "^3.24.4"
|
"zod": "^3.24.4"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"node_modules/@next/swc-darwin-x64": {
|
|
||||||
"version": "15.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.3.tgz",
|
|
||||||
"integrity": "sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@next/swc-linux-arm64-gnu": {
|
|
||||||
"version": "15.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.3.tgz",
|
|
||||||
"integrity": "sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@next/swc-linux-arm64-musl": {
|
|
||||||
"version": "15.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.3.tgz",
|
|
||||||
"integrity": "sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@next/swc-linux-x64-gnu": {
|
|
||||||
"version": "15.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.3.tgz",
|
|
||||||
"integrity": "sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@next/swc-linux-x64-musl": {
|
|
||||||
"version": "15.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.3.tgz",
|
|
||||||
"integrity": "sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@next/swc-win32-arm64-msvc": {
|
|
||||||
"version": "15.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.3.tgz",
|
|
||||||
"integrity": "sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@next/swc-win32-x64-msvc": {
|
|
||||||
"version": "15.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz",
|
|
||||||
"integrity": "sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,9 @@ const externalPort = config.getRawConfig().server.external_port;
|
||||||
export function createApiServer() {
|
export function createApiServer() {
|
||||||
const apiServer = express();
|
const apiServer = express();
|
||||||
|
|
||||||
if (config.getRawConfig().server.trust_proxy) {
|
const trustProxy = config.getRawConfig().server.trust_proxy;
|
||||||
apiServer.set("trust proxy", 1);
|
if (trustProxy) {
|
||||||
|
apiServer.set("trust proxy", trustProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
const corsConfig = config.getRawConfig().server.cors;
|
const corsConfig = config.getRawConfig().server.cors;
|
||||||
|
|
|
@ -35,8 +35,9 @@ class RedisManager {
|
||||||
password: redisConfig.password,
|
password: redisConfig.password,
|
||||||
db: redisConfig.db,
|
db: redisConfig.db,
|
||||||
tls: {
|
tls: {
|
||||||
rejectUnauthorized: false
|
rejectUnauthorized:
|
||||||
},
|
redisConfig.tls?.reject_unauthorized || false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return opts;
|
return opts;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ export const configSchema = z
|
||||||
credentials: z.boolean().optional()
|
credentials: z.boolean().optional()
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
trust_proxy: z.boolean().optional().default(true),
|
trust_proxy: z.number().int().gte(0).optional().default(1),
|
||||||
secret: z
|
secret: z
|
||||||
.string()
|
.string()
|
||||||
.optional()
|
.optional()
|
||||||
|
@ -133,7 +133,7 @@ export const configSchema = z
|
||||||
db: z.number().int().nonnegative().optional().default(0),
|
db: z.number().int().nonnegative().optional().default(0),
|
||||||
tls: z
|
tls: z
|
||||||
.object({
|
.object({
|
||||||
rejectUnauthorized: z.boolean().optional().default(true)
|
reject_unauthorized: z.boolean().optional().default(true)
|
||||||
})
|
})
|
||||||
.optional()
|
.optional()
|
||||||
})
|
})
|
||||||
|
|
|
@ -23,8 +23,8 @@ export const loginBodySchema = z
|
||||||
.object({
|
.object({
|
||||||
email: z
|
email: z
|
||||||
.string()
|
.string()
|
||||||
.email()
|
.toLowerCase()
|
||||||
.transform((v) => v.toLowerCase()),
|
.email(),
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
code: z.string().optional()
|
code: z.string().optional()
|
||||||
})
|
})
|
||||||
|
|
|
@ -20,8 +20,8 @@ export const requestPasswordResetBody = z
|
||||||
.object({
|
.object({
|
||||||
email: z
|
email: z
|
||||||
.string()
|
.string()
|
||||||
.email()
|
.toLowerCase()
|
||||||
.transform((v) => v.toLowerCase())
|
.email(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ export const resetPasswordBody = z
|
||||||
.object({
|
.object({
|
||||||
email: z
|
email: z
|
||||||
.string()
|
.string()
|
||||||
.email()
|
.toLowerCase()
|
||||||
.transform((v) => v.toLowerCase()),
|
.email(),
|
||||||
token: z.string(), // reset secret code
|
token: z.string(), // reset secret code
|
||||||
newPassword: passwordSchema,
|
newPassword: passwordSchema,
|
||||||
code: z.string().optional() // 2fa code
|
code: z.string().optional() // 2fa code
|
||||||
|
|
|
@ -26,8 +26,8 @@ import { UserType } from "@server/types/UserTypes";
|
||||||
export const signupBodySchema = z.object({
|
export const signupBodySchema = z.object({
|
||||||
email: z
|
email: z
|
||||||
.string()
|
.string()
|
||||||
.email()
|
.toLowerCase()
|
||||||
.transform((v) => v.toLowerCase()),
|
.email(),
|
||||||
password: passwordSchema,
|
password: passwordSchema,
|
||||||
inviteToken: z.string().optional(),
|
inviteToken: z.string().optional(),
|
||||||
inviteId: z.string().optional()
|
inviteId: z.string().optional()
|
||||||
|
|
|
@ -172,10 +172,10 @@ export async function validateOidcCallback(
|
||||||
const claims = arctic.decodeIdToken(idToken);
|
const claims = arctic.decodeIdToken(idToken);
|
||||||
logger.debug("ID token claims", { claims });
|
logger.debug("ID token claims", { claims });
|
||||||
|
|
||||||
const userIdentifier = jmespath.search(
|
let userIdentifier = jmespath.search(
|
||||||
claims,
|
claims,
|
||||||
existingIdp.idpOidcConfig.identifierPath
|
existingIdp.idpOidcConfig.identifierPath
|
||||||
);
|
) as string | null;
|
||||||
|
|
||||||
if (!userIdentifier) {
|
if (!userIdentifier) {
|
||||||
return next(
|
return next(
|
||||||
|
@ -186,6 +186,8 @@ export async function validateOidcCallback(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userIdentifier = userIdentifier.toLowerCase();
|
||||||
|
|
||||||
logger.debug("User identifier", { userIdentifier });
|
logger.debug("User identifier", { userIdentifier });
|
||||||
|
|
||||||
let email = null;
|
let email = null;
|
||||||
|
@ -209,6 +211,10 @@ export async function validateOidcCallback(
|
||||||
logger.debug("User email", { email });
|
logger.debug("User email", { email });
|
||||||
logger.debug("User name", { name });
|
logger.debug("User name", { name });
|
||||||
|
|
||||||
|
if (email) {
|
||||||
|
email = email.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
const [existingUser] = await db
|
const [existingUser] = await db
|
||||||
.select()
|
.select()
|
||||||
.from(users)
|
.from(users)
|
||||||
|
|
|
@ -22,8 +22,8 @@ const authWithWhitelistBodySchema = z
|
||||||
.object({
|
.object({
|
||||||
email: z
|
email: z
|
||||||
.string()
|
.string()
|
||||||
.email()
|
.toLowerCase()
|
||||||
.transform((v) => v.toLowerCase()),
|
.email(),
|
||||||
otp: z.string().optional()
|
otp: z.string().optional()
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
|
@ -39,7 +39,7 @@ const createHttpResourceSchema = z
|
||||||
isBaseDomain: z.boolean().optional(),
|
isBaseDomain: z.boolean().optional(),
|
||||||
siteId: z.number(),
|
siteId: z.number(),
|
||||||
http: z.boolean(),
|
http: z.boolean(),
|
||||||
protocol: z.string(),
|
protocol: z.enum(["tcp", "udp"]),
|
||||||
domainId: z.string()
|
domainId: z.string()
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
|
@ -71,7 +71,7 @@ const createRawResourceSchema = z
|
||||||
name: z.string().min(1).max(255),
|
name: z.string().min(1).max(255),
|
||||||
siteId: z.number(),
|
siteId: z.number(),
|
||||||
http: z.boolean(),
|
http: z.boolean(),
|
||||||
protocol: z.string(),
|
protocol: z.enum(["tcp", "udp"]),
|
||||||
proxyPort: z.number().int().min(1).max(65535)
|
proxyPort: z.number().int().min(1).max(65535)
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
|
@ -85,7 +85,7 @@ const createRawResourceSchema = z
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message: "Proxy port cannot be set"
|
message: "Raw resources are not allowed"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -400,7 +400,7 @@ async function createRawResource(
|
||||||
resourceId: newResource[0].resourceId
|
resourceId: newResource[0].resourceId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (req.userOrgRoleId != adminRole[0].roleId) {
|
if (req.user && req.userOrgRoleId != adminRole[0].roleId) {
|
||||||
// make sure the user can access the resource
|
// make sure the user can access the resource
|
||||||
await trx.insert(userResources).values({
|
await trx.insert(userResources).values({
|
||||||
userId: req.user?.userId!,
|
userId: req.user?.userId!,
|
||||||
|
|
|
@ -21,6 +21,7 @@ const bodySchema = z
|
||||||
.object({
|
.object({
|
||||||
email: z
|
email: z
|
||||||
.string()
|
.string()
|
||||||
|
.toLowerCase()
|
||||||
.optional()
|
.optional()
|
||||||
.refine((data) => {
|
.refine((data) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -28,7 +29,7 @@ const bodySchema = z
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
username: z.string().nonempty(),
|
username: z.string().nonempty().toLowerCase(),
|
||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
type: z.enum(["internal", "oidc"]).optional(),
|
type: z.enum(["internal", "oidc"]).optional(),
|
||||||
idpId: z.number().optional(),
|
idpId: z.number().optional(),
|
||||||
|
|
|
@ -30,8 +30,8 @@ const inviteUserBodySchema = z
|
||||||
.object({
|
.object({
|
||||||
email: z
|
email: z
|
||||||
.string()
|
.string()
|
||||||
.email()
|
.toLowerCase()
|
||||||
.transform((v) => v.toLowerCase()),
|
.email(),
|
||||||
roleId: z.number(),
|
roleId: z.number(),
|
||||||
validHours: z.number().gt(0).lte(168),
|
validHours: z.number().gt(0).lte(168),
|
||||||
sendEmail: z.boolean().optional(),
|
sendEmail: z.boolean().optional(),
|
||||||
|
|
|
@ -2,14 +2,16 @@ import { migrate } from "drizzle-orm/node-postgres/migrator";
|
||||||
import { db } from "../db/pg";
|
import { db } from "../db/pg";
|
||||||
import semver from "semver";
|
import semver from "semver";
|
||||||
import { versionMigrations } from "../db/pg";
|
import { versionMigrations } from "../db/pg";
|
||||||
import { __DIRNAME, APP_PATH, APP_VERSION } from "@server/lib/consts";
|
import { __DIRNAME, APP_VERSION } from "@server/lib/consts";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import m1 from "./scriptsSqlite/1.6.0";
|
||||||
|
|
||||||
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
||||||
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
||||||
|
|
||||||
// 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.6.0", run: m1 }
|
||||||
// Add new migrations here as they are created
|
// Add new migrations here as they are created
|
||||||
] as {
|
] as {
|
||||||
version: string;
|
version: string;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import m17 from "./scriptsSqlite/1.1.0";
|
||||||
import m18 from "./scriptsSqlite/1.2.0";
|
import m18 from "./scriptsSqlite/1.2.0";
|
||||||
import m19 from "./scriptsSqlite/1.3.0";
|
import m19 from "./scriptsSqlite/1.3.0";
|
||||||
import m20 from "./scriptsSqlite/1.5.0";
|
import m20 from "./scriptsSqlite/1.5.0";
|
||||||
|
import m21 from "./scriptsSqlite/1.6.0";
|
||||||
|
|
||||||
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
||||||
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
||||||
|
@ -42,6 +43,7 @@ const migrations = [
|
||||||
{ version: "1.2.0", run: m18 },
|
{ version: "1.2.0", run: m18 },
|
||||||
{ version: "1.3.0", run: m19 },
|
{ version: "1.3.0", run: m19 },
|
||||||
{ version: "1.5.0", run: m20 },
|
{ version: "1.5.0", run: m20 },
|
||||||
|
{ version: "1.6.0", run: m21 }
|
||||||
// Add new migrations here as they are created
|
// Add new migrations here as they are created
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
|
57
server/setup/scriptsPg/1.6.0.ts
Normal file
57
server/setup/scriptsPg/1.6.0.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { db } from "@server/db/pg/driver";
|
||||||
|
import { configFilePath1, configFilePath2 } from "@server/lib/consts";
|
||||||
|
import { sql } from "drizzle-orm";
|
||||||
|
import fs from "fs";
|
||||||
|
import yaml from "js-yaml";
|
||||||
|
|
||||||
|
const version = "1.6.0";
|
||||||
|
|
||||||
|
export default async function migration() {
|
||||||
|
console.log(`Running setup script ${version}...`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.execute(sql`UPDATE 'user' SET email = LOWER(email);`);
|
||||||
|
db.execute(sql`UPDATE 'user' SET username = LOWER(username);`);
|
||||||
|
console.log(`Migrated database schema`);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Unable to make all usernames and emails lowercase");
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Determine which config file exists
|
||||||
|
const filePaths = [configFilePath1, configFilePath2];
|
||||||
|
let filePath = "";
|
||||||
|
for (const path of filePaths) {
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
filePath = path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filePath) {
|
||||||
|
throw new Error(
|
||||||
|
`No config file found (expected config.yml or config.yaml).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and parse the YAML file
|
||||||
|
let rawConfig: any;
|
||||||
|
const fileContents = fs.readFileSync(filePath, "utf8");
|
||||||
|
rawConfig = yaml.load(fileContents);
|
||||||
|
|
||||||
|
if (rawConfig.server?.trust_proxy) {
|
||||||
|
rawConfig.server.trust_proxy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the updated YAML back to the file
|
||||||
|
const updatedYaml = yaml.dump(rawConfig);
|
||||||
|
fs.writeFileSync(filePath, updatedYaml, "utf8");
|
||||||
|
|
||||||
|
console.log(`Set trust_proxy to 1 in config file`);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`Unable to migrate config file. Error: ${e}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`${version} migration complete`);
|
||||||
|
}
|
66
server/setup/scriptsSqlite/1.6.0.ts
Normal file
66
server/setup/scriptsSqlite/1.6.0.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import { APP_PATH, configFilePath1, configFilePath2 } from "@server/lib/consts";
|
||||||
|
import Database from "better-sqlite3";
|
||||||
|
import fs from "fs";
|
||||||
|
import yaml from "js-yaml";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
const version = "1.6.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.pragma("foreign_keys = OFF");
|
||||||
|
db.transaction(() => {
|
||||||
|
db.exec(`
|
||||||
|
UPDATE 'user' SET email = LOWER(email);
|
||||||
|
UPDATE 'user' SET username = LOWER(username);
|
||||||
|
`);
|
||||||
|
})(); // <-- executes the transaction immediately
|
||||||
|
db.pragma("foreign_keys = ON");
|
||||||
|
console.log(`Migrated database schema`);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Unable to make all usernames and emails lowercase");
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Determine which config file exists
|
||||||
|
const filePaths = [configFilePath1, configFilePath2];
|
||||||
|
let filePath = "";
|
||||||
|
for (const path of filePaths) {
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
filePath = path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filePath) {
|
||||||
|
throw new Error(
|
||||||
|
`No config file found (expected config.yml or config.yaml).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and parse the YAML file
|
||||||
|
let rawConfig: any;
|
||||||
|
const fileContents = fs.readFileSync(filePath, "utf8");
|
||||||
|
rawConfig = yaml.load(fileContents);
|
||||||
|
|
||||||
|
if (rawConfig.server?.trust_proxy) {
|
||||||
|
rawConfig.server.trust_proxy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the updated YAML back to the file
|
||||||
|
const updatedYaml = yaml.dump(rawConfig);
|
||||||
|
fs.writeFileSync(filePath, updatedYaml, "utf8");
|
||||||
|
|
||||||
|
console.log(`Set trust_proxy to 1 in config file`);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`Unable to migrate config file. Please do it manually. Error: ${e}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`${version} migration complete`);
|
||||||
|
}
|
|
@ -42,6 +42,7 @@ export default function StepperForm() {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [isChecked, setIsChecked] = useState(false);
|
const [isChecked, setIsChecked] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [orgCreated, setOrgCreated] = useState(false);
|
||||||
|
|
||||||
const orgSchema = z.object({
|
const orgSchema = z.object({
|
||||||
orgName: z.string().min(1, { message: t('orgNameRequired') }),
|
orgName: z.string().min(1, { message: t('orgNameRequired') }),
|
||||||
|
@ -83,7 +84,7 @@ export default function StepperForm() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkOrgIdAvailability = useCallback(async (value: string) => {
|
const checkOrgIdAvailability = useCallback(async (value: string) => {
|
||||||
if (loading) {
|
if (loading || orgCreated) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -96,7 +97,7 @@ export default function StepperForm() {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setOrgIdTaken(false);
|
setOrgIdTaken(false);
|
||||||
}
|
}
|
||||||
}, []);
|
}, [loading, orgCreated, api]);
|
||||||
|
|
||||||
const debouncedCheckOrgIdAvailability = useCallback(
|
const debouncedCheckOrgIdAvailability = useCallback(
|
||||||
debounce(checkOrgIdAvailability, 300),
|
debounce(checkOrgIdAvailability, 300),
|
||||||
|
@ -129,7 +130,7 @@ export default function StepperForm() {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res && res.status === 201) {
|
if (res && res.status === 201) {
|
||||||
// setCurrentStep("site");
|
setOrgCreated(true);
|
||||||
router.push(`/${values.orgId}/settings/sites/create`);
|
router.push(`/${values.orgId}/settings/sites/create`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -78,10 +78,12 @@ export function Layout({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lightOrDark === "light") {
|
if (lightOrDark === "light") {
|
||||||
return "/logo/word_mark_black.png";
|
// return "/logo/word_mark_black.png";
|
||||||
|
return "/logo/pangolin_orange.svg";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "/logo/word_mark_white.png";
|
// return "/logo/word_mark_white.png";
|
||||||
|
return "/logo/pangolin_orange.svg";
|
||||||
}
|
}
|
||||||
|
|
||||||
setPath(getPath());
|
setPath(getPath());
|
||||||
|
@ -170,8 +172,8 @@ export function Layout({
|
||||||
<Image
|
<Image
|
||||||
src={path}
|
src={path}
|
||||||
alt="Pangolin Logo"
|
alt="Pangolin Logo"
|
||||||
width={110}
|
width={35}
|
||||||
height={25}
|
height={35}
|
||||||
priority={true}
|
priority={true}
|
||||||
quality={25}
|
quality={25}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { cookies } from "next/headers";
|
import { cookies, headers } from "next/headers";
|
||||||
import { pullEnv } from "../pullEnv";
|
import { pullEnv } from "../pullEnv";
|
||||||
|
|
||||||
export async function authCookieHeader() {
|
export async function authCookieHeader() {
|
||||||
|
@ -7,9 +7,16 @@ export async function authCookieHeader() {
|
||||||
const allCookies = await cookies();
|
const allCookies = await cookies();
|
||||||
const cookieName = env.server.sessionCookieName;
|
const cookieName = env.server.sessionCookieName;
|
||||||
const sessionId = allCookies.get(cookieName)?.value ?? null;
|
const sessionId = allCookies.get(cookieName)?.value ?? null;
|
||||||
|
|
||||||
|
// all other headers
|
||||||
|
// this is needed to pass through x-forwarded-for, x-forwarded-proto, etc.
|
||||||
|
const otherHeaders = await headers();
|
||||||
|
const otherHeadersObject = Object.fromEntries(otherHeaders.entries());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
headers: {
|
headers: {
|
||||||
Cookie: `${cookieName}=${sessionId}`,
|
Cookie: `${cookieName}=${sessionId}`,
|
||||||
|
...otherHeadersObject
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue