- Added CaptchaGuard dependency to PasswordAuthenticator. - Implemented Captcha validation in the authenticate method to enhance security. - Updated the login modal in home.html.twig to redirect to the admin panel instead of opening a modal. - Enhanced the Altcha widget with localized strings for better user experience. - Removed the login modal implementation from home.html.twig to streamline the login process. - Updated manifest.json and AST cache files to reflect changes in the codebase.
55 lines
2.1 KiB
TypeScript
55 lines
2.1 KiB
TypeScript
import React, { useEffect, useRef } from 'react';
|
|
import 'altcha';
|
|
|
|
// ALTCHA خودمیزبان: widget با گرفتن challenge از بکاند، proof-of-work را در
|
|
// پسزمینهی مرورگر حل میکند و مقدار base64 حلشده را در event `verified` میدهد.
|
|
// این مقدار باید در بدنهی درخواستِ endpoint عمومی با کلید `altcha` ارسال شود.
|
|
|
|
interface AltchaProps {
|
|
onVerified: (payload: string) => void;
|
|
challengeUrl?: string;
|
|
}
|
|
|
|
// برچسبهای فارسی widget (ترجمهی رسمی locale fa).
|
|
const FA_STRINGS = JSON.stringify({
|
|
label: 'من ربات نیستم',
|
|
verifying: 'در حال بررسی...',
|
|
verified: 'تأیید شد',
|
|
waitAlert: 'در حال بررسی... لطفاً منتظر بمانید.',
|
|
error: 'احراز هویت ناموفق بود. کمی بعد دوباره تلاش کنید.',
|
|
expired: 'احراز هویت منقضی شد. دوباره تلاش کنید.',
|
|
});
|
|
|
|
// altcha-widget یک custom element است؛ به JSX معرفی میشود (React 19: namespace زیر React.JSX).
|
|
declare module 'react' {
|
|
namespace JSX {
|
|
interface IntrinsicElements {
|
|
'altcha-widget': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
|
|
challengeurl?: string;
|
|
strings?: string;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
export default function Altcha({ onVerified, challengeUrl = '/api/v1/altcha/challenge' }: AltchaProps) {
|
|
const ref = useRef<HTMLElement>(null);
|
|
|
|
useEffect(() => {
|
|
const el = ref.current;
|
|
if (!el) return;
|
|
|
|
const onStateChange = (e: Event) => {
|
|
const detail = (e as CustomEvent).detail as { state?: string; payload?: string };
|
|
if (detail?.state === 'verified' && detail.payload) {
|
|
onVerified(detail.payload);
|
|
}
|
|
};
|
|
|
|
el.addEventListener('statechange', onStateChange);
|
|
return () => el.removeEventListener('statechange', onStateChange);
|
|
}, [onVerified]);
|
|
|
|
return <altcha-widget ref={ref as React.Ref<HTMLElement>} challengeurl={challengeUrl} strings={FA_STRINGS} />;
|
|
}
|