-
Notifications
You must be signed in to change notification settings - Fork 354
Expand file tree
/
Copy pathNewCaptcha.tsx
More file actions
136 lines (121 loc) · 5.09 KB
/
NewCaptcha.tsx
File metadata and controls
136 lines (121 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import * as React from "react";
import { useCallback, useEffect, useState } from "react";
import { Stack } from "@fluentui/react";
import { Link, Spinner, Tab, TabList } from "@fluentui/react-components";
import { ImageRegular, Speaker2Regular } from "@fluentui/react-icons";
import { CaptchaData } from "../../../../../models/captchaData";
import { BackendService } from "../../../../../services/backendService";
import { TCaptchaProps } from "./LegacyCaptcha";
type TCaptchaObj = { captchaChallenge?: string; captchaData?: CaptchaData };
enum ECaptchaType {
visual = "visual",
audio = "audio",
}
const getCaptchaChallenge = async (
challengeType: ECaptchaType,
backendService: BackendService
): Promise<TCaptchaObj> => {
const challengeData = await backendService.getCaptchaChallenge(challengeType);
if (challengeData) {
return {
captchaChallenge: challengeData.ChallengeString,
captchaData: {
challenge: {
testCaptchaRequest: {
challengeId: challengeData.ChallengeId,
inputSolution: undefined,
},
azureRegion: challengeData.AzureRegion,
challengeType: challengeData.ChallengeType,
},
solution: undefined,
},
};
} else {
return {};
}
};
export const NewCaptcha = ({ backendService, onInitComplete }: TCaptchaProps) => {
const [working, setWorking] = useState(true);
const [{ captchaChallenge, captchaData }, setCaptchaObj] = useState<TCaptchaObj>({});
const [captchaType, setCaptchaType] = useState(ECaptchaType.visual);
const updateChallengeInput = useCallback((solution: string) => setCaptchaObj(prev => {
if (!prev?.captchaData?.challenge?.testCaptchaRequest) return prev;
const next = JSON.parse(JSON.stringify(prev));
next.captchaData.challenge.testCaptchaRequest.inputSolution = solution;
return next;
}), []);
const generateCaptcha = useCallback(
(captchaType: ECaptchaType) => {
updateChallengeInput("");
setWorking(true);
return getCaptchaChallenge(captchaType, backendService)
.then(setCaptchaObj)
.finally(() => setWorking(false));
},
[updateChallengeInput, backendService]
);
useEffect(() => {
generateCaptcha(captchaType);
}, [generateCaptcha, captchaType]);
useEffect(() => {
const captchaValidate = (): "valid" | null => {
return captchaData?.challenge?.testCaptchaRequest.inputSolution ? "valid" : null;
}
const refreshCaptcha = () => generateCaptcha(captchaType);
onInitComplete(captchaValidate(), refreshCaptcha, captchaData);
}, [onInitComplete, generateCaptcha, captchaData]);
return (
<>
<Stack className="form-group">
<label htmlFor="captchaValue" className="required">Captcha</label>
<TabList
selectedValue={captchaType}
onTabSelect={(_, { value }) =>
setCaptchaType(value as ECaptchaType)
}
>
<Tab icon={<ImageRegular />} value={ECaptchaType.visual}>Visual</Tab>
<Tab icon={<Speaker2Regular />} value={ECaptchaType.audio}>Audio</Tab>
</TabList>
<div style={{ margin: "10px 0" }}>
{working ? (
<Stack.Item style={{ padding: "13px 0" }}>
<Spinner style={{ display: "inline-flex" }} label={"Loading captcha"} labelPosition="below" />
</Stack.Item>
) : captchaType === ECaptchaType.visual ? (
<Stack.Item>
<img
src={`data:image/png;base64,${captchaChallenge}`}
alt="visual challange"
/>
</Stack.Item>
) : (
<audio controls>
<source
src={`data:audio/mp3;base64,${captchaChallenge}`}
type="audio/mp3"
/>
</audio>
)}
</div>
<Stack.Item>
<Link onClick={() => generateCaptcha(captchaType)}>Generate new captcha</Link>
</Stack.Item>
</Stack>
<Stack className="form-group">
<label htmlFor="captchaValue" className="required">
Enter captcha
</label>
<input
id="captchaValue"
placeholder="Enter captcha"
type="text"
className="form-control"
value={captchaData?.challenge?.testCaptchaRequest?.inputSolution ?? ""}
onChange={(event) => updateChallengeInput(event.target.value)}
/>
</Stack>
</>
);
};