mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +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
@@ -34,9 +34,10 @@ import {
|
||||
type RegistrationUrlResponse,
|
||||
} from '@fluxer/schema/src/domains/admin/AdminSchemas';
|
||||
import {
|
||||
type AltchaCaptchaConfig,
|
||||
AltchaCaptchaConfigSchema,
|
||||
} from '@fluxer/schema/src/domains/admin/AltchaCaptchaSchemas';
|
||||
type CaptchaConfig,
|
||||
CaptchaConfigSchema,
|
||||
type CaptchaConfigUpdateRequest,
|
||||
} from '@fluxer/schema/src/domains/admin/CaptchaSchemas';
|
||||
import {
|
||||
type DomainMigrationConfig,
|
||||
DomainMigrationConfigSchema,
|
||||
@@ -64,8 +65,6 @@ import {
|
||||
type InstanceAppPublic,
|
||||
InstanceAppPublicSchema,
|
||||
type InstanceBranding,
|
||||
type InstanceCaptchaProvider,
|
||||
InstanceCaptchaProviderSchema,
|
||||
type InstanceCommunity,
|
||||
type InstanceRegistration,
|
||||
InstanceRegistrationSchema,
|
||||
@@ -79,7 +78,7 @@ import {z} from 'zod';
|
||||
const GATEWAY_ROLLOUT_CONFIG_KEY = 'gateway_rollout_config';
|
||||
const PUSH_RELAY_CONFIG_KEY = 'push_service_delivery_config';
|
||||
const DOMAIN_MIGRATION_CONFIG_KEY = 'domain_migration_config';
|
||||
const ALTCHA_CAPTCHA_CONFIG_KEY = 'altcha_captcha_config';
|
||||
const CAPTCHA_CONFIG_KEY = 'captcha_config';
|
||||
const EXPERIMENT_DELIVERY_CONFIG_KEY = 'experiment_delivery_config';
|
||||
const REGISTRATION_CONFIG_KEY = 'registration_config';
|
||||
const REGISTRATION_URLS_KEY = 'registration_urls';
|
||||
@@ -189,14 +188,6 @@ interface InstanceYoutubeIntegrationConfig {
|
||||
api_key: string | null;
|
||||
}
|
||||
|
||||
interface InstanceCaptchaIntegrationConfig {
|
||||
provider: InstanceCaptchaProvider | null;
|
||||
hcaptcha_site_key: string | null;
|
||||
hcaptcha_secret_key: string | null;
|
||||
turnstile_site_key: string | null;
|
||||
turnstile_secret_key: string | null;
|
||||
}
|
||||
|
||||
interface InstanceEmailSmtpIntegrationConfig {
|
||||
host: string | null;
|
||||
port: number | null;
|
||||
@@ -232,7 +223,6 @@ interface InstanceBlueskyIntegrationConfig {
|
||||
interface InstanceIntegrationsConfig {
|
||||
gif: InstanceGifIntegrationConfig;
|
||||
youtube: InstanceYoutubeIntegrationConfig;
|
||||
captcha: InstanceCaptchaIntegrationConfig;
|
||||
email: InstanceEmailIntegrationConfig;
|
||||
bluesky: InstanceBlueskyIntegrationConfig;
|
||||
}
|
||||
@@ -243,15 +233,6 @@ interface InstanceGifEffectiveConfig {
|
||||
available: boolean;
|
||||
}
|
||||
|
||||
export interface InstanceCaptchaEffectiveConfig {
|
||||
enabled: boolean;
|
||||
provider: InstanceCaptchaProvider;
|
||||
hcaptcha_site_key: string | null;
|
||||
hcaptcha_secret_key: string | null;
|
||||
turnstile_site_key: string | null;
|
||||
turnstile_secret_key: string | null;
|
||||
}
|
||||
|
||||
interface InstanceIntegrationsAdminConfig {
|
||||
gif: {
|
||||
klipy_api_key_set: boolean;
|
||||
@@ -261,15 +242,6 @@ interface InstanceIntegrationsAdminConfig {
|
||||
api_key_set: boolean;
|
||||
effective_available: boolean;
|
||||
};
|
||||
captcha: {
|
||||
provider: InstanceCaptchaProvider | null;
|
||||
effective_provider: InstanceCaptchaProvider;
|
||||
hcaptcha_site_key: string | null;
|
||||
hcaptcha_secret_key_set: boolean;
|
||||
turnstile_site_key: string | null;
|
||||
turnstile_secret_key_set: boolean;
|
||||
effective_enabled: boolean;
|
||||
};
|
||||
email: {
|
||||
enabled: boolean | null;
|
||||
effective_enabled: boolean;
|
||||
@@ -336,7 +308,6 @@ interface InstanceMediaAdminConfig {
|
||||
interface InstanceIntegrationsConfigPatch {
|
||||
gif?: Partial<InstanceGifIntegrationConfig>;
|
||||
youtube?: Partial<InstanceYoutubeIntegrationConfig>;
|
||||
captcha?: Partial<InstanceCaptchaIntegrationConfig>;
|
||||
email?: Partial<Omit<InstanceEmailIntegrationConfig, 'smtp'>> & {
|
||||
smtp?: Partial<InstanceEmailSmtpIntegrationConfig>;
|
||||
};
|
||||
@@ -435,7 +406,7 @@ type StoredConfigSection =
|
||||
| 'gateway rollout'
|
||||
| 'push relay'
|
||||
| 'domain migration'
|
||||
| 'altcha captcha'
|
||||
| 'captcha'
|
||||
| 'experiment delivery'
|
||||
| 'instance policy'
|
||||
| 'integrations'
|
||||
@@ -596,8 +567,8 @@ function parseStoredDomainMigrationConfig(raw: string | null): DomainMigrationCo
|
||||
return parseStoredConfigOrDefault(DomainMigrationConfigSchema, raw, 'domain migration');
|
||||
}
|
||||
|
||||
function parseStoredAltchaCaptchaConfig(raw: string | null): AltchaCaptchaConfig {
|
||||
return parseStoredConfigOrDefault(AltchaCaptchaConfigSchema, raw, 'altcha captcha');
|
||||
function parseStoredCaptchaConfig(raw: string | null): CaptchaConfig {
|
||||
return parseStoredConfigOrDefault(CaptchaConfigSchema, raw, 'captcha');
|
||||
}
|
||||
|
||||
function parseStoredExperimentDeliveryConfig(raw: string | null): ExperimentDeliveryConfig {
|
||||
@@ -718,15 +689,6 @@ const StoredBlueskyKeysSchema = z
|
||||
const StoredInstanceIntegrationsSchema = z.object({
|
||||
gif: z.object({klipy_api_key: StoredIntegrationStringSchema}).prefault({}),
|
||||
youtube: z.object({api_key: StoredIntegrationStringSchema}).prefault({}),
|
||||
captcha: z
|
||||
.object({
|
||||
provider: InstanceCaptchaProviderSchema.nullable().default(null),
|
||||
hcaptcha_site_key: StoredIntegrationStringSchema,
|
||||
hcaptcha_secret_key: StoredIntegrationStringSchema,
|
||||
turnstile_site_key: StoredIntegrationStringSchema,
|
||||
turnstile_secret_key: StoredIntegrationStringSchema,
|
||||
})
|
||||
.prefault({}),
|
||||
email: z
|
||||
.object({
|
||||
enabled: StoredNullableBooleanSchema,
|
||||
@@ -1270,7 +1232,7 @@ export class InstanceConfigRepository {
|
||||
);
|
||||
parseStoredPushRelayConfig(snapshot.get(PUSH_RELAY_CONFIG_KEY) ?? null);
|
||||
parseStoredDomainMigrationConfig(snapshot.get(DOMAIN_MIGRATION_CONFIG_KEY) ?? null);
|
||||
parseStoredAltchaCaptchaConfig(snapshot.get(ALTCHA_CAPTCHA_CONFIG_KEY) ?? null);
|
||||
parseStoredCaptchaConfig(snapshot.get(CAPTCHA_CONFIG_KEY) ?? null);
|
||||
parseStoredExperimentDeliveryConfig(snapshot.get(EXPERIMENT_DELIVERY_CONFIG_KEY) ?? null);
|
||||
parseStoredInstancePolicyConfig(snapshot.get(INSTANCE_POLICY_CONFIG_KEY) ?? null);
|
||||
checkStoredConfig('registration', () =>
|
||||
@@ -1384,20 +1346,14 @@ export class InstanceConfigRepository {
|
||||
);
|
||||
}
|
||||
|
||||
async getAltchaCaptchaConfig(): Promise<AltchaCaptchaConfig> {
|
||||
const raw = await this.getConfig(ALTCHA_CAPTCHA_CONFIG_KEY);
|
||||
return parseStoredAltchaCaptchaConfig(raw);
|
||||
async getCaptchaConfig(): Promise<CaptchaConfig> {
|
||||
const raw = await this.getConfig(CAPTCHA_CONFIG_KEY);
|
||||
return parseStoredCaptchaConfig(raw);
|
||||
}
|
||||
|
||||
async setAltchaCaptchaConfig(config: AltchaCaptchaConfig): Promise<void> {
|
||||
await this.updateAltchaCaptchaConfig(() => config);
|
||||
}
|
||||
|
||||
updateAltchaCaptchaConfig(
|
||||
update: (current: AltchaCaptchaConfig) => AltchaCaptchaConfig,
|
||||
): Promise<AltchaCaptchaConfig> {
|
||||
return this.updateStoredConfig(ALTCHA_CAPTCHA_CONFIG_KEY, (raw) =>
|
||||
validateStoredConfig(AltchaCaptchaConfigSchema, update(parseStoredAltchaCaptchaConfig(raw)), 'altcha captcha'),
|
||||
updateCaptchaConfig(patch: CaptchaConfigUpdateRequest): Promise<CaptchaConfig> {
|
||||
return this.updateStoredConfig(CAPTCHA_CONFIG_KEY, (raw) =>
|
||||
validateStoredConfig(CaptchaConfigSchema, {...parseStoredCaptchaConfig(raw), ...patch}, 'captcha'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1545,10 +1501,6 @@ export class InstanceConfigRepository {
|
||||
...current.youtube,
|
||||
...(config.youtube ?? {}),
|
||||
},
|
||||
captcha: {
|
||||
...current.captcha,
|
||||
...(config.captcha ?? {}),
|
||||
},
|
||||
email: {
|
||||
...current.email,
|
||||
...(config.email ?? {}),
|
||||
@@ -1642,33 +1594,6 @@ export class InstanceConfigRepository {
|
||||
return integrations.youtube.api_key ?? normalizeOptionalString(Config.youtube.apiKey);
|
||||
}
|
||||
|
||||
async getEffectiveCaptchaConfig(): Promise<InstanceCaptchaEffectiveConfig> {
|
||||
const integrations = await this.getInstanceIntegrationsConfig();
|
||||
const provider = integrations.captcha.provider ?? (Config.captcha.enabled ? Config.captcha.provider : 'none');
|
||||
const hcaptchaSiteKey =
|
||||
integrations.captcha.hcaptcha_site_key ?? normalizeOptionalString(Config.captcha.hcaptcha?.siteKey);
|
||||
const hcaptchaSecretKey =
|
||||
integrations.captcha.hcaptcha_secret_key ?? normalizeOptionalString(Config.captcha.hcaptcha?.secretKey);
|
||||
const turnstileSiteKey =
|
||||
integrations.captcha.turnstile_site_key ?? normalizeOptionalString(Config.captcha.turnstile?.siteKey);
|
||||
const turnstileSecretKey =
|
||||
integrations.captcha.turnstile_secret_key ?? normalizeOptionalString(Config.captcha.turnstile?.secretKey);
|
||||
const providerReady =
|
||||
provider === 'hcaptcha'
|
||||
? Boolean(hcaptchaSiteKey && hcaptchaSecretKey)
|
||||
: provider === 'turnstile'
|
||||
? Boolean(turnstileSiteKey && turnstileSecretKey)
|
||||
: false;
|
||||
return {
|
||||
enabled: providerReady,
|
||||
provider: providerReady ? provider : 'none',
|
||||
hcaptcha_site_key: hcaptchaSiteKey,
|
||||
hcaptcha_secret_key: hcaptchaSecretKey,
|
||||
turnstile_site_key: turnstileSiteKey,
|
||||
turnstile_secret_key: turnstileSecretKey,
|
||||
};
|
||||
}
|
||||
|
||||
async getEffectiveEmailConfig(): Promise<APIConfig['email']> {
|
||||
const integrations = await this.getInstanceIntegrationsConfig();
|
||||
const provider = integrations.email.provider ?? Config.email.provider;
|
||||
@@ -1731,11 +1656,10 @@ export class InstanceConfigRepository {
|
||||
}
|
||||
|
||||
async getInstanceIntegrationsAdminConfig(): Promise<InstanceIntegrationsAdminConfig> {
|
||||
const [integrations, gif, youtubeApiKey, captcha, email, bluesky] = await Promise.all([
|
||||
const [integrations, gif, youtubeApiKey, email, bluesky] = await Promise.all([
|
||||
this.getInstanceIntegrationsConfig(),
|
||||
this.getEffectiveGifConfig(),
|
||||
this.getEffectiveYoutubeApiKey(),
|
||||
this.getEffectiveCaptchaConfig(),
|
||||
this.getEffectiveEmailConfig(),
|
||||
this.getEffectiveBlueskyConfig(),
|
||||
]);
|
||||
@@ -1748,17 +1672,6 @@ export class InstanceConfigRepository {
|
||||
api_key_set: secretIsSet(integrations.youtube.api_key) || secretIsSet(Config.youtube.apiKey),
|
||||
effective_available: Boolean(youtubeApiKey),
|
||||
},
|
||||
captcha: {
|
||||
provider: integrations.captcha.provider,
|
||||
effective_provider: captcha.provider,
|
||||
hcaptcha_site_key: captcha.hcaptcha_site_key,
|
||||
hcaptcha_secret_key_set:
|
||||
secretIsSet(integrations.captcha.hcaptcha_secret_key) || secretIsSet(Config.captcha.hcaptcha?.secretKey),
|
||||
turnstile_site_key: captcha.turnstile_site_key,
|
||||
turnstile_secret_key_set:
|
||||
secretIsSet(integrations.captcha.turnstile_secret_key) || secretIsSet(Config.captcha.turnstile?.secretKey),
|
||||
effective_enabled: captcha.enabled,
|
||||
},
|
||||
email: {
|
||||
enabled: integrations.email.enabled,
|
||||
effective_enabled: email.enabled,
|
||||
|
||||
Reference in new issue
Block a user