Commit Graph
7 Commits
Author SHA1 Message Date
kate522 0bee2c605e refactor(auth): stop pre-escaping the OAuth provider URLs
get_auth_providers_data() returned esc_url()-ed URLs while all four of its
consumers (the modal, the user card, render_social_buttons and the comment
form) escaped again on output. Its sibling get_frontend_bindings_data() stores
the raw URL and lets the binding list escape it, so the class was inconsistent
with itself.

I first reported this as a double-escaping bug that broke ampersand-bearing
URLs. That was wrong: I had verified it with a stub that modelled esc_url() as
htmlspecialchars(). The real esc_url() runs wp_kses_normalize_entities()
first, which explicitly decodes double-encoded character references, so
esc_url() is idempotent on its own output. Re-checked against the WordPress
source with a faithful transcription, and re-ran the popover markup: the
WeChat href is ?tab=oauth&oauth_intent=login, one entity, unchanged.

So the escaping was redundant rather than broken. The producer now hands out
raw URLs and each surface escapes exactly once, which is where WordPress
expects it and matches get_frontend_bindings_data(). Rendered output is
byte-identical.

Extended the auth source contract to pin the invariant: the producer stays
raw and all four surfaces escape on output.

Verification: node --test across widget-system, navigation, admin,
asset-ledger, dev, front-submit and visual (614 tests), plus php -l.
2026-10-17 14:54:10 +08:00
kate522 c472045ce4 fix(auth): align the social-login surfaces with the reference theme
The "other login methods" block drifted from zibll on three axes. Gitee was
mapped to fa-code-branch because FA5 Free ships no Gitee brand glyph, so the
button showed a generic branch icon; Google showed the monochrome FA glyph
instead of the reference's multi-colour mark. The modal also printed an
implicit agreement line under the social buttons, which the reference guest
card does not have. And the top-nav user popover built its own
.social-login-divider / .oauth-row / .oauth-btn markup and then wrapped that
in a second separator and .social_loginbar, so the block rendered nested and
unlike the reference.

aksrt_brand_icon() now routes zibsvg-/customsvg- values through the shared
icon renderer, and the brand map resolves gitee to zibsvg-gitee and google to
zibsvg-google-color. Both sprite keys already exist in the runtime symbol
sheet, which the loader pulls in on every frontend page. Because
get_auth_providers_data() and binding_row() both go through
aksrt_brand_icon(), one map change fixes the icon on the modal, the user card,
the top-nav popover, the user-center binding list and the profile social
links.

render_social_buttons() is rewritten to the reference shape: an optional
.social-separator, a .social_loginbar, and one .social-login-item <type>
toggle-radius anchor per enabled provider with rel="nofollow" and a
"<label>登录" title. oauth_button_lg switches to the button-lg variant with a
label, and the WeChat entry carries qrcode-signin so auth.js opens the QR
panel instead of navigating, matching the reference. The navbar and the link
apply modal now append the block verbatim instead of re-wrapping it, and the
user-card loop adopts the same item attributes. The retired
.social-login-divider / .oauth-row / .oauth-btn rules are dropped from
base-1.css, and the binding-list icon rule gains an svg selector so the
sprite icons keep the 22px the FA glyphs had.

Verification: node --test across widget-system, navigation, admin,
asset-ledger, dev, front-submit and visual (613 tests), plus php -l on every
changed PHP file. Extended the auth source contract with the agreement-line,
brand-icon and popover-structure cases, and pinned the user-card guest
markup.
2026-10-17 14:42:42 +08:00
kate522 a4af024f32 feat(ban): align ban prompts with the reference theme modals and block page
对照参考主题(Zibll)修正四项偏差,申诉链路从页面整体迁移至弹窗:

- feat(ban): 新增三个 1:1 复刻弹窗(REST /user-ban/{info,appeal,log}-modal):
  查看禁封状态(多彩头 c-gray + 信息行 + 申诉按钮)、禁封申诉(edit-header
  gavel/c-blue + 信息框 + 资料项 data[key] 输入 + 审核中态 + 禁止申诉态)、
  禁封记录(多彩头 c-yellow + 计数 + 逐条卡片);user-ban.js 增加
  data-aksrt-ban-info/appeal/log 委托与 admin-ajax 申诉提交
- feat(ban): 禁封/解封弹窗的「当前用户已有N次禁封记录」静态文案改为可点击
  黄链(N>1),打开禁封记录弹窗;解封视图信息行改复用统一数据源
- refactor(ban): 治理展示态收敛至 Restriction::state_badges()(封号=c-red
  违规已封号 / 小黑屋=c-yellow 小黑屋禁封中 / 禁言=c-gray 禁言中,颜色与
  字段统一管理)+ get_ban_info()(状态/起止时间/原因/说明/申诉权限,
  三弹窗与禁封页共用)
