@@ -801,18 +801,9 @@ async function completeResolvedCredentialGroupEnrollment(
801801 row : NonNullable < Awaited < ReturnType < typeof resolvePublicEnrollmentRowByIdentity > > > ,
802802 identity : PublicCredentialGroupEnrollmentIdentity
803803) : Promise < boolean | null > {
804- const enrollment = await buildPublicCredentialGroupEnrollment ( row )
805- const activeOptions = enrollment . options . filter ( ( option ) => option . status === 'active' )
806- const allConnected =
807- activeOptions . length > 0 &&
808- activeOptions . every (
809- ( option ) => option . connections . length === 1 && option . connections [ 0 ] ?. status === 'connected'
810- )
811- if ( ! allConnected ) return false
812-
813- const now = new Date ( )
814804 return db . transaction ( async ( tx ) => {
815805 await lockCredentialGroupEnrollmentLifecycle ( tx , row . enrollment . id )
806+ const now = new Date ( )
816807 const [ current ] = await tx
817808 . select ( {
818809 status : credentialGroupEnrollment . status ,
@@ -832,6 +823,68 @@ async function completeResolvedCredentialGroupEnrollment(
832823 return null
833824 }
834825
826+ const [ group ] = await tx
827+ . select ( {
828+ status : credentialGroup . status ,
829+ options : credentialGroup . options ,
830+ } )
831+ . from ( credentialGroup )
832+ . where (
833+ and (
834+ eq ( credentialGroup . id , identity . credentialGroupId ) ,
835+ eq ( credentialGroup . workspaceId , identity . workspaceId )
836+ )
837+ )
838+ . limit ( 1 )
839+ . for ( 'update' )
840+ if ( ! group || group . status !== 'active' ) return null
841+
842+ const activeOptions = group . options . filter ( ( option ) => option . status === 'active' )
843+ if ( activeOptions . length === 0 ) return false
844+ const connections = await tx
845+ . select ( {
846+ optionId : credential . credentialGroupOptionId ,
847+ status : credential . managedOauthStatus ,
848+ scopeVersion : credential . managedOauthScopeVersion ,
849+ authorizationAppId : credential . authorizationAppId ,
850+ grantedScopes : credential . grantedScopes ,
851+ grantedAt : credential . grantedAt ,
852+ } )
853+ . from ( credential )
854+ . where (
855+ and (
856+ eq ( credential . type , 'managed_oauth' ) ,
857+ eq ( credential . credentialGroupEnrollmentId , row . enrollment . id )
858+ )
859+ )
860+ . for ( 'update' )
861+
862+ for ( const option of activeOptions ) {
863+ if ( ! isCredentialGroupProvider ( option . provider ) ) {
864+ throw new Error ( `Unsupported Credential Group provider: ${ option . provider } ` )
865+ }
866+ const matchingConnections = connections . filter (
867+ ( connection ) => connection . optionId === option . id
868+ )
869+ if ( matchingConnections . length !== 1 ) return false
870+ const [ connection ] = matchingConnections
871+ if ( ! connection || connection . status !== 'active' || ! connection . grantedAt ) return false
872+
873+ const adapter = getCredentialGroupProviderAdapter ( option . provider )
874+ const policy = await adapter . getPolicy ( option , {
875+ workspaceId : identity . workspaceId ,
876+ credentialGroupId : identity . credentialGroupId ,
877+ executor : tx ,
878+ } )
879+ if (
880+ connection . authorizationAppId !== policy . authorizationAppId ||
881+ connection . scopeVersion !== policy . scopeVersion ||
882+ ! adapter . hasRequiredScopes ( connection . grantedScopes ?? [ ] , policy . requiredScopes )
883+ ) {
884+ return false
885+ }
886+ }
887+
835888 const [ completed ] = await tx
836889 . update ( credentialGroupEnrollment )
837890 . set ( { status : 'completed' , completedAt : now , updatedAt : now } )
0 commit comments