mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-27 00:40:58 +01:00
refactor: replace signIn callback with signIn event, adjust getUserByEmail in adapter to check provider (#1223)
* refactor: replace signIn callback with signIn event, adjust getUserByEmail in adapter to check provider * test: adjusting tests for adapter and events * docs: add comments for unknown auth provider * fix: missing dayjs import
This commit is contained in:
@@ -12,8 +12,7 @@ import type { useForm } from "@homarr/form";
|
||||
import { useZodForm } from "@homarr/form";
|
||||
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import type { z } from "@homarr/validation";
|
||||
import { validation } from "@homarr/validation";
|
||||
import { validation, z } from "@homarr/validation";
|
||||
|
||||
interface LoginFormProps {
|
||||
providers: string[];
|
||||
@@ -22,15 +21,17 @@ interface LoginFormProps {
|
||||
callbackUrl: string;
|
||||
}
|
||||
|
||||
const extendedValidation = validation.user.signIn.extend({ provider: z.enum(["credentials", "ldap"]) });
|
||||
|
||||
export const LoginForm = ({ providers, oidcClientName, isOidcAutoLoginEnabled, callbackUrl }: LoginFormProps) => {
|
||||
const t = useScopedI18n("user");
|
||||
const router = useRouter();
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
const form = useZodForm(validation.user.signIn, {
|
||||
const form = useZodForm(extendedValidation, {
|
||||
initialValues: {
|
||||
name: "",
|
||||
password: "",
|
||||
credentialType: "basic",
|
||||
provider: "credentials",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -95,14 +96,14 @@ export const LoginForm = ({ providers, oidcClientName, isOidcAutoLoginEnabled, c
|
||||
<Stack gap="lg">
|
||||
{credentialInputsVisible && (
|
||||
<>
|
||||
<form onSubmit={form.onSubmit((credentials) => void signInAsync("credentials", credentials))}>
|
||||
<form onSubmit={form.onSubmit((credentials) => void signInAsync(credentials.provider, credentials))}>
|
||||
<Stack gap="lg">
|
||||
<TextInput label={t("field.username.label")} {...form.getInputProps("name")} />
|
||||
<PasswordInput label={t("field.password.label")} {...form.getInputProps("password")} />
|
||||
|
||||
{providers.includes("credentials") && (
|
||||
<Stack gap="sm">
|
||||
<SubmitButton isPending={isPending} form={form} credentialType="basic">
|
||||
<SubmitButton isPending={isPending} form={form} provider="credentials">
|
||||
{t("action.login.label")}
|
||||
</SubmitButton>
|
||||
<PasswordForgottenCollapse username={form.values.name} />
|
||||
@@ -110,7 +111,7 @@ export const LoginForm = ({ providers, oidcClientName, isOidcAutoLoginEnabled, c
|
||||
)}
|
||||
|
||||
{providers.includes("ldap") && (
|
||||
<SubmitButton isPending={isPending} form={form} credentialType="ldap">
|
||||
<SubmitButton isPending={isPending} form={form} provider="ldap">
|
||||
{t("action.login.labelWith", { provider: "LDAP" })}
|
||||
</SubmitButton>
|
||||
)}
|
||||
@@ -133,18 +134,18 @@ export const LoginForm = ({ providers, oidcClientName, isOidcAutoLoginEnabled, c
|
||||
interface SubmitButtonProps {
|
||||
isPending: boolean;
|
||||
form: ReturnType<typeof useForm<FormType, (values: FormType) => FormType>>;
|
||||
credentialType: "basic" | "ldap";
|
||||
provider: "credentials" | "ldap";
|
||||
}
|
||||
|
||||
const SubmitButton = ({ isPending, form, credentialType, children }: PropsWithChildren<SubmitButtonProps>) => {
|
||||
const isCurrentProviderActive = form.getValues().credentialType === credentialType;
|
||||
const SubmitButton = ({ isPending, form, provider, children }: PropsWithChildren<SubmitButtonProps>) => {
|
||||
const isCurrentProviderActive = form.getValues().provider === provider;
|
||||
|
||||
return (
|
||||
<Button
|
||||
type="submit"
|
||||
name={credentialType}
|
||||
name={provider}
|
||||
fullWidth
|
||||
onClick={() => form.setFieldValue("credentialType", credentialType)}
|
||||
onClick={() => form.setFieldValue("provider", provider)}
|
||||
loading={isPending && isCurrentProviderActive}
|
||||
disabled={isPending && !isCurrentProviderActive}
|
||||
>
|
||||
@@ -181,4 +182,4 @@ const PasswordForgottenCollapse = ({ username }: PasswordForgottenCollapseProps)
|
||||
);
|
||||
};
|
||||
|
||||
type FormType = z.infer<typeof validation.user.signIn>;
|
||||
type FormType = z.infer<typeof extendedValidation>;
|
||||
|
||||
@@ -1,17 +1,37 @@
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
import { createHandlers } from "@homarr/auth";
|
||||
import type { SupportedAuthProvider } from "@homarr/definitions";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
export const GET = async (req: NextRequest) => {
|
||||
return await createHandlers(isCredentialsRequest(req)).handlers.GET(reqWithTrustedOrigin(req));
|
||||
return await createHandlers(extractProvider(req)).handlers.GET(reqWithTrustedOrigin(req));
|
||||
};
|
||||
export const POST = async (req: NextRequest) => {
|
||||
return await createHandlers(isCredentialsRequest(req)).handlers.POST(reqWithTrustedOrigin(req));
|
||||
return await createHandlers(extractProvider(req)).handlers.POST(reqWithTrustedOrigin(req));
|
||||
};
|
||||
|
||||
const isCredentialsRequest = (req: NextRequest) => {
|
||||
return req.url.includes("credentials") && req.method === "POST";
|
||||
/**
|
||||
* This method extracts the used provider from the url and allows us to override the getUserByEmail method in the adapter.
|
||||
* @param req request containing the url
|
||||
* @returns the provider or "unknown" if the provider could not be extracted
|
||||
*/
|
||||
const extractProvider = (req: NextRequest): SupportedAuthProvider | "unknown" => {
|
||||
const url = new URL(req.url);
|
||||
|
||||
if (url.pathname.includes("oidc")) {
|
||||
return "oidc";
|
||||
}
|
||||
|
||||
if (url.pathname.includes("credentials")) {
|
||||
return "credentials";
|
||||
}
|
||||
|
||||
if (url.pathname.includes("ldap")) {
|
||||
return "ldap";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user