diff --git a/backend/apps/webui/main.py b/backend/apps/webui/main.py index b823859a6..6ec9bbace 100644 --- a/backend/apps/webui/main.py +++ b/backend/apps/webui/main.py @@ -14,6 +14,8 @@ from apps.webui.routers import ( ) from config import ( WEBUI_BUILD_HASH, + SHOW_ADMIN_DETAILS, + ADMIN_EMAIL, WEBUI_AUTH, DEFAULT_MODELS, DEFAULT_PROMPT_SUGGESTIONS, @@ -37,6 +39,11 @@ app.state.config = AppConfig() app.state.config.ENABLE_SIGNUP = ENABLE_SIGNUP app.state.config.JWT_EXPIRES_IN = JWT_EXPIRES_IN + +app.state.config.SHOW_ADMIN_DETAILS = SHOW_ADMIN_DETAILS +app.state.config.ADMIN_EMAIL = ADMIN_EMAIL + + app.state.config.DEFAULT_MODELS = DEFAULT_MODELS app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE diff --git a/backend/apps/webui/routers/auths.py b/backend/apps/webui/routers/auths.py index ce9b92061..d45879a24 100644 --- a/backend/apps/webui/routers/auths.py +++ b/backend/apps/webui/routers/auths.py @@ -269,73 +269,88 @@ async def add_user(form_data: AddUserForm, user=Depends(get_admin_user)): raise HTTPException(500, detail=ERROR_MESSAGES.DEFAULT(err)) +############################ +# GetAdminDetails +############################ + + +@router.get("/admin/details") +async def get_admin_details(request: Request, user=Depends(get_current_user)): + if request.app.state.config.SHOW_ADMIN_DETAILS: + admin_email = request.app.state.config.ADMIN_EMAIL + admin_name = None + + print(admin_email, admin_name) + + if admin_email: + admin = Users.get_user_by_email(admin_email) + if admin: + admin_name = admin.name + else: + admin = Users.get_first_user() + if admin: + admin_email = admin.email + admin_name = admin.name + + return { + "name": admin_name, + "email": admin_email, + } + else: + raise HTTPException(400, detail=ERROR_MESSAGES.ACTION_PROHIBITED) + + ############################ # ToggleSignUp ############################ -@router.get("/signup/enabled", response_model=bool) -async def get_sign_up_status(request: Request, user=Depends(get_admin_user)): - return request.app.state.config.ENABLE_SIGNUP +@router.get("/admin/config") +async def get_admin_config(request: Request, user=Depends(get_admin_user)): + return { + "SHOW_ADMIN_DETAILS": request.app.state.config.SHOW_ADMIN_DETAILS, + "ENABLE_SIGNUP": request.app.state.config.ENABLE_SIGNUP, + "DEFAULT_USER_ROLE": request.app.state.config.DEFAULT_USER_ROLE, + "JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN, + "ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING, + } -@router.get("/signup/enabled/toggle", response_model=bool) -async def toggle_sign_up(request: Request, user=Depends(get_admin_user)): - request.app.state.config.ENABLE_SIGNUP = not request.app.state.config.ENABLE_SIGNUP - return request.app.state.config.ENABLE_SIGNUP +class AdminConfig(BaseModel): + SHOW_ADMIN_DETAILS: bool + ENABLE_SIGNUP: bool + DEFAULT_USER_ROLE: str + JWT_EXPIRES_IN: str + ENABLE_COMMUNITY_SHARING: bool -############################ -# Default User Role -############################ - - -@router.get("/signup/user/role") -async def get_default_user_role(request: Request, user=Depends(get_admin_user)): - return request.app.state.config.DEFAULT_USER_ROLE - - -class UpdateRoleForm(BaseModel): - role: str - - -@router.post("/signup/user/role") -async def update_default_user_role( - request: Request, form_data: UpdateRoleForm, user=Depends(get_admin_user) +@router.post("/admin/config") +async def update_admin_config( + request: Request, form_data: AdminConfig, user=Depends(get_admin_user) ): - if form_data.role in ["pending", "user", "admin"]: - request.app.state.config.DEFAULT_USER_ROLE = form_data.role - return request.app.state.config.DEFAULT_USER_ROLE + request.app.state.config.SHOW_ADMIN_DETAILS = form_data.SHOW_ADMIN_DETAILS + request.app.state.config.ENABLE_SIGNUP = form_data.ENABLE_SIGNUP + if form_data.DEFAULT_USER_ROLE in ["pending", "user", "admin"]: + request.app.state.config.DEFAULT_USER_ROLE = form_data.DEFAULT_USER_ROLE -############################ -# JWT Expiration -############################ - - -@router.get("/token/expires") -async def get_token_expires_duration(request: Request, user=Depends(get_admin_user)): - return request.app.state.config.JWT_EXPIRES_IN - - -class UpdateJWTExpiresDurationForm(BaseModel): - duration: str - - -@router.post("/token/expires/update") -async def update_token_expires_duration( - request: Request, - form_data: UpdateJWTExpiresDurationForm, - user=Depends(get_admin_user), -): pattern = r"^(-1|0|(-?\d+(\.\d+)?)(ms|s|m|h|d|w))$" # Check if the input string matches the pattern - if re.match(pattern, form_data.duration): - request.app.state.config.JWT_EXPIRES_IN = form_data.duration - return request.app.state.config.JWT_EXPIRES_IN - else: - return request.app.state.config.JWT_EXPIRES_IN + if re.match(pattern, form_data.JWT_EXPIRES_IN): + request.app.state.config.JWT_EXPIRES_IN = form_data.JWT_EXPIRES_IN + + request.app.state.config.ENABLE_COMMUNITY_SHARING = ( + form_data.ENABLE_COMMUNITY_SHARING + ) + + return { + "SHOW_ADMIN_DETAILS": request.app.state.config.SHOW_ADMIN_DETAILS, + "ENABLE_SIGNUP": request.app.state.config.ENABLE_SIGNUP, + "DEFAULT_USER_ROLE": request.app.state.config.DEFAULT_USER_ROLE, + "JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN, + "ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING, + } ############################ diff --git a/backend/apps/webui/routers/users.py b/backend/apps/webui/routers/users.py index cd17e3a7c..eccafde10 100644 --- a/backend/apps/webui/routers/users.py +++ b/backend/apps/webui/routers/users.py @@ -19,7 +19,12 @@ from apps.webui.models.users import ( from apps.webui.models.auths import Auths from apps.webui.models.chats import Chats -from utils.utils import get_verified_user, get_password_hash, get_admin_user +from utils.utils import ( + get_verified_user, + get_password_hash, + get_current_user, + get_admin_user, +) from constants import ERROR_MESSAGES from config import SRC_LOG_LEVELS diff --git a/backend/config.py b/backend/config.py index 7c073f68f..dd3bc9e4b 100644 --- a/backend/config.py +++ b/backend/config.py @@ -601,6 +601,20 @@ WEBUI_BANNERS = PersistentConfig( [BannerModel(**banner) for banner in json.loads("[]")], ) + +SHOW_ADMIN_DETAILS = PersistentConfig( + "SHOW_ADMIN_DETAILS", + "auth.admin.show", + os.environ.get("SHOW_ADMIN_DETAILS", "true").lower() == "true", +) + +ADMIN_EMAIL = PersistentConfig( + "ADMIN_EMAIL", + "auth.admin.email", + os.environ.get("ADMIN_EMAIL", None), +) + + #################################### # WEBUI_SECRET_KEY #################################### diff --git a/backend/main.py b/backend/main.py index 080269898..4e9d1adf9 100644 --- a/backend/main.py +++ b/backend/main.py @@ -879,23 +879,7 @@ class UrlForm(BaseModel): async def update_webhook_url(form_data: UrlForm, user=Depends(get_admin_user)): app.state.config.WEBHOOK_URL = form_data.url webui_app.state.WEBHOOK_URL = app.state.config.WEBHOOK_URL - - return { - "url": app.state.config.WEBHOOK_URL, - } - - -@app.get("/api/community_sharing", response_model=bool) -async def get_community_sharing_status(request: Request, user=Depends(get_admin_user)): - return webui_app.state.config.ENABLE_COMMUNITY_SHARING - - -@app.get("/api/community_sharing/toggle", response_model=bool) -async def toggle_community_sharing(request: Request, user=Depends(get_admin_user)): - webui_app.state.config.ENABLE_COMMUNITY_SHARING = ( - not webui_app.state.config.ENABLE_COMMUNITY_SHARING - ) - return webui_app.state.config.ENABLE_COMMUNITY_SHARING + return {"url": app.state.config.WEBHOOK_URL} @app.get("/api/version") diff --git a/src/lib/apis/auths/index.ts b/src/lib/apis/auths/index.ts index 26feb29b6..e202115b4 100644 --- a/src/lib/apis/auths/index.ts +++ b/src/lib/apis/auths/index.ts @@ -1,5 +1,87 @@ import { WEBUI_API_BASE_URL } from '$lib/constants'; +export const getAdminDetails = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/auths/admin/details`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.log(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const getAdminConfig = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/auths/admin/config`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.log(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const updateAdminConfig = async (token: string, body: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/auths/admin/config`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + body: JSON.stringify(body) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.log(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const getSessionUser = async (token: string) => { let error = null; diff --git a/src/lib/components/admin/Settings/General.svelte b/src/lib/components/admin/Settings/General.svelte index 572ff82ad..a7ffdabfb 100644 --- a/src/lib/components/admin/Settings/General.svelte +++ b/src/lib/components/admin/Settings/General.svelte @@ -6,61 +6,44 @@ updateWebhookUrl } from '$lib/apis'; import { + getAdminConfig, getDefaultUserRole, getJWTExpiresDuration, getSignUpEnabledStatus, toggleSignUpEnabledStatus, + updateAdminConfig, updateDefaultUserRole, updateJWTExpiresDuration } from '$lib/apis/auths'; + import Switch from '$lib/components/common/Switch.svelte'; import { onMount, getContext } from 'svelte'; const i18n = getContext('i18n'); export let saveHandler: Function; - let signUpEnabled = true; - let defaultUserRole = 'pending'; - let JWTExpiresIn = ''; + let adminConfig = null; let webhookUrl = ''; - let communitySharingEnabled = true; - const toggleSignUpEnabled = async () => { - signUpEnabled = await toggleSignUpEnabledStatus(localStorage.token); - }; - - const updateDefaultUserRoleHandler = async (role) => { - defaultUserRole = await updateDefaultUserRole(localStorage.token, role); - }; - - const updateJWTExpiresDurationHandler = async (duration) => { - JWTExpiresIn = await updateJWTExpiresDuration(localStorage.token, duration); - }; - - const updateWebhookUrlHandler = async () => { + const updateHandler = async () => { webhookUrl = await updateWebhookUrl(localStorage.token, webhookUrl); - }; + const res = await updateAdminConfig(localStorage.token, adminConfig); - const toggleCommunitySharingEnabled = async () => { - communitySharingEnabled = await toggleCommunitySharingEnabledStatus(localStorage.token); + if (res) { + toast.success(i18n.t('Settings updated successfully')); + } else { + toast.error(i18n.t('Failed to update settings')); + } }; onMount(async () => { await Promise.all([ (async () => { - signUpEnabled = await getSignUpEnabledStatus(localStorage.token); - })(), - (async () => { - defaultUserRole = await getDefaultUserRole(localStorage.token); - })(), - (async () => { - JWTExpiresIn = await getJWTExpiresDuration(localStorage.token); + adminConfig = await getAdminConfig(localStorage.token); })(), + (async () => { webhookUrl = await getWebhookUrl(localStorage.token); - })(), - (async () => { - communitySharingEnabled = await getCommunitySharingEnabledStatus(localStorage.token); })() ]); }); @@ -69,156 +52,94 @@