ac520d8ae5
工作区直链 /MindSpace/<userId>/public/*.html 此前对所有人(含匿名访客、 转发链接收到的其他登录用户)展示完全相同的悬浮操作按钮,导致非作者也能 看到"发布 Plaza"入口——而 Plaza 发布会把内容归属到操作者自己的账号下, 必须只对作者开放。 - server.mjs: serveUserPublishFile 用现有 session/cookie 鉴权判断访问者是 否等于 URL 中的 ownerKey,结果透传给 sendPublishFile;该响应内容因人 而异,显式加 Cache-Control: private, no-store(原来未设置任何缓存头) - mindspace-public-share-widget.mjs: injectPublicFileShareButton 新增 isOwner 参数(默认 true 保持兼容),非作者时隐藏"发布 Plaza"按钮与确认 弹窗,"保存长图"/"公开分享"对所有访客保留 - mindspace-public-delivery.mjs: 透传 isOwner,并注入图片重试脚本 - mindspace-public-image-retry.mjs(新增): 页面级 onerror 之前用捕获阶段 监听拦截 mindspace 资产图片的加载失败,带退避自动重试 3 次,避免刚生成 页面时的资产物化竞态被"永久占位符"放大成显示故障 本地起服务用 owner / 非 owner 已登录用户 / 匿名访客三种身份实测验证。 Co-authored-by: Cursor <cursoragent@cursor.com>
47 lines
2.3 KiB
JavaScript
47 lines
2.3 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { injectPublicFileShareButton } from './mindspace-public-share-widget.mjs';
|
|
|
|
test('injectPublicFileShareButton adds plaza entry and confirm dialog', () => {
|
|
const result = injectPublicFileShareButton('<!doctype html><html><body><h1>Hi</h1></body></html>');
|
|
assert.match(result.html, /data-action="plaza"/);
|
|
assert.match(result.html, /发布到 Plaza/);
|
|
assert.match(result.html, /data-action="plaza-confirm"/);
|
|
assert.match(result.html, /quick-plaza-from-public-html/);
|
|
assert.match(result.html, /quick-plaza-from-public-html\/status/);
|
|
assert.match(result.html, /data-plaza-view="already"/);
|
|
assert.match(result.html, /已在广场发布/);
|
|
assert.match(result.html, /data-mindspace-public-share-dialog-panel role="dialog"/);
|
|
assert.doesNotMatch(result.html, /data-mindspace-public-share-dialog-panel"/);
|
|
assert.match(result.html, /color:#fff !important/);
|
|
assert.match(result.html, /apiErrorBody/);
|
|
assert.match(result.html, /ALREADY_PUBLISHED/);
|
|
assert.equal(result.scriptHashes.length, 1);
|
|
});
|
|
|
|
test('injectPublicFileShareButton hides Plaza entry and dialog for non-owner viewers', () => {
|
|
const result = injectPublicFileShareButton(
|
|
'<!doctype html><html><body><h1>Hi</h1></body></html>',
|
|
{ isOwner: false },
|
|
);
|
|
assert.doesNotMatch(result.html, /<button type="button" data-action="plaza">/);
|
|
assert.doesNotMatch(result.html, /发布到 Plaza/);
|
|
assert.doesNotMatch(result.html, /<button type="button" data-action="plaza-confirm">/);
|
|
assert.doesNotMatch(result.html, /<div data-mindspace-public-share-dialog/);
|
|
assert.doesNotMatch(result.html, /data-mindspace-public-share-dialog-panel role="dialog"/);
|
|
// Non-Plaza actions must remain available to visitors.
|
|
assert.match(result.html, /data-action="capture"/);
|
|
assert.match(result.html, /data-action="share"/);
|
|
assert.match(result.html, /公开分享/);
|
|
assert.equal(result.scriptHashes.length, 1);
|
|
});
|
|
|
|
test('injectPublicFileShareButton keeps Plaza entry when isOwner explicitly true', () => {
|
|
const result = injectPublicFileShareButton(
|
|
'<!doctype html><html><body><h1>Hi</h1></body></html>',
|
|
{ isOwner: true },
|
|
);
|
|
assert.match(result.html, /data-action="plaza"/);
|
|
assert.match(result.html, /data-mindspace-public-share-dialog/);
|
|
});
|