feat(identity): align auth flow with reference theme
This commit is contained in:
1 parent
5a17b399a0
commit
59901b9e10
34 files changed
+753
-3871
No files matched your search
@@ -1,106 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Identity provider configuration for the admin REST surface.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
namespace AKSRT\Settings;
|
||||
|
||||
use AKSRT\Identity\Provider\ProviderFactory;
|
||||
use AKSRT\Identity\SecretStore;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
final class IdentityAdmin {
|
||||
|
||||
private const PROVIDER_FIELDS = [
|
||||
'aliyun' => ['access_key_id', 'access_key_secret'],
|
||||
'tencent' => ['secret_id', 'secret_key'],
|
||||
];
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
public static function read(): array {
|
||||
$stored = Settings::get_all();
|
||||
$provider = sanitize_key((string) ($stored['user_verify_provider'] ?? 'aliyun'));
|
||||
if (!isset(self::PROVIDER_FIELDS[$provider])) {
|
||||
$provider = 'aliyun';
|
||||
}
|
||||
return [
|
||||
'provider' => $provider,
|
||||
'providers' => [
|
||||
'aliyun' => self::provider_state('aliyun'),
|
||||
'tencent' => self::provider_state('tencent'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $input @return array<string,mixed> */
|
||||
public static function update(array $input): array {
|
||||
if (array_key_exists('provider', $input)) {
|
||||
$provider = sanitize_key((string) $input['provider']);
|
||||
if (isset(self::PROVIDER_FIELDS[$provider])) {
|
||||
Settings::write_domain('users', 'verify', ['user_verify_provider' => $provider]);
|
||||
}
|
||||
}
|
||||
|
||||
$providers = isset($input['providers']) && is_array($input['providers']) ? $input['providers'] : [];
|
||||
foreach (self::PROVIDER_FIELDS as $provider => $fields) {
|
||||
$changes = isset($providers[$provider]) && is_array($providers[$provider]) ? $providers[$provider] : [];
|
||||
$updates = [];
|
||||
if (!empty($changes['clear_credentials'])) {
|
||||
foreach ($fields as $field) {
|
||||
$updates[$field] = null;
|
||||
}
|
||||
} else {
|
||||
$credentials = isset($changes['credentials']) && is_array($changes['credentials']) ? $changes['credentials'] : [];
|
||||
foreach ($fields as $field) {
|
||||
$value = trim((string) ($credentials[$field] ?? ''));
|
||||
if ($value !== '') {
|
||||
$updates[$field] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($updates !== []) {
|
||||
SecretStore::update($provider, $updates);
|
||||
}
|
||||
}
|
||||
return self::read();
|
||||
}
|
||||
|
||||
/** @return array{success:bool,message:string} */
|
||||
public static function test(string $provider): array {
|
||||
if (!isset(self::PROVIDER_FIELDS[$provider])) {
|
||||
return ['success' => false, 'message' => __('不支持的身份认证服务商', 'aksrt')];
|
||||
}
|
||||
$valid = ProviderFactory::make($provider)->validate_config();
|
||||
if (is_wp_error($valid)) {
|
||||
return ['success' => false, 'message' => $valid->get_error_message()];
|
||||
}
|
||||
return ['success' => true, 'message' => sprintf(__('%s配置检查通过', 'aksrt'), self::label($provider))];
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
private static function provider_state(string $provider): array {
|
||||
$secrets = SecretStore::get($provider);
|
||||
$configured_fields = [];
|
||||
$missing = [];
|
||||
foreach (self::PROVIDER_FIELDS[$provider] as $field) {
|
||||
$configured = !empty($secrets[$field]);
|
||||
$configured_fields[$field] = $configured;
|
||||
if (!$configured) {
|
||||
$missing[] = $field;
|
||||
}
|
||||
}
|
||||
return [
|
||||
'label' => self::label($provider),
|
||||
'configured' => $missing === [],
|
||||
'configured_fields' => $configured_fields,
|
||||
'missing_fields' => $missing,
|
||||
];
|
||||
}
|
||||
|
||||
private static function label(string $provider): string {
|
||||
return $provider === 'aliyun' ? __('阿里云', 'aksrt') : __('腾讯云', 'aksrt');
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,6 @@ final class MailNotifications {
|
||||
add_action('aksrt_notification_sent', [self::class, 'notification'], 20, 3);
|
||||
add_action('aksrt_withdrawal_submitted', [self::class, 'withdrawal_submitted'], 20, 2);
|
||||
add_action('aksrt_withdrawal_status_changed', [self::class, 'withdrawal_status'], 20, 4);
|
||||
add_action('aksrt_user_auth_submitted', [self::class, 'auth_submitted'], 20, 2);
|
||||
add_action('aksrt_user_auth_reviewed', [self::class, 'auth_reviewed'], 20, 4);
|
||||
add_action('aksrt_ban_appeal_submitted', [self::class, 'ban_appeal_submitted'], 20, 2);
|
||||
add_action('aksrt_ban_appeal_processed', [self::class, 'ban_appeal_processed'], 20, 3);
|
||||
add_action('aksrt_new_posts_pending', [self::class, 'post_pending'], 20, 1);
|
||||
|
||||
@@ -42,7 +42,6 @@ class Settings {
|
||||
'aksrt_notification_settings',
|
||||
'aksrt_friend_links',
|
||||
'aksrt_category_recommend',
|
||||
'aksrt_identity_secrets',
|
||||
];
|
||||
|
||||
public const SCHEMA_MANAGED_STANDALONE_OPTION_KEYS = [
|
||||
@@ -54,7 +53,6 @@ class Settings {
|
||||
*/
|
||||
public const SECRET_OPTION_KEYS = [
|
||||
'aksrt_captcha_config',
|
||||
'aksrt_identity_secrets',
|
||||
];
|
||||
|
||||
private function __construct() {}
|
||||
@@ -573,7 +571,7 @@ class Settings {
|
||||
* User identity, level, badge, and report governance settings.
|
||||
*
|
||||
* @return array{
|
||||
* verify:array{enabled:bool,public_display:bool,badge_text:string,accept_email_verified:bool,require_manual_review:bool},
|
||||
* verify:array{enabled:bool,public_display:bool,allow_apply:bool,disable_desc:string,desc:string,minimum_level:int},
|
||||
* level:array{enabled:bool,public_display:bool,source:string,label_prefix:string,thresholds:array<int,int>},
|
||||
* badge:array{enabled:bool,public_display:bool,limit:int,dictionary:array<int,array{slug:string,label:string,tone:string}>},
|
||||
* report:array{enabled:bool,public_entry:bool,categories:array<int,array{slug:string,label:string}>}
|
||||
@@ -583,26 +581,6 @@ class Settings {
|
||||
return UserRuntime::get_user_identity_settings();
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
public static function get_identity_verification_settings(): array {
|
||||
return \AKSRT\Identity\SettingsRuntime::get();
|
||||
}
|
||||
|
||||
/** @return array<string,string> */
|
||||
public static function get_identity_provider_secrets(string $provider): array {
|
||||
return \AKSRT\Identity\SecretStore::get($provider);
|
||||
}
|
||||
|
||||
/** @param array<string,string|null> $changes */
|
||||
public static function update_identity_provider_secrets(string $provider, array $changes): bool {
|
||||
return \AKSRT\Identity\SecretStore::update($provider, $changes);
|
||||
}
|
||||
|
||||
/** @return array<string,array{configured:bool,fingerprint:string}> */
|
||||
public static function get_identity_provider_secret_status(string $provider): array {
|
||||
return \AKSRT\Identity\SecretStore::status($provider);
|
||||
}
|
||||
|
||||
public static function standalone_export_keys(): array {
|
||||
return array_values(array_diff(self::STANDALONE_OPTION_KEYS, self::SCHEMA_MANAGED_STANDALONE_OPTION_KEYS, self::SECRET_OPTION_KEYS));
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ class UserRuntime {
|
||||
* User identity, level, medal, and report governance settings.
|
||||
*
|
||||
* @return array{
|
||||
* verify:array{enabled:bool,public_display:bool,allow_apply:bool,disable_desc:string,desc:string,types:array<string,array{slug:string,label:string,badge_text:string,fee:string,free_applications:int,require_real_name:bool}>},
|
||||
* verify:array{enabled:bool,public_display:bool,allow_apply:bool,disable_desc:string,desc:string,minimum_level:int},
|
||||
* level:array{enabled:bool,public_display:bool,source:string,label_prefix:string,thresholds:array<int,int>},
|
||||
* medal:array{enabled:bool,public_display:bool,limit:int,categories:array<int,array{cat_name:string,items:array<int,array{slug:string,name:string,desc:string,icon:string,get_type:string,get_val:int}>}>,items_by_slug:array<string,array{slug:string,name:string,desc:string,icon:string,get_type:string,get_val:int,cat_name:string}>},
|
||||
* badge:array{enabled:bool,public_display:bool,limit:int,dictionary:array<int,array{slug:string,label:string,tone:string,desc:string,icon_url?:string}>},
|
||||
@@ -114,41 +114,16 @@ class UserRuntime {
|
||||
*/
|
||||
public static function get_user_identity_settings(): array {
|
||||
$settings = Settings::get_all();
|
||||
$verify_types = [
|
||||
'personal' => [
|
||||
'slug' => 'personal',
|
||||
'label' => __('个人认证', 'aksrt'),
|
||||
'badge_text' => trim((string) ($settings['user_verify_personal_badge_text'] ?? '')) ?: __('个人认证', 'aksrt'),
|
||||
'fee' => self::identity_fee_setting($settings, 'user_verify_personal_fee'),
|
||||
'free_applications' => max(0, (int) ($settings['user_verify_personal_free_applications'] ?? 0)),
|
||||
'require_real_name' => true,
|
||||
],
|
||||
'enterprise' => [
|
||||
'slug' => 'enterprise',
|
||||
'label' => __('企业认证', 'aksrt'),
|
||||
'badge_text' => trim((string) ($settings['user_verify_enterprise_badge_text'] ?? '')) ?: __('企业认证', 'aksrt'),
|
||||
'fee' => self::identity_fee_setting($settings, 'user_verify_enterprise_fee'),
|
||||
'free_applications' => max(0, (int) ($settings['user_verify_enterprise_free_applications'] ?? 0)),
|
||||
'require_real_name' => true,
|
||||
],
|
||||
];
|
||||
$medal = self::parse_medal_catalog($settings);
|
||||
$provider = sanitize_key((string) ($settings['user_verify_provider'] ?? 'aliyun'));
|
||||
if (!in_array($provider, ['aliyun', 'tencent'], true)) {
|
||||
$provider = 'aliyun';
|
||||
}
|
||||
|
||||
return [
|
||||
'verify' => [
|
||||
'enabled' => !isset($settings['user_verify_enabled']) || !empty($settings['user_verify_enabled']),
|
||||
'public_display' => !isset($settings['user_verify_public_display']) || !empty($settings['user_verify_public_display']),
|
||||
'allow_apply' => !isset($settings['user_verify_allow_apply']) || !empty($settings['user_verify_allow_apply']),
|
||||
'disable_desc' => (string) ($settings['user_verify_disable_desc'] ?? ''),
|
||||
'desc' => (string) ($settings['user_verify_desc'] ?? ''),
|
||||
'provider' => $provider,
|
||||
'allow_manual_fallback' => !isset($settings['user_verify_allow_manual_fallback']) || !empty($settings['user_verify_allow_manual_fallback']),
|
||||
'poll_interval_seconds' => max(3, min(60, (int) ($settings['user_verify_poll_interval_seconds'] ?? 5))),
|
||||
'types' => $verify_types,
|
||||
'enabled' => !isset($settings['user_auth_s']) || !empty($settings['user_auth_s']),
|
||||
'public_display' => !isset($settings['user_auth_s']) || !empty($settings['user_auth_s']),
|
||||
'allow_apply' => !isset($settings['user_auth_apply_s']) || !empty($settings['user_auth_apply_s']),
|
||||
'disable_desc' => (string) ($settings['user_auth_apply_disable_desc'] ?? ''),
|
||||
'desc' => (string) ($settings['user_auth_apply_desc'] ?? ''),
|
||||
'minimum_level' => max(0, min(30, (int) ($settings['user_auth_apply_limit_level'] ?? 0))),
|
||||
],
|
||||
'level' => [
|
||||
'enabled' => !isset($settings['user_level_s']) || !empty($settings['user_level_s']),
|
||||
@@ -179,19 +154,6 @@ class UserRuntime {
|
||||
];
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $settings */
|
||||
private static function identity_fee_setting(array $settings, string $key): string {
|
||||
$value = array_key_exists($key, $settings) ? $settings[$key] : '0.00';
|
||||
if (!is_string($value)) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
return \AKSRT\Ledger\AssetAmount::balance(trim($value))->decimal();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁封/举报分区的运行时读取。
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user