@@ -37,6 +37,14 @@ async def read_root(
3737 except HTTPException as e :
3838 logger .info (f"Authentication failed at root route: { e .detail } , redirecting to login" )
3939 return RedirectResponse (url = "/login" , status_code = 302 )
40+
41+ from ..auth .dependencies import user_has_ui_permission_for_service
42+
43+ # Helper function for templates
44+ def can_perform_action (permission : str , service_name : str ) -> bool :
45+ """Check if user has UI permission for a specific service"""
46+ return user_has_ui_permission_for_service (permission , service_name , user_context .get ('ui_permissions' , {}))
47+
4048 service_data = []
4149 search_query = query .lower () if query else ""
4250
@@ -55,10 +63,18 @@ async def read_root(
5563 key = lambda p : all_servers [p ]["server_name" ]
5664 )
5765
66+ # Filter services based on UI permissions
67+ accessible_services = user_context .get ('accessible_services' , [])
68+
5869 for path in sorted_server_paths :
5970 server_info = all_servers [path ]
6071 server_name = server_info ["server_name" ]
6172
73+ # Check if user can list this service
74+ if 'all' not in accessible_services and server_name not in accessible_services :
75+ logger .debug (f"Filtering out service '{ server_name } ' - user doesn't have list_service permission" )
76+ continue
77+
6278 # Include description and tags in search
6379 searchable_text = f"{ server_name .lower ()} { server_info .get ('description' , '' ).lower ()} { ' ' .join (server_info .get ('tags' , []))} "
6480 if not search_query or search_query in searchable_text :
@@ -88,7 +104,8 @@ async def read_root(
88104 "request" : request ,
89105 "services" : service_data ,
90106 "username" : user_context ['username' ],
91- "user_context" : user_context # Pass full user context to template
107+ "user_context" : user_context , # Pass full user context to template
108+ "can_perform_action" : can_perform_action # Helper function for permission checks
92109 },
93110 )
94111
@@ -100,25 +117,28 @@ async def toggle_service_route(
100117 enabled : Annotated [str | None , Form ()] = None ,
101118 user_context : Annotated [dict , Depends (enhanced_auth )] = None ,
102119):
103- """Toggle a service on/off (requires modification permissions )."""
120+ """Toggle a service on/off (requires toggle_service UI permission )."""
104121 from ..search .service import faiss_service
105122 from ..health .service import health_service
106123 from ..core .nginx_service import nginx_service
107-
108- # Check if user can modify servers
109- if not user_context ['can_modify_servers' ]:
110- logger .warning (f"User { user_context ['username' ]} attempted to toggle service { service_path } without modify permissions" )
111- raise HTTPException (
112- status_code = status .HTTP_403_FORBIDDEN ,
113- detail = "You do not have permission to modify servers"
114- )
124+ from ..auth .dependencies import user_has_ui_permission_for_service
115125
116126 if not service_path .startswith ("/" ):
117127 service_path = "/" + service_path
118128
119129 server_info = server_service .get_server_info (service_path )
120130 if not server_info :
121131 raise HTTPException (status_code = 404 , detail = "Service path not registered" )
132+
133+ service_name = server_info ["server_name" ]
134+
135+ # Check if user has toggle_service permission for this specific service
136+ if not user_has_ui_permission_for_service ('toggle_service' , service_name , user_context .get ('ui_permissions' , {})):
137+ logger .warning (f"User { user_context ['username' ]} attempted to toggle service { service_name } without toggle_service permission" )
138+ raise HTTPException (
139+ status_code = status .HTTP_403_FORBIDDEN ,
140+ detail = f"You do not have permission to toggle { service_name } "
141+ )
122142
123143 # For non-admin users, check if they have access to this specific server
124144 if not user_context ['is_admin' ]:
@@ -194,17 +214,21 @@ async def register_service(
194214 license_str : Annotated [str , Form (alias = "license" )] = "N/A" ,
195215 user_context : Annotated [dict , Depends (enhanced_auth )] = None ,
196216):
197- """Register a new service (requires modification permissions )."""
217+ """Register a new service (requires register_service UI permission )."""
198218 from ..search .service import faiss_service
199219 from ..health .service import health_service
200220 from ..core .nginx_service import nginx_service
221+ from ..auth .dependencies import user_has_ui_permission_for_service
222+
223+ # Check if user has register_service permission for any service
224+ ui_permissions = user_context .get ('ui_permissions' , {})
225+ register_permissions = ui_permissions .get ('register_service' , [])
201226
202- # Check if user can modify servers
203- if not user_context ['can_modify_servers' ]:
204- logger .warning (f"User { user_context ['username' ]} attempted to register service without modify permissions" )
227+ if not register_permissions :
228+ logger .warning (f"User { user_context ['username' ]} attempted to register service without register_service permission" )
205229 raise HTTPException (
206230 status_code = status .HTTP_403_FORBIDDEN ,
207- detail = "You do not have permission to register new servers "
231+ detail = "You do not have permission to register new services "
208232 )
209233
210234 logger .info (f"Service registration request from user '{ user_context ['username' ]} '" )
@@ -270,14 +294,8 @@ async def edit_server_form(
270294 service_path : str ,
271295 user_context : Annotated [dict , Depends (enhanced_auth )]
272296):
273- """Show edit form for a service (requires modification permissions)."""
274- # Check if user can modify servers
275- if not user_context ['can_modify_servers' ]:
276- logger .warning (f"User { user_context ['username' ]} attempted to access edit form for { service_path } without modify permissions" )
277- raise HTTPException (
278- status_code = status .HTTP_403_FORBIDDEN ,
279- detail = "You do not have permission to edit servers"
280- )
297+ """Show edit form for a service (requires modify_service UI permission)."""
298+ from ..auth .dependencies import user_has_ui_permission_for_service
281299
282300 if not service_path .startswith ('/' ):
283301 service_path = '/' + service_path
@@ -286,6 +304,16 @@ async def edit_server_form(
286304 if not server_info :
287305 raise HTTPException (status_code = 404 , detail = "Service path not found" )
288306
307+ service_name = server_info ["server_name" ]
308+
309+ # Check if user has modify_service permission for this specific service
310+ if not user_has_ui_permission_for_service ('modify_service' , service_name , user_context .get ('ui_permissions' , {})):
311+ logger .warning (f"User { user_context ['username' ]} attempted to access edit form for { service_name } without modify_service permission" )
312+ raise HTTPException (
313+ status_code = status .HTTP_403_FORBIDDEN ,
314+ detail = f"You do not have permission to modify { service_name } "
315+ )
316+
289317 # For non-admin users, check if they have access to this specific server
290318 if not user_context ['is_admin' ]:
291319 if not server_service .user_can_access_server_path (service_path , user_context ['accessible_servers' ]):
@@ -319,24 +347,29 @@ async def edit_server_submit(
319347 is_python : Annotated [bool | None , Form ()] = False ,
320348 license_str : Annotated [str , Form (alias = "license" )] = "N/A" ,
321349):
322- """Handle server edit form submission (requires modification permissions )."""
350+ """Handle server edit form submission (requires modify_service UI permission )."""
323351 from ..search .service import faiss_service
324352 from ..core .nginx_service import nginx_service
325-
326- # Check if user can modify servers
327- if not user_context ['can_modify_servers' ]:
328- logger .warning (f"User { user_context ['username' ]} attempted to edit service { service_path } without modify permissions" )
329- raise HTTPException (
330- status_code = status .HTTP_403_FORBIDDEN ,
331- detail = "You do not have permission to edit servers"
332- )
353+ from ..auth .dependencies import user_has_ui_permission_for_service
333354
334355 if not service_path .startswith ('/' ):
335356 service_path = '/' + service_path
336357
337- # Check if the server exists
338- if not server_service .get_server_info (service_path ):
358+ # Check if the server exists and get service name
359+ server_info = server_service .get_server_info (service_path )
360+ if not server_info :
339361 raise HTTPException (status_code = 404 , detail = "Service path not found" )
362+
363+ service_name = server_info ["server_name" ]
364+
365+ # Check if user has modify_service permission for this specific service
366+ if not user_has_ui_permission_for_service ('modify_service' , service_name , user_context .get ('ui_permissions' , {})):
367+ logger .warning (f"User { user_context ['username' ]} attempted to edit service { service_name } without modify_service permission" )
368+ raise HTTPException (
369+ status_code = status .HTTP_403_FORBIDDEN ,
370+ detail = f"You do not have permission to modify { service_name } "
371+ )
372+
340373
341374 # For non-admin users, check if they have access to this specific server
342375 if not user_context ['is_admin' ]:
@@ -537,18 +570,29 @@ async def refresh_service(
537570 service_path : str ,
538571 user_context : Annotated [dict , Depends (enhanced_auth )]
539572):
540- """Refresh service health and tool information (requires read access )."""
573+ """Refresh service health and tool information (requires health_check_service permission )."""
541574 from ..search .service import faiss_service
542575 from ..health .service import health_service
543576 from ..core .mcp_client import mcp_client_service
544577 from ..core .nginx_service import nginx_service
578+ from ..auth .dependencies import user_has_ui_permission_for_service
545579
546580 if not service_path .startswith ('/' ):
547581 service_path = '/' + service_path
548582
549583 server_info = server_service .get_server_info (service_path )
550584 if not server_info :
551585 raise HTTPException (status_code = 404 , detail = "Service path not registered" )
586+
587+ service_name = server_info ["server_name" ]
588+
589+ # Check if user has health_check_service permission for this specific service
590+ if not user_has_ui_permission_for_service ('health_check_service' , service_name , user_context .get ('ui_permissions' , {})):
591+ logger .warning (f"User { user_context ['username' ]} attempted to refresh service { service_name } without health_check_service permission" )
592+ raise HTTPException (
593+ status_code = status .HTTP_403_FORBIDDEN ,
594+ detail = f"You do not have permission to refresh { service_name } "
595+ )
552596
553597 # For non-admin users, check if they have access to this specific server
554598 if not user_context ['is_admin' ]:
0 commit comments