fix: update Altcha component to properly set attributes and handle state changes

This commit is contained in:
hamed
2026-07-10 14:55:12 +03:30
parent 58a69e3345
commit 2fd0eec156
2 changed files with 22 additions and 17 deletions
+19 -17
View File
@@ -30,35 +30,37 @@ export default function Altcha({ onVerified }) {
}; };
}, [onVerified]); }, [onVerified]);
// ثبت custom element + ست‌کردن config به‌صورت attribute واقعی. در React 18
// پراپ‌های JSX روی custom element ممکن است به‌جای attribute به‌شکل property ست
// شوند و widget آن‌ها را نخواند (strings/theme اعمال نمی‌شد)؛ با setAttribute
// مطمئن می‌شویم درست خوانده می‌شوند. auto را آخر ست می‌کنیم تا بعد از config حل شود.
useEffect(() => { useEffect(() => {
if (enabled !== true) return; if (enabled !== true) return;
const el = ref.current;
if (!el) return;
let cancelled = false;
const onStateChange = (e) => { const onStateChange = (e) => {
if (e.detail?.state === "verified" && e.detail.payload) { if (e.detail?.state === "verified" && e.detail.payload) {
onVerified(e.detail.payload); onVerified(e.detail.payload);
} }
}; };
el.addEventListener("statechange", onStateChange);
// attributeها را قبل از import (قبل از upgrade شدن element) ست می‌کنیم تا // در React 18 پراپ‌های JSX روی custom element ممکن است property ست شوند و
// widget از همان ابتدا با تم روشن و متن فارسی init شود. locale رسمی fa با // widget نخواند؛ پس با setAttribute ست می‌کنیم. نام attribute در widget v3
// import ماژول i18n ثبت و با language="fa" فعال می‌شود (RTL هم خودکار است). // «challenge» است (نه «challengeurl» قدیمی که باعث fetch صفحه‌ی HTML می‌شد).
const el = ref.current; el.setAttribute("challenge", `${API}/api/v1/altcha/challenge`);
if (el) { el.setAttribute("language", "fa");
el.setAttribute("challengeurl", `${API}/api/v1/altcha/challenge`); el.setAttribute("theme", "light");
el.setAttribute("language", "fa");
el.setAttribute("theme", "light");
el.setAttribute("auto", "onload");
el.addEventListener("statechange", onStateChange);
}
Promise.all([import("altcha/i18n/fa"), import("altcha")]); // اول locale فارسی ثبت شود، سپس ماژول widget (تا هنگام upgrade، fa موجود باشد)،
// و در نهایت auto فعال شود تا حل PoW بعد از آماده‌بودن challenge/زبان انجام شود.
import("altcha/i18n/fa")
.then(() => import("altcha"))
.then(() => {
if (!cancelled) el.setAttribute("auto", "onload");
});
return () => { return () => {
el?.removeEventListener("statechange", onStateChange); cancelled = true;
el.removeEventListener("statechange", onStateChange);
}; };
}, [enabled, onVerified]); }, [enabled, onVerified]);
+3
View File
@@ -63,6 +63,9 @@ const nextConfig = {
"default-src 'self'", "default-src 'self'",
"img-src 'self' https: data: blob:", "img-src 'self' https: data: blob:",
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com", "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com",
// ALTCHA کپچا برای حل proof-of-work از Web Workerِ blob استفاده می‌کند؛
// بدون این، worker بلاک و کپچا «احراز هویت ناموفق» می‌دهد.
"worker-src 'self' blob:",
"style-src 'self' 'unsafe-inline'", "style-src 'self' 'unsafe-inline'",
"font-src 'self' data:", "font-src 'self' data:",
'connect-src ' + connectSrc, 'connect-src ' + connectSrc,