submit by hitting next
All checks were successful
Build and push image for doorman / docker (push) Successful in 55s
Build and push image for doorman / deploy-portainer (push) Successful in 25s

This commit is contained in:
Martin Dimitrov 2024-03-02 15:40:29 -08:00
parent c956db367f
commit 672b62b3ef
2 changed files with 50 additions and 29 deletions

View File

@ -1,5 +1,5 @@
import { Button, FormField, Input, SpaceBetween } from "@cloudscape-design/components";
import { useState } from "react";
import { Button, FormField, Icon, Input, SpaceBetween } from "@cloudscape-design/components";
import { useEffect, useState } from "react";
// COPIED FROM SERVER
export enum IAuthMode {
@ -13,31 +13,38 @@ export interface IAuthComponentProps {
authMode: IAuthMode,
secret: string | null;
onUnlock: () => void;
onError: (res: any) => void;
onError?: (res: any) => void;
runCheck?: number;
}
export const AuthComponent = ({ door, secret, authMode, onError, onUnlock }: IAuthComponentProps) => {
export const AuthComponent = ({ door, secret, authMode, onError, onUnlock, runCheck }: IAuthComponentProps) => {
const [ key, setKey ] = useState(secret);
return (
<>
<SpaceBetween size='l'>
<FormField label={"PIN"} constraintText={"Enter the PIN to unlock the door"}>
<Input readOnly={secret !== null} value={key || ""} onChange={({ detail }) => setKey(detail.value)} />
</FormField>
<Button
onClick={() =>
const [ error, setError ] = useState("");
useEffect(() => {
if (runCheck) {
onSubmit();
}
}, [runCheck])
const onSubmit = () => {
fetch(`/api/door/${door}/auth?key=${key}&rotatingKey=${key}`)
.then(async res => {
if (res.status !== 200) {
onError(await res.json());
setError("Incorrect PIN");
onError && onError(await res.json());
return;
}
onUnlock();
})
}
>
Unlock the door
</Button>
return (
<>
<SpaceBetween size='l'>
<FormField errorText={error} label={"PIN"} constraintText={"Enter the PIN to unlock the door"}>
<Input readOnly={secret !== null} value={key || ""} onChange={({ detail }) => setKey(detail.value)} />
</FormField>
</SpaceBetween>
</>
);

View File

@ -35,12 +35,16 @@ export function DoorPage() {
const secret = searchParams.get('key') || searchParams.get('rotatingKey');
const [ alerts, setAlerts ] = useState<FlashbarProps.MessageDefinition[]>([]);
const [ polling, setPolling ] = useState(false);
const [ inProgressAlert, setInProgressAlert ] = useState("");
const [ submitPin, setSubmitPin ] = useState(0);
const dismissAlert = (id: string) => {
setAlerts(alerts => alerts.filter(alert => alert.id !== id));
}
const dismissInProgressAlerts = () => {
setAlerts(alerts => alerts.filter(alert => alert.type !== 'in-progress'));
}
const createAlert = (type: FlashbarProps.Type, content: ReactNode): FlashbarProps.MessageDefinition => {
const id = `${Math.random()}`;
return {
@ -54,7 +58,7 @@ export function DoorPage() {
const addAlert = (type: FlashbarProps.Type, content: ReactNode): string => {
const newAlert = createAlert(type, content);
setAlerts([
setAlerts(alerts => [
newAlert,
...alerts,
]);
@ -77,13 +81,16 @@ export function DoorPage() {
setStep(3);
setPolling(false);
setAlerts(alerts =>
[createAlert("success", "Buzzer successfully unlocked"), ...alerts.filter(alert => alert.id !== inProgressAlert)]
[createAlert("success", "Buzzer successfully unlocked"), ...alerts.filter(alert => alert.type !== 'in-progress')]
);
}
}, 1000);
return () => clearInterval(timer);
return () => {
clearInterval(timer);
dismissInProgressAlerts();
}
}, [polling]);
return (
@ -131,8 +138,15 @@ export function DoorPage() {
}}
activeStepIndex={step}
onNavigate={({ detail }) => {
if (detail.requestedStepIndex < step) {
dismissInProgressAlerts();
setSubmitPin(0);
setPolling(false);
setStep(detail.requestedStepIndex);
return;
}
if (detail.requestedStepIndex === 2) {
addAlert("error", "You must unlock the door to proceed");
setSubmitPin(submitPin + 1);
return;
}
@ -144,6 +158,8 @@ export function DoorPage() {
}}
onCancel={() => {
setStep(0);
dismissInProgressAlerts();
setSubmitPin(0);
}}
steps={[
{
@ -174,14 +190,13 @@ export function DoorPage() {
>
<AuthComponent
authMode={IAuthMode.FIXED_PIN}
runCheck={submitPin}
door={door}
secret={secret}
onError={(res) => {
addAlert("error", "Authentication failed, double check the credentials");
}}
onUnlock={() => {
setStep(2);
const inprogAlert = addAlert("in-progress", (
dismissInProgressAlerts();
addAlert("in-progress", (
<CountdownBar
timeSeconds={doorResponse.timeout}
onExpiry={() => {
@ -192,7 +207,6 @@ export function DoorPage() {
/>
));
setInProgressAlert(inprogAlert);
setPolling(true);
}}
/>