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" ;
2025-06-21 16:35:22 -04:00
import { fromError } from "zod-validation-error" ;
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() {
2025-06-21 16:35:22 -04:00
const environment = readConfigFile ( ) ;
const {
data : parsedConfig ,
success ,
error
} = configSchema . safeParse ( environment ) ;
if ( ! success ) {
const errors = fromError ( error ) ;
throw new Error ( ` Invalid configuration file: ${ errors } ` ) ;
}
if ( process . env . APP_BASE_DOMAIN ) {
console . log (
2025-06-21 16:57:57 -04:00
"WARNING: You're using deprecated environment variables. Transition to the configuration file. https://docs.fossorial.io/"
2025-06-21 16:35:22 -04:00
) ;
}
2025-06-21 16:57:57 -04:00
if (
// @ts-ignore
parsedConfig . users ||
process . env . USERS_SERVERADMIN_EMAIL ||
process . env . USERS_SERVERADMIN_PASSWORD
) {
console . log (
"WARNING: Your admin credentials are still in the config file or environment variables. This method of setting admin credentials is no longer supported. It is recommended to remove them."
) ;
2025-06-21 16:35:22 -04:00
}
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 ;