From 1bb990719e27e019fda4aa3038effc7b027a8bd7 Mon Sep 17 00:00:00 2001 From: liwenju0 Date: Fri, 21 Mar 2025 09:38:15 +0800 Subject: [PATCH] Feat: Add user registration toggle feature (#6327) ### What problem does this PR solve? Feat: Add user registration toggle feature. Added a user registration toggle REGISTER_ENABLED in the settings and .env config file. The user creation interface now checks the state of this toggle to control the enabling and disabling of the user registration feature. the front-end implementation is done, the registration button does not appear if registration is not allowed. I did the actual tests on my local server and it worked smoothly. ### Type of change - [x] New Feature (non-breaking change which adds functionality) --------- Co-authored-by: wenju.li Co-authored-by: Kevin Hu --- api/apps/system_app.py | 23 ++++++++++++++++++++++- api/apps/user_app.py | 8 ++++++++ api/settings.py | 9 ++++++++- docker/.env | 3 +++ web/src/hooks/login-hooks.ts | 2 ++ web/src/hooks/system-hooks.ts | 18 ++++++++++++++++++ web/src/locales/en.ts | 1 + web/src/pages/login/index.tsx | 8 +++++++- web/src/services/user-service.ts | 5 +++++ web/src/utils/api.ts | 1 + 10 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 web/src/hooks/system-hooks.ts diff --git a/api/apps/system_app.py b/api/apps/system_app.py index c1ae5ec3b..c4a70bcac 100644 --- a/api/apps/system_app.py +++ b/api/apps/system_app.py @@ -37,7 +37,6 @@ from timeit import default_timer as timer from rag.utils.redis_conn import REDIS_CONN - @manager.route("/version", methods=["GET"]) # noqa: F821 @login_required def version(): @@ -298,3 +297,25 @@ def rm(token): [APIToken.tenant_id == current_user.id, APIToken.token == token] ) return get_json_result(data=True) + + +@manager.route('/config', methods=['GET']) # noqa: F821 +def get_config(): + """ + Get system configuration. + --- + tags: + - System + responses: + 200: + description: Return system configuration + schema: + type: object + properties: + registerEnable: + type: integer 0 means disabled, 1 means enabled + description: Whether user registration is enabled + """ + return get_json_result(data={ + "registerEnabled": settings.REGISTER_ENABLED + }) diff --git a/api/apps/user_app.py b/api/apps/user_app.py index 1cf85986c..89e771448 100644 --- a/api/apps/user_app.py +++ b/api/apps/user_app.py @@ -562,6 +562,14 @@ def user_add(): schema: type: object """ + + if not settings.REGISTER_ENABLED: + return get_json_result( + data=False, + message="User registration is disabled!", + code=settings.RetCode.OPERATING_ERROR, + ) + req = request.json email_address = req["email"] diff --git a/api/settings.py b/api/settings.py index d4b829cf9..87b4858b9 100644 --- a/api/settings.py +++ b/api/settings.py @@ -62,9 +62,12 @@ docStoreConn = None retrievaler = None kg_retrievaler = None +# user registration switch +REGISTER_ENABLED = 1 + def init_settings(): - global LLM, LLM_FACTORY, LLM_BASE_URL, LIGHTEN, DATABASE_TYPE, DATABASE, FACTORY_LLM_INFOS + global LLM, LLM_FACTORY, LLM_BASE_URL, LIGHTEN, DATABASE_TYPE, DATABASE, FACTORY_LLM_INFOS, REGISTER_ENABLED LIGHTEN = int(os.environ.get('LIGHTEN', "0")) DATABASE_TYPE = os.getenv("DB_TYPE", 'mysql') DATABASE = decrypt_database_config(name=DATABASE_TYPE) @@ -72,6 +75,10 @@ def init_settings(): LLM_DEFAULT_MODELS = LLM.get("default_models", {}) LLM_FACTORY = LLM.get("factory", "Tongyi-Qianwen") LLM_BASE_URL = LLM.get("base_url") + try: + REGISTER_ENABLED = int(os.environ.get("REGISTER_ENABLED", "1")) + except Exception: + pass 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 2b0b5b8be..40a8a3c5e 100644 --- a/docker/.env +++ b/docker/.env @@ -146,3 +146,6 @@ TIMEZONE='Asia/Shanghai' # ENDPOINT=http://oss-cn-hangzhou.aliyuncs.com # REGION=cn-hangzhou # BUCKET=ragflow65536 + +# user registration switch +REGISTER_ENABLED=1 diff --git a/web/src/hooks/login-hooks.ts b/web/src/hooks/login-hooks.ts index 8f8c292c3..ddecc3ce7 100644 --- a/web/src/hooks/login-hooks.ts +++ b/web/src/hooks/login-hooks.ts @@ -67,6 +67,8 @@ export const useRegister = () => { const { data = {} } = await userService.register(params); if (data.code === 0) { message.success(t('message.registered')); + } else if (data.message && data.message.includes('registration is disabled')) { + message.error(t('message.registerDisabled') || 'User registration is disabled'); } return data.code; }, diff --git a/web/src/hooks/system-hooks.ts b/web/src/hooks/system-hooks.ts new file mode 100644 index 000000000..b5ce92969 --- /dev/null +++ b/web/src/hooks/system-hooks.ts @@ -0,0 +1,18 @@ +import userService from '@/services/user-service'; +import { useQuery } from '@tanstack/react-query'; + +/** + * Hook to fetch system configuration including register enable status + * @returns System configuration with loading status + */ +export const useSystemConfig = () => { + const { data, isLoading } = useQuery({ + queryKey: ['systemConfig'], + queryFn: async () => { + const { data = {} } = await userService.getSystemConfig(); + return data.data || { registerEnabled: 1 }; // Default to enabling registration + }, + }); + + return { config: data, loading: isLoading }; +}; diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index c686e03a3..181bbcf34 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -705,6 +705,7 @@ This auto-tag feature enhances retrieval by adding another layer of domain-speci logout: 'logout', logged: 'logged!', pleaseSelectChunk: 'Please select chunk!', + registerDisabled: 'User registration is disabled', modified: 'Modified', created: 'Created', deleted: 'Deleted', diff --git a/web/src/pages/login/index.tsx b/web/src/pages/login/index.tsx index 0bc24cf04..dab0b264c 100644 --- a/web/src/pages/login/index.tsx +++ b/web/src/pages/login/index.tsx @@ -1,4 +1,5 @@ import { useLogin, useRegister } from '@/hooks/login-hooks'; +import { useSystemConfig } from '@/hooks/system-hooks'; import { rsaPsw } from '@/utils'; import { Button, Checkbox, Form, Input } from 'antd'; import { useEffect, useState } from 'react'; @@ -16,8 +17,13 @@ const Login = () => { const { register, loading: registerLoading } = useRegister(); const { t } = useTranslation('translation', { keyPrefix: 'login' }); const loading = signLoading || registerLoading; + const { config } = useSystemConfig(); + const registerEnabled = config?.registerEnabled !== 0; const changeTitle = () => { + if (title === 'login' && !registerEnabled) { + return; + } setTitle((title) => (title === 'login' ? 'register' : 'login')); }; const [form] = Form.useForm(); @@ -119,7 +125,7 @@ const Login = () => { )}
- {title === 'login' && ( + {title === 'login' && registerEnabled && (
{t('signInTip')}