@@ -78,7 +78,8 @@ func (h *ModelsHandler) selectSubscriptionsForListing(
7878
7979 // Single subscription selection (existing behavior)
8080 if h .subscriptionSelector != nil {
81- result , err := h .subscriptionSelector .Select (userContext .Groups , userContext .Username , requestedSubscription )
81+ //nolint:unqueryvet,nolintlint // Select is a method, not a SQL query
82+ result , err := h .subscriptionSelector .Select (userContext .Groups , userContext .Username , requestedSubscription , "" )
8283 if err != nil {
8384 h .handleSubscriptionSelectionError (c , err )
8485 return nil , true
@@ -99,6 +100,7 @@ func (h *ModelsHandler) selectSubscriptionsForListing(
99100// handleSubscriptionSelectionError handles errors from subscription selection and sends appropriate HTTP responses.
100101func (h * ModelsHandler ) handleSubscriptionSelectionError (c * gin.Context , err error ) {
101102 var multipleSubsErr * subscription.MultipleSubscriptionsError
103+ var ambiguousErr * subscription.SubscriptionAmbiguousError
102104 var accessDeniedErr * subscription.AccessDeniedError
103105 var notFoundErr * subscription.SubscriptionNotFoundError
104106 var noSubErr * subscription.NoSubscriptionError
@@ -117,6 +119,16 @@ func (h *ModelsHandler) handleSubscriptionSelectionError(c *gin.Context, err err
117119 return
118120 }
119121
122+ if errors .As (err , & ambiguousErr ) {
123+ h .logger .Debug ("Subscription name is ambiguous" )
124+ c .JSON (http .StatusForbidden , gin.H {
125+ "error" : gin.H {
126+ "message" : err .Error (),
127+ "type" : "permission_error" ,
128+ }})
129+ return
130+ }
131+
120132 if errors .As (err , & accessDeniedErr ) {
121133 h .logger .Debug ("Access denied to subscription" )
122134 c .JSON (http .StatusForbidden , gin.H {
@@ -255,7 +267,7 @@ func (h *ModelsHandler) ListLLMs(c *gin.Context) {
255267 } else {
256268 // User has zero accessible subscriptions - return empty list
257269 h .logger .Debug ("User has zero accessible subscriptions, returning empty model list" )
258- // modelList is already initialized to empty slice at line 235
270+ // modelList is already initialized to empty slice above
259271 }
260272 } else {
261273 // Filter models by subscription(s) and aggregate subscriptions
@@ -268,8 +280,22 @@ func (h *ModelsHandler) ListLLMs(c *gin.Context) {
268280 modelsByKey := make (map [modelKey ]* models.Model )
269281
270282 for _ , sub := range subscriptionsToUse {
271- h .logger .Debug ("Filtering models by subscription" , "subscription" , sub .Name , "modelCount" , len (list ))
272- filteredModels := h .modelMgr .FilterModelsByAccess (c .Request .Context (), list , authHeader , sub .Name )
283+ // Pre-filter by modelRefs if available (optimization to reduce HTTP calls)
284+ modelsToCheck := list
285+ if len (sub .ModelRefs ) > 0 {
286+ h .logger .Debug ("Pre-filtering models by subscription modelRefs" ,
287+ "subscription" , sub .Name ,
288+ "totalModels" , len (list ),
289+ "modelRefsCount" , len (sub .ModelRefs ),
290+ )
291+ modelsToCheck = filterModelsBySubscription (list , sub .ModelRefs )
292+ h .logger .Debug ("After modelRef filtering" , "modelsToCheck" , len (modelsToCheck ))
293+ }
294+
295+ // Use qualified "namespace/name" format for accurate authorization checks
296+ qualifiedSubName := sub .Namespace + "/" + sub .Name
297+ h .logger .Debug ("Filtering models by subscription" , "subscription" , qualifiedSubName , "modelCount" , len (modelsToCheck ))
298+ filteredModels := h .modelMgr .FilterModelsByAccess (c .Request .Context (), modelsToCheck , authHeader , qualifiedSubName )
273299
274300 for _ , model := range filteredModels {
275301 subInfo := models.SubscriptionInfo {
@@ -323,3 +349,29 @@ func (h *ModelsHandler) ListLLMs(c *gin.Context) {
323349 Data : modelList ,
324350 })
325351}
352+
353+ // filterModelsBySubscription filters models to only those matching the subscription's modelRefs.
354+ func filterModelsBySubscription (modelList []models.Model , modelRefs []subscription.ModelRefInfo ) []models.Model {
355+ if len (modelRefs ) == 0 {
356+ return modelList
357+ }
358+
359+ // Build map of allowed models for fast lookup
360+ allowed := make (map [string ]bool )
361+ for _ , ref := range modelRefs {
362+ key := ref .Namespace + "/" + ref .Name
363+ allowed [key ] = true
364+ }
365+
366+ // Filter models
367+ filtered := make ([]models.Model , 0 , len (modelList ))
368+ for _ , model := range modelList {
369+ // Models from MaaSModelRefLister have OwnedBy set to namespace
370+ modelKey := model .OwnedBy + "/" + model .ID
371+ if allowed [modelKey ] {
372+ filtered = append (filtered , model )
373+ }
374+ }
375+
376+ return filtered
377+ }
0 commit comments