99 isHosted ,
1010} from '@/lib/core/config/feature-flags'
1111import {
12+ DEFAULT_PERMISSION_GROUP_CONFIG ,
1213 type PermissionGroupConfig ,
1314 parsePermissionGroupConfig ,
1415} from '@/lib/permission-groups/types'
@@ -65,11 +66,36 @@ export class InvitationsNotAllowedError extends Error {
6566 }
6667}
6768
69+ /**
70+ * Merges the env allowlist into a permission config.
71+ * If `config` is null and no env allowlist is set, returns null.
72+ * If `config` is null but env allowlist is set, returns a default config with only allowedIntegrations set.
73+ * If both are set, intersects the two allowlists.
74+ */
75+ function mergeEnvAllowlist ( config : PermissionGroupConfig | null ) : PermissionGroupConfig | null {
76+ const envAllowlist = getAllowedIntegrationsFromEnv ( )
77+
78+ if ( envAllowlist === null ) {
79+ return config
80+ }
81+
82+ if ( config === null ) {
83+ return { ...DEFAULT_PERMISSION_GROUP_CONFIG , allowedIntegrations : envAllowlist }
84+ }
85+
86+ const merged =
87+ config . allowedIntegrations === null
88+ ? envAllowlist
89+ : config . allowedIntegrations . filter ( ( i ) => envAllowlist . includes ( i ) )
90+
91+ return { ...config , allowedIntegrations : merged }
92+ }
93+
6894export async function getUserPermissionConfig (
6995 userId : string
7096) : Promise < PermissionGroupConfig | null > {
7197 if ( ! isHosted && ! isAccessControlEnabled ) {
72- return null
98+ return mergeEnvAllowlist ( null )
7399 }
74100
75101 const [ membership ] = await db
@@ -79,12 +105,12 @@ export async function getUserPermissionConfig(
79105 . limit ( 1 )
80106
81107 if ( ! membership ) {
82- return null
108+ return mergeEnvAllowlist ( null )
83109 }
84110
85111 const isEnterprise = await isOrganizationOnEnterprisePlan ( membership . organizationId )
86112 if ( ! isEnterprise ) {
87- return null
113+ return mergeEnvAllowlist ( null )
88114 }
89115
90116 const [ groupMembership ] = await db
@@ -100,10 +126,10 @@ export async function getUserPermissionConfig(
100126 . limit ( 1 )
101127
102128 if ( ! groupMembership ) {
103- return null
129+ return mergeEnvAllowlist ( null )
104130 }
105131
106- return parsePermissionGroupConfig ( groupMembership . config )
132+ return mergeEnvAllowlist ( parsePermissionGroupConfig ( groupMembership . config ) )
107133}
108134
109135export async function getPermissionConfig (
@@ -160,25 +186,24 @@ export async function validateBlockType(
160186 return
161187 }
162188
163- const envAllowlist = getAllowedIntegrationsFromEnv ( )
164- if ( envAllowlist !== null && ! envAllowlist . includes ( blockType . toLowerCase ( ) ) ) {
165- logger . warn ( 'Integration blocked by env allowlist' , { blockType } )
166- throw new IntegrationNotAllowedError ( blockType , 'blocked by server ALLOWED_INTEGRATIONS policy' )
167- }
168-
169- if ( ! userId ) {
170- return
171- }
172-
173- const config = await getPermissionConfig ( userId , ctx )
189+ const config = userId ? await getPermissionConfig ( userId , ctx ) : mergeEnvAllowlist ( null )
174190
175191 if ( ! config || config . allowedIntegrations === null ) {
176192 return
177193 }
178194
179- if ( ! config . allowedIntegrations . includes ( blockType ) ) {
180- logger . warn ( 'Integration blocked by permission group' , { userId, blockType } )
181- throw new IntegrationNotAllowedError ( blockType )
195+ if ( ! config . allowedIntegrations . includes ( blockType . toLowerCase ( ) ) ) {
196+ const isEnvOnly = ! userId
197+ logger . warn (
198+ isEnvOnly
199+ ? 'Integration blocked by env allowlist'
200+ : 'Integration blocked by permission config' ,
201+ { userId, blockType }
202+ )
203+ throw new IntegrationNotAllowedError (
204+ blockType ,
205+ isEnvOnly ? 'blocked by server ALLOWED_INTEGRATIONS policy' : undefined
206+ )
182207 }
183208}
184209
0 commit comments