Compare commits
No commits in common. "5d83a122b38b9cd63dc54cddb95c3e2cf18ab111" and "b8fa107d24cd653592e014e6f50f625f43a212e3" have entirely different histories.
5d83a122b3
...
b8fa107d24
@ -1,2 +0,0 @@
|
|||||||
schema: spec-driven
|
|
||||||
created: 2026-10-10
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
## Context
|
|
||||||
|
|
||||||
脚手架进入 Phase 0 地基。`openspec/specs/shared/` 当前为空,本 change 产出 platform / data-model / api-contract 三个 capability(见 proposal.md)。技术栈已定:MySQL + Prisma + NestJS 12(后端)、Vue 3(前端)。
|
|
||||||
|
|
||||||
## Goals / Non-Goals
|
|
||||||
|
|
||||||
**Goals:**
|
|
||||||
- 给出 shared 三层的技术实现方案:DB schema、命名、鉴权、多租户、数据权限、软删。
|
|
||||||
- 产出可直接落为 Prisma schema 与 NestJS 骨架的字段字典与契约约定。
|
|
||||||
|
|
||||||
**Non-Goals:**
|
|
||||||
- 不写产品代码(本 change 只出设计;实现走后续 apply)。
|
|
||||||
- 扩展域(POST/NOTICE/JOB/FILE/MSG)后置。
|
|
||||||
- 前端具体页面/组件设计(属 Phase 1)。
|
|
||||||
|
|
||||||
## Decisions
|
|
||||||
|
|
||||||
### D1 数据库与 ORM:MySQL 8 + Prisma
|
|
||||||
选 Prisma 而非 TypeORM/Drizzle:`schema.prisma` 天然就是字段字典的单一载体,类型安全最强,迁移工具(prisma migrate)成熟;与「data-model 字段字典为唯一锚点」的约定严丝合缝。
|
|
||||||
备选:TypeORM(NestJS 原生但类型安全弱)、Drizzle(轻量但生态新)。
|
|
||||||
|
|
||||||
### D2 命名:表 `sys_` 前缀,列 snake_case
|
|
||||||
表名带 `sys_` 前缀,避免与 fork 后的业务表冲突。Prisma 模型名不带前缀(`User`/`Role`/`Resource`),用 `@@map("sys_user")` 映射表名、`@map("created_at")` 映射列名——代码干净、DB 清晰。
|
|
||||||
|
|
||||||
### D3 主键:UUID v7(存 CHAR(36))
|
|
||||||
选 UUID v7 而非自增/雪花:全局唯一、时间有序(索引友好)、多租户合并/分布式安全、不泄露业务量。v7 的时间有序缓解字符串主键的索引性能问题。
|
|
||||||
|
|
||||||
### D4 时间:DB 存 UTC DATETIME(3),API 用 Unix 毫秒
|
|
||||||
分层:DB 用 DATETIME(3)(可读、可 SQL 函数、Prisma 原生 DateTime);API 层统一 Unix 毫秒 number(无时区歧义、前端 `new Date(ms)` 直显)。**单位统一毫秒**,写死在 api-contract。
|
|
||||||
|
|
||||||
### D5 删除:业务软删 + 日志/会话硬删
|
|
||||||
业务实体带 `deleted_at`,删除即置值;`sys_audit_log`/`sys_login_log`/`sys_refresh_token` 只增或硬删。查询统一 `deleted_at IS NULL` 过滤。
|
|
||||||
|
|
||||||
### D6 认证:JWT access + refresh 旋转
|
|
||||||
- access:JWT,2h 过期,payload `{ sub, tenantId, jti }`。
|
|
||||||
- refresh:随机串(jti),存 `sys_refresh_token`(含 ip/ua/login_at),7d 过期,可撤销。
|
|
||||||
- 旋转:换发时作废旧 refresh、签发新 refresh,防重放。
|
|
||||||
- 登出/踢人 = 置 `revoked_at`。
|
|
||||||
|
|
||||||
### D7 三级鉴权守卫
|
|
||||||
公开接口(login/captcha/health)无 token;未登记接口仅校验 access;登记为 `type=api` 的接口校验 access + `code`(权限标识)。装饰器 `@RequirePermissions('system:user:list')` 比对用户角色集合。
|
|
||||||
|
|
||||||
### D8 多租户过滤
|
|
||||||
所有业务表带 `tenant_code`;通过 Prisma 扩展 client / middleware 在查询入口统一注入 `tenant_code = 当前租户` 条件,避免每处手写。登录时按 `tenantCode` 定位租户。
|
|
||||||
|
|
||||||
### D9 数据权限过滤
|
|
||||||
`role.data_scope ∈ {全部/本部门/本部门及以下/本人/自定义}`;列表查询前按用户角色集计算可见 `org_id` 集合,统一注入 `org_id IN (...)`;「自定义」查 `sys_role_org`。
|
|
||||||
|
|
||||||
### D10 枚举:VARCHAR + TS 应用层枚举
|
|
||||||
Prisma/MySQL 原生 enum 迁移困难,故用 VARCHAR 存值 + TS `const` 枚举校验;枚举值集中定义在 shared/data-model。
|
|
||||||
|
|
||||||
### D11 关联键:业务键优先,用户例外用 id
|
|
||||||
所有跨实体引用优先以业务键而非主键 id:角色/资源/组织/字典类型/租户用 code,树的父引用用 parent_code;对用户的引用用用户 id。理由:业务键稳定、可读、可预置,代码里 `@RequirePermissions('system:user:list')` 直接引用,无需查 id。resource.code 兼作按钮/接口的权限标识。
|
|
||||||
|
|
||||||
## 字段字典(字段以 shared/data-model 为源)
|
|
||||||
|
|
||||||
### 公共字段(业务软删实体通用)
|
|
||||||
|
|
||||||
| 列 | 类型 | 说明 |
|
|
||||||
|---|---|---|
|
|
||||||
| id | CHAR(36) PK | UUID v7 |
|
|
||||||
| tenant_code | VARCHAR(64) NOT NULL | 租户(sys_tenant 自身无) |
|
|
||||||
| created_at | DATETIME(3) | UTC |
|
|
||||||
| created_by | CHAR(36) NULL | 创建人 user_id |
|
|
||||||
| updated_at | DATETIME(3) | UTC |
|
|
||||||
| deleted_at | DATETIME(3) NULL | 软删标记 |
|
|
||||||
|
|
||||||
### 实体特有字段
|
|
||||||
|
|
||||||
| 表 | 特有字段 |
|
|
||||||
|---|---|
|
|
||||||
| sys_tenant | code(租户内唯一)、name、status(enabled/disabled)、remark |
|
|
||||||
| sys_user | username、password_hash、nickname、email、phone、avatar、status(enabled/disabled/locked)、org_code |
|
|
||||||
| sys_role | code(租户内唯一)、name、data_scope(all/dept/dept_and_child/self/custom)、status、remark |
|
|
||||||
| sys_resource | parent_code、type(menu/button/api)、code(租户内唯一,兼权限标识)、name、path、component、method(GET/POST/PUT/DELETE)、api_path、icon、sort、status |
|
|
||||||
| sys_org | parent_code、code(租户内唯一)、name、leader、sort、status |
|
|
||||||
| sys_dict_type | code(租户内唯一)、name、status、remark |
|
|
||||||
| sys_dict_item | dict_type_code、label、value、sort、status |
|
|
||||||
| sys_config | key、value、remark |
|
|
||||||
| sys_audit_log | user_id、username、module、action、method、path、params(TEXT)、result(TEXT)、status、error_message、ip、user_agent、duration_ms |
|
|
||||||
| sys_login_log | username、ip、user_agent、status(success/fail)、message |
|
|
||||||
| sys_refresh_token | user_id、jti(UNIQUE)、token_hash、ip、user_agent、login_at、expire_at、revoked_at |
|
|
||||||
| sys_user_role | user_id、role_code |
|
|
||||||
| sys_role_resource | role_code、resource_code |
|
|
||||||
| sys_role_org | role_code、org_code |
|
|
||||||
|
|
||||||
> 日志/会话类(audit_log/login_log/refresh_token)无 deleted_at,只带 created_at。
|
|
||||||
|
|
||||||
## Risks / Trade-offs
|
|
||||||
|
|
||||||
- [未登记接口默认放行 → 漏登记敏感接口即裸奔] → 约定:写操作/敏感查询一律登记为 `type=api` 资源,仅真正公开的留白;评审时抽查。
|
|
||||||
- [refresh 旋转的并发窗口] → 旧 refresh 在极短窗口内仍可用的容忍策略;必要时按 user 串行化刷新。
|
|
||||||
- [UUID 字符串主键索引/空间开销] → 用 v7 时间有序 + 覆盖索引,避免随机 UUID 的页分裂。
|
|
||||||
- [多租户+软删过滤需全局注入] → Prisma 扩展 client 统一处理,杜绝散落的手写 WHERE。
|
|
||||||
|
|
||||||
## Migration Plan
|
|
||||||
|
|
||||||
纯新增(无既有数据),`prisma migrate` 直接建表;无回滚压力(地基阶段可 drop 重建)。
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
## Why
|
|
||||||
|
|
||||||
通用系统管理脚手架需要一个可复用的「地基」——共享契约(全局规范 / 数据模型 / API 契约),
|
|
||||||
作为前后端开发的唯一锚点。当前 `openspec/specs/` 为空,无字段字典、无接口契约,
|
|
||||||
前后端无法按同一套字段名与接口 shape 对齐。现在启动 Phase 0,先把地基立起来。
|
|
||||||
|
|
||||||
## What Changes
|
|
||||||
|
|
||||||
- 新增 `shared/platform`:全局规范(设计令牌 / 文案 / URL 契约 / 隐私红线)。
|
|
||||||
- 新增 `shared/data-model`:数据模型(实体 + 枚举 + 状态机 = 字段字典),含 DB 设计。
|
|
||||||
- 新增 `shared/api-contract`:API 契约(endpoint + 请求/响应 shape + 统一封装 / 错误码 / 分页约定)。
|
|
||||||
- 落定核心设计决策:多租户 `tenant_id` 隔离、资源表 `RES`(菜单/按钮/接口合一)、
|
|
||||||
数据权限 `data_scope`、审计字段、软删策略、`sys_` 表前缀、字段命名与时间约定。
|
|
||||||
|
|
||||||
## Capabilities
|
|
||||||
|
|
||||||
### New Capabilities
|
|
||||||
|
|
||||||
- `shared/platform`: 跨前后端全局规范(设计令牌、文案、URL 契约、隐私红线)。
|
|
||||||
- `shared/data-model`: 数据模型 / 字段字典(实体、枚举、状态机、公共字段约定、DB 设计)。
|
|
||||||
- `shared/api-contract`: API 契约(endpoint、请求/响应 shape、统一封装、错误码、分页、鉴权约定)。
|
|
||||||
|
|
||||||
### Modified Capabilities
|
|
||||||
|
|
||||||
(无——本 change 为首次建立 shared 层,不修改既有 capability。)
|
|
||||||
|
|
||||||
## Impact
|
|
||||||
|
|
||||||
- 影响范围:`openspec/specs/shared/` 下新增 3 个 capability(platform / data-model / api-contract)。
|
|
||||||
- 后续关联:`specs/frontend/`、`specs/backend/` 将引用这些 SH 契约作为字段与接口的唯一锚点。
|
|
||||||
- 本 change 仅产出规格(spec),不含源码改动;实现走后续 apply。
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
## Purpose
|
|
||||||
|
|
||||||
定义所有接口的统一契约:响应封装、错误码、分页、鉴权层级与认证接口,作为前后端联调的唯一锚点。
|
|
||||||
|
|
||||||
## ADDED Requirements
|
|
||||||
|
|
||||||
### Requirement: 统一响应封装
|
|
||||||
所有接口 SHALL 返回 `{ code, message, data }` 结构;code=0 表示成功。
|
|
||||||
|
|
||||||
#### Scenario: 成功响应
|
|
||||||
- **WHEN** 接口处理成功
|
|
||||||
- **THEN** 返回 code=0、message=ok、data 为业务数据
|
|
||||||
|
|
||||||
#### Scenario: 失败响应
|
|
||||||
- **WHEN** 接口处理失败
|
|
||||||
- **THEN** 返回非 0 code 与可读 message,data 为空
|
|
||||||
|
|
||||||
### Requirement: 错误码分段
|
|
||||||
错误码 SHALL 与 HTTP 状态对齐分段:401xx 认证、403xx 授权、400xx 参数、404xx 资源、409xx 冲突、500xx 系统。
|
|
||||||
|
|
||||||
#### Scenario: 未登录
|
|
||||||
- **WHEN** 未携带有效 token 访问受保护接口
|
|
||||||
- **THEN** HTTP 401,code 为 401xx 段
|
|
||||||
|
|
||||||
### Requirement: 分页约定
|
|
||||||
列表接口 SHALL 使用 page/pageSize 分页,返回 `{ list, total, page, pageSize }`。
|
|
||||||
|
|
||||||
#### Scenario: 分页查询
|
|
||||||
- **WHEN** 客户端传 page=1&pageSize=20
|
|
||||||
- **THEN** 返回 data 含 list、total、page、pageSize
|
|
||||||
|
|
||||||
### Requirement: 三级鉴权
|
|
||||||
接口 SHALL 分为三级:公开接口无需 token;未登记接口仅需登录;登记为「接口」资源的接口需 token 且当前用户具备对应 code(权限标识)。
|
|
||||||
|
|
||||||
#### Scenario: 未登记接口
|
|
||||||
- **WHEN** 已登录用户访问未登记为资源的接口
|
|
||||||
- **THEN** 校验通过(仅需登录态)
|
|
||||||
|
|
||||||
#### Scenario: 登记接口越权
|
|
||||||
- **WHEN** 已登录用户访问登记为接口资源、但自身角色无该 permission 的接口
|
|
||||||
- **THEN** 系统返回 403
|
|
||||||
|
|
||||||
### Requirement: 认证接口
|
|
||||||
系统 SHALL 提供登录、刷新令牌、登出接口;登录需 tenantCode+username+password,返回 access token 与 refresh token。
|
|
||||||
|
|
||||||
#### Scenario: 登录成功
|
|
||||||
- **WHEN** 用户提供正确的租户、账号与密码
|
|
||||||
- **THEN** 返回 access token(2h 过期)与 refresh token(7d 过期)
|
|
||||||
|
|
||||||
#### Scenario: 刷新令牌
|
|
||||||
- **WHEN** access 过期后客户端携带 refresh token 请求刷新
|
|
||||||
- **THEN** 系统签发新 access 与 refresh,并作废旧 refresh
|
|
||||||
|
|
||||||
### Requirement: 核心域接口目录
|
|
||||||
系统 SHALL 为每个核心域提供 REST 资源接口(复数、kebab-case):/users、/roles、/resources、/orgs、/dict-types、/configs、/audit-logs、/login-logs。
|
|
||||||
|
|
||||||
#### Scenario: 资源 CRUD
|
|
||||||
- **WHEN** 管理端操作某核心域
|
|
||||||
- **THEN** 通过对应复数资源路径进行增删改查
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
## Purpose
|
|
||||||
|
|
||||||
定义系统数据模型的字段字典:实体目录、公共字段、枚举、状态机与命名约定,作为前后端字段一致性的唯一锚点。
|
|
||||||
|
|
||||||
## ADDED Requirements
|
|
||||||
|
|
||||||
### Requirement: 业务实体公共字段
|
|
||||||
所有业务软删实体 SHALL 携带公共字段:id(UUID v7)、tenant_code、created_at、created_by、updated_at、deleted_at;日志/会话类实体不携带 deleted_at。
|
|
||||||
|
|
||||||
#### Scenario: 创建记录
|
|
||||||
- **WHEN** 创建任一业务实体记录
|
|
||||||
- **THEN** 系统自动填充 id、tenant_code、created_at、created_by
|
|
||||||
|
|
||||||
#### Scenario: 软删
|
|
||||||
- **WHEN** 删除业务实体
|
|
||||||
- **THEN** 系统置 deleted_at 而非物理删除
|
|
||||||
|
|
||||||
### Requirement: 实体目录
|
|
||||||
系统 SHALL 包含实体 tenant、user、role、resource、org、dict_type、dict_item、config、audit_log、login_log、refresh_token,以及关联表 user_role、role_resource、role_org。
|
|
||||||
|
|
||||||
#### Scenario: 字典拆分
|
|
||||||
- **WHEN** 维护数据字典
|
|
||||||
- **THEN** 字典分为 dict_type(类型)与 dict_item(项)两类,经 dict_type_code 关联
|
|
||||||
|
|
||||||
### Requirement: 资源类型与代码
|
|
||||||
resource 实体 SHALL 通过 type 字段区分菜单(menu)、按钮(button)、接口(api)三种类型;「目录」由菜单节点是否拥有菜单子节点推导,不设独立类型。每个 resource SHALL 拥有租户内唯一的 code,作为关联键与权限标识。
|
|
||||||
|
|
||||||
#### Scenario: 按钮鉴权点
|
|
||||||
- **WHEN** 前端需要按钮级权限
|
|
||||||
- **THEN** 该按钮登记为 type=button 的资源,并携带 code 权限标识
|
|
||||||
|
|
||||||
### Requirement: 引用键约定
|
|
||||||
所有跨实体引用 SHALL 优先使用业务键:角色、资源、组织、字典类型、租户用 code,树的父引用用 parent_code;对用户的引用 SHALL 使用用户 id。关联表 sys_user_role、sys_role_resource、sys_role_org 分别保存 user_id+role_code、role_code+resource_code、role_code+org_code;其余引用(user.org_code、dict_item.dict_type_code、resource.parent_code、org.parent_code)同理。
|
|
||||||
|
|
||||||
#### Scenario: 为角色分配资源
|
|
||||||
- **WHEN** 管理员为角色分配资源
|
|
||||||
- **THEN** 关联记录保存 role_code 与 resource_code
|
|
||||||
|
|
||||||
### Requirement: 数据权限档位
|
|
||||||
role 实体 SHALL 通过 data_scope 字段支持全部/本部门/本部门及以下/本人/自定义五档;「自定义」经 role_org 关联表声明可见部门。
|
|
||||||
|
|
||||||
#### Scenario: 本部门及以下
|
|
||||||
- **WHEN** 角色数据权限为「本部门及以下」
|
|
||||||
- **THEN** 该角色用户仅可见本部门及下级部门的数据
|
|
||||||
|
|
||||||
### Requirement: 命名与表前缀
|
|
||||||
所有脚手架表 SHALL 以 sys_ 前缀命名,数据库列名采用 snake_case。
|
|
||||||
|
|
||||||
#### Scenario: 表命名
|
|
||||||
- **WHEN** 新建脚手架表
|
|
||||||
- **THEN** 表名以 sys_ 开头,列名使用 snake_case
|
|
||||||
|
|
||||||
### Requirement: 用户状态机
|
|
||||||
user 实体 SHALL 支持启用/停用/锁定状态;停用与锁定的用户 SHALL 无法登录。
|
|
||||||
|
|
||||||
#### Scenario: 锁定登录
|
|
||||||
- **WHEN** 锁定用户尝试登录
|
|
||||||
- **THEN** 系统拒绝登录并提示账号已锁定
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
## Purpose
|
|
||||||
|
|
||||||
定义跨前后端、跨模块的全局规范:时间、多租户隔离、URL 契约与安全红线,作为所有 spec 的共同约束。
|
|
||||||
|
|
||||||
## ADDED Requirements
|
|
||||||
|
|
||||||
### Requirement: 统一时间戳格式
|
|
||||||
系统 SHALL 在 API 层以 Unix 毫秒时间戳(number)表示所有时间字段,前端负责本地化显示。
|
|
||||||
|
|
||||||
#### Scenario: 接口返回时间
|
|
||||||
- **WHEN** 任一接口返回时间字段
|
|
||||||
- **THEN** 该字段为 Unix 毫秒整数(number),不返回格式化字符串
|
|
||||||
|
|
||||||
### Requirement: 多租户数据隔离
|
|
||||||
所有业务数据 SHALL 归属某一租户;任何业务接口 SHALL 仅返回当前租户的数据。
|
|
||||||
|
|
||||||
#### Scenario: 跨租户越权
|
|
||||||
- **WHEN** 用户 A(租户 1)请求租户 2 的数据
|
|
||||||
- **THEN** 系统拒绝或返回空,绝不返回租户 2 的数据
|
|
||||||
|
|
||||||
### Requirement: URL 契约
|
|
||||||
所有 API SHALL 统一挂载在 `/api/v1` 前缀下。
|
|
||||||
|
|
||||||
#### Scenario: 版本前缀
|
|
||||||
- **WHEN** 客户端调用任一业务接口
|
|
||||||
- **THEN** 路径以 `/api/v1` 开头
|
|
||||||
|
|
||||||
### Requirement: 安全红线
|
|
||||||
系统 SHALL 不以明文存储或传输密码;日志 SHALL 对手机号、邮箱、密码等敏感信息脱敏。
|
|
||||||
|
|
||||||
#### Scenario: 密码存储
|
|
||||||
- **WHEN** 用户设置或修改密码
|
|
||||||
- **THEN** 系统仅存储不可逆哈希,绝不落明文
|
|
||||||
|
|
||||||
#### Scenario: 日志脱敏
|
|
||||||
- **WHEN** 记录操作/登录日志
|
|
||||||
- **THEN** 密码字段不落日志,手机号/邮箱部分打码
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
## 1. 后端工程地基
|
|
||||||
|
|
||||||
- [x] 1.1 在 sysmgr-nest 接入 Prisma + MySQL,配置 PrismaService 与连接
|
|
||||||
- [x] 1.2 配置全局响应封装拦截器(`{code, message, data}`)
|
|
||||||
- [x] 1.3 配置全局异常过滤器(错误码分段 400xx/401xx/403xx/404xx/409xx/500xx)
|
|
||||||
|
|
||||||
## 2. 数据模型落地
|
|
||||||
|
|
||||||
- [x] 2.1 编写 Prisma schema:tenant / user / role / resource / org / dict_type / dict_item / config
|
|
||||||
- [x] 2.2 编写 Prisma schema:audit_log / login_log / refresh_token / user_role / role_resource / role_org
|
|
||||||
- [x] 2.3 生成并执行首版 migration
|
|
||||||
- [x] 2.4 定义 TS 应用层枚举(status / resource type / data_scope 等)
|
|
||||||
|
|
||||||
## 3. 认证与鉴权
|
|
||||||
|
|
||||||
- [x] 3.1 实现密码哈希工具(argon2/bcrypt)
|
|
||||||
- [x] 3.2 实现登录接口(tenantCode + username + password → access + refresh)
|
|
||||||
- [x] 3.3 实现刷新接口(refresh 旋转,作废旧 token)
|
|
||||||
- [x] 3.4 实现登出 / 踢人(置 revoked_at)
|
|
||||||
- [x] 3.5 实现 JWT access 签发与校验守卫
|
|
||||||
- [x] 3.6 实现 @RequirePermissions 装饰器与权限守卫(三级鉴权)
|
|
||||||
|
|
||||||
## 4. 横切过滤器
|
|
||||||
|
|
||||||
- [x] 4.1 实现多租户 tenant_id 过滤(Prisma 扩展 client 统一注入)
|
|
||||||
- [x] 4.2 实现软删 deleted_at 过滤
|
|
||||||
- [x] 4.3 实现数据权限 data_scope 可见部门计算与 org_id 过滤
|
|
||||||
|
|
||||||
## 5. 核心域 CRUD
|
|
||||||
|
|
||||||
- [x] 5.1 租户管理 CRUD
|
|
||||||
- [x] 5.2 用户管理 CRUD(含密码重置、启停/锁定)
|
|
||||||
- [x] 5.3 角色管理 CRUD(含资源分配、data_scope)
|
|
||||||
- [x] 5.4 资源管理 CRUD(树形,menu/button/api)
|
|
||||||
- [x] 5.5 组织管理 CRUD(树形)
|
|
||||||
- [x] 5.6 字典管理 CRUD(类型 + 项)
|
|
||||||
- [x] 5.7 参数配置 CRUD
|
|
||||||
- [x] 5.8 操作日志 / 登录日志查询接口
|
|
||||||
|
|
||||||
## 6. 前端地基
|
|
||||||
|
|
||||||
- [x] 6.1 封装 API client(`{code,message,data}` 统一处理、token 注入、401 自动刷新)
|
|
||||||
- [x] 6.2 登录页 + 路由守卫(未登录跳转)
|
|
||||||
- [x] 6.3 对接认证接口(login / refresh / logout)
|
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 7738abbbfd3ddad6401a53a4cdaab643b1cc7908
|
Subproject commit 9730b9fd5e0bf75e53bfb24b4822c9ea68985165
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit d8d3055c737f605bef8e418869ff591592805d96
|
Subproject commit dc40ca3343dc84aa2de96c1025e01db88668a399
|
||||||
Loading…
x
Reference in New Issue
Block a user