mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 21:45:31 +09:00
feat(captcha): make ALTCHA the only captcha (#3035)
This commit is contained in:
1 parent
d433a039b5
commit
4f968bbc47
209 files changed
+4097
-8692
No files matched your search
@@ -250,7 +250,6 @@ const RootComponent = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||
return [];
|
||||
}
|
||||
const inside: Array<Element> = [];
|
||||
modalDocument.querySelectorAll('iframe[src*="hcaptcha"], .h-captcha').forEach((el) => inside.push(el));
|
||||
const popoutsRoot = modalDocument.querySelector('[data-popouts-root]');
|
||||
if (popoutsRoot) inside.push(popoutsRoot);
|
||||
const mediaViewerPortalRoot = modalDocument.querySelector('[data-media-viewer-portal-root]');
|
||||
|
||||
@@ -156,12 +156,6 @@ const DEFAULT_INTEGRATION_DRAFT: ServiceIntegrationDraft = {
|
||||
klipyApiKey: '',
|
||||
youtubeMode: 'later',
|
||||
youtubeApiKey: '',
|
||||
captchaMode: 'later',
|
||||
captchaProvider: 'hcaptcha',
|
||||
hcaptchaSiteKey: '',
|
||||
hcaptchaSecretKey: '',
|
||||
turnstileSiteKey: '',
|
||||
turnstileSecretKey: '',
|
||||
emailMode: 'later',
|
||||
emailEnabled: true,
|
||||
emailFromEmail: '',
|
||||
@@ -200,8 +194,6 @@ function wizardStepToIntegrationKind(step: WizardStep): IntegrationStepKind | nu
|
||||
return 'gif';
|
||||
case 'integration_youtube':
|
||||
return 'youtube';
|
||||
case 'integration_captcha':
|
||||
return 'captcha';
|
||||
case 'integration_email':
|
||||
return 'email';
|
||||
case 'integration_bluesky':
|
||||
@@ -278,11 +270,6 @@ function isIntegrationStepValid(kind: IntegrationStepKind, draft: ServiceIntegra
|
||||
return draft.klipyApiKey.trim().length > 0;
|
||||
case 'youtube':
|
||||
return draft.youtubeMode === 'later' || draft.youtubeApiKey.trim().length > 0;
|
||||
case 'captcha':
|
||||
if (draft.captchaMode === 'later') return true;
|
||||
return draft.captchaProvider === 'hcaptcha'
|
||||
? draft.hcaptchaSiteKey.trim().length > 0 && draft.hcaptchaSecretKey.trim().length > 0
|
||||
: draft.turnstileSiteKey.trim().length > 0 && draft.turnstileSecretKey.trim().length > 0;
|
||||
case 'email':
|
||||
if (draft.emailMode === 'later' || !draft.emailEnabled) return true;
|
||||
return (
|
||||
@@ -313,13 +300,6 @@ function buildIntegrationsPatch(draft: ServiceIntegrationDraft) {
|
||||
youtube?: {
|
||||
api_key: string;
|
||||
};
|
||||
captcha?: {
|
||||
provider: 'hcaptcha' | 'turnstile';
|
||||
hcaptcha_site_key?: string;
|
||||
hcaptcha_secret_key?: string;
|
||||
turnstile_site_key?: string;
|
||||
turnstile_secret_key?: string;
|
||||
};
|
||||
email?: {
|
||||
enabled: boolean;
|
||||
provider: 'smtp';
|
||||
@@ -349,20 +329,6 @@ function buildIntegrationsPatch(draft: ServiceIntegrationDraft) {
|
||||
if (draft.youtubeMode === 'configure') {
|
||||
integrations.youtube = {api_key: draft.youtubeApiKey.trim()};
|
||||
}
|
||||
if (draft.captchaMode === 'configure') {
|
||||
integrations.captcha =
|
||||
draft.captchaProvider === 'hcaptcha'
|
||||
? {
|
||||
provider: 'hcaptcha',
|
||||
hcaptcha_site_key: draft.hcaptchaSiteKey.trim(),
|
||||
hcaptcha_secret_key: draft.hcaptchaSecretKey.trim(),
|
||||
}
|
||||
: {
|
||||
provider: 'turnstile',
|
||||
turnstile_site_key: draft.turnstileSiteKey.trim(),
|
||||
turnstile_secret_key: draft.turnstileSecretKey.trim(),
|
||||
};
|
||||
}
|
||||
if (draft.emailMode === 'configure') {
|
||||
integrations.email = {
|
||||
enabled: draft.emailEnabled,
|
||||
@@ -580,7 +546,6 @@ export const SelfHostedSetupWizardGate = observer(() => {
|
||||
});
|
||||
setIntegrationDraft((current) => ({
|
||||
...current,
|
||||
captchaProvider: next.integrations.captcha.effective_provider === 'turnstile' ? 'turnstile' : 'hcaptcha',
|
||||
emailEnabled: next.integrations.email.effective_enabled || next.integrations.email.enabled !== false,
|
||||
emailFromEmail: next.integrations.email.from_email ?? current.emailFromEmail,
|
||||
emailFromName: next.integrations.email.from_name ?? current.emailFromName,
|
||||
|
||||
@@ -14,7 +14,6 @@ export type WizardStep =
|
||||
| 'media_expiry'
|
||||
| 'integration_gif'
|
||||
| 'integration_youtube'
|
||||
| 'integration_captcha'
|
||||
| 'integration_email'
|
||||
| 'integration_bluesky'
|
||||
| 'push_relay_consent'
|
||||
@@ -34,7 +33,6 @@ export const CONFIGURE_STEPS: ReadonlyArray<WizardStep> = [
|
||||
'media_expiry',
|
||||
'integration_gif',
|
||||
'integration_youtube',
|
||||
'integration_captcha',
|
||||
'integration_email',
|
||||
'integration_bluesky',
|
||||
'push_relay_consent',
|
||||
|
||||
@@ -915,21 +915,14 @@ export interface MediaExpiryDraft {
|
||||
renewWindowDays: string;
|
||||
}
|
||||
|
||||
export type IntegrationStepKind = 'gif' | 'youtube' | 'captcha' | 'email' | 'bluesky';
|
||||
export type IntegrationStepKind = 'gif' | 'youtube' | 'email' | 'bluesky';
|
||||
export type IntegrationSetupMode = 'later' | 'configure';
|
||||
export type CaptchaProvider = 'hcaptcha' | 'turnstile';
|
||||
|
||||
export interface ServiceIntegrationDraft {
|
||||
gifMode: IntegrationSetupMode;
|
||||
klipyApiKey: string;
|
||||
youtubeMode: IntegrationSetupMode;
|
||||
youtubeApiKey: string;
|
||||
captchaMode: IntegrationSetupMode;
|
||||
captchaProvider: CaptchaProvider;
|
||||
hcaptchaSiteKey: string;
|
||||
hcaptchaSecretKey: string;
|
||||
turnstileSiteKey: string;
|
||||
turnstileSecretKey: string;
|
||||
emailMode: IntegrationSetupMode;
|
||||
emailEnabled: boolean;
|
||||
emailFromEmail: string;
|
||||
@@ -982,14 +975,6 @@ const YOUTUBE_SETUP_BODY_DESCRIPTOR = msg({
|
||||
message: 'Add a YouTube Data API key to enrich YouTube links.',
|
||||
comment: 'Setup wizard body for YouTube integration credentials.',
|
||||
});
|
||||
const CAPTCHA_SETUP_TITLE_DESCRIPTOR = msg({
|
||||
message: 'Bot protection',
|
||||
comment: 'Setup wizard title for CAPTCHA integration credentials.',
|
||||
});
|
||||
const CAPTCHA_SETUP_BODY_DESCRIPTOR = msg({
|
||||
message: 'Choose hCaptcha or Cloudflare Turnstile for signup challenges.',
|
||||
comment: 'Setup wizard body for CAPTCHA integration credentials.',
|
||||
});
|
||||
const EMAIL_SETUP_TITLE_DESCRIPTOR = msg({
|
||||
message: 'Email delivery',
|
||||
comment: 'Setup wizard title for SMTP integration credentials.',
|
||||
@@ -1006,18 +991,7 @@ const BLUESKY_SETUP_BODY_DESCRIPTOR = msg({
|
||||
message: 'Add Bluesky OAuth client metadata and a signing key.',
|
||||
comment: 'Setup wizard body for Bluesky integration credentials.',
|
||||
});
|
||||
const PROVIDER_LABEL_DESCRIPTOR = msg({
|
||||
message: 'Provider',
|
||||
comment: 'Label for an integration provider choice.',
|
||||
});
|
||||
const HCAPTCHA_NAME_DESCRIPTOR = msg({message: 'hCaptcha', comment: 'hCaptcha provider option.'});
|
||||
const TURNSTILE_NAME_DESCRIPTOR = msg({
|
||||
message: 'Cloudflare Turnstile',
|
||||
comment: 'Cloudflare Turnstile provider option.',
|
||||
});
|
||||
const API_KEY_LABEL_DESCRIPTOR = msg({message: 'API key', comment: 'Label for an integration API key input.'});
|
||||
const SITE_KEY_LABEL_DESCRIPTOR = msg({message: 'Site key', comment: 'Label for a CAPTCHA site key input.'});
|
||||
const SECRET_KEY_LABEL_DESCRIPTOR = msg({message: 'Secret key', comment: 'Label for a CAPTCHA secret key input.'});
|
||||
const ENABLE_EMAIL_LABEL_DESCRIPTOR = msg({
|
||||
message: 'Enable email delivery',
|
||||
comment: 'Label for enabling SMTP email delivery in setup.',
|
||||
@@ -1106,8 +1080,6 @@ function getIntegrationMode(draft: ServiceIntegrationDraft, kind: IntegrationSte
|
||||
return draft.gifMode;
|
||||
case 'youtube':
|
||||
return draft.youtubeMode;
|
||||
case 'captcha':
|
||||
return draft.captchaMode;
|
||||
case 'email':
|
||||
return draft.emailMode;
|
||||
case 'bluesky':
|
||||
@@ -1121,8 +1093,6 @@ function getIntegrationCopy(kind: IntegrationStepKind): {title: MessageDescripto
|
||||
return {title: GIF_SETUP_TITLE_DESCRIPTOR, body: GIF_SETUP_BODY_DESCRIPTOR};
|
||||
case 'youtube':
|
||||
return {title: YOUTUBE_SETUP_TITLE_DESCRIPTOR, body: YOUTUBE_SETUP_BODY_DESCRIPTOR};
|
||||
case 'captcha':
|
||||
return {title: CAPTCHA_SETUP_TITLE_DESCRIPTOR, body: CAPTCHA_SETUP_BODY_DESCRIPTOR};
|
||||
case 'email':
|
||||
return {title: EMAIL_SETUP_TITLE_DESCRIPTOR, body: EMAIL_SETUP_BODY_DESCRIPTOR};
|
||||
case 'bluesky':
|
||||
@@ -1302,9 +1272,6 @@ export const IntegrationStep = observer(
|
||||
case 'youtube':
|
||||
onDraftChange({youtubeMode: next});
|
||||
break;
|
||||
case 'captcha':
|
||||
onDraftChange({captchaMode: next});
|
||||
break;
|
||||
case 'email':
|
||||
onDraftChange({emailMode: next});
|
||||
break;
|
||||
@@ -1315,10 +1282,6 @@ export const IntegrationStep = observer(
|
||||
},
|
||||
[kind, onDraftChange],
|
||||
);
|
||||
const captchaOptions: ReadonlyArray<RadioOption<CaptchaProvider>> = [
|
||||
{value: 'hcaptcha', name: i18n._(HCAPTCHA_NAME_DESCRIPTOR), desc: i18n._(CAPTCHA_SETUP_BODY_DESCRIPTOR)},
|
||||
{value: 'turnstile', name: i18n._(TURNSTILE_NAME_DESCRIPTOR), desc: i18n._(CAPTCHA_SETUP_BODY_DESCRIPTOR)},
|
||||
];
|
||||
return (
|
||||
<section className={styles.step} data-flx={`app.self-hosted-setup-wizard-gate.integration-${kind}-step`}>
|
||||
<StepHeader
|
||||
@@ -1354,48 +1317,6 @@ export const IntegrationStep = observer(
|
||||
data-flx="app.setup.setup-wizard-steps.integration-step.input.draft-change--2"
|
||||
/>
|
||||
)}
|
||||
{kind === 'captcha' && (
|
||||
<>
|
||||
<div className={styles.fieldLabel} data-flx="app.setup.setup-wizard-steps.integration-step.field-label">
|
||||
{i18n._(PROVIDER_LABEL_DESCRIPTOR)}
|
||||
</div>
|
||||
<RadioGroup
|
||||
options={captchaOptions}
|
||||
value={draft.captchaProvider}
|
||||
onChange={(value) => onDraftChange({captchaProvider: value})}
|
||||
disabled={disabled}
|
||||
aria-label={i18n._(PROVIDER_LABEL_DESCRIPTOR)}
|
||||
data-flx="app.setup.setup-wizard-steps.integration-step.radio-group.draft-change"
|
||||
/>
|
||||
<Input
|
||||
label={i18n._(SITE_KEY_LABEL_DESCRIPTOR)}
|
||||
value={draft.captchaProvider === 'hcaptcha' ? draft.hcaptchaSiteKey : draft.turnstileSiteKey}
|
||||
onChange={(event) =>
|
||||
onDraftChange(
|
||||
draft.captchaProvider === 'hcaptcha'
|
||||
? {hcaptchaSiteKey: event.target.value}
|
||||
: {turnstileSiteKey: event.target.value},
|
||||
)
|
||||
}
|
||||
disabled={disabled}
|
||||
data-flx="app.setup.setup-wizard-steps.integration-step.input.draft-change--3"
|
||||
/>
|
||||
<Input
|
||||
label={i18n._(SECRET_KEY_LABEL_DESCRIPTOR)}
|
||||
type="password"
|
||||
value={draft.captchaProvider === 'hcaptcha' ? draft.hcaptchaSecretKey : draft.turnstileSecretKey}
|
||||
onChange={(event) =>
|
||||
onDraftChange(
|
||||
draft.captchaProvider === 'hcaptcha'
|
||||
? {hcaptchaSecretKey: event.target.value}
|
||||
: {turnstileSecretKey: event.target.value},
|
||||
)
|
||||
}
|
||||
disabled={disabled}
|
||||
data-flx="app.setup.setup-wizard-steps.integration-step.input.draft-change.password"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{kind === 'email' && (
|
||||
<>
|
||||
<Switch
|
||||
|
||||
@@ -12,7 +12,6 @@ import {Logger} from '@app/features/platform/utils/AppLogger';
|
||||
import {MS_PER_HOUR, MS_PER_MINUTE} from '@fluxer/date_utils/src/DateConstants';
|
||||
import type {
|
||||
InstanceAppPublic,
|
||||
InstanceCaptcha,
|
||||
InstanceCommunity,
|
||||
InstanceDiscoveryResponse,
|
||||
InstanceEndpoints,
|
||||
@@ -34,7 +33,6 @@ export interface InstanceConfig {
|
||||
fetchedAt: number;
|
||||
apiCodeVersion: number;
|
||||
endpoints: InstanceEndpoints;
|
||||
captcha: InstanceCaptcha;
|
||||
features: InstanceFeatures;
|
||||
registration: InstanceRegistration;
|
||||
community: InstanceCommunity;
|
||||
@@ -145,7 +143,6 @@ class InstanceConfigs {
|
||||
fetchedAt: Date.now(),
|
||||
apiCodeVersion: data.api_code_version,
|
||||
endpoints: data.endpoints,
|
||||
captcha: data.captcha,
|
||||
features: data.features,
|
||||
gif: {
|
||||
provider: gifProviderInfo.name,
|
||||
@@ -208,11 +205,6 @@ class InstanceConfigs {
|
||||
gift: RuntimeConfig.giftEndpoint,
|
||||
webapp: RuntimeConfig.webAppEndpoint,
|
||||
},
|
||||
captcha: {
|
||||
provider: RuntimeConfig.captchaProvider,
|
||||
hcaptcha_site_key: RuntimeConfig.hcaptchaSiteKey,
|
||||
turnstile_site_key: RuntimeConfig.turnstileSiteKey,
|
||||
},
|
||||
features: RuntimeConfig.features,
|
||||
gif: {
|
||||
provider: RuntimeConfig.gifProvider,
|
||||
|
||||
@@ -12,7 +12,6 @@ import {http} from '@app/features/platform/transport/RestTransport';
|
||||
import {API_CODE_VERSION} from '@fluxer/constants/src/AppConstants';
|
||||
import type {
|
||||
InstanceAppPublic,
|
||||
InstanceCaptcha,
|
||||
InstanceCommunity,
|
||||
InstanceDiscoveryResponse,
|
||||
InstanceFeatures,
|
||||
@@ -28,7 +27,6 @@ import {makeAutoObservable, reaction, runInAction} from 'mobx';
|
||||
export type {
|
||||
GifProvider,
|
||||
GifProviderInfo,
|
||||
InstanceCaptcha,
|
||||
InstanceCommunity,
|
||||
InstanceDiscoveryResponse,
|
||||
InstanceFeatures,
|
||||
@@ -51,9 +49,6 @@ export interface RuntimeConfigSnapshot {
|
||||
gifProvider: GifProvider;
|
||||
gifProviderDisplayName: string;
|
||||
gifAttributionRequired: boolean;
|
||||
captchaProvider: 'hcaptcha' | 'turnstile' | 'none';
|
||||
hcaptchaSiteKey: string | null;
|
||||
turnstileSiteKey: string | null;
|
||||
apiCodeVersion: number;
|
||||
features: InstanceFeatures;
|
||||
sso: InstanceSsoConfig | null;
|
||||
@@ -295,9 +290,6 @@ class RuntimeConfig {
|
||||
gifProvider: GifProvider = DEFAULT_GIF_PROVIDER_INFO.name;
|
||||
gifProviderDisplayName: string = DEFAULT_GIF_PROVIDER_INFO.displayName;
|
||||
gifAttributionRequired: boolean = DEFAULT_GIF_PROVIDER_INFO.attributionRequired;
|
||||
captchaProvider: 'hcaptcha' | 'turnstile' | 'none' = 'none';
|
||||
hcaptchaSiteKey: string | null = null;
|
||||
turnstileSiteKey: string | null = null;
|
||||
apiCodeVersion: number = API_CODE_VERSION;
|
||||
features: InstanceFeatures = {...DEFAULT_INSTANCE_FEATURES};
|
||||
sso: InstanceSsoConfig | null = null;
|
||||
@@ -342,9 +334,6 @@ class RuntimeConfig {
|
||||
gifProvider: this.gifProvider,
|
||||
gifProviderDisplayName: this.gifProviderDisplayName,
|
||||
gifAttributionRequired: this.gifAttributionRequired,
|
||||
captchaProvider: this.captchaProvider,
|
||||
hcaptchaSiteKey: this.hcaptchaSiteKey,
|
||||
turnstileSiteKey: this.turnstileSiteKey,
|
||||
apiCodeVersion: this.apiCodeVersion,
|
||||
features: {...this.features},
|
||||
sso: this.sso ? {...this.sso} : null,
|
||||
@@ -448,9 +437,6 @@ class RuntimeConfig {
|
||||
this.gifProvider = gifProviderInfo.name;
|
||||
this.gifProviderDisplayName = gifProviderInfo.displayName;
|
||||
this.gifAttributionRequired = gifProviderInfo.attributionRequired;
|
||||
this.captchaProvider = instance.captcha.provider;
|
||||
this.hcaptchaSiteKey = instance.captcha.hcaptcha_site_key;
|
||||
this.turnstileSiteKey = instance.captcha.turnstile_site_key;
|
||||
this.apiCodeVersion = instance.api_code_version;
|
||||
this.features = {
|
||||
...DEFAULT_INSTANCE_FEATURES,
|
||||
|
||||
Reference in new issue
Block a user