- feat(ban): 登录行为对齐参考主题——移除登录期拦截(enforce_login_ban)
  与 complete_login 禁封闸门,封号用户可正常登录;新增 template_redirect
  前台禁封页(1:1 zib_user_ban_restrict_login/zib_die_page:红盒提示 +
  信息行 + 申诉权限 + 退出登录/申诉按钮,模板 templates/parts/user/ban-block.php)
- feat(profile): 公开主页禁封状态从资料卡下方提示框改为占据身份行元信息位
  的 badg 徽章(参考主题 author_header_identity 语义);用户中心元信息改为
  but 按钮(徽章+箭头)打开查看禁封状态弹窗;评论拒绝态链接同源
- refactor: 移除申诉页面模板(page-ban-appeal.php)及其资产/注册/入队、
  get_profile_notice/profile_notice 链、state_labels/state_notices/
  login_ban_message、UserRuntime 的 public_notice/ban_notice_text 死配置、
  report_settings 死键、无消费方的 aksrt_ban_appeal_status 端点
- feat(ban): BanAppeal::ajax_submit 兼容弹窗 data[key] 表单结构
  (逐项清洗入库,申诉说明取 data['申诉说明'],旧平铺字段保持兼容)
- chore: 重新构建 public.css/public.min.css(三个新弹窗几何与头部样式)
- test: 契约测试重写(徽章元信息位、三弹窗与记录链接、禁封页、允许登录 +
  前台拦截、死代码移除断言),全量 362 项通过
2026-09-22 19:14:02 +08:00
kate522 11eda33e58 fix(ban): state-aware ban copy and real login failure reasons
- fix(profile): 封号用户的公开主页提示不再沿用「当前账号处于限制状态,
  部分互动能力已关闭」——封号=全面限制(无法登录),该描述与语境不符。
  提示尾句按治理展示态分级:封号→禁封期间无法登录、账号功能全面停用;
  小黑屋→发布、评论等操作已受限制;禁言→暂时无法发表评论。
  UserRuntime 不再烘焙通用默认文案,缺省时由 get_profile_notice 按态取
- fix(auth): 登录失败透传真实原因——REST auth_login 此前将
  Service::login_user 返回的具体错误硬编码为「账号或密码错误」,
  禁封用户登录时 Toast 语境错误;现透传 error 字段,
  friendly_login_error 识别 user_banned 错误码后直接返回禁封文案
  (无法登录 + 解封时间/永久 + 原因)
- fix(auth): 禁封闸口覆盖全部登录路径——此前仅密码登录经
  enforce_login_ban 拦截,短信验证码、公众号扫码、第三方 OAuth 均
  直连 complete_login 可绕过封号限制;现将闸口收敛至 complete_login
  (返回 WP_Error),各调用方中止登录并透出原因;OAuth 重定向新增
  account_banned 错误码,auth.js 与 user-center.js 同步文案映射
- test: 新增登录禁封面契约测试(文案单一来源、Toast 透传、免密闸口、
  统一收口、前端映射),全量 362 项通过
2026-09-22 18:36:09 +08:00
kate522 ff4ec1eb43 feat(captcha): 打通人机验证 11 个场景的前后端完整链路
- 统一验证入口 aksrt_require_captcha(),返回 true|WP_Error,启用场景配置缺失时 fail-closed 拒绝
- 前端公共 API 重构为 window.AKSRTCaptcha(verify/collect/reset/run),单飞锁防并发重复验证,一次性 proof 绑定浏览器 cookie+场景+服务商+主机名
- challenge/exchange REST 端点:challenge 原子占用防票据放大厂商调用,增加频率限制
- 新增 OAuth bind pass:服务端签发 5 分钟一次性令牌,绑定用户+服务商+浏览器,微信扫码延迟消费
- 覆盖场景:评论、登录、注册、绑定第三方、绑定手机、找回密码、修改密码、更改邮箱、资料下载、签到、前台投稿
- 移除 Service 层重复验证与 _auth_code_verified/_defer_login 等客户端可伪造标志,删除下载共享 pass 死代码
- 修复腾讯 TC3 签名 scope、Cloudflare action/cdata/hostname 严格校验、阿里云验签错误码映射
- 后台 Schema 保存对 secret 字段做掩码/保留合并;导入导出过滤 aksrt_captcha_config
- 重建 public bundle 与 admin SPA;新增 captcha 运行时/安全/业务契约测试与 harness
2026-09-02 13:03:24 +08:00
kate522 780e1eba21 优化了一些问题 2026-08-29 22:03:48 +08:00
kate522 8c5b1555c9 refactor: flatten src/AKSRT → src (drop theme-identifier dir)
Move all domain folders from src/AKSRT/{Domain} to src/{Domain}; remap
Composer PSR-4 "AKSRT\\": "src/"; update audit script + README + ADR
paths; remove dead tools/build-psr4-map.php (scanned deleted inc/classes).
2026-08-02 22:06:06 +08:00