Skip to content

Latest commit

 

History

History
353 lines (243 loc) · 15.9 KB

prd_cn.md

File metadata and controls

353 lines (243 loc) · 15.9 KB

通用信息

系统结构-按耦合度区分

  • Librarian 服务端
    • Sephirah 核心逻辑,Librarian的访问入口,不会向外部系统发出连接
    • Mapper 图数据库封装
    • Porter 外部系统接口封装
    • Searcher 搜索引擎封装
  • Waiter 客户端
  • Sentinel 监控端,用于特定功能

系统结构-按功能区分

功能模块名取自《废墟图书馆》,仅作为区分,没有实际含义
功能模块之间可能存在无法避免的代码耦合
区分功能模块的目的不是为了让每个模块都能独立运行,而是从宏观上划分系统中的各种功能

  • Tiphereth 用户与账户模块,提供用户信息存储、登录令牌的生成、身份校验等功能
  • Gebura 游戏商店模块,为任何游戏或应用提供游戏信息存储、游戏时长统计、存档备份等功能
  • Yesod 信息流阅读器模块,在实现RSS阅读器的基础上,提供更加丰富的信息流获取与展示功能
  • Binah 二进制传输模块,所有二进制数据均通过此模块传输
  • Netzach 通知与推送模块,提供推送端点配置,通知路由等功能
  • Angela 当功能逻辑需要跨越不同模块实现时,放入此模块中以标识该部分代码具有较高的耦合度

用户与账户(Tiphereth)

用户指本系统内能够登录的角色;账户指第三方系统中的用户

涉及页面:登录、用户管理、账户管理

用户权限

权限设计使用简单的硬编码的“用户-角色-权限”结构

用户分AdminNormalSentinel三种角色:

  • Admin 能够访问除个人敏感数据外的所有数据
  • Normal 能够访问自己的和其他人公开的数据
  • Sentinel 扫描器专用,仅能访问非常有限的接口

用户鉴权

认证流程

认证采用双token机制,access_token用于每次调用的鉴权,refresh_token用于续期

  • 除登录接口外的接口,除特殊规定,均需要access_token
  • 在需要认证的请求中设置 Bearer Token,值为该接口要求使用的token
  • 需要考虑Web平台的安全性】客户端可以持久化储存token,但不应尝试解析token
客户端
  1. 客户端通过GetToken接口获取access_tokenrefresh_tokenaccess_token的有效期大约为几个小时,refresh_token的有效期大约为几天,客户端不需要关心准确的过期时间
  2. 客户端使用access_token访问其他接口
  3. 需确认实现难度】若服务端因access_token过期拒绝访问接口,则客户端通过RefreshToken接口获取新的access_tokenrefresh_token
  4. 若服务端因refresh_token过期拒绝给出新token,则客户端回到第一步。若成功获取到新token,则客户端回到第二步
  • 提前调用RefreshToken接口不会使旧的access_token立即失效,但更旧的access_token可能立即失效(根据服务端的安全策略而定)
服务端

JWT是一个token生成规范,是通过将一个包含数字签名的明文json序列化生成的,服务端依靠数字签名保证其不可伪造。服务端所有种类的token都通过jwt生成,遵循以下要求

  • jwt是明文,所以不应包含敏感信息
  • access_token 可以不在服务端存储,token中需要设置字段以使服务端能够识别用户和token有效期
  • refresh_token 必须在服务端存储,使用时以服务端存储的数据为准,token中只需要设置必要的字段
  • 由于jwt中的json没有字段规范,任何功能都不应依赖于让客户端解析jwt中的字段

安全性

暴力破解
  • 登录接口需要通过必要的手段防止暴力破解,由于系统设计是私有化部署,可以选择封禁ip等较激进的措施
  • 其他接口由于只需要通过计算验证签名即可验证token的有效性,验证过程不需要访问存储服务,所以可以有效地保护
中间人攻击
  • 强制使用tls加密连接,可以避免大多数的攻击
  • access_token 由于每次传输都会携带,所以最有可能泄露,但其有效期短,且不能用于生成新token,造成的影响有限
  • refresh_token 由于是在服务端存储,仅能使用一次,若泄露后到用户刷新token这段时间内没有被使用,则token失效;若被使用了,则用户能够从服务端得知可能存在泄露

用户管理(User)

系统初始必须有一个可用的Admin用户,用户权限如下:

  • Admin 能够管理包括其他Admin在内的所有用户,不同Admin之间不设保护
  • Normal 能够管理自己(复用或设计单独的页面)。能够创建和管理自己的Sentinel
  • Sentinel 没有任何权限

任何密码修改操作都必须携带被修改账号的原密码

账户管理(Account)

绑定账户的用途会在需要的时候介绍

系统初始没有账户信息,账户信息有两种来源,只有系统支持该平台以后才能绑定

  1. 用户通过绑定生成的账户信息
  2. 系统在自动化收集信息时自动创建的账户信息

一个平台的一个账户只能同时绑定一个用户,一个用户每个平台最多绑定一个账户。 绑定时系统不验证用户与账户的同一性,目前阶段用户禁止绑定第二种来源生成的账户

