feat(security): 新增网站安全扩展模块并支持修改手机脱敏验证

This commit is contained in:
2026-10-06 09:26:55 +08:00
parent 224f86ec08
commit af72364078
30 changed files with 1389 additions and 73 deletions
@@ -25,10 +25,21 @@ test('account dialogs expose configured email steps, phone steps, and reference
assert.match(template, /data-aksrt-sms-scene="bind_new_phone"/);
assert.match(template, /\$account_close_icon = function_exists\('aksrt_icon_markup'\)/);
assert.match(template, /<i class="fa far fa-envelope"/);
assert.match(template, /\$account_phone_display = strlen\(\$account_phone\) > 10 \? substr_replace\(\$account_phone, '\*\*\*\*', 3, 4\)/);
assert.match(template, /\$account_phone_display = function_exists\('aksrt_phone_mask_display'\) \? aksrt_phone_mask_display\(\$account_phone\) : \$account_phone;/);
assert.match(template, /\$account_phone !== '' \? \$account_phone_display : __\('暂未绑定'/);
assert.match(template, /<span class="badg">' \. esc_html\(\$account_phone_display\)/);
assert.match(template, /name="phone" value="<\?php echo esc_attr\(\$account_phone\); \?>"/);
assert.doesNotMatch(template, /name="phone" value="/);
assert.match(template, /data-aksrt-phone-digits data-hidden-length/);
assert.match(template, /class="aksrt-phone-digit" inputmode="numeric" maxlength="1"/);
assert.match(template, /aria-label="<\?php echo esc_attr\(sprintf\(__\('手机号第 %d 位数字', 'aksrt'\), 4 \+ \$phone_digit_index\)\); \?>"/);
assert.match(template, /data-aksrt-phone-code-area<\?php echo \$phone_mask !== null \? ' hidden' : ''; \?>/);
assert.match(template, /data-aksrt-phone-digits-error/);
assert.match(javascript, /\/user\/phone-match/);
assert.match(javascript, /middle: middle/);
assert.match(javascript, /stage: 'reset_old_phone'/);
assert.match(javascript, /function initPhoneDigits\(/);
assert.match(css, /\.aksrt-settings-modal \.aksrt-phone-digit \{/);
assert.match(css, /\.aksrt-settings-modal \.aksrt-phone-digits\.has-error \.aksrt-phone-digit \{/);
assert.match(template, /aksrt_render_captcha\('change_email'\)[\s\S]*?id="email-code"/);
assert.match(template, /aksrt_render_captcha\('bind_phone'\)[\s\S]*?id="bind-phone-code"/);
assert.match(template, /if \(!\$account_oauth_new\)[\s\S]*?name="passwordold"/);
@@ -73,6 +84,10 @@ test('email update keeps both proofs through validation failures and consumes th
assert.match(send, /\['verify_email', 'change_email'\]/);
assert.match(send, /email_exists\(\$target\)/);
assert.match(send, /SendLimit::check\(\$target\)/);
assert.match(send, /SendLimit::record\(\$target\)/);
assert.doesNotMatch(send, /aksrt_account_email_rate_/);
assert.doesNotMatch(ajax, /aksrt_account_email_rate_/);
assert.match(verify, /aksrt_require_captcha\(\s*'change_email'/);
assert.match(verify, /aksrt_account_set_proof\(\$user_id, 'email_old'/);
assert.match(change, /aksrt_account_email_verification_required\(\)/);
@@ -93,8 +108,15 @@ test('phone replacement requires old-number proof and a new-number code while re
const bind = controller.slice(controller.indexOf('public function user_bind_phone('), controller.indexOf('public function test_sms_send('));
assert.match(routes, /\/user\/phone-verify[\s\S]*?user_verify_phone/);
assert.match(routes, /\/user\/phone-match[\s\S]*?user_phone_match/);
assert.match(code, /verify_old_phone/);
assert.match(code, /bind_new_phone/);
assert.match(code, /public function user_phone_match\(/);
assert.match(code, /auth_middle_matches\(\$parts, \$middle\)/);
assert.match(code, /reset_old_phone/);
assert.match(code, /填写的号码与绑定手机号不一致/);
assert.match(code, /\$phone = \$current_phone;/);
assert.doesNotMatch(code, /auth_rate_limited\('account-phone-code'/);
assert.match(verify, /auth_consume_code\('account_verify_old_phone_' \./);
assert.match(verify, /aksrt_account_phone_old_/);
assert.match(bind, /aksrt_account_phone_old_/);
@@ -113,7 +135,11 @@ test('password change retains old-password limits and captcha; recovery uses sha
assert.match(password, /get_user_meta\(\$user_id, 'oauth_new', true\)/);
assert.match(password, /wp_check_password\(\$old/);
assert.match(password, /aksrt_account_rate_limited\(\$user_id, 'change_password'\)/);
assert.match(password, /SecurityHardening::error_frequency_wait\(\)/);
assert.match(password, /SecurityHardening::error_frequency_record\(\)/);
assert.doesNotMatch(password, /aksrt_account_rate_limited/);
assert.doesNotMatch(ajax, /function aksrt_account_rate_limited/);
assert.doesNotMatch(ajax, /function aksrt_account_reset_rate/);
assert.match(password, /aksrt_require_captcha\('change_password'/);
assert.match(password, /Auth\\Service::validate_password\(\$password, \$password2\)/);
assert.doesNotMatch(password, /email.*code|password.*strength/i);