cairo/src/views/AuthenticateView.tsx

96 lines
3.7 KiB
TypeScript

import { Box, Button, Heading, Input, Stack, Image, Text } from "@chakra-ui/react";
import { Policy } from "@lib/Policies";
import { Resource } from "@lib/vix/AppResources";
import { SyntheticEvent, useState } from "react";
import { toast } from "react-toastify";
import { useAuth } from "@src/ctx/AuthContext";
import { Links, rootLink, useAutoRedirect } from "@src/util/links";
import { ClientError } from "@dunemask/vix/bridge";
import { AuthErrors } from "@lib/vix/ClientErrors";
import { PasswordInput } from "@src/components/common/Inputs";
import { ResourcePolicyType } from "@dunemask/vix/util";
import { postProjectAuthLogin } from "@src/util/api/GeneratedRequests";
import { Navigate, useSearchParams } from "react-router-dom";
import { useProjectContext } from "@src/ctx/ProjectContext";
export default function AuthenticateView() {
const { auth, login } = useAuth();
const { projectId } = useProjectContext();
const autoRedirect = useAutoRedirect();
const [search] = useSearchParams();
const [identity, setIdentity] = useState<string>("");
const [password, setPassword] = useState<string>("");
const identityChange = (e: SyntheticEvent) => setIdentity((e.target as HTMLInputElement).value);
function submitCredentials() {
const loginPromise = postProjectAuthLogin(projectId, { identity: identity, password }).then(async (creds) => {
if (!creds.token) return toast.error("Server didn't provide token!");
await login(
creds.user,
creds.token,
Policy.parseResourcePolicies<Resource>(creds.policies as ResourcePolicyType<Resource>[]),
);
autoRedirect();
});
toast.promise(loginPromise, {
pending: "Logging in",
success: "Logged in successfully!",
error: {
render({ data }) {
const clientError = data as ClientError;
if (clientError.isError(AuthErrors.UnauthorizedRequest)) return "Incorrect credentials!";
console.error(data);
return "Error logging in!";
},
},
});
setPassword("");
}
function detectEnter(e: KeyboardEvent) {
if (e.key === "Enter") submitCredentials();
}
if (auth) return <Navigate to={rootLink(Links.AutoRedirect)} />;
return (
<Box width="100%" height="90vh" display="flex" alignItems="center" justifyContent="center">
<Box p="2rem" width="100%" maxWidth="350px" boxShadow="md" borderRadius="md" bg="background.paper">
<Stack spacing="4" align="center" w="100%">
<Stack spacing="2" textAlign="center" w="100%">
<Heading size="md" display="flex" alignItems="center">
Sign in
<Image src={`${import.meta.env.BASE_URL}icons/android-chrome-512x512.png`} boxSize="24px" ml="1rem" alt="Logo" />
</Heading>
<Text fontSize="sm" w="100%" textAlign="left">
Please enter your credentials below
</Text>
</Stack>
<Stack spacing="4" w="100%">
<Input
value={identity}
placeholder="Identity"
onChange={identityChange}
isRequired
autoFocus
width="100%"
borderColor="primary"
/>
<PasswordInput value={password} setPassword={setPassword} isRequired />
</Stack>
<Stack direction="row" spacing="4" mt="4" justifyContent="space-between" w="100%">
<Button
onClick={submitCredentials}
variant="outline"
colorScheme="primary"
ml="auto"
isDisabled={!identity || !password}
>
Sign in
</Button>
</Stack>
</Stack>
</Box>
</Box>
);
}