@prosopo/client-bundle-example 2.11.3 → 2.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$cjs.log +4 -7
- package/.turbo/turbo-build$colon$tsc.log +11 -14
- package/.turbo/turbo-build.log +4 -10
- package/CHANGELOG.md +27 -0
- package/LICENSE +201 -0
- package/README.md +6 -6
- package/dist/cjs/plugins/pages.cjs +7 -0
- package/dist/plugins/pages.js +7 -0
- package/env.staging +5 -4
- package/package.json +52 -53
- package/vite.config.ts +50 -1
- package/env.development +0 -7
- package/env.production +0 -6
- package/src/assets/dummy.txt +0 -0
- package/src/frictionless-explicit-web3.html +0 -237
- package/src/frictionless-explicit.html +0 -205
- package/src/frictionless-implicit.html +0 -192
- package/src/frictionless-manual-start.html +0 -204
- package/src/image-explicit-web3.html +0 -182
- package/src/image-explicit.html +0 -151
- package/src/image-implicit.html +0 -192
- package/src/index.html +0 -192
- package/src/index.ts +0 -15
- package/src/invisible-frictionless-explicit.html +0 -123
- package/src/invisible-frictionless-implicit.html +0 -187
- package/src/invisible-image-explicit.html +0 -146
- package/src/invisible-image-implicit.html +0 -187
- package/src/invisible-pow-explicit.html +0 -146
- package/src/invisible-pow-implicit.html +0 -94
- package/src/invisible-puzzle-explicit.html +0 -145
- package/src/invisible-puzzle-implicit.html +0 -94
- package/src/plugins/code-snippet-injector.ts +0 -179
- package/src/plugins/form-filler-injector.ts +0 -148
- package/src/plugins/layout-injector.ts +0 -256
- package/src/plugins/logo.ts +0 -15
- package/src/plugins/pages.ts +0 -219
- package/src/plugins/placement-injector.ts +0 -114
- package/src/plugins/slots.ts +0 -32
- package/src/plugins/status-log-injector.ts +0 -143
- package/src/pow-explicit-web3.html +0 -179
- package/src/pow-explicit.html +0 -143
- package/src/pow-implicit-sessionid.html +0 -209
- package/src/pow-implicit.html +0 -192
- package/src/puzzle-bind-explicit.html +0 -83
- package/src/puzzle-explicit.html +0 -151
- package/src/puzzle-implicit.html +0 -192
- package/src/styles/demo.css +0 -803
- package/src/tests/explicitRender.unit.test.ts +0 -49
- package/src/tests/plugins.unit.test.ts +0 -490
- package/tsconfig.cjs.json +0 -25
- package/tsconfig.json +0 -31
- package/tsconfig.tsbuildinfo +0 -1
- package/tsconfig.types.json +0 -9
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
<title>Procaptcha demo: Frictionless, explicit rendering, web3</title>
|
|
6
|
-
<script type="module">
|
|
7
|
-
window.onCaptchaFailed = function () {
|
|
8
|
-
console.log('Challenge failed');
|
|
9
|
-
updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
window.addEventListener('load', () => {
|
|
13
|
-
updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
|
|
14
|
-
|
|
15
|
-
window.setIsError = (isError) => {
|
|
16
|
-
const messageContainer = document.getElementById('messageContainer');
|
|
17
|
-
messageContainer.style.color = isError ? 'red' : 'black';
|
|
18
|
-
messageContainer.style.display = 'block';
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
window.setMessage = (message) => {
|
|
22
|
-
document.getElementById('message').innerText = message;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
window.onLoggedIn = (token) => {
|
|
26
|
-
updateCaptchaStatus('Logged in, fetching private resource', 'info');
|
|
27
|
-
const url = new URL("/private", config.serverUrl).href;
|
|
28
|
-
console.log("getting private resource with token ", token, "at", url);
|
|
29
|
-
fetch(url, {
|
|
30
|
-
method: "GET",
|
|
31
|
-
headers: {
|
|
32
|
-
Origin: "http://localhost:9232", // TODO: change this to env var
|
|
33
|
-
"Content-Type": "application/json",
|
|
34
|
-
Authorization: `Bearer ${token}`,
|
|
35
|
-
},
|
|
36
|
-
})
|
|
37
|
-
.then(async (res) => {
|
|
38
|
-
try {
|
|
39
|
-
const jsonRes = await res.json();
|
|
40
|
-
if (res.status === 200) {
|
|
41
|
-
updateCaptchaStatus(`Successfully accessed private resource`, 'success');
|
|
42
|
-
setMessage(jsonRes.message);
|
|
43
|
-
} else {
|
|
44
|
-
updateCaptchaStatus(`Failed to access private resource: ${res.status}`, 'error');
|
|
45
|
-
}
|
|
46
|
-
} catch (err) {
|
|
47
|
-
console.log(err);
|
|
48
|
-
updateCaptchaStatus(`Error parsing response: ${err}`, 'error');
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
.catch((err) => {
|
|
52
|
-
console.log(err);
|
|
53
|
-
updateCaptchaStatus(`Fetch error: ${err}`, 'error');
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
window.onActionHandler = () => {
|
|
58
|
-
updateCaptchaStatus('Form submission initiated', 'info');
|
|
59
|
-
|
|
60
|
-
const procaptchaElements = document.getElementsByName('procaptcha-response');
|
|
61
|
-
|
|
62
|
-
if (!procaptchaElements.length) {
|
|
63
|
-
updateCaptchaStatus('Error: No CAPTCHA response found', 'error');
|
|
64
|
-
alert("Must complete captcha");
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const procaptchaToken = procaptchaElements[0].value;
|
|
69
|
-
updateCaptchaStatus(`Token received: ${procaptchaToken.substring(0, 15)}...`, 'success');
|
|
70
|
-
|
|
71
|
-
const payload = {
|
|
72
|
-
email: document.getElementById('email').value,
|
|
73
|
-
name: document.getElementById('name').value,
|
|
74
|
-
password: document.getElementById('password').value,
|
|
75
|
-
siteKey: import.meta.env.PROSOPO_SITE_KEY_FRICTIONLESS,
|
|
76
|
-
"procaptcha-response": procaptchaToken,
|
|
77
|
-
};
|
|
78
|
-
const url = new URL('signup', import.meta.env.PROSOPO_SERVER_URL).href;
|
|
79
|
-
console.log("posting to", url, "with payload", payload);
|
|
80
|
-
fetch(url, {
|
|
81
|
-
method: "POST",
|
|
82
|
-
headers: {
|
|
83
|
-
"Content-Type": "application/json",
|
|
84
|
-
},
|
|
85
|
-
body: JSON.stringify(payload),
|
|
86
|
-
contentType: "application/json",
|
|
87
|
-
}).then((response) => {
|
|
88
|
-
return new Promise((resolve) => response.json()
|
|
89
|
-
.then((json) => resolve({
|
|
90
|
-
status: response.status,
|
|
91
|
-
ok: response.ok,
|
|
92
|
-
json,
|
|
93
|
-
})))
|
|
94
|
-
})
|
|
95
|
-
.then(async ({status, json, ok}) => {
|
|
96
|
-
console.log("status", status, "json", json.message, "ok", ok);
|
|
97
|
-
console.log("json", json)
|
|
98
|
-
try {
|
|
99
|
-
if (status !== 200) {
|
|
100
|
-
updateCaptchaStatus(`API Error: ${json.message}`, 'error');
|
|
101
|
-
setIsError(true);
|
|
102
|
-
setMessage(json.message);
|
|
103
|
-
} else {
|
|
104
|
-
updateCaptchaStatus(`API Success: ${json.message}`, 'success');
|
|
105
|
-
setIsError(false);
|
|
106
|
-
setMessage(json.message);
|
|
107
|
-
}
|
|
108
|
-
} catch (err) {
|
|
109
|
-
console.log(err);
|
|
110
|
-
updateCaptchaStatus(`Error processing response: ${err}`, 'error');
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
.catch((err) => {
|
|
114
|
-
console.log(err);
|
|
115
|
-
updateCaptchaStatus(`Fetch error: ${err}`, 'error');
|
|
116
|
-
setIsError(true);
|
|
117
|
-
setMessage("Error: " + err);
|
|
118
|
-
});
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
// Monitor DOM for CAPTCHA initialization
|
|
122
|
-
const observer = new MutationObserver((mutations) => {
|
|
123
|
-
mutations.forEach((mutation) => {
|
|
124
|
-
if (mutation.addedNodes.length) {
|
|
125
|
-
for (let i = 0; i < mutation.addedNodes.length; i++) {
|
|
126
|
-
const node = mutation.addedNodes[i];
|
|
127
|
-
if (node.classList && (node.classList.contains('procaptcha') ||
|
|
128
|
-
node.querySelector && node.querySelector('.procaptcha'))) {
|
|
129
|
-
updateCaptchaStatus('CAPTCHA DOM elements initialized', 'info');
|
|
130
|
-
observer.disconnect();
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
</script>
|
|
142
|
-
</head>
|
|
143
|
-
<body>
|
|
144
|
-
|
|
145
|
-
<div class="demo-card">
|
|
146
|
-
|
|
147
|
-
<!-- nosemgrep: python.django.security.django-no-csrf-token.django-no-csrf-token -->
|
|
148
|
-
<form action="%PROSOPO_SERVER_URL%/signup" method="POST" class="demo-form" id="demo-form">
|
|
149
|
-
<h2>Create an account</h2>
|
|
150
|
-
<div class="demo-field">
|
|
151
|
-
<label for="name">Name</label>
|
|
152
|
-
<input id="name" type="text" name="name" required/>
|
|
153
|
-
</div>
|
|
154
|
-
<div class="demo-field">
|
|
155
|
-
<label for="email">Email Address</label>
|
|
156
|
-
<input id="email" type="email" name="email" required/>
|
|
157
|
-
</div>
|
|
158
|
-
<div class="demo-field">
|
|
159
|
-
<label for="password">Password</label>
|
|
160
|
-
<input id="password" type="password" name="password" required/>
|
|
161
|
-
</div>
|
|
162
|
-
<div class="demo-field">
|
|
163
|
-
<div id="procaptcha-container"></div>
|
|
164
|
-
</div>
|
|
165
|
-
<div id="messageContainer" style="display: none; color: black;"><span id="message"></span></div>
|
|
166
|
-
<button type="button" class="demo-button" onclick="onActionHandler()" data-cy="submit-button">Submit</button>
|
|
167
|
-
</form>
|
|
168
|
-
|
|
169
|
-
</div>
|
|
170
|
-
<script type="module">
|
|
171
|
-
// Pattern to avoid race condition between Procaptcha script loading and Procaptcha render function call
|
|
172
|
-
import { render } from "%VITE_BUNDLE_URL%"
|
|
173
|
-
import { web3AccountsSubscribe, web3Enable } from "@polkadot/extension-dapp";
|
|
174
|
-
|
|
175
|
-
// Define a callback function to be called when the CAPTCHA is verified
|
|
176
|
-
function onCaptchaVerified(output) {
|
|
177
|
-
console.log('Challenge passed');
|
|
178
|
-
window.updateCaptchaStatus('Challenge passed successfully!', 'success');
|
|
179
|
-
window.updateCaptchaStatus(`Token generated: ${output.substring(0, 15)}...`, 'success');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Get web3 accounts and create select element
|
|
183
|
-
async function getWeb3Accounts() {
|
|
184
|
-
return new Promise((resolve) =>{ web3AccountsSubscribe((accounts) => {
|
|
185
|
-
if (accounts.length === 0) {
|
|
186
|
-
window.updateCaptchaStatus('No accounts found. Please connect your wallet.', 'error');
|
|
187
|
-
} else {
|
|
188
|
-
window.updateCaptchaStatus(`Connected to ${accounts.length} account(s).`, 'info');
|
|
189
|
-
// render a modal and get the user to select 1 account
|
|
190
|
-
const accountSelect = document.createElement('select');
|
|
191
|
-
accountSelect.id = 'account-select';
|
|
192
|
-
accountSelect.classList.add('account-select');
|
|
193
|
-
accounts.forEach((account) => {
|
|
194
|
-
const option = document.createElement('option');
|
|
195
|
-
option.value = account.address;
|
|
196
|
-
option.textContent = `${account.meta.name} (${account.address})`;
|
|
197
|
-
accountSelect.appendChild(option);
|
|
198
|
-
});
|
|
199
|
-
const accountContainer = document.createElement('div');
|
|
200
|
-
accountContainer.innerHTML = '<label for="account-select"><h2>Select Account:</h2></label>';
|
|
201
|
-
accountContainer.appendChild(accountSelect);
|
|
202
|
-
document.getElementById('demo-form').prepend(accountContainer);
|
|
203
|
-
window.updateCaptchaStatus('Accounts loaded successfully', 'info');
|
|
204
|
-
}
|
|
205
|
-
resolve(accounts);
|
|
206
|
-
})});
|
|
207
|
-
}
|
|
208
|
-
// Wait for DOM content to be loaded
|
|
209
|
-
document.addEventListener('DOMContentLoaded', async function() {
|
|
210
|
-
await web3Enable("Procaptcha Demo");
|
|
211
|
-
|
|
212
|
-
await getWeb3Accounts();
|
|
213
|
-
|
|
214
|
-
// Get the selected account from the dropdown
|
|
215
|
-
const account = document.getElementById('account-select') ? document.getElementById('account-select').value : null;
|
|
216
|
-
window.updateCaptchaStatus(`Rendering the CAPTCHA for account ${account}`, 'info');
|
|
217
|
-
|
|
218
|
-
// Get the Element using elementId
|
|
219
|
-
const captchaContainer = document.getElementById('procaptcha-container');
|
|
220
|
-
|
|
221
|
-
// Render the CAPTCHA
|
|
222
|
-
const widgetId = await render(captchaContainer, {
|
|
223
|
-
siteKey: import.meta.env.PROSOPO_SITE_KEY_FRICTIONLESS,
|
|
224
|
-
callback: onCaptchaVerified,
|
|
225
|
-
"failed-callback": function () {
|
|
226
|
-
console.log('Challenge failed');
|
|
227
|
-
window.updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
|
|
228
|
-
},
|
|
229
|
-
web3: true,
|
|
230
|
-
userAccountAddress: account
|
|
231
|
-
});
|
|
232
|
-
window.updateCaptchaStatus('CAPTCHA render function called with widget ID: ' + widgetId, 'info');
|
|
233
|
-
})
|
|
234
|
-
|
|
235
|
-
</script>
|
|
236
|
-
</body>
|
|
237
|
-
</html>
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
<title>Procaptcha demo: Frictionless, explicit rendering</title>
|
|
6
|
-
<script type="module">
|
|
7
|
-
window.onCaptchaFailed = function () {
|
|
8
|
-
console.log('Challenge failed');
|
|
9
|
-
updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
window.addEventListener('load', () => {
|
|
13
|
-
updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
|
|
14
|
-
|
|
15
|
-
window.setIsError = (isError) => {
|
|
16
|
-
const messageContainer = document.getElementById('messageContainer');
|
|
17
|
-
messageContainer.style.color = isError ? 'red' : 'black';
|
|
18
|
-
messageContainer.style.display = 'block';
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
window.setMessage = (message) => {
|
|
22
|
-
document.getElementById('message').innerText = message;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
window.onLoggedIn = (token) => {
|
|
26
|
-
updateCaptchaStatus('Logged in, fetching private resource', 'info');
|
|
27
|
-
const url = new URL("/private", config.serverUrl).href;
|
|
28
|
-
console.log("getting private resource with token ", token, "at", url);
|
|
29
|
-
fetch(url, {
|
|
30
|
-
method: "GET",
|
|
31
|
-
headers: {
|
|
32
|
-
Origin: "http://localhost:9232", // TODO: change this to env var
|
|
33
|
-
"Content-Type": "application/json",
|
|
34
|
-
Authorization: `Bearer ${token}`,
|
|
35
|
-
},
|
|
36
|
-
})
|
|
37
|
-
.then(async (res) => {
|
|
38
|
-
try {
|
|
39
|
-
const jsonRes = await res.json();
|
|
40
|
-
if (res.status === 200) {
|
|
41
|
-
updateCaptchaStatus(`Successfully accessed private resource`, 'success');
|
|
42
|
-
setMessage(jsonRes.message);
|
|
43
|
-
} else {
|
|
44
|
-
updateCaptchaStatus(`Failed to access private resource: ${res.status}`, 'error');
|
|
45
|
-
}
|
|
46
|
-
} catch (err) {
|
|
47
|
-
console.log(err);
|
|
48
|
-
updateCaptchaStatus(`Error parsing response: ${err}`, 'error');
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
.catch((err) => {
|
|
52
|
-
console.log(err);
|
|
53
|
-
updateCaptchaStatus(`Fetch error: ${err}`, 'error');
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
window.onActionHandler = () => {
|
|
58
|
-
updateCaptchaStatus('Form submission initiated', 'info');
|
|
59
|
-
|
|
60
|
-
const procaptchaElements = document.getElementsByName('procaptcha-response');
|
|
61
|
-
|
|
62
|
-
if (!procaptchaElements.length) {
|
|
63
|
-
updateCaptchaStatus('Error: No CAPTCHA response found', 'error');
|
|
64
|
-
alert("Must complete captcha");
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const procaptchaToken = procaptchaElements[0].value;
|
|
69
|
-
updateCaptchaStatus(`Token received: ${procaptchaToken.substring(0, 15)}...`, 'success');
|
|
70
|
-
|
|
71
|
-
const payload = {
|
|
72
|
-
email: document.getElementById('email').value,
|
|
73
|
-
name: document.getElementById('name').value,
|
|
74
|
-
password: document.getElementById('password').value,
|
|
75
|
-
siteKey: import.meta.env.PROSOPO_SITE_KEY_FRICTIONLESS,
|
|
76
|
-
"procaptcha-response": procaptchaToken,
|
|
77
|
-
};
|
|
78
|
-
const url = new URL('signup', import.meta.env.PROSOPO_SERVER_URL).href;
|
|
79
|
-
console.log("posting to", url, "with payload", payload);
|
|
80
|
-
fetch(url, {
|
|
81
|
-
method: "POST",
|
|
82
|
-
headers: {
|
|
83
|
-
"Content-Type": "application/json",
|
|
84
|
-
},
|
|
85
|
-
body: JSON.stringify(payload),
|
|
86
|
-
contentType: "application/json",
|
|
87
|
-
}).then((response) => {
|
|
88
|
-
return new Promise((resolve) => response.json()
|
|
89
|
-
.then((json) => resolve({
|
|
90
|
-
status: response.status,
|
|
91
|
-
ok: response.ok,
|
|
92
|
-
json,
|
|
93
|
-
})))
|
|
94
|
-
})
|
|
95
|
-
.then(async ({status, json, ok}) => {
|
|
96
|
-
console.log("status", status, "json", json.message, "ok", ok);
|
|
97
|
-
console.log("json", json)
|
|
98
|
-
try {
|
|
99
|
-
if (status !== 200) {
|
|
100
|
-
updateCaptchaStatus(`API Error: ${json.message}`, 'error');
|
|
101
|
-
setIsError(true);
|
|
102
|
-
setMessage(json.message);
|
|
103
|
-
} else {
|
|
104
|
-
updateCaptchaStatus(`API Success: ${json.message}`, 'success');
|
|
105
|
-
setIsError(false);
|
|
106
|
-
setMessage(json.message);
|
|
107
|
-
}
|
|
108
|
-
} catch (err) {
|
|
109
|
-
console.log(err);
|
|
110
|
-
updateCaptchaStatus(`Error processing response: ${err}`, 'error');
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
.catch((err) => {
|
|
114
|
-
console.log(err);
|
|
115
|
-
updateCaptchaStatus(`Fetch error: ${err}`, 'error');
|
|
116
|
-
setIsError(true);
|
|
117
|
-
setMessage("Error: " + err);
|
|
118
|
-
});
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
// Monitor DOM for CAPTCHA initialization
|
|
122
|
-
const observer = new MutationObserver((mutations) => {
|
|
123
|
-
mutations.forEach((mutation) => {
|
|
124
|
-
if (mutation.addedNodes.length) {
|
|
125
|
-
for (let i = 0; i < mutation.addedNodes.length; i++) {
|
|
126
|
-
const node = mutation.addedNodes[i];
|
|
127
|
-
if (node.classList && (node.classList.contains('procaptcha') ||
|
|
128
|
-
node.querySelector && node.querySelector('.procaptcha'))) {
|
|
129
|
-
updateCaptchaStatus('CAPTCHA DOM elements initialized', 'info');
|
|
130
|
-
observer.disconnect();
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
</script>
|
|
142
|
-
</head>
|
|
143
|
-
<body>
|
|
144
|
-
|
|
145
|
-
<div class="demo-card">
|
|
146
|
-
|
|
147
|
-
<!-- nosemgrep: python.django.security.django-no-csrf-token.django-no-csrf-token -->
|
|
148
|
-
<form action="%PROSOPO_SERVER_URL%/signup" method="POST" class="demo-form">
|
|
149
|
-
<h2>Create an account</h2>
|
|
150
|
-
<div class="demo-field">
|
|
151
|
-
<label for="name">Name</label>
|
|
152
|
-
<input id="name" type="text" name="name" required/>
|
|
153
|
-
</div>
|
|
154
|
-
<div class="demo-field">
|
|
155
|
-
<label for="email">Email Address</label>
|
|
156
|
-
<input id="email" type="email" name="email" required/>
|
|
157
|
-
</div>
|
|
158
|
-
<div class="demo-field">
|
|
159
|
-
<label for="password">Password</label>
|
|
160
|
-
<input id="password" type="password" name="password" required/>
|
|
161
|
-
</div>
|
|
162
|
-
<div class="demo-field">
|
|
163
|
-
<div id="procaptcha-container"></div>
|
|
164
|
-
</div>
|
|
165
|
-
<div id="messageContainer" style="display: none; color: black;"><span id="message"></span></div>
|
|
166
|
-
<button type="button" class="demo-button" onclick="onActionHandler()" data-cy="submit-button">Submit</button>
|
|
167
|
-
</form>
|
|
168
|
-
|
|
169
|
-
</div>
|
|
170
|
-
<script type="module">
|
|
171
|
-
// Pattern to avoid race condition between Procaptcha script loading and Procaptcha render function call
|
|
172
|
-
import { render } from "%VITE_BUNDLE_URL%"
|
|
173
|
-
|
|
174
|
-
// Define a callback function to be called when the CAPTCHA is verified
|
|
175
|
-
function onCaptchaVerified(output) {
|
|
176
|
-
console.log('Challenge passed');
|
|
177
|
-
window.updateCaptchaStatus('Challenge passed successfully!', 'success');
|
|
178
|
-
window.updateCaptchaStatus(`Token generated: ${output.substring(0, 15)}...`, 'success');
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Get the Element using elementId
|
|
182
|
-
const captchaContainer = document.getElementById('procaptcha-container');
|
|
183
|
-
|
|
184
|
-
// ?placement=float anchors the challenge to the widget; the default is popup.
|
|
185
|
-
const placement =
|
|
186
|
-
new URLSearchParams(window.location.search).get("placement") === "float"
|
|
187
|
-
? "float"
|
|
188
|
-
: "popup";
|
|
189
|
-
window.updateCaptchaStatus('Challenge placement: ' + placement, 'info');
|
|
190
|
-
|
|
191
|
-
// Render the CAPTCHA
|
|
192
|
-
const widgetId = await render(captchaContainer, {
|
|
193
|
-
siteKey: import.meta.env.PROSOPO_SITE_KEY_FRICTIONLESS,
|
|
194
|
-
placement,
|
|
195
|
-
callback: onCaptchaVerified,
|
|
196
|
-
"failed-callback": function () {
|
|
197
|
-
console.log('Challenge failed');
|
|
198
|
-
window.updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
|
-
window.updateCaptchaStatus('CAPTCHA render function called with widget ID: ' + widgetId, 'info');
|
|
202
|
-
|
|
203
|
-
</script>
|
|
204
|
-
</body>
|
|
205
|
-
</html>
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
<title>Procaptcha demo: Frictionless, implicit rendering</title>
|
|
6
|
-
<script type="module">
|
|
7
|
-
|
|
8
|
-
window.addEventListener('load', () => {
|
|
9
|
-
|
|
10
|
-
window.setIsError = (isError) => {
|
|
11
|
-
const messageContainer = document.getElementById('messageContainer');
|
|
12
|
-
messageContainer.style.color = isError ? 'red' : 'black';
|
|
13
|
-
messageContainer.style.display = 'block';
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
window.setMessage = (message) => {
|
|
17
|
-
document.getElementById('message').innerText = message;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
window.onLoggedIn = (token) => {
|
|
21
|
-
updateCaptchaStatus('Logged in, fetching private resource', 'info');
|
|
22
|
-
const url = new URL("/private", config.serverUrl).href;
|
|
23
|
-
console.log("getting private resource with token ", token, "at", url);
|
|
24
|
-
fetch(url, {
|
|
25
|
-
method: "GET",
|
|
26
|
-
headers: {
|
|
27
|
-
Origin: "http://localhost:9232", // TODO: change this to env var
|
|
28
|
-
"Content-Type": "application/json",
|
|
29
|
-
Authorization: `Bearer ${token}`,
|
|
30
|
-
},
|
|
31
|
-
})
|
|
32
|
-
.then(async (res) => {
|
|
33
|
-
try {
|
|
34
|
-
const jsonRes = await res.json();
|
|
35
|
-
if (res.status === 200) {
|
|
36
|
-
updateCaptchaStatus(`Successfully accessed private resource`, 'success');
|
|
37
|
-
setMessage(jsonRes.message);
|
|
38
|
-
} else {
|
|
39
|
-
updateCaptchaStatus(`Failed to access private resource: ${res.status}`, 'error');
|
|
40
|
-
}
|
|
41
|
-
} catch (err) {
|
|
42
|
-
console.log(err);
|
|
43
|
-
updateCaptchaStatus(`Error parsing response: ${err}`, 'error');
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
.catch((err) => {
|
|
47
|
-
console.log(err);
|
|
48
|
-
updateCaptchaStatus(`Fetch error: ${err}`, 'error');
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
window.onActionHandler = () => {
|
|
53
|
-
updateCaptchaStatus('Form submission initiated', 'info');
|
|
54
|
-
|
|
55
|
-
const procaptchaElements = document.getElementsByName('procaptcha-response');
|
|
56
|
-
|
|
57
|
-
if (!procaptchaElements.length) {
|
|
58
|
-
updateCaptchaStatus('Error: No CAPTCHA response found', 'error');
|
|
59
|
-
alert("Must complete captcha");
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const procaptchaToken = procaptchaElements[0].value;
|
|
64
|
-
updateCaptchaStatus(`Token received: ${procaptchaToken.substring(0, 15)}...`, 'success');
|
|
65
|
-
|
|
66
|
-
const payload = {
|
|
67
|
-
email: document.getElementById('email').value,
|
|
68
|
-
name: document.getElementById('name').value,
|
|
69
|
-
password: document.getElementById('password').value,
|
|
70
|
-
siteKey: import.meta.env.PROSOPO_SITE_KEY_FRICTIONLESS,
|
|
71
|
-
"procaptcha-response": procaptchaToken,
|
|
72
|
-
};
|
|
73
|
-
const url = new URL('signup', import.meta.env.PROSOPO_SERVER_URL).href;
|
|
74
|
-
console.log("posting to", url, "with payload", payload);
|
|
75
|
-
fetch(url, {
|
|
76
|
-
method: "POST",
|
|
77
|
-
headers: {
|
|
78
|
-
"Content-Type": "application/json",
|
|
79
|
-
},
|
|
80
|
-
body: JSON.stringify(payload),
|
|
81
|
-
contentType: "application/json",
|
|
82
|
-
}).then((response) => {
|
|
83
|
-
return new Promise((resolve) => response.json()
|
|
84
|
-
.then((json) => resolve({
|
|
85
|
-
status: response.status,
|
|
86
|
-
ok: response.ok,
|
|
87
|
-
json,
|
|
88
|
-
})))
|
|
89
|
-
})
|
|
90
|
-
.then(async ({status, json, ok}) => {
|
|
91
|
-
console.log("status", status, "json", json.message, "ok", ok);
|
|
92
|
-
console.log("json", json)
|
|
93
|
-
try {
|
|
94
|
-
if (status !== 200) {
|
|
95
|
-
updateCaptchaStatus(`API Error: ${json.message}`, 'error');
|
|
96
|
-
setIsError(true);
|
|
97
|
-
setMessage(json.message);
|
|
98
|
-
} else {
|
|
99
|
-
updateCaptchaStatus(`API Success: ${json.message}`, 'success');
|
|
100
|
-
setIsError(false);
|
|
101
|
-
setMessage(json.message);
|
|
102
|
-
}
|
|
103
|
-
} catch (err) {
|
|
104
|
-
console.log(err);
|
|
105
|
-
updateCaptchaStatus(`Error processing response: ${err}`, 'error');
|
|
106
|
-
}
|
|
107
|
-
})
|
|
108
|
-
.catch((err) => {
|
|
109
|
-
console.log(err);
|
|
110
|
-
updateCaptchaStatus(`Fetch error: ${err}`, 'error');
|
|
111
|
-
setIsError(true);
|
|
112
|
-
setMessage("Error: " + err);
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
|
|
117
|
-
|
|
118
|
-
// Monitor DOM for CAPTCHA initialization
|
|
119
|
-
const observer = new MutationObserver((mutations) => {
|
|
120
|
-
mutations.forEach((mutation) => {
|
|
121
|
-
if (mutation.addedNodes.length) {
|
|
122
|
-
for (let i = 0; i < mutation.addedNodes.length; i++) {
|
|
123
|
-
const node = mutation.addedNodes[i];
|
|
124
|
-
if (node.classList && (node.classList.contains('procaptcha') ||
|
|
125
|
-
node.querySelector && node.querySelector('.procaptcha'))) {
|
|
126
|
-
updateCaptchaStatus('CAPTCHA DOM elements initialized', 'info');
|
|
127
|
-
observer.disconnect();
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
window.onCaptchaFailed = function () {
|
|
139
|
-
console.log('Challenge failed');
|
|
140
|
-
updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
window.onCaptchaVerified = (output) => {
|
|
144
|
-
console.log('Challenge passed');
|
|
145
|
-
updateCaptchaStatus('Challenge passed successfully!', 'success');
|
|
146
|
-
updateCaptchaStatus(`Token generated: ${output.substring(0, 15)}...`, 'success');
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Add custom event listener for CAPTCHA verification stages
|
|
150
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
151
|
-
setTimeout(() => {
|
|
152
|
-
updateCaptchaStatus('CAPTCHA script loaded and initialized', 'info');
|
|
153
|
-
updateCaptchaStatus('Waiting for user interaction...', 'info');
|
|
154
|
-
}, 500);
|
|
155
|
-
});
|
|
156
|
-
</script>
|
|
157
|
-
<script id="procaptchaScript" type="module" src="%VITE_BUNDLE_URL%" async defer></script>
|
|
158
|
-
</head>
|
|
159
|
-
<body>
|
|
160
|
-
|
|
161
|
-
<div class="demo-card">
|
|
162
|
-
|
|
163
|
-
<form action="%PROSOPO_SERVER_URL%/signup" method="POST" class="demo-form">
|
|
164
|
-
<h2>Create an account</h2>
|
|
165
|
-
<div class="demo-field">
|
|
166
|
-
<label for="name">Name</label>
|
|
167
|
-
<input id="name" type="text" name="name" required/>
|
|
168
|
-
</div>
|
|
169
|
-
<div class="demo-field">
|
|
170
|
-
<label for="email">Email Address</label>
|
|
171
|
-
<input id="email" type="email" name="email" required/>
|
|
172
|
-
</div>
|
|
173
|
-
<div class="demo-field">
|
|
174
|
-
<label for="password">Password</label>
|
|
175
|
-
<input id="password" type="password" name="password" required/>
|
|
176
|
-
</div>
|
|
177
|
-
<div class="demo-field">
|
|
178
|
-
<div
|
|
179
|
-
class="procaptcha"
|
|
180
|
-
data-theme="light"
|
|
181
|
-
data-sitekey="%PROSOPO_SITE_KEY_FRICTIONLESS%"
|
|
182
|
-
data-failed-callback="onCaptchaFailed"
|
|
183
|
-
data-callback="onCaptchaVerified"
|
|
184
|
-
></div>
|
|
185
|
-
</div>
|
|
186
|
-
<div id="messageContainer" style="display: none; color: black;"><span id="message"></span></div>
|
|
187
|
-
<button type="button" class="demo-button" onclick="onActionHandler()" data-cy="submit-button">Submit</button>
|
|
188
|
-
</form>
|
|
189
|
-
|
|
190
|
-
</div>
|
|
191
|
-
</body>
|
|
192
|
-
</html>
|