mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {StyleSheet} from 'react-native'
3
4// @ts-ignore web only, we will always redirect to the app on web (CORS)
5const REDIRECT_HOST = new URL(window.location.href).host
6
7export function CaptchaWebView({
8 url,
9 stateParam,
10 onSuccess,
11 onError,
12}: {
13 url: string
14 stateParam: string
15 onSuccess: (code: string) => void
16 onError: (error: unknown) => void
17}) {
18 React.useEffect(() => {
19 const timeout = setTimeout(() => {
20 onError({
21 errorMessage: 'User did not complete the captcha within 30 seconds',
22 })
23 }, 30e3)
24
25 return () => {
26 clearTimeout(timeout)
27 }
28 }, [onError])
29
30 const onLoad = React.useCallback(() => {
31 // @ts-ignore web
32 const frame: HTMLIFrameElement = document.getElementById(
33 'captcha-iframe',
34 ) as HTMLIFrameElement
35
36 try {
37 // @ts-ignore web
38 const href = frame?.contentWindow?.location.href
39 if (!href) return
40 const urlp = new URL(href)
41
42 // This shouldn't happen with CORS protections, but for good measure
43 if (urlp.host !== REDIRECT_HOST) return
44
45 const code = urlp.searchParams.get('code')
46 if (urlp.searchParams.get('state') !== stateParam || !code) {
47 onError({error: 'Invalid state or code'})
48 return
49 }
50 onSuccess(code)
51 } catch (e: unknown) {
52 // We don't actually want to record an error here, because this will happen quite a bit. We will only be able to
53 // get hte href of the iframe if it's on our domain, so all the hcaptcha requests will throw here, although it's
54 // harmless. Our other indicators of time-to-complete and back press should be more reliable in catching issues.
55 }
56 }, [stateParam, onSuccess, onError])
57
58 return (
59 <iframe
60 src={url}
61 style={styles.iframe}
62 id="captcha-iframe"
63 onLoad={onLoad}
64 />
65 )
66}
67
68const styles = StyleSheet.create({
69 iframe: {
70 flex: 1,
71 borderWidth: 0,
72 borderRadius: 10,
73 backgroundColor: 'transparent',
74 },
75})