@@ -684,7 +684,7 @@ async def register_gateway(
684684 # Notify subscribers
685685 await self ._notify_gateway_added (db_gateway )
686686
687- return GatewayRead .model_validate (db_gateway ).masked ()
687+ return GatewayRead .model_validate (self . _prepare_gateway_for_read ( db_gateway ) ).masked ()
688688 except* GatewayConnectionError as ge : # pragma: no mutate
689689 if TYPE_CHECKING :
690690 ge : ExceptionGroup [GatewayConnectionError ]
@@ -872,7 +872,7 @@ async def list_gateways(self, db: Session, include_inactive: bool = False, tags:
872872 # # print(f"Gateway auth_type: {g['auth_type']}")
873873 # print("******************************************************************")
874874
875- return [GatewayRead .model_validate (g ).masked () for g in gateways ]
875+ return [GatewayRead .model_validate (self . _prepare_gateway_for_read ( g ) ).masked () for g in gateways ]
876876
877877 async def list_gateways_for_user (
878878 self , db : Session , user_email : str , team_id : Optional [str ] = None , visibility : Optional [str ] = None , include_inactive : bool = False , skip : int = 0 , limit : int = 100
@@ -936,7 +936,7 @@ async def list_gateways_for_user(
936936 query = query .offset (skip ).limit (limit )
937937
938938 gateways = db .execute (query ).scalars ().all ()
939- return [GatewayRead .model_validate (g ).masked () for g in gateways ]
939+ return [GatewayRead .model_validate (self . _prepare_gateway_for_read ( g ) ).masked () for g in gateways ]
940940
941941 async def update_gateway (
942942 self ,
@@ -1083,19 +1083,21 @@ async def update_gateway(
10831083 if gateway_update .oauth_config is not None :
10841084 gateway .oauth_config = gateway_update .oauth_config
10851085
1086- if getattr (gateway , "auth_value" , "" ) != "" :
1087- token = gateway_update .auth_token
1088- password = gateway_update .auth_password
1089- header_value = gateway_update .auth_header_value
1090-
1091- # Support multiple custom headers on update
1092- if hasattr (gateway_update , "auth_headers" ) and gateway_update .auth_headers :
1093- header_dict = {h ["key" ]: h ["value" ] for h in gateway_update .auth_headers if h .get ("key" )}
1094- gateway .auth_value = header_dict # Store as dict for DB JSON field
1095- elif settings .masked_auth_value not in (token , password , header_value ):
1096- # Check if values differ from existing ones
1097- if gateway .auth_value != gateway_update .auth_value :
1098- gateway .auth_value = decode_auth (gateway_update .auth_value ) if isinstance (gateway_update .auth_value , str ) else gateway_update .auth_value
1086+ # Handle auth_value updates (both existing and new auth values)
1087+ token = gateway_update .auth_token
1088+ password = gateway_update .auth_password
1089+ header_value = gateway_update .auth_header_value
1090+
1091+ # Support multiple custom headers on update
1092+ if hasattr (gateway_update , "auth_headers" ) and gateway_update .auth_headers :
1093+ header_dict = {h ["key" ]: h ["value" ] for h in gateway_update .auth_headers if h .get ("key" )}
1094+ gateway .auth_value = header_dict # Store as dict for DB JSON field
1095+ elif settings .masked_auth_value not in (token , password , header_value ):
1096+ # Check if values differ from existing ones or if setting for first time
1097+ decoded_auth = decode_auth (gateway_update .auth_value ) if gateway_update .auth_value else {}
1098+ current_auth = getattr (gateway , "auth_value" , {}) or {}
1099+ if current_auth != decoded_auth :
1100+ gateway .auth_value = decoded_auth
10991101
11001102 # Try to reinitialize connection if URL changed
11011103 if gateway_update .url is not None :
@@ -1139,7 +1141,10 @@ async def update_gateway(
11391141 existing_tool .input_schema = tool .input_schema
11401142 existing_tool .jsonpath_filter = tool .jsonpath_filter
11411143 existing_tool .auth_type = gateway .auth_type
1142- existing_tool .auth_value = gateway .auth_value
1144+ if isinstance (gateway .auth_value , dict ):
1145+ existing_tool .auth_value = encode_auth (gateway .auth_value )
1146+ else :
1147+ existing_tool .auth_value = gateway .auth_value
11431148 existing_tool .visibility = gateway .visibility
11441149
11451150 # If the tool doesn't exist, create a new one
@@ -1221,7 +1226,7 @@ async def update_gateway(
12211226
12221227 logger .info (f"Updated gateway: { gateway .name } " )
12231228
1224- return GatewayRead .model_validate (gateway )
1229+ return GatewayRead .model_validate (self . _prepare_gateway_for_read ( gateway ) )
12251230 # Gateway is inactive and include_inactive is False → skip update, return None
12261231 return None
12271232 except GatewayNameConflictError as ge :
@@ -1295,7 +1300,7 @@ async def get_gateway(self, db: Session, gateway_id: str, include_inactive: bool
12951300 raise GatewayNotFoundError (f"Gateway not found: { gateway_id } " )
12961301
12971302 if gateway .enabled or include_inactive :
1298- return GatewayRead .model_validate (gateway ).masked ()
1303+ return GatewayRead .model_validate (self . _prepare_gateway_for_read ( gateway ) ).masked ()
12991304
13001305 raise GatewayNotFoundError (f"Gateway not found: { gateway_id } " )
13011306
@@ -1408,7 +1413,7 @@ async def toggle_gateway_status(self, db: Session, gateway_id: str, activate: bo
14081413
14091414 logger .info (f"Gateway status: { gateway .name } - { 'enabled' if activate else 'disabled' } and { 'accessible' if reachable else 'inaccessible' } " )
14101415
1411- return GatewayRead .model_validate (gateway ).masked ()
1416+ return GatewayRead .model_validate (self . _prepare_gateway_for_read ( gateway ) ).masked ()
14121417
14131418 except Exception as e :
14141419 db .rollback ()
@@ -2419,6 +2424,22 @@ async def _notify_gateway_removed(self, gateway: DbGateway) -> None:
24192424 }
24202425 await self ._publish_event (event )
24212426
2427+ def _prepare_gateway_for_read (self , gateway : DbGateway ) -> DbGateway :
2428+ """Prepare a gateway object for GatewayRead validation.
2429+
2430+ Ensures auth_value is in the correct format (encoded string) for the schema.
2431+
2432+ Args:
2433+ gateway: Gateway database object
2434+
2435+ Returns:
2436+ Gateway object with properly formatted auth_value
2437+ """
2438+ # If auth_value is a dict, encode it to string for GatewayRead schema
2439+ if isinstance (gateway .auth_value , dict ):
2440+ gateway .auth_value = encode_auth (gateway .auth_value )
2441+ return gateway
2442+
24222443 def _create_db_tool (
24232444 self ,
24242445 tool : ToolCreate ,
@@ -2455,7 +2476,7 @@ def _create_db_tool(
24552476 annotations = tool .annotations ,
24562477 jsonpath_filter = tool .jsonpath_filter ,
24572478 auth_type = gateway .auth_type ,
2458- auth_value = gateway .auth_value ,
2479+ auth_value = encode_auth ( gateway . auth_value ) if isinstance ( gateway . auth_value , dict ) else gateway .auth_value ,
24592480 # Federation metadata - consistent across all scenarios
24602481 created_by = created_by or "system" ,
24612482 created_from_ip = created_from_ip ,
0 commit comments