From b183f30df930f6e5d5c65b4dd4b4a068e74b3725 Mon Sep 17 00:00:00 2001 From: LukeGus Date: Mon, 8 Sep 2025 00:34:34 -0500 Subject: [PATCH] Undo admin settings changes --- src/ui/Desktop/Admin/AdminSettings.tsx | 829 ++++++++++++------------- 1 file changed, 399 insertions(+), 430 deletions(-) diff --git a/src/ui/Desktop/Admin/AdminSettings.tsx b/src/ui/Desktop/Admin/AdminSettings.tsx index b2bb1f4a..ca1ab4f0 100644 --- a/src/ui/Desktop/Admin/AdminSettings.tsx +++ b/src/ui/Desktop/Admin/AdminSettings.tsx @@ -8,474 +8,443 @@ import {Input} from "@/components/ui/input.tsx"; import {Label} from "@/components/ui/label.tsx"; import {Tabs, TabsContent, TabsList, TabsTrigger} from "@/components/ui/tabs.tsx"; import { -    Table, -    TableBody, -    TableCell, -    TableHead, -    TableHeader, -    TableRow, + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, } from "@/components/ui/table.tsx"; -// 🎯 Import the Eye and EyeOff icons from lucide-react -import {Shield, Trash2, Users, Eye, EyeOff} from "lucide-react"; +import {Shield, Trash2, Users} from "lucide-react"; import {toast} from "sonner"; import {useTranslation} from "react-i18next"; import { -    getOIDCConfig, -    getRegistrationAllowed, -    getUserList, -    updateRegistrationAllowed, -    updateOIDCConfig, -    makeUserAdmin, -    removeAdminStatus, -    deleteUser + getOIDCConfig, + getRegistrationAllowed, + getUserList, + updateRegistrationAllowed, + updateOIDCConfig, + makeUserAdmin, + removeAdminStatus, + deleteUser } from "@/ui/main-axios.ts"; function getCookie(name: string) { -    return document.cookie.split('; ').reduce((r, v) => { -        const parts = v = v.split('='); -        return parts[0] === name ? decodeURIComponent(parts[1]) : r; -    }, ""); + return document.cookie.split('; ').reduce((r, v) => { + const parts = v.split('='); + return parts[0] === name ? decodeURIComponent(parts[1]) : r; + }, ""); } interface AdminSettingsProps { -    isTopbarOpen?: boolean; + isTopbarOpen?: boolean; } export function AdminSettings({isTopbarOpen = true}: AdminSettingsProps): React.ReactElement { -    const {t} = useTranslation(); -    const {state: sidebarState} = useSidebar(); + const {t} = useTranslation(); + const {state: sidebarState} = useSidebar(); -    const [allowRegistration, setAllowRegistration] = React.useState(true); -    const [regLoading, setRegLoading] = React.useState(false); + const [allowRegistration, setAllowRegistration] = React.useState(true); + const [regLoading, setRegLoading] = React.useState(false); - // 🎯 New state to manage password visibility - const [showClientSecret, setShowClientSecret] = React.useState(false); + const [oidcConfig, setOidcConfig] = React.useState({ + client_id: '', + client_secret: '', + issuer_url: '', + authorization_url: '', + token_url: '', + identifier_path: 'sub', + name_path: 'name', + scopes: 'openid email profile', + userinfo_url: '' + }); + const [oidcLoading, setOidcLoading] = React.useState(false); + const [oidcError, setOidcError] = React.useState(null); -    const [oidcConfig, setOidcConfig] = React.useState({ -        client_id: '', -        client_secret: '', -        issuer_url: '', -        authorization_url: '', -        token_url: '', -        identifier_path: 'sub', -        name_path: 'name', -        scopes: 'openid email profile', -        userinfo_url: '' -    }); -    const [oidcLoading, setOidcLoading] = React.useState(false); -    const [oidcError, setOidcError] = React.useState(null); + const [users, setUsers] = React.useState>([]); + const [usersLoading, setUsersLoading] = React.useState(false); + const [newAdminUsername, setNewAdminUsername] = React.useState(""); + const [makeAdminLoading, setMakeAdminLoading] = React.useState(false); + const [makeAdminError, setMakeAdminError] = React.useState(null); -    const [users, setUsers] = React.useState>([]); -    const [usersLoading, setUsersLoading] = React.useState(false); -    const [newAdminUsername, setNewAdminUsername] = React.useState(""); -    const [makeAdminLoading, setMakeAdminLoading] = React.useState(false); -    const [makeAdminError, setMakeAdminError] = React.useState(null); + React.useEffect(() => { + const jwt = getCookie("jwt"); + if (!jwt) return; + getOIDCConfig() + .then(res => { + if (res) setOidcConfig(res); + }) + .catch(() => { + }); + fetchUsers(); + }, []); -    React.useEffect(() => { -        const jwt = getCookie("jwt"); -        if (!jwt) return; -        getOIDCConfig() -            .then(res => { -                if (res) setOidcConfig(res); -            }) -            .catch(() => { -            }); -        fetchUsers(); -    }, []); + React.useEffect(() => { + getRegistrationAllowed() + .then(res => { + if (typeof res?.allowed === 'boolean') { + setAllowRegistration(res.allowed); + } + }) + .catch(() => { + }); + }, []); -    React.useEffect(() => { -        getRegistrationAllowed() -            .then(res => { -                if (typeof res?.allowed === 'boolean') { -                    setAllowRegistration(res.allowed); -                } -            }) -            .catch(() => { -            }); -    }, []); + const fetchUsers = async () => { + const jwt = getCookie("jwt"); + if (!jwt) return; + setUsersLoading(true); + try { + const response = await getUserList(); + setUsers(response.users); + } finally { + setUsersLoading(false); + } + }; -    const fetchUsers = async () => { -        const jwt = getCookie("jwt"); -        if (!jwt) return; -        setUsersLoading(true); -        try { -            const response = await getUserList(); -            setUsers(response.users); -        } finally { -            setUsersLoading(false); -        } -    }; + const handleToggleRegistration = async (checked: boolean) => { + setRegLoading(true); + const jwt = getCookie("jwt"); + try { + await updateRegistrationAllowed(checked); + setAllowRegistration(checked); + } finally { + setRegLoading(false); + } + }; -    const handleToggleRegistration = async (checked: boolean) => { -        setRegLoading(true); -        const jwt = getCookie("jwt"); -        try { -            await updateRegistrationAllowed(checked); -            setAllowRegistration(checked); -        } finally { -            setRegLoading(false); -        } -    }; + const handleOIDCConfigSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setOidcLoading(true); + setOidcError(null); -    const handleOIDCConfigSubmit = async (e: React.FormEvent) => { -        e.preventDefault(); -        setOidcLoading(true); -        setOidcError(null); + const required = ['client_id', 'client_secret', 'issuer_url', 'authorization_url', 'token_url']; + const missing = required.filter(f => !oidcConfig[f as keyof typeof oidcConfig]); + if (missing.length > 0) { + setOidcError(t('admin.missingRequiredFields', { fields: missing.join(', ') })); + setOidcLoading(false); + return; + } -        const required = ['client_id', 'client_secret', 'issuer_url', 'authorization_url', 'token_url']; -        const missing = required.filter(f => !oidcConfig[f as keyof typeof oidcConfig]); -        if (missing.length > 0) { -            setOidcError(t('admin.missingRequiredFields', { fields: missing.join(', ') })); -            setOidcLoading(false); -            return; -        } + const jwt = getCookie("jwt"); + try { + await updateOIDCConfig(oidcConfig); + toast.success(t('admin.oidcConfigurationUpdated')); + } catch (err: any) { + setOidcError(err?.response?.data?.error || t('admin.failedToUpdateOidcConfig')); + } finally { + setOidcLoading(false); + } + }; -        const jwt = getCookie("jwt"); -        try { -            await updateOIDCConfig(oidcConfig); -            toast.success(t('admin.oidcConfigurationUpdated')); -        } catch (err: any) { -            setOidcError(err?.response?.data?.error || t('admin.failedToUpdateOidcConfig')); -        } finally { -            setOidcLoading(false); -        } -    }; + const handleOIDCConfigChange = (field: string, value: string) => { + setOidcConfig(prev => ({...prev, [field]: value})); + }; -    const handleOIDCConfigChange = (field: string, value: string) => { -        setOidcConfig(prev => ({...prev, [field]: value})); -    }; + const handleMakeUserAdmin = async (e: React.FormEvent) => { + e.preventDefault(); + if (!newAdminUsername.trim()) return; + setMakeAdminLoading(true); + setMakeAdminError(null); + const jwt = getCookie("jwt"); + try { + await makeUserAdmin(newAdminUsername.trim()); + toast.success(t('admin.userIsNowAdmin', { username: newAdminUsername })); + setNewAdminUsername(""); + fetchUsers(); + } catch (err: any) { + setMakeAdminError(err?.response?.data?.error || t('admin.failedToMakeUserAdmin')); + } finally { + setMakeAdminLoading(false); + } + }; -    const handleMakeUserAdmin = async (e: React.FormEvent) => { -        e.preventDefault(); -        if (!newAdminUsername.trim()) return; -        setMakeAdminLoading(true); -        setMakeAdminError(null); -        const jwt = getCookie("jwt"); -        try { -            await makeUserAdmin(newAdminUsername.trim()); -            toast.success(t('admin.userIsNowAdmin', { username: newAdminUsername })); -            setNewAdminUsername(""); -            fetchUsers(); -        } catch (err: any) { -            setMakeAdminError(err?.response?.data?.error || t('admin.failedToMakeUserAdmin')); -        } finally { -            setMakeAdminLoading(false); -        } -    }; + const handleRemoveAdminStatus = async (username: string) => { + if (!confirm(t('admin.removeAdminStatus', { username }))) return; + const jwt = getCookie("jwt"); + try { + await removeAdminStatus(username); + toast.success(t('admin.adminStatusRemoved', { username })); + fetchUsers(); + } catch (err: any) { + console.error('Failed to remove admin status:', err); + toast.error(t('admin.failedToRemoveAdminStatus')); + } + }; -    const handleRemoveAdminStatus = async (username: string) => { -        if (!confirm(t('admin.removeAdminStatus', { username }))) return; -        const jwt = getCookie("jwt"); -        try { -            await removeAdminStatus(username); -            toast.success(t('admin.adminStatusRemoved', { username })); -            fetchUsers(); -        } catch (err: any) { -            console.error('Failed to remove admin status:', err); -            toast.error(t('admin.failedToRemoveAdminStatus')); -        } -    }; + const handleDeleteUser = async (username: string) => { + if (!confirm(t('admin.deleteUser', { username }))) return; + const jwt = getCookie("jwt"); + try { + await deleteUser(username); + toast.success(t('admin.userDeletedSuccessfully', { username })); + fetchUsers(); + } catch (err: any) { + console.error('Failed to delete user:', err); + toast.error(t('admin.failedToDeleteUser')); + } + }; -    const handleDeleteUser = async (username: string) => { -        if (!confirm(t('admin.deleteUser', { username }))) return; -        const jwt = getCookie("jwt"); -        try { -            await deleteUser(username); -            toast.success(t('admin.userDeletedSuccessfully', { username })); -            fetchUsers(); -        } catch (err: any) { -            console.error('Failed to delete user:', err); -            toast.error(t('admin.failedToDeleteUser')); -        } -    }; + const topMarginPx = isTopbarOpen ? 74 : 26; + const leftMarginPx = sidebarState === 'collapsed' ? 26 : 8; + const bottomMarginPx = 8; + const wrapperStyle: React.CSSProperties = { + marginLeft: leftMarginPx, + marginRight: 17, + marginTop: topMarginPx, + marginBottom: bottomMarginPx, + height: `calc(100vh - ${topMarginPx + bottomMarginPx}px)` + }; -    const topMarginPx = isTopbarOpen ? 74 : 26; -    const leftMarginPx = sidebarState === 'collapsed' ? 26 : 8; -    const bottomMarginPx = 8; -    const wrapperStyle: React.CSSProperties = { -        marginLeft: leftMarginPx, -        marginRight: 17, -        marginTop: topMarginPx, -        marginBottom: bottomMarginPx, -        height: `calc(100vh - ${topMarginPx + bottomMarginPx}px)` -    }; + return ( +
+
+
+

