存储插件引入与操作逻辑

1850 字
9 分钟
存储插件引入与操作逻辑

以S3插件安装为例

安装插件#

  1. 从仓库源安装s3插件
  2. 保存后存储源对s3插件生效
  3. 配置s3参数设置,点击保存生效插件
  4. 参数保存位置:
数据保存位置
存储源配置桌面端配置目录下的 storage-plugin-sources.json
Access Key、Secret Key、OAuth 等敏感凭据操作系统凭据存储,不写入 JSON
插件程序和 manifeststorage-plugins///
照片元数据服务端 PostgreSQL 的 Photo 表
上传成功但尚未登记的任务pending-storage-registrations.json

 

上传照片#

  1. 选择照片
  2. 选择存储源(s3插件)
  3. 上传照片

 

云端照片(S3)限制#

  1. 无法对通过插件上传的照片移动、删除,因为这涉及到对应存储源的操作,但可以修改其他不涉及到对存储源的操作,如相册、类型、备注等信息

 

插件交互方面#

  1. 安装插件后,上传以及其他在使用插件的过程中,不得对插件进行操作,避免数据损坏
  2. 安装插件后,允许卸载插件,但若重新安装插件时,其配置信息可以恢复

考虑场景#

官方存储源配置参数变更#

桌面端配置目录由 /D:/Projects/mo-gallery/mo-gallery-web/desktop/config/config.go:313 决定:

  • Windows:%APPDATA%\mo-gallery-desktop
  • macOS:~/Library/Application Support/mo-gallery-desktop
  • Linux:~/.config/mo-gallery-desktop

所以 Windows 上通常是:

%APPDATA%\mo-gallery-desktop\storage-plugin-sources.json

其中保存的是类似下面的非敏感信息:

{
"id": "source-uuid",
"name": "Official S3",
"pluginId": "com.example.s3",
"pluginVersion": "1.2.0",
"config": {
"endpoint": "https://s3.example.com",
"bucket": "photos",
"region": "auto",
"basePath": "gallery/"
},
"credentialRefs": {
"accessKey": "..."
},
"enabled": true
}

真正的密钥不会出现在这个文件里。代码会把凭据保存为类似:

mo-gallery-desktop/storage/<sourceId>/<credentialName>

的引用。Windows 当前使用 Windows Credential Manager;其他平台的凭据存储目前还没有完整实现。

因此,官方更换存储源参数时:

  • endpoint、bucket、region、basePath 等非敏感参数在 storage-plugin-sources.json 中更新;
  • Access Key、Secret Key 等需要重新写入系统凭据存储;
  • 只要 source ID、Bucket 和对象 key 空间不变,照片的 Photo 记录和远程文件都不需要迁移;
  • 如果换了 Bucket 或 key 规则,就必须迁移远程对象,并更新服务端 Photo.storageSourceId、storageKey 等字段。

还要注意:插件 manifest 中的 configSchema 只是描述“配置长什么样”,不是用户实际配置的存储位置。官方发布新版本时,应提供旧配置到 新配置的迁移逻辑;不能因为字段名改变,就直接丢弃用户本地的 source 配置。

另外,备份时不能只备份 storage-plugin-sources.json。它只包含凭据引用,不包含凭据值;完整恢复还需要同时处理操作系统凭据存储。

和StorageSource数据表的联系 #

  1. Web 存储源:服务端 StorageSource 表

prisma.schema 中的 StorageSource 表保存:

  • type:local、github、s3
  • endpoint、bucket、region、basePath
  • 加密后的 Access Key、Secret Key
  • public URL 等配置

当照片的:

storageRuntime = "web"

并且有 storageSourceId 时,服务端会把这个 ID 当作 StorageSource.id,通过 /D:/Projects/mo-gallery/mo-gallery-web/server/lib/ storage/config.ts:96 查询配置。

所以 Web S3 官方源修改参数时,直接更新同一条 StorageSource 记录即可。只要 Bucket 和 object key 没变,已有照片不需要修改。

  1. Desktop 插件存储源:桌面本地配置

当照片的: storageRuntime = "desktop-plugin"时,storageSourceId 保存的是桌面端插件 source 的 UUID。这个 UUID 对应的是:

%APPDATA%\mo-gallery-desktop\storage-plugin-sources.json中的 source,而不是服务端 StorageSource 表中的记录。

桌面端通过本地插件管理器解析这个 source,再从操作系统凭据存储中读取密钥。服务端只保存照片元数据,例如:

storageRuntime
storagePluginId
storageSourceId
storageKey
thumbnailStorageKey
url
thumbnailUrl

