Skip to content

Commit d21b0d0

Browse files
committed
feat(app): add Cloudflare Turnstile widget for OpenBuild OAuth
1 parent 03a4ea0 commit d21b0d0

File tree

4 files changed

+84
-9
lines changed

4 files changed

+84
-9
lines changed

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ NEXT_PUBLIC_ASPECTA_ID=
1010

1111
NEXT_PUBLIC_GA_ID=
1212
NEXT_PUBLIC_GA_KEY=
13+
14+
NEXT_PUBLIC_WEB3BIO=
15+
NEXT_PUBLIC_TURNSTILE_SITEKEY=

src/app/oauth/page.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import Logo from 'public/images/svg/logo-black.svg';
2323
import { useEffect, useState } from 'react';
2424

2525
import { Button } from '@/components/Button';
26+
import CloudflareTurnstile from '@/components/control/cf-turnstile';
2627
import { SvgIcon } from '@/components/Image';
2728
import Loader from '@/components/Loader';
2829
import useMounted from '@/hooks/useMounted';
@@ -43,7 +44,7 @@ export default function Page() {
4344

4445
const { status } = useSession();
4546

46-
const [disabled, setDisabled] = useState(false);
47+
const [disabled, setDisabled] = useState(true);
4748
const [loading, setLoading] = useState(true);
4849
const [clientInfo, setClientInfo] = useState(null);
4950

@@ -92,14 +93,22 @@ export default function Page() {
9293
}
9394
}, [status]); // eslint-disable-line react-hooks/exhaustive-deps
9495

96+
const handleVerify = token => {
97+
if (!token) {
98+
return;
99+
}
100+
101+
setDisabled(false);
102+
};
103+
95104
return (
96105
loading ? <Loader /> : (
97106
<div className="flex min-h-screen flex-col items-center pt-9 md:pt-[60px] p-4 font-['Nunito_Sans'] relative">
98107
<div className="relative w-[192px] md:w-[320px]">
99108
<div className="absolute top-1/2 left-0 w-full border-b-2 border-dashed border-[#d1d9e0]" />
100109
<div className="flex items-center justify-between py-9">
101110
<div className="relative bg-white rounded-full size-[60px] md:size-[100px]">
102-
<img src={clientInfo?.icon} alt="Logo" className="!size-full" />
111+
<Image src={clientInfo?.icon} alt="Logo" className="!size-full" fill />
103112
</div>
104113
<div className="flex items-center gap-2 relative">
105114
<SvgIcon name="circle-check" size={20} />
@@ -123,13 +132,16 @@ export default function Page() {
123132
<NoteItem icon="personal" title="Personal user data" description="Email addresses (read-only), profile information (read-only)" />
124133
<NoteItem icon="international" title="Public data only" description="Limited access to your public data" />
125134
</div>
126-
<div className="flex gap-3 border-y border-gray-600 p-6 mx-[-24px]">
127-
<Button variant="outlined" className="flex-1" onClick={handleCancel}>
128-
Cancel
129-
</Button>
130-
<Button variant="contained" className="flex-1" onClick={authorize} disabled={disabled}>
131-
Authorize
132-
</Button>
135+
<div className="mx-[-24px] p-6 border-y border-gray-600">
136+
<CloudflareTurnstile className="mb-2" onVerify={handleVerify} />
137+
<div className="flex gap-3">
138+
<Button variant="outlined" className="flex-1" onClick={handleCancel}>
139+
Cancel
140+
</Button>
141+
<Button variant="contained" className="flex-1" onClick={authorize} disabled={disabled}>
142+
Authorize
143+
</Button>
144+
</div>
133145
</div>
134146
<div className="pt-6 flex items-center gap-3">
135147
<SvgIcon name="lock" size={16} />
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Copyright 2024 OpenBuild
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import Script from 'next/script';
18+
19+
import { isFunction } from '../../../utils';
20+
21+
const sitekey = process.env.NEXT_PUBLIC_TURNSTILE_SITEKEY;
22+
23+
function CloudflareTurnstile({ className, onVerify }) {
24+
const handleScriptLoad = () => {
25+
window.turnstile.render('#cfTurnstile', {
26+
sitekey,
27+
callback: token => isFunction(onVerify) && onVerify(token),
28+
});
29+
};
30+
31+
return sitekey && (
32+
<>
33+
<Script
34+
src="https://challenges.cloudflare.com/turnstile/v0/api.js"
35+
strategy="afterInteractive"
36+
onLoad={handleScriptLoad}
37+
/>
38+
<div id="cfTurnstile" className={className} />
39+
</>
40+
);
41+
};
42+
43+
export default CloudflareTurnstile;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright 2024 OpenBuild
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
export { default } from './CloudflareTurnstile';

0 commit comments

Comments
 (0)