```bash type NodePermission struct { NodeID int64 `gorm:"primaryKey;autoIncrement:false"` PermissionID int64 `gorm:"primaryKey;autoIncrement:false"` } ``` 在上述示例中,我们使用 primaryKey 标签将 NodeID 和 PermissionID 设置为联合主键,并且通过 autoIncrement:false 来禁止自增。这样,NodePermission 表就能够记录节点和权限的关联关系,而不需要额外的独立的 ID。 // 在关联表中添加联合主键约束 db.AutoMigrate(&NodePermission{}) ```bash # 假设要删除 RoleID 为 1 且 PermissionID 为 2 的记录 result := db.Where("role_id = ? AND permission_id = ?", 1, 2).Delete(&RolePermission{}) if result.Error != nil { // 处理错误 } else { // 处理成功 } ``` #### Clauses Clauses 是 Gorm 中用于添加查询子句(Clauses)的方法。在这个上下文中,Clauses(clause.OnConflict{UpdateAll: true}) 是为了使用 Gorm 的 Upsert(插入或更新)功能。 具体来说,clause.OnConflict{UpdateAll: true} 表示当发生冲突(即主键或唯一索引冲突)时,使用更新所有字段的方式进行更新。这意味着如果数据库中已经存在具有相同主键或唯一索引的记录,那么会更新已存在记录的所有字段,而不是报错或忽略。 在示例中,Create(&defaultUser) 会尝试向数据库插入一条记录,如果该记录已经存在(主键冲突),则会根据 clause.OnConflict{UpdateAll: true} 中定义的规则进行更新。这样可以保证在执行初始化操作时,如果默认用户已经存在,就更新用户信息而不是报错。 总体来说,Clauses 允许您在 Gorm 中添加灵活的查询子句,而这里特别使用了 Upsert 功能。 ```bash package main import ( "fmt" "time" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/clause" ) // 数据模型定义 type User struct { ID int64 `gorm:"primary_key;not_null;auto_increment" json:"id"` Username string `json:"username"` Nickname string `json:"nickname"` Email string `json:"email"` Phone string `json:"phone"` // 新增手机号字段 Password string `json:"-"` // 这里使用 "-" 表示在 JSON 输出时不包含密码字段 Teams []Team `gorm:"many2many:user_teams;" json:"teams"` Roles []Role `gorm:"many2many:user_roles;" json:"roles"` CreatedBy int64 `json:"created_by"` } type Role struct { ID int64 `gorm:"primary_key;not_null;auto_increment" json:"id"` Name string `json:"name"` } type Node struct { ID int64 `gorm:"primary_key;not_null;auto_increment" json:"id"` ParentID int64 `json:"parent_id"` // 父节点ID,根节点为0 Name string `json:"name"` // 节点名称 } type Permission struct { ID int64 `gorm:"primary_key;not_null;auto_increment" json:"id"` Name string `json:"name"` } type Team struct { ID int64 `gorm:"primary_key;not_null;auto_increment" json:"id"` Name string `json:"name"` // 团队名称 Description string `json:"description"` // 团队描述 LeaderID int64 `json:"leader_id"` // 团队领导的用户 ID CreatedBy string `json:"created_by"` // 创建团队的用户 CreateTime int64 `json:"create_time"` // 团队创建时间 Leader User `gorm:"foreignkey:LeaderID" json:"leader"` Members []User `gorm:"many2many:user_teams;" json:"members"` Roles []Role `gorm:"many2many:team_roles;" json:"roles"` Permissions []Permission `gorm:"many2many:team_permissions;" json:"permissions"` Website string `json:"website"` // 团队网站 MaxMembers int `json:"max_members"` // 团队最大成员数 } // 关联表 type UserTeam struct { UserID int64 `gorm:"index"` TeamID int64 `gorm:"index"` } type UserRole struct { UserID int64 `gorm:"index"` RoleID int64 `gorm:"index"` } type NodePermission struct { NodeID int64 `gorm:"index"` PermissionID int64 `gorm:"index"` } type TeamPermission struct { TeamID int64 `gorm:"index"` PermissionID int64 `gorm:"index"` } // 权限常量 const ( // 用户权限 UserRead = "user:read" UserWrite = "user:write" UserDelete = "user:delete" // 团队权限 TeamRead = "team:read" TeamWrite = "team:write" TeamDelete = "team:delete" // 角色权限 RoleRead = "role:read" RoleWrite = "role:write" RoleDelete = "role:delete" // 通用权限 ManageAll = "*:manage" ViewAll = "*:view" // 节点权限 NodeRead = "node:read" NodeWrite = "node:write" NodeDelete = "node:delete" ) // 数据填充函数 func seedData(db *gorm.DB) { // 创建用户、角色、节点、权限、团队 user1 := User{Username: "user1", Nickname: "User 1", Email: "user1@example.com", Phone: "123456789", CreatedBy: 1} user2 := User{Username: "user2", Nickname: "User 2", Email: "user2@example.com", Phone: "987654321", CreatedBy: 1} user3 := User{Username: "user3", Nickname: "User 3", Email: "user3@example.com", Phone: "111222333", CreatedBy: 2} role1 := Role{Name: "Admin"} role2 := Role{Name: "Member"} node1 := Node{Name: "Node 1"} node2 := Node{Name: "Node 2"} node3 := Node{Name: "Node 3"} permission1 := Permission{Name: "Permission 1"} permission2 := Permission{Name: "Permission 2"} permission3 := Permission{Name: "Permission 3"} team1 := Team{Name: "Team 1", Description: "Description 1", LeaderID: 1, CreatedBy: "Admin", CreateTime: 1637190745} team2 := Team{Name: "Team 2", Description: "Description 2", LeaderID: 2, CreatedBy: "Admin", CreateTime: 1637190745} team3 := Team{Name: "Team 3", Description: "Description 3", LeaderID: 3, CreatedBy: "User2", CreateTime: 1637190745} // 创建关联关系 db.Create(&user1) db.Create(&user2) db.Create(&user3) db.Create(&role1) db.Create(&role2) db.Create(&node1) db.Create(&node2) db.Create(&node3) db.Create(&permission1) db.Create(&permission2) db.Create(&permission3) db.Create(&team1) db.Create(&team2) db.Create(&team3) db.Create(&UserTeam{UserID: user1.ID, TeamID: team1.ID}) db.Create(&UserTeam{UserID: user2.ID, TeamID: team2.ID}) db.Create(&UserTeam{UserID: user3.ID, TeamID: team3.ID}) db.Create(&UserRole{UserID: user1.ID, RoleID: role1.ID}) db.Create(&UserRole{UserID: user2.ID, RoleID: role2.ID}) db.Create(&UserRole{UserID: user3.ID, RoleID: role2.ID}) db.Create(&NodePermission{NodeID: node1.ID, PermissionID: permission1.ID}) db.Create(&NodePermission{NodeID: node2.ID, PermissionID: permission2.ID}) db.Create(&NodePermission{NodeID: node3.ID, PermissionID: permission3.ID}) db.Create(&TeamPermission{TeamID: team1.ID, PermissionID: permission1.ID}) db.Create(&TeamPermission{TeamID: team2.ID, PermissionID: permission2.ID}) db.Create(&TeamPermission{TeamID: team3.ID, PermissionID: permission3.ID}) } func main() { // 连接数据库 dsn := "test.db" db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") } // 自动迁移模型 err = db.AutoMigrate(&User{}, &Role{}, &Node{}, &Permission{}, &Team{}, &UserTeam{}, &UserRole{}, &NodePermission{}, &TeamPermission{}) if err != nil { panic("failed to migrate database") } // 数据填充 seedData(db) fmt.Println("Database seeded successfully.") } ``` 下面是关于 Permission, Role, 和 RolePermission 的基本流程: ```bash # Permission 模型 type Permission struct { ID int64 `gorm:"primary_key;not_null;auto_increment" json:"id"` Name string `json:"name"` Description string `json:"description"` Roles []Role `gorm:"many2many:role_permissions;" json:"roles"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } # Role 模型 type Role struct { ID int64 `gorm:"primary_key;not_null;auto_increment" json:"id"` Name string `json:"name"` Description string `json:"description"` Permissions []Permission `gorm:"many2many:role_permissions;" json:"permissions"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } # RolePermission 模型 type RolePermission struct { RoleID int64 `gorm:"index"` PermissionID int64 `gorm:"index"` Grant bool `json:"grant"` // 表示角色是否被授予相应的权限 } ``` 关联模型: >Permission 和 Role 通过 many2many 关联表 RolePermission 关联。 RolePermission 中有 Grant 字段,表示角色是否被授予相应的权限。 创建和查询流程: ```bash # 创建权限 permission := Permission{ Name: "ReadUser", Description: "Permission to read user information", } db.Create(&permission) # 创建角色 role := Role{ Name: "Admin", Description: "Administrator role", } db.Create(&role) # 关联权限和角色 rolePermission := RolePermission{ RoleID: role.ID, PermissionID: permission.ID, Grant: true, // 授予角色相应权限 } db.Create(&rolePermission) # 查询角色的所有权限 db.Preload("Permissions").Find(&role) # 查询权限的所有角色 db.Preload("Roles").Find(&permission) ``` 更新和删除流程: ```bash # 更新权限信息 db.Model(&permission).Update("Description", "Updated description") # 更新角色信息 db.Model(&role).Update("Description", "Updated description") # 撤销角色的权限 db.Where("RoleID = ? AND PermissionID = ?", role.ID, permission.ID).Delete(&RolePermission{}) # 删除权限 db.Delete(&permission) # 删除角色 db.Delete(&role) ``` 这个流程展示了如何创建、关联、查询、更新和删除 Permission, Role, 和 RolePermission 的基本操作。请根据你的具体需求和系统设计进行调整。 在 GORM 中,如果你的 Team 模型有一个名为 Members 的字段,表示与 User 模型之间的多对多关系,你可以使用以下方式来向团队添加成员。 通过关联模型创建: ```bash // 假设 teamID 为团队的 ID,userID 为要添加的用户的 ID // 首先查询要添加的用户和团队 var team Team var user User if err := db.First(&team, teamID).Error; err != nil { // 处理团队不存在的情况 } if err := db.First(&user, userID).Error; err != nil { // 处理用户不存在的情况 } // 将用户添加到团队的 Members 中 db.Model(&team).Association("Members").Append(&user) ``` 上述代码首先通过团队 ID 和用户 ID 查询相应的团队和用户,然后使用 Association 和 Append 方法将用户添加到团队的 Members 中。 直接更新模型字段: ```bash // 假设 teamID 为团队的 ID,userID 为要添加的用户的 ID // 查询要添加的用户和团队 var team Team var user User if err := db.First(&team, teamID).Error; err != nil { // 处理团队不存在的情况 } if err := db.First(&user, userID).Error; err != nil { // 处理用户不存在的情况 } // 直接将用户添加到团队的 Members 中 db.Model(&team).Update("Members", gorm.Expr("ARRAY_APPEND(members, ?)", userID)) ``` 这种方法通过直接更新模型字段来添加用户到团队的 Members 中,使用了 ARRAY_APPEND 函数。 你可以根据你的具体需求选择其中的一种方法。如果你使用的是 PostgreSQL,ARRAY_APPEND 函数是合适的。确保替换代码中的数据库查询和错误处理,以适应你的应用程序逻辑。 team 下有多少角色: ```bash // 假设 teamID 为团队的 ID var team Team if err := db.Preload("Roles").First(&team, teamID).Error; err != nil { // 处理团队不存在的情况 } // 现在你可以访问 team.Roles,这是一个包含团队下所有角色的切片 ``` team 下有多少用户: ```bash // 假设 teamID 为团队的 ID var team Team if err := db.Preload("Members").First(&team, teamID).Error; err != nil { // 处理团队不存在的情况 } // 现在你可以访问 team.Members,这是一个包含团队下所有用户的切片 ``` 如果在创建角色时,关联的权限已经存在,您可以首先查询权限,然后再关联到角色。以下是一个示例: ```bash // 假设您已经有一个名为 "Admin" 的权限存在,并且知道它的 PermissionID // 查询权限 var adminPermission Permission db.Where("name = ?", "Admin").First(&adminPermission) // 创建角色并关联权限 adminRole := Role{ Name: "Admin", Description: "Administrator role", Permissions: []Permission{adminPermission}, } db.Create(&adminRole) ``` ```bash // 获取以 "Employee:" 前缀开头的权限 var employeePermissions []Permission db.Where("name LIKE ?", "Employee:%").Find(&employeePermissions) ``` #### Mysql 设置字符集 ```bash ALTER DATABASE paas CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; SHOW VARIABLES LIKE 'character_set_database'; ``` [//]: # ( - docker run --name authorization-service --restart=always -d -p 8091:8091 sghharbor.com/sghblog-project/authorization-service:v1.0.0)