Files
huang c9fee7f2f6
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m42s
fix: 修复授权记录备注修改权限问题
- 实现备注权限检查逻辑(authorization_service.go)
- 添加备注权限验证存储层(authorization_store.go)
- 新增集成测试覆盖备注权限场景
- 归档 fix-authorization-remark-permission 变更
- 同步 enterprise-card-authorization spec 规范
2026-01-29 14:29:11 +08:00

181 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## MODIFIED Requirements
### Requirement: 企业单卡授权管理
系统 SHALL 支持将 IoT 卡授权给企业使用,授权不转移所有权,仅授予使用权限。
**授权规则**
- 代理只能授权自己的卡owner_type="agent" 且 owner_id=自己的 shop_id给自己的企业
- 平台可以授权任意卡,但如果是代理的卡,只能授权给该代理的企业
- 支持批量授权最多1000张卡
- **已绑定设备的卡不能通过单卡授权接口授权MUST 使用设备授权接口**
- 只能授权状态为 "已分销(2)" 的卡
**授权记录存储**
- 使用 `enterprise_card_authorization` 表记录授权关系
- 通过单卡授权创建的记录 device_auth_id 为 NULL
- 不使用 `asset_allocation_record` 表(该表用于分配,非授权)
**权限控制**
- 企业用户只能查看被授权的卡
- 授权后卡的 shop_id 保持不变(所有权不转移)
- 回收授权后企业立即失去访问权限
#### Scenario: 代理授权自己的卡给自己的企业
- **WHEN** 代理shop_id=10将自己的未绑定设备的卡授权给企业enterprise_id=5, owner_shop_id=10
- **THEN** 系统创建授权记录device_auth_id=NULL企业可以查看和管理该卡
#### Scenario: 平台授权任意卡给企业
- **WHEN** 平台管理员将未绑定设备的卡授权给企业
- **THEN** 系统创建授权记录device_auth_id=NULL企业获得该卡的访问权限
#### Scenario: 代理无法授权其他代理的卡
- **WHEN** 代理shop_id=10尝试授权其他代理的卡owner_id=20给企业
- **THEN** 系统拒绝操作,返回权限错误
#### Scenario: 已绑定设备的卡不能通过单卡授权
- **WHEN** 用户尝试通过单卡授权接口授权已绑定到设备的卡
- **THEN** 系统拒绝操作,返回错误码 CodeCannotAuthorizeBoundCard提示"该卡已绑定设备,请使用设备授权功能"
#### Scenario: 只能授权已分销状态的卡
- **WHEN** 用户尝试授权非"已分销"状态的卡
- **THEN** 系统拒绝操作,提示只能授权"已分销"状态的卡
---
### Requirement: 企业卡授权数据模型
系统 SHALL 定义 EnterpriseCardAuthorization 实体,记录企业卡授权关系。
**实体字段**
- `id`: 主键BIGINT
- `enterprise_id`: 被授权企业IDBIGINT关联 enterprises 表)
- `card_id`: IoT卡IDBIGINT关联 iot_cards 表)
- `authorizer_id`: 授权人账号IDBIGINT关联 accounts 表)
- `authorizer_type`: 授权人类型SMALLINT2=平台用户 3=代理账号)
- `authorized_at`: 授权时间TIMESTAMP
- `revoked_at`: 回收时间TIMESTAMP可空
- `revoked_by`: 回收人账号IDBIGINT可空
- `remark`: 备注VARCHAR(500)
- **`device_auth_id`: 关联的设备授权IDBIGINT可空**
- NULL = 通过单卡授权创建
- 有值 = 通过设备授权创建
- `created_at`: 创建时间TIMESTAMP
- `updated_at`: 更新时间TIMESTAMP
**新增索引**
- `idx_eca_device_auth ON tb_enterprise_card_authorization(device_auth_id)`
#### Scenario: 创建单卡授权记录
- **WHEN** 通过单卡授权接口授权卡给企业时
- **THEN** 系统创建 EnterpriseCardAuthorization 记录device_auth_id 为 NULL
#### Scenario: 创建设备关联卡授权记录
- **WHEN** 通过设备授权创建卡授权记录时
- **THEN** 系统创建 EnterpriseCardAuthorization 记录device_auth_id 指向对应的设备授权ID
#### Scenario: 回收授权
- **WHEN** 回收企业的卡授权时
- **THEN** 系统更新对应记录的 revoked_at 和 revoked_by 字段,不删除记录(保留历史)
---
### Requirement: 批量授权接口
系统 SHALL 提供批量授权接口,支持一次授权多张卡给企业。
**接口设计**
- 路径:`POST /api/admin/enterprises/:id/allocate-cards`
- 请求体:
```json
{
"iccids": ["8986001234567890", "8986001234567891"],
"remark": "批量授权"
}
```
- 响应:成功/失败的卡列表及原因
**处理流程**
1. 验证每张卡的授权权限
2. 检查卡状态是否为"已分销"
3. **检查卡是否已绑定设备,绑定设备的卡直接拒绝并返回错误**
4. 检查是否已授权给该企业
5. 创建授权记录device_auth_id = NULL
6. 返回处理结果
**移除功能**
- ~~DeviceBundle 预检和确认流程~~(已移除)
- ~~confirm_device_bundles 参数~~(已移除)
- ~~AllocatedDevices 响应字段~~(已移除)
#### Scenario: 批量授权成功
- **WHEN** 代理批量授权 5 张未绑定设备的卡给企业
- **THEN** 系统创建 5 条授权记录device_auth_id 均为 NULL返回全部成功
#### Scenario: 批量授权遇到设备卡
- **WHEN** 代理批量授权 5 张卡,其中 2 张已绑定设备
- **THEN** 系统创建 3 条授权记录,返回 3 张成功、2 张失败,失败原因为"该卡已绑定设备,请使用设备授权功能"
#### Scenario: 批量授权部分成功
- **WHEN** 代理批量授权 5 张卡,其中 1 张已绑定设备、1 张非已分销状态
- **THEN** 系统创建 3 条授权记录,返回 3 张成功、2 张失败及各自失败原因
---
## ADDED Requirements
### Requirement: 授权记录备注修改权限
系统 SHALL 对授权记录备注修改操作实施严格的权限控制,确保只有有权限的用户才能修改授权记录的备注信息。
**权限规则**
- **超级管理员/平台用户**:可以修改任意授权记录的备注
- **代理账号**仅可修改自己创建的授权记录的备注authorized_by 等于自己的账号 ID
- **企业账号**:禁止修改授权记录备注(即使是授权给自己企业的记录)
**实施方式**
- Service 层 MUST 在 `UpdateRecordRemark` 方法中校验用户权限和创建者匹配
- Store 层 MUST 在更新语句中增加 `authorized_by` 约束条件(对代理用户)
- Handler 层 MUST 将权限失败场景返回统一错误码和中文错误消息
**错误处理**
- 代理尝试修改他人创建的记录:返回错误码 `CodePermissionDenied`1003消息"无权修改该授权记录的备注"
- 企业用户尝试修改:返回错误码 `CodePermissionDenied`1003消息"企业用户无权修改授权记录备注"
- 记录不存在或不在可见范围:返回错误码 `CodeRecordNotFound`2001消息"授权记录不存在"
#### Scenario: 平台用户修改任意授权记录备注
- **WHEN** 平台用户调用备注修改接口,指定任意授权记录 ID 和新备注内容
- **THEN** 系统成功更新该授权记录的 `remark` 字段,返回成功响应
#### Scenario: 代理修改自己创建的授权记录备注
- **WHEN** 代理账号account_id=100调用备注修改接口修改自己创建的授权记录authorized_by=100的备注
- **THEN** 系统成功更新该授权记录的 `remark` 字段,返回成功响应
#### Scenario: 代理尝试修改他人创建的授权记录备注
- **WHEN** 代理账号account_id=100调用备注修改接口尝试修改其他代理创建的授权记录authorized_by=200的备注
- **THEN** 系统拒绝操作,返回错误码 `1003`,错误消息"无权修改该授权记录的备注",不执行任何更新
#### Scenario: 企业用户尝试修改授权记录备注
- **WHEN** 企业账号调用备注修改接口,尝试修改授权给自己企业的授权记录的备注
- **THEN** 系统拒绝操作,返回错误码 `1003`,错误消息"企业用户无权修改授权记录备注",不执行任何更新
#### Scenario: 代理修改不存在或不可见的授权记录备注
- **WHEN** 代理账号调用备注修改接口,指定的授权记录 ID 不存在或不在其数据权限范围内
- **THEN** 系统返回错误码 `2001`,错误消息"授权记录不存在",不执行任何更新