@@ -6,10 +6,13 @@ import { Redis } from "ioredis";
66import { PERMISSION_SYNC_SUPPORTED_CODE_HOST_TYPES } from "../constants.js" ;
77import { env } from "../env.js" ;
88import { createOctokitFromToken , getReposForAuthenticatedUser } from "../github.js" ;
9+ import { createGitLabFromOAuthToken , createGitLabFromPersonalAccessToken , getProjectsForAuthenticatedUser } from "../gitlab.js" ;
910import { hasEntitlement } from "@sourcebot/shared" ;
1011import { Settings } from "../types.js" ;
1112
12- const logger = createLogger ( 'user-permission-syncer' ) ;
13+ const LOG_TAG = 'user-permission-syncer' ;
14+ const logger = createLogger ( LOG_TAG ) ;
15+ const createJobLogger = ( jobId : string ) => createLogger ( `${ LOG_TAG } :job:${ jobId } ` ) ;
1316
1417const QUEUE_NAME = 'userPermissionSyncQueue' ;
1518
@@ -132,6 +135,8 @@ export class UserPermissionSyncer {
132135
133136 private async runJob ( job : Job < UserPermissionSyncJob > ) {
134137 const id = job . data . jobId ;
138+ const logger = createJobLogger ( id ) ;
139+
135140 const { user } = await this . db . userPermissionSyncJob . update ( {
136141 where : {
137142 id,
@@ -183,6 +188,37 @@ export class UserPermissionSyncer {
183188 }
184189 } ) ;
185190
191+ repos . forEach ( repo => aggregatedRepoIds . add ( repo . id ) ) ;
192+ } else if ( account . provider === 'gitlab' ) {
193+ if ( ! account . access_token ) {
194+ throw new Error ( `User '${ user . email } ' does not have a GitLab OAuth access token associated with their GitLab account.` ) ;
195+ }
196+
197+ const api = await createGitLabFromOAuthToken ( {
198+ oauthToken : account . access_token ,
199+ url : env . AUTH_EE_GITLAB_BASE_URL ,
200+ } ) ;
201+
202+ // @note : we only care about the private and internal repos since we don't need to build a mapping
203+ // for public repos.
204+ // @see : packages/web/src/prisma.ts
205+ const privateGitLabProjects = await getProjectsForAuthenticatedUser ( 'private' , api ) ;
206+ const internalGitLabProjects = await getProjectsForAuthenticatedUser ( 'internal' , api ) ;
207+
208+ const gitLabProjectIds = [
209+ ...privateGitLabProjects ,
210+ ...internalGitLabProjects ,
211+ ] . map ( project => project . id . toString ( ) ) ;
212+
213+ const repos = await this . db . repo . findMany ( {
214+ where : {
215+ external_codeHostType : 'gitlab' ,
216+ external_id : {
217+ in : gitLabProjectIds ,
218+ }
219+ }
220+ } ) ;
221+
186222 repos . forEach ( repo => aggregatedRepoIds . add ( repo . id ) ) ;
187223 }
188224 }
@@ -212,6 +248,8 @@ export class UserPermissionSyncer {
212248 }
213249
214250 private async onJobCompleted ( job : Job < UserPermissionSyncJob > ) {
251+ const logger = createJobLogger ( job . data . jobId ) ;
252+
215253 const { user } = await this . db . userPermissionSyncJob . update ( {
216254 where : {
217255 id : job . data . jobId ,
@@ -234,6 +272,8 @@ export class UserPermissionSyncer {
234272 }
235273
236274 private async onJobFailed ( job : Job < UserPermissionSyncJob > | undefined , err : Error ) {
275+ const logger = createJobLogger ( job ?. data . jobId ?? 'unknown' ) ;
276+
237277 Sentry . captureException ( err , {
238278 tags : {
239279 jobId : job ?. data . jobId ,
@@ -260,7 +300,7 @@ export class UserPermissionSyncer {
260300
261301 logger . error ( errorMessage ( user . email ?? user . id ) ) ;
262302 } else {
263- logger . error ( errorMessage ( 'unknown user (id not found)' ) ) ;
303+ logger . error ( errorMessage ( 'unknown job (id not found)' ) ) ;
264304 }
265305 }
266306}
0 commit comments