解绑只删除绑定关系,不删除账户数据

用户权限:

  • AdminNormal均可绑定与解绑账户

文件传输(Binah)

所有需要传输二进制文件的接口均由此模块完成实际的传输工作

收发接口通过upload_tokendownload_token鉴权,遵循以下要求

  • 两种token由其他接口生成,生成token时服务端已得知待传输文件的名称大小等信息,服务端能够通过token得知这些信息
  • 两种token有效期不应过长,upload_token在上传成功后立即失效,download_token不限制下载次数
  • 在上传时,上传接口能够根据token信息实现服务端的后续逻辑

上传

sequenceDiagram
    participant C as Client
    participant F as FunctionInterface
    participant T as TransferInterface
    C->>+F: require to upload file
    F->>F: check request
    F->>-C: accept with `upload_token`
    C->>+T: start upload file
    T->>T: check token
    loop
        C-->>T: file bytes
        T-->>C: bytes recieved
    end
    T->>T: check file
    T-->>+F: file recieved, do the rest
    F-->>-T: done
    T->>-C: upload success
Loading

下载

sequenceDiagram
    participant C as Client
    participant F as FunctionInterface
    participant T as TransferInterface
    C->>+F: require to download file
    F->>F: check request
    F->>-C: accept with `download_token`
    C->>+T: start download file
    T->>T: check token
    loop
        T-->>C: file bytes
        opt advanced transfer
            C-->>T: require exact chunk
        end
    end
    T->>-C: download finish
Loading

游戏商店(Gebura)

基本功能与steam等游戏商店相同,以游戏为主软件工具为辅

涉及页面:商店、库存、游戏文件管理、游戏存档管理(可能会在同一个页面上,以实际UI设计为准)

游戏信息(App)

有以下两种来源:

  • 用户手动填写的 InternalApp
  • 系统自动收集的 ExternalApp
    • 例如:用户绑定Steam账户后,系统自动获取该Steam账户拥有的游戏并将游戏信息存入系统
    • 需细化】在系统新增了与游戏有关的内容时尝试自动匹配

App仅存储游戏的基本信息,这里主要需要解决不同来源的游戏信息的匹配问题: InternalAppExternalApp都各自存入数据库中,然后通过自动或手动的方式进行绑定(类似于前文中用户与账户的关系)。 对于拥有绑定关系的App,客户端需要合并为同一个App显示。在合并时,通过固定优先级或用户自定义优先级的方式选择显示哪个来源的App的信息

一个ExternalApp最多且必须绑定一个InternalApp,一个InternalApp每个平台最多绑定一个ExternalApp

用户权限:

  • ExternalApp的信息禁止编辑
  • NormalSentinel可以通过一些操作触发系统的自动行为
  • InternalApp的编辑、绑定关系的编辑仅限Admin

游戏文件(AppPackage)

有以下两种来源:

  • 用户手动填写
  • Sentinel 上报(不涉及客户端,将在Sentinel部分详细解释)

AppPackage存储了一个游戏文件的信息,这些信息指向一个具体的二进制文件或“最新版本”, 但系统内并不会存储这个文件,所以无法保证文件的可访问性。
AppAppPackage是一对多的关系,每个AppPackage最多从属于一个App,多个AppPackage表示一个App的多个版本

用户权限:

  • 所有用户均可拥有自己的AppPackage,可以绑定到任意一个InternalApp上,可以选择公开给其他用户
  • AdminNormal能够管理自己创建的Sentinel拥有的AppPackage
  • AdminNormal具有同等权限,不可管理他人的AppPackage

时长统计(AppPackageRunTime)

  • 客户端记录每个AppPackage的运行时间,每次运行生成一条AppPackageRunTime信息,包含原始启动及关闭时间, 记录的准确性完全依靠客户端维护及验证,服务端不做任何校验
  • 服务端在AppAppPackage维度上统计总时长、最后启动时间

用户权限:

  • AdminNormal能够增加或删除自己的AppPackageRunTime,不能修改,可以选择公开给其他用户

游戏存档配置文件(AppPackageSaveDataConfig)

  • 用户在客户端生成配置文件
  • AppPackageAppPackageSaveDataConfig是一对多的关系
  • AppPackageSaveDataConfig在创建时必须指定所关联的AppPackage并且不能修改(客户端可以为复用配置文件提供便利)

用户权限:

  • AdminNormal能够创建自己的AppPackageSaveDataConfig,可以选择公开给其他用户

配置文件为有效的json字符串,schema定义:v1

  • 配置文件必须声明schema
  • 配置文件中不应出现schema定义以外的值
  • 每个entry包含了一个特定路径的配置,通常情况下仅需要一个
    • pathMode路径模式否则必须为相对路径,相对路径的起始路径由具体设置决定
      • absolute路径必须为绝对路径
      • game路径必须为相对路径,以用户设置的游戏可执行文件所在路径为起始(该路径由客户端持久化存储,不是本配置文件的一部分)
      • document路径必须为相对路径,以用户文档目录为起始
      • profile路径必须为相对路径,以用户主目录为起始
    • path路径信息,内容必须为有效的路径(Windows平台下使用Windows平台格式,相对路径分隔符使用正斜杠/),若为文件则以文件名结尾,若为文件夹则以/结尾
    • id唯一标识符,生成的备份文件中应当有一个同名文件夹,文件夹内容为依据本entry定义应当备份的文件