{t('admin.title')}

+
+ -    return ( -       
-           
-               
-                   

{t('admin.title')}

-               
-                +
+ + + + + {t('admin.general')} + + + + OIDC + + + + {t('admin.users')} + + + + {t('admin.adminManagement')} + + -               
-                    -                        -                            -                                -                                {t('admin.general')} -                            -                            -                                -                                OIDC -                            -                            -                                -                                {t('admin.users')} -                            -                            -                                -                                {t('admin.adminManagement')} -                            -                        + +
+

{t('admin.userRegistration')}

+ +
+
-                        -                           
-                               

{t('admin.userRegistration')}

-                                -                           
-                       
+ +
+

{t('admin.externalAuthentication')}

+

{t('admin.configureExternalProvider')}

-                        -                           
-                               

{t('admin.externalAuthentication')}

-                               

{t('admin.configureExternalProvider')}

+ {oidcError && ( + + {t('common.error')} + {oidcError} + + )} -                                {oidcError && ( -                                    -                                        {t('common.error')} -                                        {oidcError} -                                    -                                )} +
+
+ + handleOIDCConfigChange('client_id', e.target.value)} + placeholder={t('placeholders.clientId')} required/> +
+
+ + handleOIDCConfigChange('client_secret', e.target.value)} + placeholder={t('placeholders.clientSecret')} required/> +
+
+ + handleOIDCConfigChange('authorization_url', e.target.value)} + placeholder={t('placeholders.authUrl')} + required/> +
+
+ + handleOIDCConfigChange('issuer_url', e.target.value)} + placeholder={t('placeholders.redirectUrl')} required/> +
+
+ + handleOIDCConfigChange('token_url', e.target.value)} + placeholder={t('placeholders.tokenUrl')} required/> +
+
+ + handleOIDCConfigChange('identifier_path', e.target.value)} + placeholder={t('placeholders.userIdField')} required/> +
+
+ + handleOIDCConfigChange('name_path', e.target.value)} + placeholder={t('placeholders.usernameField')} required/> +
+
+ + handleOIDCConfigChange('scopes', e.target.value)} + placeholder={t('placeholders.scopes')} required/> +
+
+ + handleOIDCConfigChange('userinfo_url', e.target.value)} + placeholder="https://your-provider.com/application/o/userinfo/"/> +
+
+ + +
+
+
+
-                               
-                                   
-                                        -                                        handleOIDCConfigChange('client_id', e.target.value)} -                                               placeholder={t('placeholders.clientId')} required/> -                                   
- {/* 🎯 Updated block for client_secret input */} -                                   
-                                        -      
- handleOIDCConfigChange('client_secret', e.target.value)} - placeholder={t('placeholders.clientSecret')} - required - // 🎯 Add padding to the right for the button - className="pr-10" - /> - + +
+
+

