Full-project rename. `git grep -i aksrt` is now empty apart from the
DBMigrator 3.3.0 changelog note that documents the rename itself.
Code identifiers
- PHP namespace AKSRT\ -> Jio\ (composer PSR-4 + 378 declarations)
- global constants AKSRT_* -> JIO_* (VERSION/DIR/URI, PAY_TYPE_*, CAPTCHA_*)
- procedural functions, hooks, options, meta keys, table names,
cookies, query vars, ajax actions and nonces: aksrt_ -> jio_
- text domain aksrt -> jio; Theme Name -> Jio
- JS globals: aksrtData/aksrtAdminData/... -> jioData/jioAdminData/...,
window.AKSRTCaptcha & friends -> window.JioCaptcha, Aksrt* -> Jio*
- Vue components Aks*.vue -> Jio*.vue (15 files renamed + imports)
- CSS classes/data-attrs/custom properties: aksrt- -> jio-
- REST namespace aksrt/v1 -> jio/v1 (incl. payment gateway callbacks)
Storage layer
- DB tables {prefix}aksrt_* -> {prefix}jio_*; SCHEMA_VERSION 3.2.0 -> 3.3.0
so dbDelta creates the new names on install
- widget id_base aksrt_widget_* -> jio_widget_*
- uninstall.php drop list rebuilt from the actual migrator tables
(dropped 3 stale entries, added the 17 missing ones)
Removed
- hardcoded https://api.aksrt.com/version.json default update endpoint;
get_endpoint() now reads the 「更新端点」 setting and do_check() no-ops
when it is empty
Files renamed: inc/helpers/aksrt-*.php -> jio-*.php (54),
assets/admin/src/components/form/Aks*.vue -> Jio*.vue (15).
Build artifacts regenerated: assets/css/build, assets/js/runtime,
assets/admin/build.
Verified: audit-psr4-paths errors=0, audit-admin-contracts errors=0
(warnings=56, unchanged baseline), 813/813 widget-system tests,
44/44 phpunit, php -l clean across all PHP.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
156 lines
10 KiB
JavaScript
156 lines
10 KiB
JavaScript
'use strict';
|
|
|
|
const assert = require('node:assert/strict');
|
|
const { execFileSync } = require('node:child_process');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const test = require('node:test');
|
|
|
|
const root = path.resolve(__dirname, '..', '..');
|
|
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
|
|
|
|
test('account dialogs expose configured email steps, phone steps, and reference password branches', () => {
|
|
const template = read('inc/helpers/user-center-renderers/settings-account.php');
|
|
const javascript = read('assets/js/routes/user-center.js');
|
|
const css = read('assets/css/routes/user-center/settings.css');
|
|
|
|
assert.match(template, /\$email_verify_required = \$account_email !== '' && !empty\(\$user_settings\['email_set_captch'\]\)/);
|
|
assert.match(template, /data-account-step="email-old"[\s\S]*?data-account-step="email-new"[\s\S]*?data-account-step="email-success"/);
|
|
assert.match(template, /if \(\$email_verify_required\)/);
|
|
assert.match(template, /if \(\$email_verify_required\)[\s\S]*?else : \?>[\s\S]*?jio-settings-modal__pane/);
|
|
assert.match(template, /if \(!empty\(\$user_settings\['email_set_captch'\]\)\)/);
|
|
assert.match(template, /data-account-step="phone-old"[\s\S]*?data-account-step="phone-new"[\s\S]*?data-account-step="phone-success"/);
|
|
assert.match(template, /if \(\$account_phone !== ''\)[\s\S]*?else : \?>[\s\S]*?jio-settings-modal__pane/);
|
|
assert.match(template, /data-jio-sms-scene="verify_old_phone"/);
|
|
assert.match(template, /data-jio-sms-scene="bind_new_phone"/);
|
|
assert.match(template, /\$account_close_icon = function_exists\('jio_icon_markup'\)/);
|
|
assert.match(template, /<i class="fa far fa-envelope"/);
|
|
assert.match(template, /\$account_phone_display = function_exists\('jio_phone_mask_display'\) \? jio_phone_mask_display\(\$account_phone\) : \$account_phone;/);
|
|
assert.match(template, /\$account_phone !== '' \? \$account_phone_display : __\('暂未绑定'/);
|
|
assert.doesNotMatch(template, /为确认是您本人操作,请补全绑定手机号 %s/);
|
|
assert.match(template, /为确认是您本人操作,请补全绑定手机号/);
|
|
assert.match(template, /class="jio-phone-digit__edge"><\?php echo esc_html\(\(\$phone_mask\['leading_plus'\] \? '\+' : ''\) \. \(string\) \$phone_mask\['prefix'\]\); \?><\/span>/);
|
|
assert.match(template, /<span class="jio-phone-digit__edge"><\?php echo esc_html\(\(string\) \$phone_mask\['suffix'\]\); \?><\/span>/);
|
|
assert.doesNotMatch(template, /name="phone" value="/);
|
|
assert.match(template, /data-jio-phone-digits data-hidden-length/);
|
|
assert.match(template, /class="jio-phone-digit" inputmode="numeric" maxlength="1"/);
|
|
assert.match(template, /aria-label="<\?php echo esc_attr\(sprintf\(__\('手机号第 %d 位数字', 'jio'\), 4 \+ \$phone_digit_index\)\); \?>"/);
|
|
assert.match(template, /data-jio-phone-code-area<\?php echo \$phone_mask !== null \? ' hidden' : ''; \?>/);
|
|
assert.match(template, /data-jio-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, /\.jio-settings-modal \.jio-phone-digit \{/);
|
|
assert.match(css, /\.jio-settings-modal \.jio-phone-digit__edge \{/);
|
|
assert.match(css, /background-color: var\(--main-bg-color, #f7f8fa\)/);
|
|
assert.match(css, /\.jio-settings-modal \.jio-phone-digits\.has-error \.jio-phone-digit \{/);
|
|
assert.match(template, /jio_render_captcha\('change_email'\)[\s\S]*?id="email-code"/);
|
|
assert.match(template, /jio_render_captcha\('bind_phone'\)[\s\S]*?id="bind-phone-code"/);
|
|
assert.match(template, /if \(!\$account_oauth_new\)[\s\S]*?name="passwordold"/);
|
|
assert.match(template, /if \(!\$account_oauth_new && \$can_recover_password\)/);
|
|
assert.match(template, /data-account-password-pane="recovery"/);
|
|
assert.match(javascript, /\/auth\/code/);
|
|
assert.match(javascript, /\/auth\/reset-password/);
|
|
assert.match(javascript, /className: 'jio-user-settings-modal modal-mini full-sm'/);
|
|
assert.doesNotMatch(template + javascript + css, /pwd-strength|pwd-send-code|email-send-code/);
|
|
assert.match(css, /\.jio-modal-runtime\.jio-user-settings-modal\.jio-modal-runtime--bottom \.jio-modal-runtime__dialog \{[\s\S]*?width: 400px/);
|
|
assert.match(css, /@media \(max-width: 640px\)[\s\S]*?width: 100%/);
|
|
assert.match(css, /modal-line-field--code \.yztx\.abs-right[\s\S]*?top: 50%[\s\S]*?right: \.7em/);
|
|
assert.doesNotMatch(css, /\.code-send-btn \{ min-width:/);
|
|
|
|
const emailConditionStart = template.indexOf('<?php if ($email_verify_required) : ?>');
|
|
const emailElse = template.indexOf('<?php else : ?>', emailConditionStart);
|
|
const emailEnd = template.indexOf('<?php endif; ?>', emailElse);
|
|
const emailSteps = template.slice(emailConditionStart, emailElse);
|
|
const emailDirect = template.slice(emailElse, emailEnd);
|
|
const phoneConditionStart = template.indexOf('<?php if ($account_phone !== \'\') : ?>');
|
|
const phoneElse = template.indexOf('<?php else : ?>', phoneConditionStart);
|
|
const phoneEnd = template.indexOf('<?php endif; ?>', phoneElse);
|
|
const phoneSteps = template.slice(phoneConditionStart, phoneElse);
|
|
const phoneDirect = template.slice(phoneElse, phoneEnd);
|
|
assert.match(emailSteps, /account-step-list/);
|
|
assert.doesNotMatch(emailDirect, /account-step-list|data-account-step=/);
|
|
assert.match(phoneSteps, /account-step-list/);
|
|
assert.doesNotMatch(phoneDirect, /account-step-list|data-account-step=/);
|
|
});
|
|
|
|
test('account PHP harness exercises email and password state transitions', () => {
|
|
const harness = path.join(root, 'tests', 'widget-system', 'account-settings-harness.php');
|
|
const output = execFileSync('php', [harness], { encoding: 'utf8' });
|
|
assert.match(output, /Account settings harness passed/);
|
|
});
|
|
|
|
test('email update keeps both proofs through validation failures and consumes them only after the write', () => {
|
|
const ajax = read('inc/modules/user-parts/account-ajax.php');
|
|
const send = ajax.slice(ajax.indexOf("add_action('wp_ajax_jio_send_account_email_code'"), ajax.indexOf("add_action('wp_ajax_jio_verify_account_email'"));
|
|
const verify = ajax.slice(ajax.indexOf("add_action('wp_ajax_jio_verify_account_email'"), ajax.indexOf("add_action('wp_ajax_jio_change_password'"));
|
|
const change = ajax.slice(ajax.indexOf("add_action('wp_ajax_jio_change_email'"));
|
|
|
|
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, /jio_account_email_rate_/);
|
|
assert.doesNotMatch(ajax, /jio_account_email_rate_/);
|
|
assert.match(verify, /jio_require_captcha\(\s*'change_email'/);
|
|
assert.match(verify, /jio_account_set_proof\(\$user_id, 'email_old'/);
|
|
assert.match(change, /jio_account_email_verification_required\(\)/);
|
|
assert.match(change, /jio_account_consume_proof\([^;]+false\)/);
|
|
assert.match(change, /jio_account_consume_code\([\s\S]*?false\s*\)/);
|
|
assert.ok(change.indexOf('wp_update_user(') < change.indexOf("delete_transient(jio_account_proof_key"));
|
|
assert.ok(change.indexOf('wp_update_user(') < change.indexOf("delete_transient(jio_account_code_key"));
|
|
assert.match(change, /\$agreement\['required'\]/);
|
|
assert.doesNotMatch(ajax, /wp_ajax_jio_send_email_code/);
|
|
});
|
|
|
|
test('phone replacement requires old-number proof and a new-number code while reusing bind side effects', () => {
|
|
const controller = read('src/Admin/UserControllerAuthPhoneOperations.php');
|
|
const routes = read('src/Admin/UserController.php');
|
|
const binding = read('src/Auth/ServicePart1b.php');
|
|
const code = controller.slice(controller.indexOf('public function user_phone_code('), controller.indexOf('public function user_verify_phone('));
|
|
const verify = controller.slice(controller.indexOf('public function user_verify_phone('), controller.indexOf('public function user_bind_phone('));
|
|
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, /jio_account_phone_old_/);
|
|
assert.match(bind, /jio_account_phone_old_/);
|
|
assert.match(bind, /auth_consume_code\(\$code_scene, \$phone, \$code, false\)/);
|
|
assert.ok(bind.indexOf("Auth\\Service::bind_phone") < bind.indexOf("delete_transient($this->auth_code_key($code_scene, $phone))"));
|
|
assert.match(bind, /jio_get_auth_agreement_view/);
|
|
assert.match(bind, /Auth\\Service::bind_phone\(\$payload, true\)/);
|
|
assert.match(binding, /jio_user_phone_changed/);
|
|
assert.doesNotMatch(controller, /auth_consume_code\('bind_phone'/);
|
|
});
|
|
|
|
test('password change retains old-password limits and captcha; recovery uses shared auth endpoints', () => {
|
|
const ajax = read('inc/modules/user-parts/account-ajax.php');
|
|
const javascript = read('assets/js/routes/user-center.js');
|
|
const password = ajax.slice(ajax.indexOf("add_action('wp_ajax_jio_change_password'"), ajax.indexOf("add_action('wp_ajax_jio_change_email'"));
|
|
|
|
assert.match(password, /get_user_meta\(\$user_id, 'oauth_new', true\)/);
|
|
assert.match(password, /wp_check_password\(\$old/);
|
|
assert.match(password, /SecurityHardening::error_frequency_wait\(\)/);
|
|
assert.match(password, /SecurityHardening::error_frequency_record\(\)/);
|
|
assert.doesNotMatch(password, /jio_account_rate_limited/);
|
|
assert.doesNotMatch(ajax, /function jio_account_rate_limited/);
|
|
assert.doesNotMatch(ajax, /function jio_account_reset_rate/);
|
|
assert.match(password, /jio_require_captcha\('change_password'/);
|
|
assert.match(password, /Auth\\Service::validate_password\(\$password, \$password2\)/);
|
|
assert.doesNotMatch(password, /email.*code|password.*strength/i);
|
|
assert.match(javascript, /scene: 'resetpassword', target: target, channel:/);
|
|
assert.match(javascript, /\/auth\/code/);
|
|
assert.match(javascript, /\/auth\/reset-password/);
|
|
assert.match(javascript, /data-recovery-channel/);
|
|
});
|