服务端不会保存 Desktop Credential Manager 中的实际凭据,也不能依靠 StorageSource 表去启动桌面插件。文档已经明确说明:桌面插件的storageSourceId 可以写入服务端,但不能假设它对应 StorageSource 行。

当前 Photo.storageSourceId 没有 Prisma 外键,原因就是它同时兼容两种运行时:

storageRuntimestorageSourceId 的含义
web服务端 StorageSource.id
desktop-plugin桌面本地插件 source UUID

因此:

  • 修改 Web 官方源:更新 PostgreSQL 的 StorageSource 行。
  • 修改 Desktop 官方源:更新桌面本地 storage-plugin-sources.json 和系统凭据。
  • 两者都应尽量保持 source ID 不变。
  • 不要为了“同步”而给每个桌面插件 source 在服务端 StorageSource 表里创建一条镜像记录,这会造成两套配置和凭据不一致。
  • 如果删除并重建 source 导致 ID 改变,就需要批量迁移照片的 storageSourceId;否则旧照片仍会指向原 source。

所以 StorageSource 表保存的是 Web 端的连接配置,不是所有插件存储源的总表,更不是照片文件本身的存储位置。照片文件仍然在 S3/R2 等远程 Bucket 中。

 


 

逐条核对

  • 安装:一致。必须先装插件(生产模式要求签名 verified)才能建存储源(desktop/storage_plugins/manager.go:401)。小修正:「保存」 只是落库,不会真正启动插件/校验配置;要等「连接测试」(TestSource → source.validate) 或首次上传时插件进程才启动生效。
  • 上传:一致。补充两点:插件上传走「原图+缩略图双对象」,按 fileHash+sourceID+key 幂等;对象上传成功但登记失败会进 pending- storage-registrations.json 等待重试,不是直接失败。
  • 云端限制:方向对,但要精确化。
    • Web 端确实拒绝对象操作:删除带 deleteOriginal/deleteThumbnail、移动(改 storagePath)、重上传、缩略图生成、颜色重分析,都 返回 409(hono/photos.ts:1246、:1617、:1861、:1914、:2061)。
    • 但「无法删除」只针对对象:Web 端仍可「仅解除关联」(两者都不勾时只删元数据,hono/photos.ts:1275);桌面端在插件在位时更是 可以正常「删对象+删元数据」(desktop/app.go:519)。
    • 相册/类型/备注等纯元数据修改不受限,这条是对的。
    • 补充:reanalyze-colors 也被拒,因为要重新读对象——这类「看着像元数据、实际碰对象」的操作需要归入限制范围。
  • 交互 1「使用中不得操作插件」:目前只是约定,没有强制。安装/升级路径不会先停 runtime(InstallPluginPackage → commitInstalledPackage 直接换目录,Windows 上可能因文件占用失败或旧进程继续跑旧代码);回滚会停 runtime 但不检查是否有正在上 传的任务;卸载/删 source 也不检查 in-flight 上传和 pending 任务。要落实这条,需要在安装/升级/回滚/卸载前检查插件是否 busy(有 上传任务则拒绝或排队)。 与你的预期不符的一点
  • 「允许卸载,重新安装时配置可恢复」:当前不满足。卸载前必须删掉所有 source;删 source 会同时删除配置(sources.json)和凭据 (desktop/storage_plugins/manager.go:452 → registry.remove → deleteSourceCredentials)。重新安装插件后,存储源配置和凭据都不 会自动恢复,用户要重建 source、重录凭据。
  • 要满足你的要求,二选一:
    • 卸载时保留 source 配置(标记为禁用/孤儿,不删凭据),重装后自动恢复;或
    • 提供「插件与存储源配置导出/导入」,凭据只导出引用、恢复时重录(凭据值本身不进导出文件)。 其他建议补充
  • 卸载前生成「受影响对象清单」:pending 登记任务 + 引用该插件的云端 Photo 数,确认后再删,避免远端对象变孤儿。
  • 安装/卸载/回滚补审计日志(目前照片/故事有日志,插件操作没有)。
  • 插件级「启用/停用」缺失(spec 承诺过):停用比卸载安全,可保留全部数据。
  • 升级后 configSchema 可能变化,旧配置可能不被新版本接受;升级前应提示导出配置,升级后强制 re-validate。

 

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

存储插件引入与操作逻辑
https://shaio.top/posts/03mogallery/插件系统/存储插件引入与操作逻辑/
作者
沙海
发布于
2026-09-02
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
沙海
Hello, I'm Shai.
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
84
分类
15
标签
48
总字数
67,035
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.12.2
文章许可
CC BY-NC-SA 4.0

文章目录