游戏存档(AppPackageSaveData)

服务端

  • 一份存档为一个有效的zip文件,上传时服务端进行文件大小和checksum检查,但不检查文件内容
  • 除二进制文件外,还需要储存每份存档的生成时间、checksum等基本信息
  • 对于每个用户的每个AppPackage,支持有限数量的滚动存档,上传时只能上传一份新存档,自动覆盖最旧的备份,下载时不设限制。删除旧存档时,可以仅删除二进制文件但保留基本信息
  • 对于每个用户的每个AppPackage,支持有限数量的固定存档,可以将任意可用的滚动存档设为固定存档,设置后即使滚动存档被覆盖,仍然可以通过固定存档入口获取

客户端

  • 滚动存档
    • 支持启动游戏前检查存档更新,游戏关闭后上传存档
    • 需确认可行性】游戏进程未正常退出时,询问用户是否上传本次存档
    • 支持下载还原
  • 固定存档
    • 支持设置与下载还原

存档生成与还原规则:

  • 文件
    • 备份文件必须是一个有效的zip文件
    • 备份文件中的所有文件名、文本文件等文本内容均使用 UTF-8 编码
    • 备份文件中必须有一个名为tuihub_savedata_config.json的配置文件,内容参考v1-example
    • 备份文件中的其他内容必须遵循配置文件的设置
  • 备份
    • 依据用户预先设置的配置文件生成备份
    • 不应出现除读取之外的任何io操作
  • 还原
    • 依据待还原文件中的配置文件执行
    • 当出现无法修复的错误导致无法完成还原时应当自动回滚

传输

传输的实际操作由Binah执行,在客户端需要上传或下载文件时

  1. 客户端请求存档传输,服务端进行权限校验和字段验证
  2. 服务端通过Binah生成upload_tokendownload_token,返回给客户端
  3. 客户端调用Binah的接口执行传输过程
  4. 在传输的过程中和结束时通过服务端内部逻辑,Binah调用与存档相关的后处理逻辑。服务端应正确设置token内容以便可以从中读出需要执行的后处理逻辑

待定内容

需要考虑安全性及可行性:

  • AppPackage可以有全局的特殊存档(即,所有用户均拥有只读权限),内容为全存档/修改数值的存档等 AppPackage全局存档放入对应AppPackage
  • AppPackage可以有全局存档配置文件(即,所有用户均拥有只读权限),内容为默认存档配置
  • 对于相同游戏引擎(存档位置相同),全局存档配置是在每个AppPackage存储相同的一份,还是仅存储一个引用
  • 添加正则filters(部分游戏引擎存档有平台相关内容,备份还原时需要排除)以及filters优先级

需要确定打包规则:

指定固定文件名的json文件作为配置文件,打包时包括所有存档文件和此配置文件
打包时,重命名各个Entry对应文件/文件夹为配置中Id项,还原时,恢复为配置中OriginalName

信息流聚合(Yesod)

与常规的RSS阅读器类似,但更加专用,会针对具体平台优化

涉及页面:源管理、时间线

Feed源管理(FeedConfig)

仅支持用户手动设置

支持两种类型的源

  • 通用类型:符合RSS标准的源。即使不同用户设置了同一个url的源,服务端也要作为不同的源处理
  • 专用类型:依靠服务端内置的逻辑将特定来源的信息归一化为系统内的Feed格式

获取全文

暂无计划

Feed阅读器

UI为时间线+详情的结构(参考B站、微博、推特、GitHub等平台)

  • 用户设置的所有Feed源的信息按时间顺序排列在时间线上,支持按照作者或平台过滤
  • 支持显示html文本
  • 需要论证可行性】当同一个源的信息过多时折叠显示

消息推送(Netzach)

用户可配置的第三方平台消息推送

涉及页面:推送平台管理,推送路由管理

平台管理(NotifyTarget)

在用户配置了推送平台之后才能进行推送

  • 推送平台需要得到服务端的支持,没有通用配置
  • 每个用户均可配置任意数量的NotifyTarget,仅自己可见
  • 配置内容为平台类型和授权token

路由管理(NotifyFlow)

推送路由配置了哪些信息应该被推送到哪些平台

随着功能的增加,可以预见路由配置将会变得越来越复杂

  • 每个路由都支持多个消息源和多个目标
  • 每个用户均可配置任意数量的NotifyFlow,仅自己可见
  • 当用户配置多个路由时,服务端不会检查它们之间是否发生了重合

已支持或将要支持的消息源及目标平台

消息源

  • 来自Yesod的Feed信息

目标平台

  • Telegram
  • Yesod提供的Feed端点

服务端逻辑(Angela)

这是一个抽象模块,用于集中描述服务端内部需要支持的逻辑

待补充