{t('admin.userManagement')}

+ +
+ {usersLoading ? ( +
{t('admin.loadingUsers')}
+ ) : ( +
+ + + + {t('admin.username')} + {t('admin.type')} + {t('admin.actions')} + + + + {users.map((user) => ( + + + {user.username} + {user.is_admin && ( + {t('admin.adminBadge')} + )} + + {user.is_oidc ? t('admin.external') : t('admin.local')} + + + + + ))} + +
+
+ )} +
+
+ + +
+

{t('admin.adminManagement')}

+
+

{t('admin.makeUserAdmin')}

+ +
+ +
+ setNewAdminUsername(e.target.value)} + placeholder={t('admin.enterUsernameToMakeAdmin')} required/> + +
-                                   
- {/* 🎯 End of updated block */} -                                   
-                                        -                                        handleOIDCConfigChange('authorization_url', e.target.value)} -                                               placeholder={t('placeholders.authUrl')} -                                               required/> -                                   
-                                   
-                                        -                                        handleOIDCConfigChange('issuer_url', e.target.value)} -                                               placeholder={t('placeholders.redirectUrl')} required/> -                                   
-                                   
-                                        -                                        handleOIDCConfigChange('token_url', e.target.value)} -                                               placeholder={t('placeholders.tokenUrl')} required/> -                                   
-                                   
-                                        -                                        handleOIDCConfigChange('identifier_path', e.target.value)} -                                               placeholder={t('placeholders.userIdField')} required/> -                                   
-                                   
-                                        -                                        handleOIDCConfigChange('name_path', e.target.value)} -                                               placeholder={t('placeholders.usernameField')} required/> -                                   
-                                   
-                                        -                                        handleOIDCConfigChange('scopes', e.target.value)} -                                               placeholder={t('placeholders.scopes')} required/> -                                   
-                                   
-                                        -                                        handleOIDCConfigChange('userinfo_url', e.target.value)} -                                               placeholder="https://your-provider.com/application/o/userinfo/"/> -                                   
-                                   
-                                        -                                        -                                   
-                                -                           
-                       
+ {makeAdminError && ( + + {t('common.error')} + {makeAdminError} + + )} -                        -                           
-                               
-                                   

