2022-11-24 19:48:51 +01:00
|
|
|
import env from "../environment"
|
2022-11-28 18:54:04 +01:00
|
|
|
import * as tenancy from "../tenancy"
|
2022-03-22 01:23:22 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Read the TENANT_FEATURE_FLAGS env var and return an array of features flags for each tenant.
|
|
|
|
* The env var is formatted as:
|
|
|
|
* tenant1:feature1:feature2,tenant2:feature1
|
|
|
|
*/
|
2023-02-02 12:38:10 +01:00
|
|
|
export function buildFeatureFlags() {
|
2022-03-22 01:23:22 +01:00
|
|
|
if (!env.TENANT_FEATURE_FLAGS) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-11-24 19:48:51 +01:00
|
|
|
const tenantFeatureFlags: Record<string, string[]> = {}
|
2022-03-22 01:23:22 +01:00
|
|
|
|
|
|
|
env.TENANT_FEATURE_FLAGS.split(",").forEach(tenantToFeatures => {
|
|
|
|
const [tenantId, ...features] = tenantToFeatures.split(":")
|
|
|
|
|
|
|
|
features.forEach(feature => {
|
|
|
|
if (!tenantFeatureFlags[tenantId]) {
|
|
|
|
tenantFeatureFlags[tenantId] = []
|
|
|
|
}
|
|
|
|
tenantFeatureFlags[tenantId].push(feature)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
return tenantFeatureFlags
|
|
|
|
}
|
|
|
|
|
2022-11-24 19:48:51 +01:00
|
|
|
export function isEnabled(featureFlag: string) {
|
2022-03-22 01:23:22 +01:00
|
|
|
const tenantId = tenancy.getTenantId()
|
2022-11-24 19:48:51 +01:00
|
|
|
const flags = getTenantFeatureFlags(tenantId)
|
2022-09-07 13:08:10 +02:00
|
|
|
return flags.includes(featureFlag)
|
2022-03-22 01:23:22 +01:00
|
|
|
}
|
|
|
|
|
2022-11-24 19:48:51 +01:00
|
|
|
export function getTenantFeatureFlags(tenantId: string) {
|
2023-02-01 15:12:43 +01:00
|
|
|
let flags: string[] = []
|
2023-02-02 12:38:10 +01:00
|
|
|
const envFlags = buildFeatureFlags()
|
|
|
|
if (envFlags) {
|
|
|
|
const globalFlags = envFlags["*"]
|
|
|
|
const tenantFlags = envFlags[tenantId] || []
|
2023-02-01 15:12:43 +01:00
|
|
|
|
|
|
|
// Explicitly exclude tenants from global features if required.
|
|
|
|
// Prefix the tenant flag with '!'
|
2023-02-02 12:38:10 +01:00
|
|
|
const tenantOverrides = tenantFlags.reduce(
|
|
|
|
(acc: string[], flag: string) => {
|
|
|
|
if (flag.startsWith("!")) {
|
|
|
|
let stripped = flag.substring(1)
|
|
|
|
acc.push(stripped)
|
|
|
|
}
|
|
|
|
return acc
|
|
|
|
},
|
|
|
|
[]
|
|
|
|
)
|
2022-09-07 13:08:10 +02:00
|
|
|
|
|
|
|
if (globalFlags) {
|
|
|
|
flags.push(...globalFlags)
|
|
|
|
}
|
2023-02-01 15:12:43 +01:00
|
|
|
if (tenantFlags.length) {
|
2022-09-07 13:08:10 +02:00
|
|
|
flags.push(...tenantFlags)
|
|
|
|
}
|
2023-02-01 15:12:43 +01:00
|
|
|
|
|
|
|
// Purge any tenant specific overrides
|
|
|
|
flags = flags.filter(flag => {
|
|
|
|
return tenantOverrides.indexOf(flag) == -1 && !flag.startsWith("!")
|
|
|
|
})
|
2022-03-22 01:23:22 +01:00
|
|
|
}
|
|
|
|
|
2022-09-07 13:08:10 +02:00
|
|
|
return flags
|
2022-03-22 01:23:22 +01:00
|
|
|
}
|
|
|
|
|
2022-11-24 19:48:51 +01:00
|
|
|
export enum TenantFeatureFlag {
|
|
|
|
LICENSING = "LICENSING",
|
|
|
|
GOOGLE_SHEETS = "GOOGLE_SHEETS",
|
|
|
|
USER_GROUPS = "USER_GROUPS",
|
2023-02-02 12:38:10 +01:00
|
|
|
ONBOARDING_TOUR = "ONBOARDING_TOUR",
|
2022-03-22 01:23:22 +01:00
|
|
|
}
|