Implement captcha (#2882)

* web height adjustment

border radius incase of dark/dim mismatch

rm country codes

adjust height

general form refactor

more form refactor

refactor form submission

activity indicator after finished

remove remaining phone stuff

adjust captcha height

adjust state to reflect switch

move handle to the second step

pass color scheme param

ts

ts

update state when captcha is complete

web views and callbacks

remove old state

allow specified hosts

replace phone verification with a webview

* remove log

* height adjustment

* few changes

* use the correct url

* remove some debug

* validate handle before continuing

* explicitly check if there is a did, dont rely on error

* rm throw

* update allowed hosts

* update redirect host for webview

* fix handle

* fix handle check

* adjust height for full challenge
This commit is contained in:
Hailey 2024-02-17 16:03:47 -08:00 committed by GitHub
parent dc143d6a6e
commit fbdf4517c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 441 additions and 793 deletions

View file

@ -1,19 +1,23 @@
import React from 'react'
import {StyleSheet, View} from 'react-native'
import {CreateAccountState, CreateAccountDispatch} from './state'
import {Text} from 'view/com/util/text/Text'
import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {
CreateAccountState,
CreateAccountDispatch,
useSubmitCreateAccount,
} from './state'
import {StepHeader} from './StepHeader'
import {s} from 'lib/styles'
import {TextInput} from '../util/TextInput'
import {createFullHandle} from 'lib/strings/handles'
import {usePalette} from 'lib/hooks/usePalette'
import {ErrorMessage} from 'view/com/util/error/ErrorMessage'
import {msg, Trans} from '@lingui/macro'
import {isWeb} from 'platform/detection'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
/** STEP 3: Your user handle
* @field User handle
*/
import {nanoid} from 'nanoid/non-secure'
import {CaptchaWebView} from 'view/com/auth/create/CaptchaWebView'
import {useTheme} from 'lib/ThemeContext'
import {createFullHandle} from 'lib/strings/handles'
const CAPTCHA_PATH = '/gate/signup'
export function Step3({
uiState,
uiDispatch,
@ -21,33 +25,66 @@ export function Step3({
uiState: CreateAccountState
uiDispatch: CreateAccountDispatch
}) {
const pal = usePalette('default')
const {_} = useLingui()
const theme = useTheme()
const submit = useSubmitCreateAccount(uiState, uiDispatch)
const [completed, setCompleted] = React.useState(false)
const stateParam = React.useMemo(() => nanoid(15), [])
const url = React.useMemo(() => {
const newUrl = new URL(uiState.serviceUrl)
newUrl.pathname = CAPTCHA_PATH
newUrl.searchParams.set(
'handle',
createFullHandle(uiState.handle, uiState.userDomain),
)
newUrl.searchParams.set('state', stateParam)
newUrl.searchParams.set('colorScheme', theme.colorScheme)
console.log(newUrl)
return newUrl.href
}, [
uiState.serviceUrl,
uiState.handle,
uiState.userDomain,
stateParam,
theme.colorScheme,
])
const onSuccess = React.useCallback(
(code: string) => {
setCompleted(true)
submit(code)
},
[submit],
)
const onError = React.useCallback(() => {
uiDispatch({
type: 'set-error',
value: _(msg`Error receiving captcha response.`),
})
}, [_, uiDispatch])
return (
<View>
<StepHeader uiState={uiState} title={_(msg`Your user handle`)} />
<View style={s.pb10}>
<TextInput
testID="handleInput"
icon="at"
placeholder="e.g. alice"
value={uiState.handle}
editable
autoFocus
autoComplete="off"
autoCorrect={false}
onChange={value => uiDispatch({type: 'set-handle', value})}
// TODO: Add explicit text label
accessibilityLabel={_(msg`User handle`)}
accessibilityHint={_(msg`Input your user handle`)}
/>
<Text type="lg" style={[pal.text, s.pl5, s.pt10]}>
<Trans>Your full handle will be</Trans>{' '}
<Text type="lg-bold" style={pal.text}>
@{createFullHandle(uiState.handle, uiState.userDomain)}
</Text>
</Text>
<StepHeader uiState={uiState} title={_(msg`Complete the challenge`)} />
<View style={[styles.container, completed && styles.center]}>
{!completed ? (
<CaptchaWebView
url={url}
stateParam={stateParam}
uiState={uiState}
onSuccess={onSuccess}
onError={onError}
/>
) : (
<ActivityIndicator size="large" />
)}
</View>
{uiState.error ? (
<ErrorMessage message={uiState.error} style={styles.error} />
) : undefined}
@ -58,5 +95,20 @@ export function Step3({
const styles = StyleSheet.create({
error: {
borderRadius: 6,
marginTop: 10,
},
// @ts-expect-error: Suppressing error due to incomplete `ViewStyle` type definition in react-native-web, missing `cursor` prop as discussed in https://github.com/necolas/react-native-web/issues/832.
touchable: {
...(isWeb && {cursor: 'pointer'}),
},
container: {
minHeight: 500,
width: '100%',
paddingBottom: 20,
overflow: 'hidden',
},
center: {
alignItems: 'center',
justifyContent: 'center',
},
})