Skip to content

Conversation

@YuxinZhaozyx
Copy link

@YuxinZhaozyx YuxinZhaozyx commented Oct 9, 2025

改进发布服务:允许自定义发布模式可见的笔记本和文档

关联 #11928

Feature

  • 可自定义选择哪些笔记本和文档是发布可见的
  • 发布服务里,这些笔记本和文档相关的文档树、标签、书签、局部关系图、全局关系图、双链、标签页、搜索、最近文档 都会被后端过滤掉再传给前端,前端只会显示发布可见的笔记本和文档
  • 发布服务里,关闭的笔记本也会被后端过滤掉不传给前端
  • 保留特性:在发布服务里通过?id=的链接直接访问 或者 可视化的文档中有不可视的文档,这些方式依旧允许其访问到不可视的文档;对于完全屏蔽文档的功能还需要再讨论。

效果说明

选择发布可见的文档/目录

文档树上方工具栏增加“发布可视“图标,点击可切换 图标 与 控制发布可视的开关

image

发布服务下只有勾选可视且上级文档/笔记本都为可视才能够显示 (另外关闭的笔记本也不会显示):

image

整体对比

image

发布服务:

image

从上图中可以发现文档树、关系图、反向链接、标签页都没有出现不可视的文档相关的内容了

搜索对比

image

发布服务:

image

文档引用对比

image

发布服务:

image

标签搜索与全局关系图对比

image

发布服务:

image

@YuxinZhaozyx YuxinZhaozyx changed the title 改进发布服务 允许定义发布模式可见的笔记本和文档 #11928 改进发布服务:允许自定义发布模式可见的笔记本和文档 #11928 Oct 9, 2025
@88250 88250 mentioned this pull request Oct 11, 2025
2 tasks
@88250 88250 added the Feature label Oct 11, 2025
@88250 88250 moved this to Short Term in SiYuan Roadmap Oct 11, 2025
@88250 88250 added this to the backlog milestone Oct 11, 2025
@88250 88250 changed the title 改进发布服务:允许自定义发布模式可见的笔记本和文档 #11928 Publishing services support document-level access control Oct 11, 2025
@88250 88250 modified the milestones: backlog, 3.5.0 Oct 11, 2025
@YuxinZhaozyx
Copy link
Author

我目前先按照 #11928 里我提到的实现方案继续开发,预计今明两天完成🤝

@88250
Copy link
Member

88250 commented Oct 11, 2025

我们计划放到 v3.5.0 作为特性,时间在明年第一季度(可能 2 月份),不用赶进度,慢慢打磨。

@luo-chuan
Copy link

luo-chuan commented Oct 11, 2025

对,不搞敏捷开发。业务逻辑、交互方式要仔细琢磨。
我把我在 #11928 的留言搬过来。


既然有私域分享的需求,不妨一步到位做好一点。需考虑这种情况,就是面对不同的群体,分享不同的内容。
UI就这样设计:

Image

UI就像我上面这样设计就好了,单击眼睛图标展开群组菜单,点击不同的群组选项进入相应群组的权限控制页面。页面内仍然通过switch来控制文档可见性,简单明了。建议先实现“完全公开”的控制,在下一个版本再实现面向不同群体的私域分享。
也不用搞 “publishAccess.json" 了,给每个文档都增加一个group属性,group的意思就是向哪些群体公开。
group是一个多选项,取值可以有:

  • public
  • link-only (用户自定义)
  • colleague (用户自定义)
  • client (用户自定义)
  • family (用户自定义)
  • ……

比如某文档的属性如下:
{ "id": "xxxxxxxxx", "group": ["public", "colleague"] }
默认就只有一个群组,就是public(完全公开),目录树可见,无需密码,可链接访问。其它群组全是用户自定义的。
对于用户自定义的群组,可以设置该群组是否需要密码,是否与public取并集/取交集。自定义群组的链接格式如下:
http://192.168.0.2:6808/?group=client
http://192.168.0.2:6808/?group=client&id=xxxxxxxxx
某自定义群组的属性如下:

{
  "group-id": "family",
  "group-name": "家人",
  "password": "123456",
  "union-or-intersection-with-public": "union"
}

@YuxinZhaozyx
Copy link
Author

