92 lines
2.6 KiB
TypeScript
92 lines
2.6 KiB
TypeScript
import { Button, Form, FormField, Icon, Input, SpaceBetween } from "@cloudscape-design/components";
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { AuthRequest, AuthRequestSchema } from "../../../doorman-schema/src";
|
|
import { fetchUrlEncoded } from "../helpers/FetchHelper";
|
|
import { useForm } from "react-hook-form";
|
|
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import CInput from "react-hook-form-cloudscape/components/input";
|
|
|
|
// COPIED FROM SERVER
|
|
export enum IAuthMode {
|
|
FIXED_PIN = "Fixed Pin",
|
|
RANDOM_ROTATING_KEY = "Random Rotating Key",
|
|
}
|
|
|
|
export interface IAuthComponentProps {
|
|
door: string,
|
|
authMode: IAuthMode,
|
|
secret: string | null;
|
|
onUnlock: () => void;
|
|
onError?: (res: any) => void;
|
|
runCheck?: number;
|
|
}
|
|
|
|
export const AuthComponent = ({ door, secret, authMode, onError, onUnlock, runCheck }: IAuthComponentProps) => {
|
|
const { control, setError, formState, handleSubmit, setValue, getValues } = useForm<AuthRequest>({
|
|
resolver: zodResolver(AuthRequestSchema),
|
|
defaultValues: {
|
|
key: secret || "",
|
|
door,
|
|
}
|
|
});
|
|
|
|
const [isLoading, setLoading] = useState(false);
|
|
|
|
const onSubmit = async (body: AuthRequest) => {
|
|
setLoading(true);
|
|
await fetchUrlEncoded('/api/door/auth', body)
|
|
.then(async res => {
|
|
if (res.status !== 200) {
|
|
setError("key", { type: "validate", message: "Incorrect PIN"});
|
|
onError && onError(await res.json());
|
|
return;
|
|
}
|
|
onUnlock();
|
|
});
|
|
setLoading(false);
|
|
};
|
|
|
|
useEffect(() => {
|
|
// don't allow us to submit while we are submitting
|
|
if (runCheck && !isLoading) {
|
|
handleSubmit(onSubmit)();
|
|
}
|
|
}, [runCheck]);
|
|
|
|
|
|
// try and submit on load if the pin is passed in by query params
|
|
useEffect(() => {
|
|
setLoading(true);
|
|
fetch('https://api.ipify.org?format=json')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
return data.ip;
|
|
})
|
|
.catch(error => {
|
|
console.log('Error:', error);
|
|
return "null";
|
|
})
|
|
.then(async ip => {
|
|
setValue("ip", ip);
|
|
|
|
// if the key is there, then try submitting right away
|
|
if (secret !== null) {
|
|
await handleSubmit(onSubmit)();
|
|
}
|
|
|
|
setLoading(false);
|
|
});
|
|
}, [secret]);
|
|
|
|
return (
|
|
<>
|
|
<SpaceBetween size='l'>
|
|
<FormField errorText={formState.errors.key?.message} label={"PIN"} constraintText={"Enter the PIN to unlock the door"}>
|
|
<CInput type="password" name="key" readOnly={secret !== null} control={control} />
|
|
</FormField>
|
|
</SpaceBetween>
|
|
</>
|
|
);
|
|
} |