diff --git a/apps/client/src/ee/components/ldap-login-modal.tsx b/apps/client/src/ee/components/ldap-login-modal.tsx new file mode 100644 index 00000000..9360651d --- /dev/null +++ b/apps/client/src/ee/components/ldap-login-modal.tsx @@ -0,0 +1,124 @@ +import React, { useState } from "react"; +import { Modal, TextInput, PasswordInput, Button, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { zodResolver } from "mantine-form-zod-resolver"; +import { z } from "zod"; +import { notifications } from "@mantine/notifications"; +import { useNavigate } from "react-router-dom"; +import { useTranslation } from "react-i18next"; +import { IAuthProvider } from "@/ee/security/types/security.types"; +import APP_ROUTE from "@/lib/app-route"; +import { ldapLogin } from "@/ee/security/services/ldap-auth-service"; + +const formSchema = z.object({ + username: z.string().min(1, { message: "Username is required" }), + password: z.string().min(1, { message: "Password is required" }), +}); + +interface LdapLoginModalProps { + opened: boolean; + onClose: () => void; + provider: IAuthProvider; + workspaceId: string; +} + +export function LdapLoginModal({ + opened, + onClose, + provider, + workspaceId, +}: LdapLoginModalProps) { + const { t } = useTranslation(); + const navigate = useNavigate(); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const form = useForm({ + validate: zodResolver(formSchema), + initialValues: { + username: "", + password: "", + }, + }); + + const handleSubmit = async (values: { + username: string; + password: string; + }) => { + setIsLoading(true); + setError(null); + + try { + const response = await ldapLogin({ + username: values.username, + password: values.password, + providerId: provider.id, + workspaceId, + }); + + // Handle MFA like the regular login + if (response?.userHasMfa) { + onClose(); + navigate(APP_ROUTE.AUTH.MFA_CHALLENGE); + } else if (response?.requiresMfaSetup) { + onClose(); + navigate(APP_ROUTE.AUTH.MFA_SETUP_REQUIRED); + } else { + onClose(); + navigate(APP_ROUTE.HOME); + } + } catch (err: any) { + setIsLoading(false); + const errorMessage = + err.response?.data?.message || "Authentication failed"; + setError(errorMessage); + + notifications.show({ + message: errorMessage, + color: "red", + }); + } + }; + + const handleClose = () => { + form.reset(); + setError(null); + onClose(); + }; + + return ( + +
+ + + + + + + +
+
+ ); +} diff --git a/apps/client/src/ee/components/sso-login.tsx b/apps/client/src/ee/components/sso-login.tsx index 8de93c29..8c96d9c5 100644 --- a/apps/client/src/ee/components/sso-login.tsx +++ b/apps/client/src/ee/components/sso-login.tsx @@ -1,29 +1,62 @@ +import { useState } from "react"; import { useWorkspacePublicDataQuery } from "@/features/workspace/queries/workspace-query.ts"; import { Button, Divider, Stack } from "@mantine/core"; -import { IconLock } from "@tabler/icons-react"; +import { IconLock, IconServer } from "@tabler/icons-react"; import { IAuthProvider } from "@/ee/security/types/security.types.ts"; import { buildSsoLoginUrl } from "@/ee/security/sso.utils.ts"; import { SSO_PROVIDER } from "@/ee/security/contants.ts"; import { GoogleIcon } from "@/components/icons/google-icon.tsx"; import { isCloud } from "@/lib/config.ts"; +import { LdapLoginModal } from "@/ee/components/ldap-login-modal.tsx"; export default function SsoLogin() { const { data, isLoading } = useWorkspacePublicDataQuery(); + const [ldapModalOpened, setLdapModalOpened] = useState(false); + const [selectedLdapProvider, setSelectedLdapProvider] = useState(null); if (!data?.authProviders || data?.authProviders?.length === 0) { return null; } const handleSsoLogin = (provider: IAuthProvider) => { - window.location.href = buildSsoLoginUrl({ - providerId: provider.id, - type: provider.type, - workspaceId: data.id, - }); + if (provider.type === SSO_PROVIDER.LDAP) { + // Open modal for LDAP instead of redirecting + setSelectedLdapProvider(provider); + setLdapModalOpened(true); + } else { + // Redirect for other SSO providers + window.location.href = buildSsoLoginUrl({ + providerId: provider.id, + type: provider.type, + workspaceId: data.id, + }); + } + }; + + const getProviderIcon = (provider: IAuthProvider) => { + if (provider.type === SSO_PROVIDER.GOOGLE) { + return ; + } else if (provider.type === SSO_PROVIDER.LDAP) { + return ; + } else { + return ; + } }; return ( <> + {selectedLdapProvider && ( + { + setLdapModalOpened(false); + setSelectedLdapProvider(null); + }} + provider={selectedLdapProvider} + workspaceId={data.id} + /> + )} + {(isCloud() || data.hasLicenseKey) && ( <> @@ -31,13 +64,7 @@ export default function SsoLogin() {