Update initgui.js
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test (18.x) (push) Has been cancelled
test / test (20.x) (push) Has been cancelled
test / test (22.x) (push) Has been cancelled

This commit is contained in:
jelveh
2025-08-27 17:29:34 -07:00
parent 42d561416e
commit 245a04047e
+257 -37
View File
@@ -151,6 +151,201 @@ if(jQuery){
};
}
/**
* Shows a Turnstile challenge modal for first-time temp user creation
* @param {Object} options - Configuration options
* @param {Function} options.onSuccess - Callback when challenge is completed successfully
* @param {Function} options.onError - Callback when challenge fails
*/
window.showTurnstileChallenge = function(options) {
return new Promise((resolve) => {
const modalId = 'turnstile-challenge-modal';
const siteKey = window.gui_params?.turnstileSiteKey;
if (!siteKey) {
options.onError('Turnstile site key not configured');
return resolve();
}
// Create modal HTML
let modalHtml = `
<div id="${modalId}" class="modal" style="
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
">
<div class="modal-content" style="
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
max-width: 400px;
width: 90%;
text-align: center;
position: relative;
">
<div class="modal-header" style="margin-bottom: 20px;">
<img src="${window.icons['logo-white.svg']}" style="
width: 40px;
height: 40px;
margin: 0 auto 15px;
display: block;
padding: 10px;
background-color: #3b82f6;
border-radius: 8px;
">
<h2 style="
margin: 0;
color: #1f2937;
font-size: 24px;
font-weight: 600;
line-height: 1.2;
">Welcome to Puter</h2>
<p style="
margin: 10px 0 0 0;
color: #6b7280;
font-size: 14px;
line-height: 1.4;
">Please complete the security verification to continue</p>
</div>
<div class="turnstile-container" style="
display: flex;
justify-content: center;
margin: 20px 0;
min-height: 80px;
align-items: center;
">
<div id="turnstile-widget-${modalId}" class="cf-turnstile" data-sitekey="${siteKey}"></div>
</div>
<div class="loading-state" style="
display: none;
margin: 20px 0;
color: #6b7280;
font-size: 14px;
">
<div style="
display: inline-block;
width: 20px;
height: 20px;
border: 2px solid #e5e7eb;
border-radius: 50%;
border-top: 2px solid #3b82f6;
animation: spin 1s linear infinite;
margin-right: 10px;
vertical-align: middle;
"></div>
Setting up your account...
</div>
<div class="error-message" style="
display: none;
color: #dc2626;
font-size: 14px;
margin-top: 15px;
padding: 10px;
background-color: #fef2f2;
border: 1px solid #fecaca;
border-radius: 6px;
"></div>
</div>
</div>
<style>
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
`;
// Add modal to DOM
document.body.insertAdjacentHTML('beforeend', modalHtml);
const modal = document.getElementById(modalId);
const errorMessage = modal.querySelector('.error-message');
const loadingState = modal.querySelector('.loading-state');
const turnstileContainer = modal.querySelector('.turnstile-container');
// Initialize Turnstile widget
const initTurnstile = () => {
if (!window.turnstile) {
setTimeout(initTurnstile, 100);
return;
}
try {
window.turnstile.render(`#turnstile-widget-${modalId}`, {
sitekey: siteKey,
callback: function(token) {
// Show loading state
turnstileContainer.style.display = 'none';
loadingState.style.display = 'block';
// Call success callback
options.onSuccess(token);
// Remove modal after a brief delay
setTimeout(() => {
modal.remove();
resolve();
}, 500);
},
'expired-callback': function() {
showError('Verification expired. Please try again.');
},
'error-callback': function() {
showError('Verification failed. Please refresh the page and try again.');
options.onError('Turnstile verification failed');
}
});
} catch (error) {
console.error('Failed to initialize Turnstile:', error);
showError('Failed to load security verification. Please refresh the page.');
options.onError(error);
}
};
const showError = (message) => {
errorMessage.textContent = message;
errorMessage.style.display = 'block';
};
// Start initialization
initTurnstile();
// Prevent modal from closing by clicking outside
modal.addEventListener('click', (e) => {
if (e.target === modal) {
// Don't close - force users to complete verification
turnstileContainer.style.transform = 'scale(1.05)';
setTimeout(() => {
if (turnstileContainer) {
turnstileContainer.style.transform = 'scale(1)';
}
}, 200);
}
});
// Add transition styles
modal.style.opacity = '0';
modal.style.transition = 'opacity 0.3s ease';
// Fade in
requestAnimationFrame(() => {
modal.style.opacity = '1';
});
});
};
window.initgui = async function(options){
const url = new URL(window.location).href;
window.url = url;
@@ -812,7 +1007,7 @@ window.initgui = async function(options){
}
// -------------------------------------------------------------------------------------
// Un-authed and first visit ever -> create temp user
// Un-authed and first visit ever -> create temp user with Turnstile challenge
// -------------------------------------------------------------------------------------
else if(!window.is_auth() && window.first_visit_ever && !window.disable_temp_users){
let referrer;
@@ -838,49 +1033,74 @@ window.initgui = async function(options){
if(window.custom_headers)
headers = window.custom_headers;
// if this is a popup, show a spinner
let spinner_init_ts = Date.now();
if(window.embedded_in_popup){
puter.ui.showSpinner('<span style="-webkit-font-smoothing: antialiased;">Setting up your <a href="https://puter.com" target="_blank">Puter.com</a> account for secure AI and Cloud features</span>');
}
// Function to create temp user after captcha completion
const createTempUser = (turnstileToken) => {
// if this is a popup, show a spinner
let spinner_init_ts = Date.now();
if(window.embedded_in_popup){
puter.ui.showSpinner('<span style="-webkit-font-smoothing: antialiased;">Setting up your <a href="https://puter.com" target="_blank">Puter.com</a> account for secure AI and Cloud features</span>');
}
$.ajax({
url: window.gui_origin + "/signup",
type: 'POST',
async: true,
headers: headers,
contentType: "application/json",
data: JSON.stringify({
const requestData = {
referrer: referrer,
referral_code: window.referral_code,
is_temp: true,
}),
success: async function (data){
// if this is a popup, hide the spinner, make sure it was visible for at least 2 seconds
if(window.embedded_in_popup){
let spinner_duration = (Date.now() - spinner_init_ts);
setTimeout(() => {
window.update_auth_data(data.token, data.user);
document.dispatchEvent(new Event("login", { bubbles: true}));
puter.ui.hideSpinner();
}, spinner_duration > 2000 ? 10 : 2000 - spinner_duration);
};
return;
}else{
window.update_auth_data(data.token, data.user);
document.dispatchEvent(new Event("login", { bubbles: true}));
}
},
error: async (err) => {
UIAlert({
message: html_encode(err.responseText),
});
},
complete: function(){
// Add Turnstile token if available
if (turnstileToken) {
requestData['cf-turnstile-response'] = turnstileToken;
}
});
$.ajax({
url: window.gui_origin + "/signup",
type: 'POST',
async: true,
headers: headers,
contentType: "application/json",
data: JSON.stringify(requestData),
success: async function (data){
// if this is a popup, hide the spinner, make sure it was visible for at least 2 seconds
if(window.embedded_in_popup){
let spinner_duration = (Date.now() - spinner_init_ts);
setTimeout(() => {
window.update_auth_data(data.token, data.user);
document.dispatchEvent(new Event("login", { bubbles: true}));
puter.ui.hideSpinner();
}, spinner_duration > 2000 ? 10 : 2000 - spinner_duration);
return;
}else{
window.update_auth_data(data.token, data.user);
document.dispatchEvent(new Event("login", { bubbles: true}));
}
},
error: async (err) => {
UIAlert({
message: html_encode(err.responseText),
});
},
complete: function(){
}
});
};
// Check if Turnstile is enabled and show challenge
if (window.gui_params?.turnstileSiteKey) {
window.showTurnstileChallenge({
onSuccess: createTempUser,
onError: (error) => {
console.error('Turnstile verification failed:', error);
UIAlert({
message: 'Security verification failed. Please refresh the page and try again.',
});
}
});
} else {
// No Turnstile configured, proceed without challenge
createTempUser();
}
}
// if there is at least one window open (only non-Explorer windows), ask user for confirmation when navigating away from puter