2025-01-01 16:40:01 -05:00
|
|
|
import { z } from "zod";
|
2025-05-12 17:21:03 -04:00
|
|
|
import { __DIRNAME, APP_VERSION } from "@server/lib/consts";
|
2025-06-04 12:02:07 -04:00
|
|
|
import { db } from "@server/db";
|
|
|
|
import { SupporterKey, supporterKey } from "@server/db";
|
2025-03-21 17:13:41 -04:00
|
|
|
import { eq } from "drizzle-orm";
|
2025-04-27 13:03:00 -04:00
|
|
|
import { license } from "@server/license/license";
|
2025-06-04 12:02:07 -04:00
|
|
|
import { configSchema, readConfigFile } from "./readConfigFile";
|
2024-10-12 18:21:31 -04:00
|
|
|
|
2025-01-01 16:40:01 -05:00
|
|
|
export class Config {
|
2025-01-15 23:26:31 -05:00
|
|
|
private rawConfig!: z.infer<typeof configSchema>;
|
2024-12-30 15:48:34 -05:00
|
|
|
|
2025-03-20 22:16:02 -04:00
|
|
|
supporterData: SupporterKey | null = null;
|
|
|
|
|
|
|
|
supporterHiddenUntil: number | null = null;
|
|
|
|
|
2025-03-31 10:10:28 -04:00
|
|
|
isDev: boolean = process.env.ENVIRONMENT !== "prod";
|
|
|
|
|
2025-01-01 16:40:01 -05:00
|
|
|
constructor() {
|
2025-05-12 17:21:03 -04:00
|
|
|
this.load();
|
2025-01-01 16:40:01 -05:00
|
|
|
}
|
2024-12-30 15:48:34 -05:00
|
|
|
|
2025-05-12 17:21:03 -04:00
|
|
|
public load() {
|
|
|
|
const parsedConfig = readConfigFile();
|
2024-10-12 18:21:31 -04:00
|
|
|
|
2025-02-02 15:30:41 -05:00
|
|
|
process.env.APP_VERSION = APP_VERSION;
|
2024-12-24 12:06:13 -05:00
|
|
|
|
2025-05-12 17:21:03 -04:00
|
|
|
process.env.NEXT_PORT = parsedConfig.server.next_port.toString();
|
2025-01-01 16:40:01 -05:00
|
|
|
process.env.SERVER_EXTERNAL_PORT =
|
2025-05-12 17:21:03 -04:00
|
|
|
parsedConfig.server.external_port.toString();
|
2025-01-01 16:40:01 -05:00
|
|
|
process.env.SERVER_INTERNAL_PORT =
|
2025-05-12 17:21:03 -04:00
|
|
|
parsedConfig.server.internal_port.toString();
|
|
|
|
process.env.FLAGS_EMAIL_VERIFICATION_REQUIRED = parsedConfig.flags
|
2025-01-01 16:40:01 -05:00
|
|
|
?.require_email_verification
|
|
|
|
? "true"
|
|
|
|
: "false";
|
2025-05-12 17:21:03 -04:00
|
|
|
process.env.FLAGS_ALLOW_RAW_RESOURCES = parsedConfig.flags
|
2025-02-03 21:18:16 -05:00
|
|
|
?.allow_raw_resources
|
|
|
|
? "true"
|
|
|
|
: "false";
|
2025-01-01 16:40:01 -05:00
|
|
|
process.env.SESSION_COOKIE_NAME =
|
2025-05-12 17:21:03 -04:00
|
|
|
parsedConfig.server.session_cookie_name;
|
|
|
|
process.env.EMAIL_ENABLED = parsedConfig.email ? "true" : "false";
|
|
|
|
process.env.DISABLE_SIGNUP_WITHOUT_INVITE = parsedConfig.flags
|
2025-01-01 16:40:01 -05:00
|
|
|
?.disable_signup_without_invite
|
|
|
|
? "true"
|
|
|
|
: "false";
|
2025-05-12 17:21:03 -04:00
|
|
|
process.env.DISABLE_USER_CREATE_ORG = parsedConfig.flags
|
2025-01-01 16:40:01 -05:00
|
|
|
?.disable_user_create_org
|
|
|
|
? "true"
|
|
|
|
: "false";
|
2025-01-12 20:42:16 -05:00
|
|
|
process.env.RESOURCE_ACCESS_TOKEN_PARAM =
|
2025-05-12 17:21:03 -04:00
|
|
|
parsedConfig.server.resource_access_token_param;
|
2025-04-05 22:28:47 -04:00
|
|
|
process.env.RESOURCE_ACCESS_TOKEN_HEADERS_ID =
|
2025-05-12 17:21:03 -04:00
|
|
|
parsedConfig.server.resource_access_token_headers.id;
|
2025-04-05 22:28:47 -04:00
|
|
|
process.env.RESOURCE_ACCESS_TOKEN_HEADERS_TOKEN =
|
2025-05-12 17:21:03 -04:00
|
|
|
parsedConfig.server.resource_access_token_headers.token;
|
2025-01-26 14:42:02 -05:00
|
|
|
process.env.RESOURCE_SESSION_REQUEST_PARAM =
|
2025-05-12 17:21:03 -04:00
|
|
|
parsedConfig.server.resource_session_request_param;
|
|
|
|
process.env.FLAGS_ALLOW_BASE_DOMAIN_RESOURCES = parsedConfig.flags
|
2025-02-03 21:18:16 -05:00
|
|
|
?.allow_base_domain_resources
|
|
|
|
? "true"
|
|
|
|
: "false";
|
2025-05-12 17:21:03 -04:00
|
|
|
process.env.DASHBOARD_URL = parsedConfig.app.dashboard_url;
|
2025-01-01 16:40:01 -05:00
|
|
|
|
2025-05-12 17:21:03 -04:00
|
|
|
license.setServerSecret(parsedConfig.server.secret);
|
2025-04-28 21:14:09 -04:00
|
|
|
|
2025-04-27 13:03:00 -04:00
|
|
|
this.checkKeyStatus();
|
2025-03-20 22:16:02 -04:00
|
|
|
|
2025-05-12 17:21:03 -04:00
|
|
|
this.rawConfig = parsedConfig;
|
2025-01-01 16:40:01 -05:00
|
|
|
}
|
2025-01-01 17:50:12 -05:00
|
|
|
|
2025-04-27 13:03:00 -04:00
|
|
|
private async checkKeyStatus() {
|
|
|
|
const licenseStatus = await license.check();
|
|
|
|
if (!licenseStatus.isHostLicensed) {
|
|
|
|
this.checkSupporterKey();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-01 17:50:12 -05:00
|
|
|
public getRawConfig() {
|
|
|
|
return this.rawConfig;
|
|
|
|
}
|
|
|
|
|
2025-01-28 21:26:34 -05:00
|
|
|
public getNoReplyEmail(): string | undefined {
|
|
|
|
return (
|
|
|
|
this.rawConfig.email?.no_reply || this.rawConfig.email?.smtp_user
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2025-02-23 23:03:40 -05:00
|
|
|
public getDomain(domainId: string) {
|
|
|
|
return this.rawConfig.domains[domainId];
|
|
|
|
}
|
2025-03-20 22:16:02 -04:00
|
|
|
|
|
|
|
public hideSupporterKey(days: number = 7) {
|
|
|
|
const now = new Date().getTime();
|
|
|
|
|
|
|
|
if (this.supporterHiddenUntil && now < this.supporterHiddenUntil) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.supporterHiddenUntil = now + 1000 * 60 * 60 * 24 * days;
|
|
|
|
}
|
|
|
|
|
|
|
|
public isSupporterKeyHidden() {
|
|
|
|
const now = new Date().getTime();
|
|
|
|
|
|
|
|
if (this.supporterHiddenUntil && now < this.supporterHiddenUntil) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async checkSupporterKey() {
|
|
|
|
const [key] = await db.select().from(supporterKey).limit(1);
|
|
|
|
|
|
|
|
if (!key) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const { key: licenseKey, githubUsername } = key;
|
|
|
|
|
2025-03-22 12:24:20 -04:00
|
|
|
try {
|
|
|
|
const response = await fetch(
|
2025-04-28 21:50:48 -04:00
|
|
|
"https://api.fossorial.io/api/v1/license/validate",
|
2025-03-22 12:24:20 -04:00
|
|
|
{
|
|
|
|
method: "POST",
|
|
|
|
headers: {
|
|
|
|
"Content-Type": "application/json"
|
|
|
|
},
|
|
|
|
body: JSON.stringify({
|
|
|
|
licenseKey,
|
|
|
|
githubUsername
|
|
|
|
})
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
this.supporterData = key;
|
|
|
|
return;
|
2025-03-20 22:16:02 -04:00
|
|
|
}
|
|
|
|
|
2025-03-22 12:24:20 -04:00
|
|
|
const data = await response.json();
|
2025-03-20 22:16:02 -04:00
|
|
|
|
2025-03-22 12:24:20 -04:00
|
|
|
if (!data.data.valid) {
|
|
|
|
this.supporterData = {
|
|
|
|
...key,
|
|
|
|
valid: false
|
|
|
|
};
|
|
|
|
return;
|
|
|
|
}
|
2025-03-20 22:16:02 -04:00
|
|
|
|
|
|
|
this.supporterData = {
|
|
|
|
...key,
|
2025-03-22 12:24:20 -04:00
|
|
|
tier: data.data.tier,
|
|
|
|
valid: true
|
2025-03-20 22:16:02 -04:00
|
|
|
};
|
|
|
|
|
2025-03-22 12:24:20 -04:00
|
|
|
// update the supporter key in the database
|
|
|
|
await db
|
2025-04-05 22:28:47 -04:00
|
|
|
.update(supporterKey)
|
|
|
|
.set({
|
|
|
|
tier: data.data.tier || null,
|
|
|
|
phrase: data.data.cutePhrase || null,
|
|
|
|
valid: true
|
|
|
|
})
|
|
|
|
.where(eq(supporterKey.keyId, key.keyId));
|
2025-03-22 12:24:20 -04:00
|
|
|
} catch (e) {
|
|
|
|
this.supporterData = key;
|
|
|
|
console.error("Failed to validate supporter key", e);
|
|
|
|
}
|
2025-03-20 22:16:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public getSupporterData() {
|
|
|
|
return this.supporterData;
|
|
|
|
}
|
2024-12-30 15:48:34 -05:00
|
|
|
}
|
2024-10-12 21:23:12 -04:00
|
|
|
|
2025-01-01 16:40:01 -05:00
|
|
|
export const config = new Config();
|
|
|
|
|
|
|
|
export default config;
|