aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/web/components/signup/SignUpForm.tsx42
-rw-r--r--apps/web/lib/clientConfig.tsx1
-rw-r--r--apps/web/package.json1
3 files changed, 44 insertions, 0 deletions
diff --git a/apps/web/components/signup/SignUpForm.tsx b/apps/web/components/signup/SignUpForm.tsx
index a1e8dadf..bd4a1cf2 100644
--- a/apps/web/components/signup/SignUpForm.tsx
+++ b/apps/web/components/signup/SignUpForm.tsx
@@ -25,6 +25,7 @@ import { Input } from "@/components/ui/input";
import { useClientConfig } from "@/lib/clientConfig";
import { api } from "@/lib/trpc";
import { zodResolver } from "@hookform/resolvers/zod";
+import { Turnstile } from "@marsidev/react-turnstile";
import { TRPCClientError } from "@trpc/client";
import { AlertCircle, UserX } from "lucide-react";
import { signIn } from "next-auth/react";
@@ -43,11 +44,13 @@ export default function SignUpForm() {
name: "",
password: "",
confirmPassword: "",
+ turnstileToken: "",
},
});
const [errorMessage, setErrorMessage] = useState("");
const router = useRouter();
const clientConfig = useClientConfig();
+ const turnstileSiteKey = clientConfig.turnstile?.siteKey;
const createUserMutation = api.users.create.useMutation();
@@ -97,6 +100,14 @@ export default function SignUpForm() {
<Form {...form}>
<form
onSubmit={form.handleSubmit(async (value) => {
+ if (turnstileSiteKey && !value.turnstileToken) {
+ form.setError("turnstileToken", {
+ type: "manual",
+ message: "Please complete the verification challenge",
+ });
+ return;
+ }
+ form.clearErrors("turnstileToken");
try {
await createUserMutation.mutateAsync(value);
} catch (e) {
@@ -205,6 +216,37 @@ export default function SignUpForm() {
)}
/>
+ {turnstileSiteKey && (
+ <FormField
+ control={form.control}
+ name="turnstileToken"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>Verification</FormLabel>
+ <FormControl>
+ <Turnstile
+ siteKey={turnstileSiteKey}
+ onSuccess={(token) => {
+ field.onChange(token);
+ form.clearErrors("turnstileToken");
+ }}
+ onExpire={() => field.onChange("")}
+ onError={() => {
+ field.onChange("");
+ form.setError("turnstileToken", {
+ type: "manual",
+ message:
+ "Verification failed, please reload the challenge",
+ });
+ }}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ )}
+
<ActionButton
type="submit"
loading={
diff --git a/apps/web/lib/clientConfig.tsx b/apps/web/lib/clientConfig.tsx
index 03089e49..9331a7af 100644
--- a/apps/web/lib/clientConfig.tsx
+++ b/apps/web/lib/clientConfig.tsx
@@ -10,6 +10,7 @@ export const ClientConfigCtx = createContext<ClientConfig>({
disableSignups: false,
disablePasswordAuth: false,
},
+ turnstile: null,
inference: {
isConfigured: false,
inferredTagLang: "english",
diff --git a/apps/web/package.json b/apps/web/package.json
index 67ce2560..0c53490d 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -32,6 +32,7 @@
"@lexical/plain-text": "^0.20.2",
"@lexical/react": "^0.20.2",
"@lexical/rich-text": "^0.20.2",
+ "@marsidev/react-turnstile": "^1.3.1",
"@radix-ui/react-collapsible": "^1.1.11",
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",