2025-04-25 05:28:13 +00:00
import { env } from "@/env.mjs"
2025-05-29 00:35:18 +00:00
import { Entitlement , entitlementsByPlan , Plan } from "./constants"
2025-04-25 05:28:13 +00:00
import { base64Decode } from "@/lib/utils" ;
import { z } from "zod" ;
import { SOURCEBOT_SUPPORT_EMAIL } from "@/lib/constants" ;
2025-06-02 18:16:01 +00:00
import { createLogger } from "@sourcebot/logger" ;
const logger = createLogger ( 'entitlements' ) ;
2025-04-25 05:28:13 +00:00
const eeLicenseKeyPrefix = "sourcebot_ee_" ;
2025-05-28 23:08:42 +00:00
export const SOURCEBOT_UNLIMITED_SEATS = - 1 ;
2025-04-25 05:28:13 +00:00
const eeLicenseKeyPayloadSchema = z . object ( {
id : z.string ( ) ,
2025-05-28 23:08:42 +00:00
seats : z.number ( ) ,
2025-04-25 05:28:13 +00:00
// ISO 8601 date string
2025-05-28 23:08:42 +00:00
expiryDate : z.string ( ) . datetime ( ) ,
2025-04-25 05:28:13 +00:00
} ) ;
2025-05-28 23:08:42 +00:00
type LicenseKeyPayload = z . infer < typeof eeLicenseKeyPayloadSchema > ;
2025-04-25 05:28:13 +00:00
2025-05-28 23:08:42 +00:00
const decodeLicenseKeyPayload = ( payload : string ) : LicenseKeyPayload = > {
try {
const decodedPayload = base64Decode ( payload ) ;
const payloadJson = JSON . parse ( decodedPayload ) ;
return eeLicenseKeyPayloadSchema . parse ( payloadJson ) ;
} catch ( error ) {
2025-06-02 18:16:01 +00:00
logger . error ( ` Failed to decode license key payload: ${ error } ` ) ;
2025-05-28 23:08:42 +00:00
process . exit ( 1 ) ;
2025-04-25 05:28:13 +00:00
}
2025-05-28 23:08:42 +00:00
}
2025-04-25 05:28:13 +00:00
2025-05-28 23:08:42 +00:00
export const getLicenseKey = ( ) : LicenseKeyPayload | null = > {
2025-04-25 05:28:13 +00:00
const licenseKey = env . SOURCEBOT_EE_LICENSE_KEY ;
if ( licenseKey && licenseKey . startsWith ( eeLicenseKeyPrefix ) ) {
const payload = licenseKey . substring ( eeLicenseKeyPrefix . length ) ;
2025-05-28 23:08:42 +00:00
return decodeLicenseKeyPayload ( payload ) ;
}
return null ;
}
2025-04-25 05:28:13 +00:00
2025-05-28 23:08:42 +00:00
export const getPlan = ( ) : Plan = > {
if ( env . NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT ) {
2025-05-29 00:35:18 +00:00
if ( env . NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === "demo" ) {
return "cloud:demo" ;
}
2025-05-28 23:08:42 +00:00
return "cloud:team" ;
}
2025-04-25 05:28:13 +00:00
2025-05-28 23:08:42 +00:00
const licenseKey = getLicenseKey ( ) ;
if ( licenseKey ) {
const expiryDate = new Date ( licenseKey . expiryDate ) ;
if ( expiryDate . getTime ( ) < new Date ( ) . getTime ( ) ) {
2025-06-02 18:16:01 +00:00
logger . error ( ` The provided license key has expired ( ${ expiryDate . toLocaleString ( ) } ). Falling back to oss plan. Please contact ${ SOURCEBOT_SUPPORT_EMAIL } for support. ` ) ;
2025-05-28 23:08:42 +00:00
process . exit ( 1 ) ;
}
2025-04-25 05:28:13 +00:00
2025-05-28 23:08:42 +00:00
return licenseKey . seats === SOURCEBOT_UNLIMITED_SEATS ? "self-hosted:enterprise-unlimited" : "self-hosted:enterprise" ;
} else {
2025-06-02 18:16:01 +00:00
logger . info ( ` No valid license key found. Falling back to oss plan. ` ) ;
2025-05-28 23:08:42 +00:00
return "oss" ;
2025-04-25 05:28:13 +00:00
}
2025-05-28 23:08:42 +00:00
}
2025-04-25 05:28:13 +00:00
2025-05-28 23:08:42 +00:00
export const getSeats = ( ) : number = > {
const licenseKey = getLicenseKey ( ) ;
return licenseKey ? . seats ? ? SOURCEBOT_UNLIMITED_SEATS ;
2025-04-25 05:28:13 +00:00
}
export const hasEntitlement = ( entitlement : Entitlement ) = > {
2025-05-28 23:08:42 +00:00
const entitlements = getEntitlements ( ) ;
2025-04-25 05:28:13 +00:00
return entitlements . includes ( entitlement ) ;
}
2025-05-28 23:08:42 +00:00
export const getEntitlements = ( ) : Entitlement [ ] = > {
const plan = getPlan ( ) ;
return entitlementsByPlan [ plan ] ;
}