mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-27 07:16:40 +00:00
Chungus
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import * as z from "zod";
|
||||
@@ -22,10 +22,7 @@ import {
|
||||
CardTitle
|
||||
} from "@app/components/ui/card";
|
||||
import { Alert, AlertDescription } from "@app/components/ui/alert";
|
||||
import { LoginResponse } from "@server/routers/auth";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { formatAxiosError } from "@app/lib/api";
|
||||
import { LockIcon, FingerprintIcon } from "lucide-react";
|
||||
import { createApiClient } from "@app/lib/api";
|
||||
import {
|
||||
@@ -49,6 +46,9 @@ import {
|
||||
} from "@app/actions/server";
|
||||
import { redirect as redirectTo } from "next/navigation";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
// @ts-ignore
|
||||
import { loadReoScript } from "reodotdev";
|
||||
import { build } from "@server/build";
|
||||
|
||||
export type LoginFormIDP = {
|
||||
idpId: number;
|
||||
@@ -60,13 +60,18 @@ type LoginFormProps = {
|
||||
redirect?: string;
|
||||
onLogin?: () => void | Promise<void>;
|
||||
idps?: LoginFormIDP[];
|
||||
orgId?: string;
|
||||
};
|
||||
|
||||
export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
export default function LoginForm({
|
||||
redirect,
|
||||
onLogin,
|
||||
idps,
|
||||
orgId
|
||||
}: LoginFormProps) {
|
||||
const router = useRouter();
|
||||
|
||||
const { env } = useEnvContext();
|
||||
|
||||
const api = createApiClient({ env });
|
||||
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -77,10 +82,32 @@ export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
const [showSecurityKeyPrompt, setShowSecurityKeyPrompt] = useState(false);
|
||||
|
||||
const t = useTranslations();
|
||||
const currentHost = typeof window !== "undefined" ? window.location.hostname : "";
|
||||
const currentHost =
|
||||
typeof window !== "undefined" ? window.location.hostname : "";
|
||||
const expectedHost = new URL(env.app.dashboardUrl).host;
|
||||
const isExpectedHost = currentHost === expectedHost;
|
||||
|
||||
const [reo, setReo] = useState<any | undefined>(undefined);
|
||||
useEffect(() => {
|
||||
async function init() {
|
||||
if (env.app.environment !== "prod") {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const clientID = env.server.reoClientId;
|
||||
const reoClient = await loadReoScript({ clientID });
|
||||
await reoClient.init({ clientID });
|
||||
setReo(reoClient);
|
||||
} catch (e) {
|
||||
console.error("Failed to load Reo script", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (build == "saas") {
|
||||
init();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const formSchema = z.object({
|
||||
email: z.string().email({ message: t("emailInvalid") }),
|
||||
password: z.string().min(8, { message: t("passwordRequirementsChars") })
|
||||
@@ -183,26 +210,13 @@ export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
if (e.isAxiosError) {
|
||||
setError(
|
||||
formatAxiosError(
|
||||
e,
|
||||
t("securityKeyAuthError", {
|
||||
defaultValue:
|
||||
"Failed to authenticate with security key"
|
||||
})
|
||||
)
|
||||
);
|
||||
} else {
|
||||
console.error(e);
|
||||
setError(
|
||||
e.message ||
|
||||
t("securityKeyAuthError", {
|
||||
defaultValue:
|
||||
"Failed to authenticate with security key"
|
||||
})
|
||||
);
|
||||
}
|
||||
console.error(e);
|
||||
setError(
|
||||
t("securityKeyAuthError", {
|
||||
defaultValue:
|
||||
"An unexpected error occurred. Please try again."
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setShowSecurityKeyPrompt(false);
|
||||
@@ -224,6 +238,18 @@ export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
code
|
||||
});
|
||||
|
||||
try {
|
||||
const identity = {
|
||||
username: email,
|
||||
type: "email" // can be one of email, github, linkedin, gmail, userID,
|
||||
};
|
||||
if (reo) {
|
||||
reo.identify(identity);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Reo identify error:", e);
|
||||
}
|
||||
|
||||
if (response.error) {
|
||||
setError(response.message);
|
||||
return;
|
||||
@@ -253,7 +279,11 @@ export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
|
||||
if (data.emailVerificationRequired) {
|
||||
if (!isExpectedHost) {
|
||||
setError(t("emailVerificationRequired", { dashboardUrl: env.app.dashboardUrl }));
|
||||
setError(
|
||||
t("emailVerificationRequired", {
|
||||
dashboardUrl: env.app.dashboardUrl
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (redirect) {
|
||||
@@ -266,7 +296,11 @@ export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
|
||||
if (data.twoFactorSetupRequired) {
|
||||
if (!isExpectedHost) {
|
||||
setError(t("twoFactorSetupRequired", { dashboardUrl: env.app.dashboardUrl }));
|
||||
setError(
|
||||
t("twoFactorSetupRequired", {
|
||||
dashboardUrl: env.app.dashboardUrl
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
const setupUrl = `/auth/2fa/setup?email=${encodeURIComponent(email)}${redirect ? `&redirect=${encodeURIComponent(redirect)}` : ""}`;
|
||||
@@ -278,25 +312,13 @@ export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
await onLogin();
|
||||
}
|
||||
} catch (e: any) {
|
||||
if (e.isAxiosError) {
|
||||
const errorMessage = formatAxiosError(
|
||||
e,
|
||||
t("loginError", {
|
||||
defaultValue: "Failed to log in"
|
||||
})
|
||||
);
|
||||
setError(errorMessage);
|
||||
return;
|
||||
} else {
|
||||
console.error(e);
|
||||
setError(
|
||||
e.message ||
|
||||
t("loginError", {
|
||||
defaultValue: "Failed to log in"
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
console.error(e);
|
||||
setError(
|
||||
t("loginError", {
|
||||
defaultValue:
|
||||
"An unexpected error occurred. Please try again."
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -307,7 +329,8 @@ export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
try {
|
||||
const data = await generateOidcUrlProxy(
|
||||
idpId,
|
||||
redirect || "/"
|
||||
redirect || "/",
|
||||
orgId
|
||||
);
|
||||
const url = data.data?.redirectUrl;
|
||||
if (data.error) {
|
||||
@@ -527,7 +550,8 @@ export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
</div>
|
||||
|
||||
{idps.map((idp) => {
|
||||
const effectiveType = idp.variant || idp.name.toLowerCase();
|
||||
const effectiveType =
|
||||
idp.variant || idp.name.toLowerCase();
|
||||
|
||||
return (
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user