@@ -217,6 +217,22 @@ pub(crate) async fn load_network_access(app_state: &AppState) -> bool {
217217 load_network_access_from_repo ( & app_state. settings_repository ) . await
218218}
219219
220+ pub ( crate ) async fn load_gateway_auth_disabled_from_repo (
221+ settings_repository : & Arc < dyn mcpmux_core:: AppSettingsRepository > ,
222+ ) -> bool {
223+ settings_repository
224+ . get ( GATEWAY_AUTH_DISABLED_KEY )
225+ . await
226+ . ok ( )
227+ . flatten ( )
228+ . map ( |value| value == "true" )
229+ . unwrap_or ( false )
230+ }
231+
232+ pub ( crate ) async fn load_gateway_auth_disabled ( app_state : & AppState ) -> bool {
233+ load_gateway_auth_disabled_from_repo ( & app_state. settings_repository ) . await
234+ }
235+
220236pub ( crate ) fn advertised_base_url ( public_base_url : Option < & str > , port : u16 ) -> String {
221237 public_base_url
222238 . map ( str:: trim)
@@ -1037,18 +1053,8 @@ pub async fn start_gateway(
10371053 // Seed the system-wide inbound-auth toggle into the running gateway from
10381054 // persisted settings (default: auth required). Live changes go through
10391055 // `set_gateway_auth_disabled`.
1040- {
1041- let disabled = app_state
1042- . settings_repository
1043- . get ( GATEWAY_AUTH_DISABLED_KEY )
1044- . await
1045- . ok ( )
1046- . flatten ( )
1047- . map ( |v| v == "true" )
1048- . unwrap_or ( false ) ;
1049- if disabled {
1050- gw_state. write ( ) . await . set_auth_disabled ( true ) ;
1051- }
1056+ if load_gateway_auth_disabled ( & app_state) . await {
1057+ gw_state. write ( ) . await . set_auth_disabled ( true ) ;
10521058 }
10531059
10541060 // Subscribe to OAuth completions BEFORE spawn so we don't miss early
@@ -2041,3 +2047,37 @@ mod public_base_url_tests {
20412047 assert_eq ! ( super :: bind_host_for( true ) , "0.0.0.0" ) ;
20422048 }
20432049}
2050+
2051+ #[ cfg( test) ]
2052+ mod gateway_auth_settings_tests {
2053+ use super :: { load_gateway_auth_disabled_from_repo, GATEWAY_AUTH_DISABLED_KEY } ;
2054+ use mcpmux_core:: AppSettingsRepository ;
2055+ use mcpmux_storage:: { Database , SqliteAppSettingsRepository } ;
2056+ use std:: sync:: Arc ;
2057+ use tokio:: sync:: Mutex ;
2058+
2059+ fn settings_repo ( ) -> Arc < dyn AppSettingsRepository > {
2060+ let database = Database :: open_in_memory ( ) . expect ( "create in-memory database" ) ;
2061+ Arc :: new ( SqliteAppSettingsRepository :: new ( Arc :: new ( Mutex :: new (
2062+ database,
2063+ ) ) ) )
2064+ }
2065+
2066+ #[ tokio:: test]
2067+ async fn auth_remains_required_when_disable_setting_is_missing ( ) {
2068+ let repository = settings_repo ( ) ;
2069+
2070+ assert ! ( !load_gateway_auth_disabled_from_repo( & repository) . await ) ;
2071+ }
2072+
2073+ #[ tokio:: test]
2074+ async fn persisted_disable_setting_is_restored_on_gateway_start ( ) {
2075+ let repository = settings_repo ( ) ;
2076+ repository
2077+ . set ( GATEWAY_AUTH_DISABLED_KEY , "true" )
2078+ . await
2079+ . unwrap ( ) ;
2080+
2081+ assert ! ( load_gateway_auth_disabled_from_repo( & repository) . await ) ;
2082+ }
2083+ }
0 commit comments