@@ -48,6 +48,16 @@ export const userScopedPrismaClientExtension = async (user?: UserWithAccounts) =
4848 ...getRepoPermissionFilterForUser ( user ) ,
4949 } ;
5050
51+ return query ( args ) ;
52+ }
53+ } ,
54+ searchContext : {
55+ async $allOperations ( { args, query } ) {
56+ injectRepoPermissionFilterIntoRelation (
57+ args as Record < string , unknown > ,
58+ getRepoPermissionFilterForUser ( user ) ,
59+ ) ;
60+
5161 return query ( args ) ;
5262 }
5363 }
@@ -57,6 +67,43 @@ export const userScopedPrismaClientExtension = async (user?: UserWithAccounts) =
5767 } )
5868}
5969
70+ /**
71+ * Injects a `Repo` permission filter into a nested `repos` relation referenced
72+ * by an operation's `include` or `select` clause. Mutates `args` in place,
73+ * normalizing `repos: true` into `repos: { where: <filter> }` and ANDing the
74+ * filter onto any existing `where`.
75+ */
76+ const injectRepoPermissionFilterIntoRelation = (
77+ args : Record < string , unknown > ,
78+ filter : Prisma . RepoWhereInput ,
79+ ) => {
80+ for ( const key of [ 'include' , 'select' ] as const ) {
81+ const clause = args [ key ] ;
82+ if ( ! clause || typeof clause !== 'object' ) {
83+ continue ;
84+ }
85+
86+ const clauseRecord = clause as Record < string , unknown > ;
87+ const repos = clauseRecord . repos ;
88+
89+ // `repos` is either absent or explicitly excluded - nothing to filter.
90+ if ( repos === undefined || repos === false ) {
91+ continue ;
92+ }
93+
94+ // Normalize `repos: true` into an object so we can attach a `where`.
95+ const reposArgs = ( repos === true ? { } : { ...( repos as Record < string , unknown > ) } ) as {
96+ where ?: Prisma . RepoWhereInput ;
97+ } ;
98+
99+ reposArgs . where = reposArgs . where
100+ ? { AND : [ reposArgs . where , filter ] }
101+ : filter ;
102+
103+ clauseRecord . repos = reposArgs ;
104+ }
105+ } ;
106+
60107/**
61108 * Returns a filter for repositories that the user has access to.
62109 */
0 commit comments