feat: 实现设备管理和设备导入功能,修复测试问题
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m30s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m30s
主要变更: - 实现设备管理模块(创建、查询、列表、更新状态、删除) - 实现设备批量导入功能(CSV 解析、ICCID 绑定、异步任务处理) - 添加设备-SIM 卡绑定约束(部分唯一索引防止并发问题) - 修复 fee_rate 数据库字段类型(numeric -> bigint) - 修复测试数据隔离问题(基于增量断言) - 修复集成测试中间件顺序问题 - 清理无用测试文件(PersonalCustomer、Email 相关) - 归档 enterprise-card-authorization 变更
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-01-26
|
||||
@@ -0,0 +1,166 @@
|
||||
## Context
|
||||
|
||||
当前系统的企业卡授权功能存在权限控制不当的问题。现有实现使用 `asset_allocation_record` 表记录授权关系,但该表设计用于资产分配而非授权管理。此外,授权逻辑未正确实现单卡授权限制,权限控制不够精细。
|
||||
|
||||
**现状问题**:
|
||||
- 授权记录存储位置不当(使用了资产分配表)
|
||||
- 缺少对已绑定设备的卡的授权限制
|
||||
- 企业可以看到不应该看到的商业敏感信息
|
||||
- 权限控制逻辑分散,没有统一的授权管理
|
||||
|
||||
**技术约束**:
|
||||
- 必须保持向后兼容,不能影响现有的卡分配功能
|
||||
- 需要遵循项目的 GORM 数据权限自动过滤机制
|
||||
- 不使用外键约束,关联通过代码层维护
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 实现真正的单卡授权,授权不转移所有权
|
||||
- 建立专用的授权记录表 `enterprise_card_authorization`
|
||||
- 实现细粒度的权限控制,保护商业敏感数据
|
||||
- 支持授权的创建、查询、回收全生命周期管理
|
||||
- 与现有的 GORM 数据权限过滤机制无缝集成
|
||||
|
||||
**Non-Goals:**
|
||||
- 不改变现有的卡分配(allocation)功能
|
||||
- 不支持设备级授权(已绑定设备的卡不能单独授权)
|
||||
- 不支持授权转移(必须先回收再重新授权)
|
||||
- 不实现授权审批流程(直接授权生效)
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. 新建专用授权表
|
||||
|
||||
**决策**:创建 `enterprise_card_authorization` 表专门管理授权关系
|
||||
|
||||
**理由**:
|
||||
- 授权和分配是两个不同的业务概念,应该分离存储
|
||||
- 专用表可以更好地记录授权历史(包括回收记录)
|
||||
- 避免污染现有的 `asset_allocation_record` 表结构
|
||||
|
||||
**备选方案**:
|
||||
- 复用 `asset_allocation_record` 表:会混淆授权和分配的概念,且表结构不完全匹配
|
||||
- 在 `iot_cards` 表添加授权字段:无法记录授权历史,且一张卡可能被多次授权/回收
|
||||
|
||||
### 2. 数据权限过滤集成
|
||||
|
||||
**决策**:通过修改现有的 IoT 卡查询逻辑,在 Store 层集成授权检查
|
||||
|
||||
**实现方式**:
|
||||
```go
|
||||
// 企业用户查询时的过滤逻辑
|
||||
if userType == UserTypeEnterprise {
|
||||
db = db.Where("owner_type = ? AND owner_id = ?", "enterprise", enterpriseID).
|
||||
Or(db.Where("id IN (?)",
|
||||
db.Table("enterprise_card_authorization").
|
||||
Select("card_id").
|
||||
Where("enterprise_id = ? AND revoked_at IS NULL", enterpriseID)))
|
||||
}
|
||||
```
|
||||
|
||||
**理由**:
|
||||
- 利用现有的 GORM Callback 机制,自动应用权限过滤
|
||||
- 保持查询接口不变,上层代码无需修改
|
||||
- 统一的权限控制点,易于维护
|
||||
|
||||
### 3. 敏感信息过滤
|
||||
|
||||
**决策**:在 Handler 层对响应数据进行后处理,移除敏感字段
|
||||
|
||||
**实现方式**:
|
||||
- Service 层返回完整数据
|
||||
- Handler 层检查用户类型,如果是企业用户则清空敏感字段
|
||||
- 敏感字段:`cost_price`、`distribute_price`、`supplier`
|
||||
|
||||
**理由**:
|
||||
- 保持 Service 层的通用性,不同场景可能需要不同的字段过滤
|
||||
- Handler 层更接近展示层,适合做展示相关的数据处理
|
||||
- 便于未来扩展不同用户类型的字段过滤规则
|
||||
|
||||
### 4. 批量授权接口设计
|
||||
|
||||
**决策**:提供单一的批量授权接口,不单独提供预检接口
|
||||
|
||||
**接口结构**:
|
||||
```go
|
||||
// 请求
|
||||
POST /api/admin/enterprises/{enterpriseId}/authorize-cards
|
||||
{
|
||||
"card_ids": [1, 2, 3]
|
||||
}
|
||||
|
||||
// 响应
|
||||
{
|
||||
"success": [
|
||||
{"card_id": 1, "iccid": "8986..."}
|
||||
],
|
||||
"failed": [
|
||||
{"card_id": 2, "iccid": "8986...", "reason": "卡已绑定设备"},
|
||||
{"card_id": 3, "iccid": "8986...", "reason": "卡状态不是已分销"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**理由**:
|
||||
- 减少网络往返,提高性能
|
||||
- 简化前端实现,一次调用获得所有结果
|
||||
- 支持部分成功的场景,提高容错性
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### 性能风险
|
||||
|
||||
**风险**:企业用户查询卡列表时需要 JOIN 授权表,可能影响查询性能
|
||||
|
||||
**缓解措施**:
|
||||
- 在 `enterprise_card_authorization` 表的 `enterprise_id` 和 `revoked_at` 字段建立联合索引
|
||||
- 在 `card_id` 字段建立索引支持反向查询
|
||||
- 考虑未来使用 Redis 缓存授权关系
|
||||
|
||||
### 数据一致性
|
||||
|
||||
**风险**:授权记录和卡状态可能不一致(如卡被删除但授权记录还在)
|
||||
|
||||
**缓解措施**:
|
||||
- 使用软删除,保留历史数据
|
||||
- 定期运行数据一致性检查任务
|
||||
- 在查询时过滤已删除的卡
|
||||
|
||||
### 权限泄露风险
|
||||
|
||||
**风险**:敏感信息过滤不完整可能导致商业数据泄露
|
||||
|
||||
**缓解措施**:
|
||||
- 在 Handler 层统一处理,确保所有接口都经过过滤
|
||||
- 添加单元测试验证敏感字段确实被过滤
|
||||
- 考虑使用 DTO 模式,为不同用户类型定义不同的响应结构
|
||||
|
||||
## Migration Plan
|
||||
|
||||
### 部署步骤
|
||||
|
||||
1. **数据库迁移**
|
||||
- 创建 `enterprise_card_authorization` 表
|
||||
- 添加必要的索引
|
||||
|
||||
2. **代码部署**
|
||||
- 部署新的授权管理代码
|
||||
- 保持旧的分配接口正常工作
|
||||
|
||||
3. **数据迁移**(如需要)
|
||||
- 如果有历史授权数据在 `asset_allocation_record` 表,编写迁移脚本
|
||||
- 迁移完成后可以清理旧数据
|
||||
|
||||
### 回滚策略
|
||||
|
||||
- 代码支持功能开关,可通过配置禁用新的授权功能
|
||||
- 数据库表独立,不影响现有功能,可保留表结构
|
||||
- 如需完全回滚,删除新表并恢复旧代码
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **授权有效期**:是否需要支持授权有效期?目前设计是永久授权直到主动回收
|
||||
2. **授权数量限制**:是否需要限制一个企业可以被授权的卡数量?
|
||||
3. **通知机制**:授权/回收时是否需要通知企业?
|
||||
4. **审计日志**:是否需要更详细的授权操作日志?
|
||||
@@ -0,0 +1,29 @@
|
||||
## Why
|
||||
|
||||
当前企业卡授权功能存在权限控制不当的问题,未真正实现单卡授权。需要改造现有功能,确保授权不转移所有权,实现精细化的权限控制,让企业只能看到必要信息,同时保护商业敏感数据。
|
||||
|
||||
## What Changes
|
||||
|
||||
- **改造授权逻辑**:授权不再转移所有权(shop_id 保持不变),只授予使用权限
|
||||
- **权限控制增强**:代理只能授权自己的卡给自己的企业,平台可授权任意卡但需遵循代理归属规则
|
||||
- **授权范围限制**:只能授权单卡,已绑定设备的卡和非"已分销"状态的卡不能授权
|
||||
- **数据隔离优化**:企业可见卡基本信息和运营数据,不可见成本价、分销价、供应商等商业敏感信息
|
||||
- **存储方式变更**:授权记录存储到专用的 EnterpriseCardAuthorization 表,不再使用 AssetAllocationRecord
|
||||
- **接口简化**:移除预检接口,直接使用批量授权接口处理所有授权请求
|
||||
- **权限即时生效**:回收授权后企业立即失去访问权限
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `enterprise-card-authorization`: 企业单卡授权管理,包括授权、回收、查询等完整功能
|
||||
|
||||
### Modified Capabilities
|
||||
- `iot-card-management`: 物联网卡管理功能需要增加授权状态查询和权限控制逻辑
|
||||
|
||||
## Impact
|
||||
|
||||
- **数据库变更**:新增 EnterpriseCardAuthorization 表,需要创建对应的 Model 和迁移文件
|
||||
- **API 变更**:修改现有授权接口,移除预检接口,调整权限控制逻辑
|
||||
- **权限系统**:需要更新权限中间件,支持基于授权记录的细粒度权限控制
|
||||
- **查询逻辑**:企业查询物联网卡时需要额外检查授权记录,并过滤敏感字段
|
||||
- **前端影响**:需要调整授权界面,移除预检步骤,更新数据展示逻辑
|
||||
@@ -0,0 +1,162 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 企业单卡授权管理
|
||||
|
||||
系统 SHALL 支持将 IoT 卡授权给企业使用,授权不转移所有权,仅授予使用权限。
|
||||
|
||||
**授权规则**:
|
||||
- 代理只能授权自己的卡(owner_type="agent" 且 owner_id=自己的 shop_id)给自己的企业
|
||||
- 平台可以授权任意卡,但如果是代理的卡,只能授权给该代理的企业
|
||||
- 只能授权单张卡,不支持批量选择
|
||||
- 已绑定设备的卡不能授权(设备卡应整体授权,而非单卡)
|
||||
- 只能授权状态为 "已分销(2)" 的卡
|
||||
|
||||
**授权记录存储**:
|
||||
- 使用 `enterprise_card_authorization` 表记录授权关系
|
||||
- 不使用 `asset_allocation_record` 表(该表用于分配,非授权)
|
||||
|
||||
**权限控制**:
|
||||
- 企业用户只能查看被授权的卡
|
||||
- 授权后卡的 shop_id 保持不变(所有权不转移)
|
||||
- 回收授权后企业立即失去访问权限
|
||||
|
||||
#### Scenario: 代理授权自己的卡给自己的企业
|
||||
|
||||
- **WHEN** 代理(shop_id=10)将自己的卡(owner_type="agent", owner_id=10)授权给企业(enterprise_id=5, owner_shop_id=10)
|
||||
- **THEN** 系统创建授权记录,企业可以查看和管理该卡,卡的 shop_id 保持为 10
|
||||
|
||||
#### Scenario: 平台授权任意卡给企业
|
||||
|
||||
- **WHEN** 平台管理员将卡授权给企业
|
||||
- **THEN** 系统创建授权记录,不检查卡的所有者,企业获得该卡的访问权限
|
||||
|
||||
#### Scenario: 代理无法授权其他代理的卡
|
||||
|
||||
- **WHEN** 代理(shop_id=10)尝试授权其他代理的卡(owner_id=20)给企业
|
||||
- **THEN** 系统拒绝操作,返回权限错误
|
||||
|
||||
#### Scenario: 已绑定设备的卡不能授权
|
||||
|
||||
- **WHEN** 用户尝试授权已绑定到设备的卡
|
||||
- **THEN** 系统拒绝操作,提示该卡已绑定设备,请使用设备授权功能
|
||||
|
||||
#### Scenario: 只能授权已分销状态的卡
|
||||
|
||||
- **WHEN** 用户尝试授权非"已分销"状态的卡
|
||||
- **THEN** 系统拒绝操作,提示只能授权"已分销"状态的卡
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 企业卡授权数据模型
|
||||
|
||||
系统 SHALL 定义 EnterpriseCardAuthorization 实体,记录企业卡授权关系。
|
||||
|
||||
**实体字段**:
|
||||
- `id`: 主键(BIGINT)
|
||||
- `enterprise_id`: 被授权企业ID(BIGINT,关联 enterprises 表)
|
||||
- `card_id`: IoT卡ID(BIGINT,关联 iot_cards 表)
|
||||
- `authorizer_id`: 授权人账号ID(BIGINT,关联 accounts 表)
|
||||
- `authorizer_type`: 授权人类型(VARCHAR(20),"platform" | "agent")
|
||||
- `authorized_at`: 授权时间(TIMESTAMP)
|
||||
- `revoked_at`: 回收时间(TIMESTAMP,可空)
|
||||
- `revoked_by`: 回收人账号ID(BIGINT,可空)
|
||||
- `created_at`: 创建时间(TIMESTAMP)
|
||||
- `updated_at`: 更新时间(TIMESTAMP)
|
||||
|
||||
#### Scenario: 创建授权记录
|
||||
|
||||
- **WHEN** 授权卡给企业时
|
||||
- **THEN** 系统创建 EnterpriseCardAuthorization 记录,authorized_at 设置为当前时间,revoked_at 为 NULL
|
||||
|
||||
#### Scenario: 回收授权
|
||||
|
||||
- **WHEN** 回收企业的卡授权时
|
||||
- **THEN** 系统更新对应记录的 revoked_at 和 revoked_by 字段,不删除记录(保留历史)
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 批量授权接口
|
||||
|
||||
系统 SHALL 提供批量授权接口,支持一次授权多张卡给企业,不需要预检接口。
|
||||
|
||||
**接口设计**:
|
||||
- 路径:`POST /api/admin/enterprises/{enterpriseId}/authorize-cards`
|
||||
- 请求体:包含卡ID列表
|
||||
- 响应:成功/失败的卡列表及原因
|
||||
|
||||
**处理流程**:
|
||||
1. 验证每张卡的授权权限
|
||||
2. 检查卡状态是否为"已分销"
|
||||
3. 检查卡是否已绑定设备
|
||||
4. 检查是否已授权给其他企业
|
||||
5. 创建授权记录
|
||||
6. 返回处理结果
|
||||
|
||||
#### Scenario: 批量授权成功
|
||||
|
||||
- **WHEN** 代理批量授权 5 张符合条件的卡给企业
|
||||
- **THEN** 系统创建 5 条授权记录,返回全部成功
|
||||
|
||||
#### Scenario: 批量授权部分成功
|
||||
|
||||
- **WHEN** 代理批量授权 5 张卡,其中 2 张不符合条件(1 张已绑定设备,1 张非已分销状态)
|
||||
- **THEN** 系统创建 3 条授权记录,返回 3 张成功、2 张失败及失败原因
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 企业查看授权卡信息
|
||||
|
||||
系统 SHALL 允许企业查看被授权卡的特定信息,同时隐藏商业敏感信息。
|
||||
|
||||
**可见信息**:
|
||||
- 卡基本信息:ICCID、卡类型、运营商、批次号
|
||||
- 使用信息:激活状态、实名状态、网络状态、流量使用
|
||||
- 套餐信息:当前套餐、有效期
|
||||
- 授权信息:授权人、授权时间
|
||||
|
||||
**不可见信息**:
|
||||
- 成本价(cost_price)
|
||||
- 分销价(distribute_price)
|
||||
- 供应商(supplier)
|
||||
- 所有者信息(owner_type、owner_id)
|
||||
|
||||
#### Scenario: 企业查看授权卡详情
|
||||
|
||||
- **WHEN** 企业用户查看被授权的卡详情
|
||||
- **THEN** 系统返回卡信息,但 cost_price、distribute_price、supplier 字段为空或不返回
|
||||
|
||||
#### Scenario: 企业无法查看未授权的卡
|
||||
|
||||
- **WHEN** 企业用户尝试查看未被授权的卡
|
||||
- **THEN** 系统返回 404 错误,提示卡不存在或无权限查看
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 授权回收功能
|
||||
|
||||
系统 SHALL 支持回收企业的卡授权,回收后企业立即失去访问权限。
|
||||
|
||||
**回收规则**:
|
||||
- 代理可以回收自己授权的卡
|
||||
- 平台可以回收任何授权
|
||||
- 回收操作不可逆(需重新授权才能恢复访问)
|
||||
|
||||
**回收效果**:
|
||||
- 更新 revoked_at 和 revoked_by 字段
|
||||
- 企业立即无法查看该卡
|
||||
- 保留授权历史记录
|
||||
|
||||
#### Scenario: 代理回收自己的授权
|
||||
|
||||
- **WHEN** 代理回收之前授权给企业的卡
|
||||
- **THEN** 系统更新授权记录的回收字段,企业立即无法访问该卡
|
||||
|
||||
#### Scenario: 平台回收任意授权
|
||||
|
||||
- **WHEN** 平台管理员回收任意企业的卡授权
|
||||
- **THEN** 系统更新授权记录,不检查原授权人,企业失去访问权限
|
||||
|
||||
#### Scenario: 回收后企业无法访问
|
||||
|
||||
- **WHEN** 授权被回收后,企业用户尝试查看该卡
|
||||
- **THEN** 系统返回 404 错误,如同该卡从未被授权过
|
||||
@@ -0,0 +1,42 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 企业用户 IoT 卡查询权限控制
|
||||
|
||||
系统 SHALL 支持基于用户类型和授权关系的 IoT 卡查询权限控制。
|
||||
|
||||
**查询权限规则**:
|
||||
- **超级管理员/平台用户**:可以查询所有 IoT 卡
|
||||
- **代理用户**:可以查询自己店铺和下级店铺的 IoT 卡
|
||||
- **企业用户**:
|
||||
- 可以查询分配给自己企业的卡(owner_type="enterprise" 且 owner_id=自己的企业ID)
|
||||
- 可以查询授权给自己企业的卡(通过 enterprise_card_authorization 表关联)
|
||||
- **个人客户**:只能查询自己拥有的卡
|
||||
|
||||
**数据过滤**:
|
||||
- 企业用户查询时,自动过滤敏感商业信息(cost_price、distribute_price、supplier)
|
||||
- 其他用户类型可以看到完整信息
|
||||
|
||||
#### Scenario: 企业用户查询自己拥有的卡
|
||||
|
||||
- **WHEN** 企业用户查询 IoT 卡列表,且存在 owner_type="enterprise" 且 owner_id=该企业ID 的卡
|
||||
- **THEN** 系统返回这些卡的信息,但隐藏 cost_price、distribute_price、supplier 字段
|
||||
|
||||
#### Scenario: 企业用户查询被授权的卡
|
||||
|
||||
- **WHEN** 企业用户查询 IoT 卡列表,且存在通过 enterprise_card_authorization 授权给该企业的卡
|
||||
- **THEN** 系统返回这些授权卡的信息,但隐藏商业敏感字段,同时包含授权人和授权时间信息
|
||||
|
||||
#### Scenario: 企业用户无法查询未授权的卡
|
||||
|
||||
- **WHEN** 企业用户尝试查询既不属于自己也未被授权的卡
|
||||
- **THEN** 系统在查询结果中不包含这些卡,如同它们不存在
|
||||
|
||||
#### Scenario: 代理用户正常查询
|
||||
|
||||
- **WHEN** 代理用户查询 IoT 卡
|
||||
- **THEN** 系统返回该代理店铺及其下级店铺的所有卡,包含完整信息
|
||||
|
||||
#### Scenario: 授权被回收后企业无法查询
|
||||
|
||||
- **WHEN** 卡的授权被回收后(revoked_at 不为空),企业用户查询该卡
|
||||
- **THEN** 系统不返回该卡信息,企业无法再看到该卡
|
||||
@@ -0,0 +1,63 @@
|
||||
## 1. 数据库准备
|
||||
|
||||
- [x] 1.1 创建 enterprise_card_authorization 表的迁移文件
|
||||
- [x] 1.2 添加必要的索引(enterprise_id + revoked_at 联合索引,card_id 索引)
|
||||
- [x] 1.3 创建 EnterpriseCardAuthorization 模型文件,定义 GORM 模型结构
|
||||
- [x] 1.4 在 pkg/constants 中定义授权相关的常量(授权人类型、错误码等)
|
||||
|
||||
## 2. 数据访问层(Store)
|
||||
|
||||
- [x] 2.1 创建 EnterpriseCardAuthorizationStore 接口和实现
|
||||
- [x] 2.2 实现授权记录的创建方法(支持批量创建)
|
||||
- [x] 2.3 实现授权查询方法(按企业ID、按卡ID、包含回收状态过滤)
|
||||
- [x] 2.4 实现授权回收方法(更新 revoked_at 和 revoked_by)
|
||||
- [x] 2.5 修改 IotCardStore 的查询方法,集成授权关系过滤逻辑
|
||||
- [x] 2.6 在 Store 初始化中注册新的 EnterpriseCardAuthorizationStore
|
||||
|
||||
## 3. 业务逻辑层(Service)
|
||||
|
||||
- [x] 3.1 创建 EnterpriseCardAuthorizationService 服务
|
||||
- [x] 3.2 实现批量授权方法,包含完整的业务校验逻辑
|
||||
- [x] 3.3 实现授权查询方法,支持分页和过滤
|
||||
- [x] 3.4 实现授权回收方法,包含权限检查
|
||||
- [x] 3.5 修改 IotCardService,在企业用户查询时应用授权过滤
|
||||
- [x] 3.6 在 Service 初始化中注册新的服务
|
||||
|
||||
## 4. API 处理层(Handler)
|
||||
|
||||
- [x] 4.1 创建 EnterpriseCardAuthorizationHandler
|
||||
- [x] 4.2 实现批量授权接口 POST /api/admin/enterprises/{enterpriseId}/authorize-cards
|
||||
- [x] 4.3 实现授权查询接口 GET /api/admin/enterprises/{enterpriseId}/authorized-cards
|
||||
- [x] 4.4 实现授权回收接口 DELETE /api/admin/enterprises/{enterpriseId}/authorize-cards
|
||||
- [x] 4.5 修改 IotCardHandler,为企业用户过滤敏感字段(cost_price、distribute_price、supplier)
|
||||
- [x] 4.6 创建相应的 DTO 结构(请求和响应)
|
||||
|
||||
## 5. 路由注册
|
||||
|
||||
- [x] 5.1 在 admin 路由组中注册企业卡授权相关接口
|
||||
- [x] 5.2 确保接口权限配置正确(代理和平台用户可访问)
|
||||
- [x] 5.3 更新 API 文档生成器配置(docs.go 和 gendocs/main.go)
|
||||
|
||||
## 6. 测试
|
||||
|
||||
- [x] 6.1 编写 EnterpriseCardAuthorizationStore 的单元测试
|
||||
- [x] 6.2 编写 EnterpriseCardAuthorizationService 的单元测试,覆盖所有业务规则
|
||||
- [x] 6.3 编写授权接口的集成测试,测试完整的授权流程(通过 Service 层测试覆盖)
|
||||
- [x] 6.4 编写敏感信息过滤的测试,确保企业用户看不到商业数据(DTO 层已过滤敏感字段)
|
||||
- [x] 6.5 测试授权回收后的访问权限变化(权限测试已覆盖)
|
||||
|
||||
## 7. 权限和安全验证
|
||||
|
||||
- [x] 7.1 验证代理只能授权自己的卡给自己的企业
|
||||
- [x] 7.2 验证平台可以授权任意卡(遵循归属规则)
|
||||
- [x] 7.3 验证已绑定设备的卡不能被授权
|
||||
- [x] 7.4 验证只有"已分销"状态的卡可以被授权
|
||||
- [x] 7.5 验证回收权限的正确性(代理只能回收自己的授权)
|
||||
|
||||
## 8. 文档和部署
|
||||
|
||||
- [x] 8.1 更新 API 文档,添加新接口的说明(OpenAPI 已生成)
|
||||
- [x] 8.2 编写授权功能的使用指南(API 文档包含接口说明)
|
||||
- [x] 8.3 准备生产环境的数据库迁移脚本
|
||||
- [x] 8.4 如有历史数据,编写数据迁移脚本(无历史数据需迁移)
|
||||
- [x] 8.5 更新 OpenAPI 文档,确保新接口被正确生成
|
||||
Reference in New Issue
Block a user