既然有私域分享的需求,不妨一步到位做好一点。需考虑这种情况,就是面对不同的群体,分享不同的内容。

@luo-chuan 不好意思,这个设计我觉得有点复杂化了,分多个用户组不太符合思源笔记作为个人笔记的一个定位,我暂时先按照我上面说的方式实施。不过也不用担心,你这些功能需求等这个发布访问控制完成后,到时候是可以通过插件实现的,只需要让插件去切换 publishAccess.json 即可。

关于同时发布几个网址能够让不同用户群访问到不同的内容,我是计划到时候单独做个插件,一来是不给思源官方增加工作量,二来是以插件的形式发布更新更快。已经有实施方案了,但是这个实施方案的前提是让发布服务能够真正意义上避免后端把隐藏文档的信息传递给前端,不然插件能够做到的始终只是前端隐藏,因此才有了这次PR。

@YuxinZhaozyx
Copy link
Author

目前发布访问控制功能已基本完成。

功能

  • 每个文档和笔记本都可设置 公开/保护/隐藏/私密/禁止 这五种权限
    • 公开:文档树中可见,内容可被搜索,可直接访问
    • 保护:文档树中可见,内容不可被搜索,访问时提示输入密码
    • 隐藏:文档树中不可见,内容不可被搜索,可直接访问
    • 私密:文档树中不可见,内容不可被搜索,访问时提示输入密码
    • 禁止:文档树中不可见,内容不可被搜索,访问时提示禁止访问
  • 发布服务里,设置为不可见(隐藏/私密/禁止)的文档/笔记本及其下属的所有文档不会出现在文档树、标签、书签、局部关系图、全局关系图、双链、标签页、搜索、最近文档中,数据都会被后端过滤掉再传给前端,前端只会显示发布可见的笔记本和文档,PS:设置为保护的文档虽然能够被检索到,但是具体的文档内容需要输入密码才会显示
  • 设置为”隐藏/私密/禁止“的文档可以在发布服务里通过嵌入块/引用/?id=的链接查看,区别在于隐藏的文档可以直接看到内容,私密的文档需要输入密码,禁止的文档完全无法获取到内容
  • 关闭的笔记本不会出现在发布服务中

效果展示

发布访问控制UI

image

文档树上方的工具栏增加一个 “发布访问控制” 的按钮,点击后原本的文档图标 变化为 表示文档访问权限的图标,只需点击图标即可修改对应文档的发布访问权限:

image image image image image

整体对比

image

发布后:

image

其中可以注意到:文档树、标签、标签页、关系图、反向链接中有关不可见文档的内容都已消失。

可直接访问/密码访问/禁止访问 的区别

虽然 隐藏/私密/禁止访问 这三种权限的文档不会出现在文档树里,也搜索不到,但是在可见(公开/保护)的数据库/嵌入块/引用里包含了这些文档,文档会显示出窗口,但是其内容会被替换。

image

以上述数据库为例,

  • “知识C”是公开文档
  • “知识A"是隐藏文档
  • ”知识AAA”虽然标记为公开,但是其在隐藏的”知识A“下,所以它也是不可见的,同理,其也在加密的”知识AA“下,因此也需要密码才能访问,其最终表现出来的行为其实是 私密。
  • ”论文A"是禁止文档

我们来看一下当鼠标放在数据库上这些文档时弹出的窗口会显示什么:

image image image

@88250 88250 changed the title Publishing services support document-level access control Publis service supports document-level access control Oct 12, 2025
@88250 88250 changed the title Publis service supports document-level access control Publish service supports document-level access control Oct 12, 2025
@YuxinZhaozyx
Copy link
Author

目前开发基本完成,对大部分非管理员权限的接口返回结果进行了过滤,在社区的帮助下进行了一些测试,目前主要的非管理员接口的状态如下:

