11import { PrismaClient , RepoIndexingJobType } from '@sourcebot/db' ;
2- import { createLogger } from '@sourcebot/shared' ;
2+ import { createLogger , env , hasEntitlement } from '@sourcebot/shared' ;
33import express , { Request , Response } from 'express' ;
44import 'express-async-errors' ;
55import * as http from "http" ;
66import z from 'zod' ;
77import { ConnectionManager } from './connectionManager.js' ;
8+ import { AccountPermissionSyncer } from './ee/accountPermissionSyncer.js' ;
89import { PromClient } from './promClient.js' ;
910import { RepoIndexManager } from './repoIndexManager.js' ;
1011import { createGitHubRepoRecord } from './repoCompileUtils.js' ;
1112import { Octokit } from '@octokit/rest' ;
12- import { SINGLE_TENANT_ORG_ID } from './constants.js' ;
13+ import { PERMISSION_SYNC_SUPPORTED_IDENTITY_PROVIDERS , SINGLE_TENANT_ORG_ID } from './constants.js' ;
1314
1415const logger = createLogger ( 'api' ) ;
1516const PORT = 3060 ;
@@ -22,6 +23,7 @@ export class Api {
2223 private prisma : PrismaClient ,
2324 private connectionManager : ConnectionManager ,
2425 private repoIndexManager : RepoIndexManager ,
26+ private accountPermissionSyncer : AccountPermissionSyncer ,
2527 ) {
2628 const app = express ( ) ;
2729 app . use ( express . json ( ) ) ;
@@ -36,6 +38,7 @@ export class Api {
3638
3739 app . post ( '/api/sync-connection' , this . syncConnection . bind ( this ) ) ;
3840 app . post ( '/api/index-repo' , this . indexRepo . bind ( this ) ) ;
41+ app . post ( '/api/trigger-account-permission-sync' , this . triggerAccountPermissionSync . bind ( this ) ) ;
3942 app . post ( `/api/experimental/add-github-repo` , this . experimental_addGithubRepo . bind ( this ) ) ;
4043
4144 this . server = app . listen ( PORT , ( ) => {
@@ -96,6 +99,41 @@ export class Api {
9699 res . status ( 200 ) . json ( { jobId } ) ;
97100 }
98101
102+ private async triggerAccountPermissionSync ( req : Request , res : Response ) {
103+ if ( env . EXPERIMENT_EE_PERMISSION_SYNC_ENABLED !== 'true' || ! hasEntitlement ( 'permission-syncing' ) ) {
104+ res . status ( 403 ) . json ( { error : 'Permission syncing is not enabled.' } ) ;
105+ return ;
106+ }
107+
108+ const schema = z . object ( {
109+ accountId : z . string ( ) ,
110+ } ) . strict ( ) ;
111+
112+ const parsed = schema . safeParse ( req . body ) ;
113+ if ( ! parsed . success ) {
114+ res . status ( 400 ) . json ( { error : parsed . error . message } ) ;
115+ return ;
116+ }
117+
118+ const { accountId } = parsed . data ;
119+ const account = await this . prisma . account . findUnique ( {
120+ where : { id : accountId } ,
121+ } ) ;
122+
123+ if ( ! account ) {
124+ res . status ( 404 ) . json ( { error : 'Account not found' } ) ;
125+ return ;
126+ }
127+
128+ if ( ! PERMISSION_SYNC_SUPPORTED_IDENTITY_PROVIDERS . includes ( account . provider as typeof PERMISSION_SYNC_SUPPORTED_IDENTITY_PROVIDERS [ number ] ) ) {
129+ res . status ( 400 ) . json ( { error : `Provider '${ account . provider } ' does not support permission syncing.` } ) ;
130+ return ;
131+ }
132+
133+ const jobId = await this . accountPermissionSyncer . schedulePermissionSyncForAccount ( account ) ;
134+ res . status ( 200 ) . json ( { jobId } ) ;
135+ }
136+
99137 private async experimental_addGithubRepo ( req : Request , res : Response ) {
100138 const schema = z . object ( {
101139 owner : z . string ( ) ,
0 commit comments