{t('admin.userManagement')}

-                                    -                               
-                                {usersLoading ? ( -                                   
{t('admin.loadingUsers')}
-                                ) : ( -                                   
-                                        -                                            -                                                -                                                    {t('admin.username')} -                                                    {t('admin.type')} -                                                    {t('admin.actions')} -                                                -                                            -                                            -                                                {users.map((user) => ( -                                                    -                                                        -                                                            {user.username} -                                                            {user.is_admin && ( -                                                                {t('admin.adminBadge')} -                                                            )} -                                                        -                                                        {user.is_oidc ? t('admin.external') : t('admin.local')} -                                                        -                                                            -                                                        -                                                    -                                                ))} -                                            -                                       
-                                   
-                                )} -                           
-                       
+ +
-                        -                           
-                               

{t('admin.adminManagement')}

-                               
-                                   

{t('admin.makeUserAdmin')}

-                                   
-                                       
-                                            -                                           
-                                                setNewAdminUsername(e.target.value)} -                                                       placeholder={t('admin.enterUsernameToMakeAdmin')} required/> -                                                -                                           
-                                       
-                                        {makeAdminError && ( -                                            -                                                {t('common.error')} -                                                {makeAdminError} -                                            -                                        )} - -                                   
-                               
- -                               
-                                   

{t('admin.currentAdmins')}

-                                   
-                                        -                                            -                                                -                                                    {t('admin.username')} -                                                    {t('admin.type')} -                                                    {t('admin.actions')} -                                                -                                            -                                            -                                                {users.filter(u => u.is_admin).map((admin) => ( -                                                    -                                                        -                                                            {admin.username} -                                                            {t('admin.adminBadge')} -                                                        -                                                        {admin.is_oidc ? t('admin.external') : t('admin.local')} -                                                        -                                                            -                                                        -                                                    -                                                ))} -                                            -                                       
-                                   
-                               
-                           
-                       
-                    -               
-           
-       
-    ); +
+

{t('admin.currentAdmins')}

+
+ + + + {t('admin.username')} + {t('admin.type')} + {t('admin.actions')} + + + + {users.filter(u => u.is_admin).map((admin) => ( + + + {admin.username} + {t('admin.adminBadge')} + + {admin.is_oidc ? t('admin.external') : t('admin.local')} + + + + + ))} + +
+
+
+
+ + +
+
+
+ ); } export default AdminSettings; \ No newline at end of file