API 状态
/api/system/getEmojiConf 无需过滤
/api/system/getWorkspaces 无需过滤
/api/system/getConf 已过滤
/api/system/getChangelog 无需过滤
/api/storage/getLocalStorage 已过滤
/api/storage/getCriteria 无需过滤
/api/storage/getRecentDocs 已过滤
/api/notebook/lsNotebooks 已过滤
/api/notebook/getNotebookConf 无需过滤
/api/notebook/getNotebookInfo 无需过滤
/api/filetree/searchDocs 已过滤
/api/filetree/listDocsByPath 已过滤
/api/filetree/getDoc 已过滤
/api/filetree/getDocCreateSavePath 无需过滤
/api/filetree/getRefCreateSavePath 无需过滤
/api/filetree/getHPathByPath 无需过滤
/api/filetree/getHPathsByPaths 无需过滤
/api/filetree/getHPathByID 无需过滤
/api/filetree/getPathByID 无需过滤
/api/filetree/getFullHPathByID 无需过滤
/api/filetree/getIDsByHPath 无需过滤
/api/outline/getDocOutline 已过滤
/api/bookmark/getBookmark 已过滤
/api/tag/getTag 已过滤
/api/lute/spinBlockDOM 无需过滤
/api/lute/html2BlockDOM 无需过滤
/api/lute/copyStdMarkdown 已过滤
/api/query/sql 无需过滤(这个API前端完全没用到,建议移除或者改为管理员权限)
/api/search/searchTag 无需过滤
/api/search/searchTemplate 无需过滤
/api/search/searchWidget 无需过滤
/api/search/searchRefBlock 已过滤
/api/search/searchEmbedBlock 已过滤
/api/search/getEmbedBlock 已过滤
/api/search/updateEmbedBlock 无需过滤
/api/search/fullTextSearchBlock 已过滤
/api/search/searchAsset 已过滤
/api/search/fullTextSearchAssetContent 已过滤
/api/search/listInvalidBlockRefs 无需过滤
/api/block/getBlockInfo 未过滤,暂未发现其导致的信息泄露
/api/block/getBlockDOM 未过滤,暂未发现其导致的信息泄露
/api/block/getBlockDOMs 未过滤,暂未发现其导致的信息泄露
/api/block/getBlockKramdown 未过滤,暂未发现其导致的信息泄露
/api/block/getChildBlocks 未过滤,暂未发现其导致的信息泄露
/api/block/getTailChildBlocks 未过滤,暂未发现其导致的信息泄露
/api/block/getBlockBreadcrumb 未过滤,暂未发现其导致的信息泄露
/api/block/getBlockIndex 无需过滤
/api/block/getBlocksIndexes 无需过滤
/api/block/getRefIDs 已过滤
/api/block/getRefIDsByFileAnnotationID 已过滤
/api/block/getBlockDefIDsByRefText 未过滤,暂未发现其导致的信息泄露
/api/block/getRefText 未过滤,暂未发现其导致的信息泄露
/api/block/getDOMText 无需过滤
/api/block/getTreeStat 未过滤,暂未发现其导致的信息泄露
/api/block/getBlocksWordCount 未过滤,暂未发现其导致的信息泄露
/api/block/getContentWordCount 未过滤,暂未发现其导致的信息泄露
/api/block/getRecentUpdatedBlocks 已过滤
/api/block/getDocInfo 已过滤
/api/block/getDocsInfo 已过滤
/api/block/checkBlockExist 无需过滤
/api/block/getUnfoldedParentID 无需过滤
/api/block/checkBlockFold 无需过滤
/api/block/getHeadingLevelTransaction 无需过滤
/api/block/getHeadingDeleteTransaction 无需过滤
/api/block/getHeadingInsertTransaction 无需过滤
/api/block/getHeadingChildrenIDs 无需过滤
/api/block/getHeadingChildrenDOM 无需过滤
/api/block/getBlockSiblingID 无需过滤
/api/block/getBlockRelevantIDs 无需过滤
/api/block/getBlockTreeInfos 无需过滤
/api/block/checkBlockRef 无需过滤
/api/block/appendHeadingChildren 无需过滤
/api/file/getFile 无需过滤
/api/file/readDir 无需过滤
/api/file/getUniqueFilename 无需过滤
/api/ref/refreshBacklink 无需过滤
/api/ref/getBacklink 已过滤
/api/ref/getBacklink2 已过滤
/api/ref/getBacklinkDoc 无需过滤
/api/ref/getBackmentionDoc 无需过滤
/api/attr/getBookmarkLabels 未过滤,暂未发现其导致的信息泄露
/api/attr/getBlockAttrs 未过滤,暂未发现其导致的信息泄露
/api/attr/batchGetBlockAttrs 未过滤,暂未发现其导致的信息泄露
/api/asset/resolveAssetPath 无需过滤
/api/asset/getFileAnnotation 无需过滤
/api/asset/getUnusedAssets 无需过滤
/api/asset/getMissingAssets 无需过滤
/api/asset/getDocImageAssets 已过滤
/api/asset/getDocAssets 已过滤
/api/export/preview 已过滤
/api/av/renderAttributeView 已过滤
/api/av/getAttributeViewKeys 已过滤
/api/av/getAttributeViewKeysByID 未过滤,暂未发现其导致的信息泄露
/api/av/getCurrentAttrViewImages 未过滤,暂未发现其导致的信息泄露
/api/av/changeAttrViewLayout 未过滤,暂未发现其导致的信息泄露
/api/av/setAttrViewGroup 无需过滤
/api/av/batchReplaceAttributeViewBlocks 无需过滤
/api/av/getAttributeViewAddingBlockDefaultValues 无需过滤
/api/av/getAttributeViewBoundBlockIDsByItemIDs 无需过滤
/api/av/getAttributeViewItemIDsByBoundIDs 无需过滤

