diff --git a/api/apps/system_app.py b/api/apps/system_app.py index b15054490b..da634ee7f0 100644 --- a/api/apps/system_app.py +++ b/api/apps/system_app.py @@ -371,4 +371,7 @@ def get_config(): type: integer 0 means disabled, 1 means enabled description: Whether user registration is enabled """ - return get_json_result(data={"registerEnabled": settings.REGISTER_ENABLED}) + return get_json_result(data={ + "registerEnabled": settings.REGISTER_ENABLED, + "disablePasswordLogin": settings.DISABLE_PASSWORD_LOGIN, + }) diff --git a/common/config_utils.py b/common/config_utils.py index ac55f7e972..d367536de1 100644 --- a/common/config_utils.py +++ b/common/config_utils.py @@ -102,7 +102,7 @@ def show_configs(): if "authentication" in k: v = copy.deepcopy(v) for key, val in v.items(): - if "http_secret_key" in val: + if isinstance(val, dict) and "http_secret_key" in val: val["http_secret_key"] = "*" * 8 msg += f"\n\t{k}: {v}" logging.info(msg) @@ -152,4 +152,4 @@ def update_config(key, value, conf_name=SERVICE_CONF): with FileLock(os.path.join(os.path.dirname(conf_path), ".lock")): config = load_yaml_conf(conf_path=conf_path) or {} config[key] = value - rewrite_yaml_conf(conf_path=conf_path, config=config) + rewrite_yaml_conf(conf_path=conf_path, config=config) \ No newline at end of file diff --git a/common/settings.py b/common/settings.py index de26353637..fe3d07b33c 100644 --- a/common/settings.py +++ b/common/settings.py @@ -92,6 +92,8 @@ kg_retriever = None # user registration switch REGISTER_ENABLED = 1 +# SSO-only mode: hide password login form +DISABLE_PASSWORD_LOGIN = False # sandbox-executor-manager SANDBOX_HOST = None @@ -186,6 +188,17 @@ def init_settings(): except Exception: pass + global DISABLE_PASSWORD_LOGIN + try: + env_val = os.environ.get("DISABLE_PASSWORD_LOGIN", "").lower() + if env_val in ("1", "true", "yes"): + DISABLE_PASSWORD_LOGIN = True + else: + authentication_conf = get_base_config("authentication", {}) + DISABLE_PASSWORD_LOGIN = bool(authentication_conf.get("disable_password_login", False)) + except Exception: + pass + global FACTORY_LLM_INFOS try: with open(os.path.join(get_project_base_directory(), "conf", "llm_factories.json"), "r") as f: diff --git a/docker/.env b/docker/.env index 57a42ac1ab..8e20e257bb 100644 --- a/docker/.env +++ b/docker/.env @@ -276,4 +276,7 @@ DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 # Used for ThreadPoolExecutor -THREAD_POOL_MAX_WORKERS=128 \ No newline at end of file +THREAD_POOL_MAX_WORKERS=128 + +#Option to disable login form for SSO +DISABLE_PASSWORD_LOGIN=false \ No newline at end of file diff --git a/docker/service_conf.yaml.template b/docker/service_conf.yaml.template index 4fac37f55d..ba30a0240d 100644 --- a/docker/service_conf.yaml.template +++ b/docker/service_conf.yaml.template @@ -143,12 +143,13 @@ user_default_llm: # client_secret: "your_client_secret" # redirect_uri: "https://your-app.com/v1/user/oauth/callback/github" # authentication: -# client: -# switch: false -# http_app_key: -# http_secret_key: -# site: -# switch: false +# client: +# switch: false +# http_app_key: +# http_secret_key: +# site: +# switch: false +# disable_password_login: false # permission: # switch: false # component: false diff --git a/test/testcases/test_web_api/test_system_app/test_system_routes_unit.py b/test/testcases/test_web_api/test_system_app/test_system_routes_unit.py index 08e24992d9..a00ecdbb6f 100644 --- a/test/testcases/test_web_api/test_system_app/test_system_routes_unit.py +++ b/test/testcases/test_web_api/test_system_app/test_system_routes_unit.py @@ -76,6 +76,7 @@ def _load_system_module(monkeypatch): settings_mod.STORAGE_IMPL_TYPE = "MINIO" settings_mod.DATABASE_TYPE = "MYSQL" settings_mod.REGISTER_ENABLED = True + settings_mod.DISABLE_PASSWORD_LOGIN = False common_pkg.settings = settings_mod monkeypatch.setitem(sys.modules, "common.settings", settings_mod) diff --git a/web/src/pages/login-next/index.tsx b/web/src/pages/login-next/index.tsx index 0384296b36..69c929b89c 100644 --- a/web/src/pages/login-next/index.tsx +++ b/web/src/pages/login-next/index.tsx @@ -43,6 +43,7 @@ type LoginFormContentProps = { channels: { channel: string; icon?: string; display_name: string }[]; handleLoginWithChannel: (channel: string) => void; t: ReturnType['t']; + disablePasswordLogin?: boolean; }; function LoginFormContent({ @@ -56,6 +57,7 @@ function LoginFormContent({ channels, handleLoginWithChannel, t, + disablePasswordLogin, }: LoginFormContentProps) { const face = useContext(FlipFaceContext); const isActiveFace = isLoginPage ? face === 'front' : face === 'back'; @@ -68,6 +70,7 @@ function LoginFormContent({
+ {!disablePasswordLogin && (
{title === 'login' ? t('login') : t('continue')} - {title === 'login' && channels && channels.length > 0 && ( -
- {channels.map((item) => ( - - ))} -
- )}
+ )} - {title === 'login' && registerEnabled && ( + {title === 'login' && channels && channels.length > 0 && ( +
+ {channels.map((item) => ( + + ))} +
+ )} + + {!disablePasswordLogin && title === 'login' && registerEnabled && (

{t('signInTip')} @@ -217,7 +223,7 @@ function LoginFormContent({

)} - {title === 'register' && ( + {!disablePasswordLogin && title === 'register' && (

{t('signUpTip')} @@ -369,14 +375,8 @@ const Login = () => {

{t('title')}

- {/* border border-accent-primary rounded-full */} - {/*
- {t('start')} -
*/}
- {/* Logo and Header */} - {/* Login Form */} { channels={channels || []} handleLoginWithChannel={handleLoginWithChannel} t={t} + disablePasswordLogin={!!config?.disablePasswordLogin} />
@@ -398,4 +399,4 @@ const Login = () => { ); }; -export default Login; +export default Login; \ No newline at end of file