Files
lijiaoqiao/supply-api/internal/iam/model/user_role.go
Your Name 89104bd0db feat(P1/P2): 完成TDD开发及P1/P2设计文档
## 设计文档
- multi_role_permission_design: 多角色权限设计 (CONDITIONAL GO)
- audit_log_enhancement_design: 审计日志增强 (CONDITIONAL GO)
- routing_strategy_template_design: 路由策略模板 (CONDITIONAL GO)
- sso_saml_technical_research: SSO/SAML调研 (CONDITIONAL GO)
- compliance_capability_package_design: 合规能力包设计 (CONDITIONAL GO)

## TDD开发成果
- IAM模块: supply-api/internal/iam/ (111个测试)
- 审计日志模块: supply-api/internal/audit/ (40+测试)
- 路由策略模块: gateway/internal/router/ (33+测试)
- 合规能力包: gateway/internal/compliance/ + scripts/ci/compliance/

## 规范文档
- parallel_agent_output_quality_standards: 并行Agent产出质量规范
- project_experience_summary: 项目经验总结 (v2)
- 2026-04-02-p1-p2-tdd-execution-plan: TDD执行计划

## 评审报告
- 5个CONDITIONAL GO设计文档评审报告
- fix_verification_report: 修复验证报告
- full_verification_report: 全面质量验证报告
- tdd_module_quality_verification: TDD模块质量验证
- tdd_execution_summary: TDD执行总结

依据: Superpowers执行框架 + TDD规范
2026-04-02 23:35:53 +08:00

173 lines
4.4 KiB
Go
Raw 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.
package model
import (
"time"
)
// UserRoleMapping 用户-角色关联模型
// 对应数据库 iam_user_roles 表
type UserRoleMapping struct {
ID int64 // 主键ID
UserID int64 // 用户ID
RoleID int64 // 角色ID (FK -> iam_roles.id)
TenantID int64 // 租户范围NULL表示全局0也代表全局
GrantedBy int64 // 授权人ID
ExpiresAt *time.Time // 角色过期时间nil表示永不过期
IsActive bool // 是否激活
// 审计字段
RequestID string // 请求追踪ID
CreatedIP string // 创建者IP
UpdatedIP string // 更新者IP
Version int // 乐观锁版本号
// 时间戳
CreatedAt *time.Time // 创建时间
UpdatedAt *time.Time // 更新时间
GrantedAt *time.Time // 授权时间
}
// NewUserRoleMapping 创建新的用户-角色映射
func NewUserRoleMapping(userID, roleID, tenantID int64) *UserRoleMapping {
now := time.Now()
return &UserRoleMapping{
UserID: userID,
RoleID: roleID,
TenantID: tenantID,
IsActive: true,
RequestID: generateRequestID(),
Version: 1,
CreatedAt: &now,
UpdatedAt: &now,
}
}
// NewUserRoleMappingWithGrant 创建带授权信息的用户-角色映射
func NewUserRoleMappingWithGrant(userID, roleID, tenantID, grantedBy int64, expiresAt *time.Time) *UserRoleMapping {
now := time.Now()
return &UserRoleMapping{
UserID: userID,
RoleID: roleID,
TenantID: tenantID,
GrantedBy: grantedBy,
ExpiresAt: expiresAt,
GrantedAt: &now,
IsActive: true,
RequestID: generateRequestID(),
Version: 1,
CreatedAt: &now,
UpdatedAt: &now,
}
}
// HasRole 检查用户是否拥有指定角色
func (m *UserRoleMapping) HasRole(roleID int64) bool {
return m.RoleID == roleID && m.IsActive
}
// IsGlobalRole 检查是否为全局角色租户ID为0或nil
func (m *UserRoleMapping) IsGlobalRole() bool {
return m.TenantID == 0
}
// IsExpired 检查角色是否已过期
func (m *UserRoleMapping) IsExpired() bool {
if m.ExpiresAt == nil {
return false // 永不过期
}
return time.Now().After(*m.ExpiresAt)
}
// IsValid 检查角色分配是否有效(激活且未过期)
func (m *UserRoleMapping) IsValid() bool {
return m.IsActive && !m.IsExpired()
}
// Revoke 撤销角色分配
func (m *UserRoleMapping) Revoke() {
m.IsActive = false
m.UpdatedAt = nowPtr()
}
// Grant 重新授予角色
func (m *UserRoleMapping) Grant() {
m.IsActive = true
m.UpdatedAt = nowPtr()
}
// IncrementVersion 递增版本号
func (m *UserRoleMapping) IncrementVersion() {
m.Version++
m.UpdatedAt = nowPtr()
}
// ExtendExpiration 延长过期时间
func (m *UserRoleMapping) ExtendExpiration(newExpiresAt *time.Time) {
m.ExpiresAt = newExpiresAt
m.UpdatedAt = nowPtr()
}
// UserRoleMappingInfo 用户-角色映射信息用于API响应
type UserRoleMappingInfo struct {
UserID int64 `json:"user_id"`
RoleID int64 `json:"role_id"`
TenantID int64 `json:"tenant_id"`
IsActive bool `json:"is_active"`
ExpiresAt *string `json:"expires_at,omitempty"`
}
// ToInfo 转换为映射信息
func (m *UserRoleMapping) ToInfo() *UserRoleMappingInfo {
info := &UserRoleMappingInfo{
UserID: m.UserID,
RoleID: m.RoleID,
TenantID: m.TenantID,
IsActive: m.IsActive,
}
if m.ExpiresAt != nil {
expStr := m.ExpiresAt.Format(time.RFC3339)
info.ExpiresAt = &expStr
}
return info
}
// UserRoleAssignmentInfo 用户角色分配详情用于API响应
type UserRoleAssignmentInfo struct {
UserID int64 `json:"user_id"`
RoleCode string `json:"role_code"`
RoleName string `json:"role_name"`
TenantID int64 `json:"tenant_id"`
GrantedBy int64 `json:"granted_by"`
GrantedAt string `json:"granted_at"`
ExpiresAt string `json:"expires_at,omitempty"`
IsActive bool `json:"is_active"`
IsExpired bool `json:"is_expired"`
}
// UserRoleWithDetails 用户角色分配(含角色详情)
type UserRoleWithDetails struct {
*UserRoleMapping
RoleCode string
RoleName string
}
// ToAssignmentInfo 转换为分配详情
func (m *UserRoleWithDetails) ToAssignmentInfo() *UserRoleAssignmentInfo {
info := &UserRoleAssignmentInfo{
UserID: m.UserID,
RoleCode: m.RoleCode,
RoleName: m.RoleName,
TenantID: m.TenantID,
GrantedBy: m.GrantedBy,
IsActive: m.IsActive,
IsExpired: m.IsExpired(),
}
if m.GrantedAt != nil {
info.GrantedAt = m.GrantedAt.Format(time.RFC3339)
}
if m.ExpiresAt != nil {
info.ExpiresAt = m.ExpiresAt.Format(time.RFC3339)
}
return info
}