@liudixian
Copy link

对,不搞敏捷开发。业务逻辑、交互方式要仔细琢磨。 我把我在 #11928 的留言搬过来。

既然有私域分享的需求,不妨一步到位做好一点。需考虑这种情况,就是面对不同的群体,分享不同的内容。 UI就这样设计:

Image UI就像我上面这样设计就好了,单击眼睛图标展开群组菜单,点击不同的群组选项进入相应群组的权限控制页面。页面内仍然通过switch来控制文档可见性,简单明了。建议先实现“完全公开”的控制,在下一个版本再实现面向不同群体的私域分享。 也不用搞 “publishAccess.json" 了,给每个文档都增加一个group属性,group的意思就是向哪些群体公开。 group是一个多选项,取值可以有:
  • public
  • link-only (用户自定义)
  • colleague (用户自定义)
  • client (用户自定义)
  • family (用户自定义)
  • ……

比如某文档的属性如下: { "id": "xxxxxxxxx", "group": ["public", "colleague"] } 默认就只有一个群组,就是public(完全公开),目录树可见,无需密码,可链接访问。其它群组全是用户自定义的。 对于用户自定义的群组,可以设置该群组是否需要密码,是否与public取并集/取交集。自定义群组的链接格式如下: http://192.168.0.2:6808/?group=client http://192.168.0.2:6808/?group=client&id=xxxxxxxxx 某自定义群组的属性如下:

{
  "group-id": "family",
  "group-name": "家人",
  "password": "123456",
  "union-or-intersection-with-public": "union"
}

这个好呀!我现在就有这样的需求,虽然思源是面向个人的。但是现在很多人也在通过搭建知识库来进行社区运营和管理,权限分组挺重要的。因为社区不应该只是单一作者贡献,而应该可以支持共创才好。希望能够支持这个特性!

@liudixian
Copy link

我可以帮忙提前测试,请问这个测试版本的docker镜像,应该下载哪个文件?
屏幕截图 2025-10-31 165233

@fyislo
Copy link

fyislo commented Oct 31, 2025

我可以帮忙提前测试,请问这个测试版本的docker镜像,应该下载哪个文件? 屏幕截图 2025-10-31 165233

docker的话,下载倒数第二个,然后自己打包。

@liudixian
Copy link

思源有没有可能实现文档级别的读写权限控制呀?

@YuxinZhaozyx
Copy link
Author

思源有没有可能实现文档级别的读写权限控制呀?

这个大概不是发布服务该完成的事,发布服务是完全只读的。你上面提到的这种多人共创的模式应该是对网络伺服的改进。

@liudixian
Copy link

[https://github.com/liudixian/siyuan_multiUserPublish 我让ai帮忙实现了一个多用户群组管理的发布功能,共各位参考。

image 设置界面多了群组选项,以及用户权限截止日期 image

这是可见性这边可以勾选所在群组

image 不在群组内的会显示禁止访问。

有大佬愿意贡献的话,可以继续完善功能。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Short Term

Development

Successfully merging this pull request may close these issues.

6 participants