From 740bd48f4212b991d32101ca020e7bc866e906fd Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Oct 2026 21:00:49 +0800 Subject: [PATCH] refactor(users): drop dead WeChat notify settings surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit users/wechat schema 页写入 aksrt_settings 的 wechat_notify_* / wechat_app_* / wechat_template_* 等 15 个键全仓无任何消费方,与活配置面 aksrt_wechat_settings(WeChatNotify 读取、/users/wechat-template 页管理)构成双路;PHP 与 JS 两份 schema 的字段集早已不一致(15 vs 10),是死面腐烂的直接证据。 移除 SchemaUsers 的 wechat 分组、JS schema 文件及其注册、菜单 schema 页条目,微信配置收敛为单一自定义页入口;契约测试锁定死键零残留与活配置面唯一。 --- assets/admin/src/constants/sections/users.js | 10 --- .../admin/src/schema/sections/users/index.js | 2 - .../admin/src/schema/sections/users/wechat.js | 51 ----------- src/Admin/Schema/SchemaUsers.php | 30 ------- .../wechat-settings-rest-contract.test.cjs | 84 +++++++++++++++++++ 5 files changed, 84 insertions(+), 93 deletions(-) delete mode 100644 assets/admin/src/schema/sections/users/wechat.js create mode 100644 tests/admin/wechat-settings-rest-contract.test.cjs diff --git a/assets/admin/src/constants/sections/users.js b/assets/admin/src/constants/sections/users.js index ce1521ce..01eaa2d4 100644 --- a/assets/admin/src/constants/sections/users.js +++ b/assets/admin/src/constants/sections/users.js @@ -108,16 +108,6 @@ export const usersSection = { canonicalDomain: 'users', section: 'sms', }), - schemaPage({ - key: 'users-wechat', - name: 'UsersWechat', - label: '微信通知', - route: '/users/wechat', - title: '微信通知', - desc: '配置微信模板消息、订阅/解绑和站外通知策略。', - canonicalDomain: 'users', - section: 'wechat', - }), customPage({ key: 'users-wechat-template', name: 'UsersWechatTemplate', diff --git a/assets/admin/src/schema/sections/users/index.js b/assets/admin/src/schema/sections/users/index.js index 023dae92..c5957f64 100644 --- a/assets/admin/src/schema/sections/users/index.js +++ b/assets/admin/src/schema/sections/users/index.js @@ -10,7 +10,6 @@ import { featuresSchema } from './features.js' import { verifySchema } from './verify.js' import { levelSchema } from './level.js' import { badgeSchema } from './badge.js' -import { wechatSchema } from './wechat.js' import { reportSchema } from './report.js' import { smsSchema } from './sms.js' @@ -23,7 +22,6 @@ export const usersSchemas = { verify: verifySchema, level: levelSchema, badge: badgeSchema, - wechat: wechatSchema, report: reportSchema, sms: smsSchema, } diff --git a/assets/admin/src/schema/sections/users/wechat.js b/assets/admin/src/schema/sections/users/wechat.js deleted file mode 100644 index ff88ce51..00000000 --- a/assets/admin/src/schema/sections/users/wechat.js +++ /dev/null @@ -1,51 +0,0 @@ -export const wechatSchema = { - key: 'users.wechat', - title: '微信通知', - icon: 'fa fab fa-weixin', - description: '配置微信模板消息、订阅/解绑和站外通知策略。', - defaults: { - wechat_notify_enabled: false, - wechat_app_id: '', - wechat_app_secret: '', - wechat_template_id: '', - wechat_token: '', - wechat_encoding_aes_key: '', - wechat_notify_comment: true, - wechat_notify_reply: true, - wechat_notify_system: true, - wechat_bind_entry: true, - }, - groups: [ - { - key: 'account', - title: '公众号配置', - icon: 'fa fab fa-weixin', - fields: [ - { key: 'wechat_notify_enabled', label: '启用微信通知', type: 'switch', default: false, help: '开启后用户可绑定微信接收通知' }, - { key: 'wechat_app_id', label: 'AppID', type: 'input', default: '', dependsOn: { key: 'wechat_notify_enabled', value: true } }, - { key: 'wechat_app_secret', label: 'AppSecret', type: 'input', default: '', dependsOn: { key: 'wechat_notify_enabled', value: true } }, - { key: 'wechat_template_id', label: '模板消息 ID', type: 'input', default: '', dependsOn: { key: 'wechat_notify_enabled', value: true }, help: '在微信公众平台申请的模板消息 ID' }, - ], - }, - { - key: 'verify', - title: '服务器验证', - icon: 'fa fas fa-check-circle', - fields: [ - { key: 'wechat_token', label: 'Token', type: 'input', default: '', dependsOn: { key: 'wechat_notify_enabled', value: true }, help: '微信公众平台服务器配置中的 Token' }, - { key: 'wechat_encoding_aes_key', label: 'EncodingAESKey', type: 'input', default: '', dependsOn: { key: 'wechat_notify_enabled', value: true } }, - ], - }, - { - key: 'triggers', - title: '通知触发器', - icon: 'fa fas fa-bell', - fields: [ - { key: 'wechat_notify_comment', label: '新评论通知', type: 'switch', default: true, dependsOn: { key: 'wechat_notify_enabled', value: true } }, - { key: 'wechat_notify_reply', label: '评论回复通知', type: 'switch', default: true, dependsOn: { key: 'wechat_notify_enabled', value: true } }, - { key: 'wechat_notify_system', label: '系统通知', type: 'switch', default: true, dependsOn: { key: 'wechat_notify_enabled', value: true } }, - { key: 'wechat_bind_entry', label: '显示绑定入口', type: 'switch', default: true, dependsOn: { key: 'wechat_notify_enabled', value: true }, help: '在用户中心显示微信绑定/解绑按钮' }, - ], - }, - ], -} diff --git a/src/Admin/Schema/SchemaUsers.php b/src/Admin/Schema/SchemaUsers.php index 13fa08b2..f6af01f7 100644 --- a/src/Admin/Schema/SchemaUsers.php +++ b/src/Admin/Schema/SchemaUsers.php @@ -611,36 +611,6 @@ class SchemaUsers { ]], ], ], - 'wechat' => [ - 'key' => 'wechat', - 'title' => '微信通知', - 'version' => '1.0.0', - 'option_key' => 'aksrt_settings', - 'groups' => [ - ['key' => 'account', 'title' => '公众号配置', 'fields' => [ - ['key' => 'wechat_notify_enabled', 'label' => '启用微信通知', 'type' => 'switch', 'default' => false], - ['key' => 'wechat_app_id', 'label' => 'AppID', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ['key' => 'wechat_app_secret', 'label' => 'AppSecret', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ]], - ['key' => 'verify', 'title' => '服务器验证', 'fields' => [ - ['key' => 'wechat_token', 'label' => 'Token', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ['key' => 'wechat_encoding_aes_key', 'label' => 'EncodingAESKey', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ]], - ['key' => 'templates', 'title' => '模板消息', 'fields' => [ - ['key' => 'wechat_template_comment', 'label' => '评论通知模板', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ['key' => 'wechat_template_reply', 'label' => '回复通知模板', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ['key' => 'wechat_template_system', 'label' => '系统通知模板', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ['key' => 'wechat_template_order', 'label' => '订单通知模板', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ]], - ['key' => 'triggers', 'title' => '通知触发器', 'fields' => [ - ['key' => 'wechat_notify_comment', 'label' => '新评论通知', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ['key' => 'wechat_notify_reply', 'label' => '评论回复通知', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ['key' => 'wechat_notify_system', 'label' => '系统通知', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ['key' => 'wechat_notify_order', 'label' => '订单通知', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ['key' => 'wechat_bind_entry', 'label' => '显示绑定入口', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'wechat_notify_enabled', 'value' => true]], - ]], - ], - ], ], ]; } diff --git a/tests/admin/wechat-settings-rest-contract.test.cjs b/tests/admin/wechat-settings-rest-contract.test.cjs new file mode 100644 index 00000000..9cd12613 --- /dev/null +++ b/tests/admin/wechat-settings-rest-contract.test.cjs @@ -0,0 +1,84 @@ +'use strict'; + +/** + * 微信模板消息 REST 契约(修复存量审计错误): + * 1) /wechat/status 与 /wechat/settings 的路由回调方法在 UserController 中真实存在; + * 2) 状态读取委托 WeChatNotify::get_status(),写入委托 Settings::update_wechat_settings(); + * 3) app_secret 掩码 *** 不覆盖已存密钥,输入经 sanitize_text_field 消毒; + * 4) PHP harness 驱动真实控制器验证上述行为; + * 5) aksrt_settings 上的微信通知死键(wechat_notify_* 等)已彻底移除, + * 活配置面仅剩 aksrt_wechat_settings(/users/wechat-template 自定义页)。 + */ + +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 controller = fs.readFileSync(path.join(root, 'src/Admin/UserController.php'), 'utf8'); +const schemaUsers = fs.readFileSync(path.join(root, 'src/Admin/Schema/SchemaUsers.php'), 'utf8'); +const usersSchemaIndex = fs.readFileSync(path.join(root, 'assets/admin/src/schema/sections/users/index.js'), 'utf8'); +const usersSections = fs.readFileSync(path.join(root, 'assets/admin/src/constants/sections/users.js'), 'utf8'); + +// 死双路面:写进 aksrt_settings、全仓无消费方的微信通知键。 +const DEAD_WECHAT_KEYS = [ + 'wechat_notify_enabled', + 'wechat_app_id', + 'wechat_app_secret', + 'wechat_template_id', + 'wechat_token', + 'wechat_encoding_aes_key', + 'wechat_template_comment', + 'wechat_template_reply', + 'wechat_template_system', + 'wechat_template_order', + 'wechat_notify_comment', + 'wechat_notify_reply', + 'wechat_notify_system', + 'wechat_notify_order', + 'wechat_bind_entry', +]; + +test('路由与回调方法配对存在', () => { + assert.match(controller, /register_rest_route\(self::API_NAMESPACE, '\/wechat\/status'[\s\S]*?'callback'\s*=>\s*\[\$this, 'get_wechat_status'\]/); + assert.match(controller, /register_rest_route\(self::API_NAMESPACE, '\/wechat\/settings'[\s\S]*?'callback'\s*=>\s*\[\$this, 'update_wechat_settings'\]/); + assert.match(controller, /public function get_wechat_status\(\\WP_REST_Request \$request\)/); + assert.match(controller, /public function update_wechat_settings\(\\WP_REST_Request \$request\)/); +}); + +test('状态与写入委托既有服务层', () => { + assert.match(controller, /WeChatNotify::get_instance\(\)->get_status\(\)/); + assert.match(controller, /Settings::update_wechat_settings\(/); +}); + +test('密钥掩码与输入消毒', () => { + assert.match(controller, /\$params\['app_secret'\] !== '\*\*\*'/); + assert.match(controller, /sanitize_text_field\(\(string\) \$params\['app_id'\]\)/); + assert.match(controller, /sanitize_text_field\(\(string\) \$params\['app_secret'\]\)/); + assert.match(controller, /sanitize_text_field\(\(string\) \$params\['template_id'\]\)/); +}); + +test('微信设置行为 harness 通过', () => { + const harness = path.join(root, 'tests', 'admin', 'wechat-settings-harness.php'); + const output = execFileSync('php', [harness], { encoding: 'utf8' }); + assert.match(output, /WeChat settings harness passed/); +}); + +test('死双路面(aksrt_settings 微信通知键)已彻底移除', () => { + for (const key of DEAD_WECHAT_KEYS) { + assert.ok(!schemaUsers.includes(key), `SchemaUsers 残留: ${key}`); + assert.ok(!usersSections.includes(key), `users 菜单常量残留: ${key}`); + } + assert.ok(!usersSchemaIndex.includes('wechatSchema'), 'users schema index 残留 wechatSchema 注册'); + assert.ok(!usersSections.includes("route: '/users/wechat',"), '用户菜单残留微信通知 schema 页'); + assert.ok(!fs.existsSync(path.join(root, 'assets/admin/src/schema/sections/users/wechat.js')), 'wechat.js 未删除'); +}); + +test('活配置面保持唯一(aksrt_wechat_settings + 自定义页)', () => { + assert.match(usersSections, /key: 'users-wechat-template'/); + assert.match(usersSections, /route: '\/users\/wechat-template'/); + assert.match(controller, /WeChatNotify::get_instance\(\)->get_status\(\)/); + assert.match(controller, /Settings::update_wechat_settings\(/); +});