up
This commit is contained in:
		
							parent
							
								
									af4d55d0d1
								
							
						
					
					
						commit
						ae75582d11
					
				| @ -0,0 +1,104 @@ | ||||
| package controllers | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/services" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
| 
 | ||||
| // CreateRole 创建新角色 | ||||
| func CreateRole(c *gin.Context) { | ||||
| 	var roleData struct { | ||||
| 		Name        string `json:"name" binding:"required"` | ||||
| 		Description string `json:"description"` | ||||
| 	} | ||||
| 	if err := c.ShouldBindJSON(&roleData); err != nil { | ||||
| 		c.JSON(400, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	role, err := services.CreateRole(roleData.Name, roleData.Description) | ||||
| 	if err != nil { | ||||
| 		c.JSON(500, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 	c.JSON(201, role) | ||||
| } | ||||
| 
 | ||||
| // GetRoles 获取所有角色 | ||||
| func GetRoles(c *gin.Context) { | ||||
| 	roles, err := services.GetAllRoles() | ||||
| 	if err != nil { | ||||
| 		c.JSON(500, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 	c.JSON(200, roles) | ||||
| } | ||||
| 
 | ||||
| // CreatePermission 创建新权限 | ||||
| func CreatePermission(c *gin.Context) { | ||||
| 	var permissionData struct { | ||||
| 		Name        string `json:"name" binding:"required"` | ||||
| 		Description string `json:"description"` | ||||
| 		Resource    string `json:"resource" binding:"required"` | ||||
| 		Action      string `json:"action" binding:"required"` | ||||
| 	} | ||||
| 	if err := c.ShouldBindJSON(&permissionData); err != nil { | ||||
| 		c.JSON(400, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	permission, err := services.CreatePermission(permissionData.Name, permissionData.Description, permissionData.Resource, permissionData.Action) | ||||
| 	if err != nil { | ||||
| 		c.JSON(500, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 	c.JSON(201, permission) | ||||
| } | ||||
| 
 | ||||
| // AssignRoleToUser 为用户分配角色 | ||||
| func AssignRoleToUser(c *gin.Context) { | ||||
| 	var assignmentData struct { | ||||
| 		UserID uint `json:"user_id" binding:"required"` | ||||
| 		RoleID uint `json:"role_id" binding:"required"` | ||||
| 	} | ||||
| 	if err := c.ShouldBindJSON(&assignmentData); err != nil { | ||||
| 		c.JSON(400, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	err := services.AssignRoleToUser(assignmentData.UserID, assignmentData.RoleID) | ||||
| 	if err != nil { | ||||
| 		c.JSON(500, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 	c.JSON(200, gin.H{"message": "Role assigned successfully"}) | ||||
| } | ||||
| 
 | ||||
| // AssignPermissionToRole 为角色分配权限 | ||||
| func AssignPermissionToRole(c *gin.Context) { | ||||
| 	var assignmentData struct { | ||||
| 		RoleID       uint `json:"role_id" binding:"required"` | ||||
| 		PermissionID uint `json:"permission_id" binding:"required"` | ||||
| 	} | ||||
| 	if err := c.ShouldBindJSON(&assignmentData); err != nil { | ||||
| 		c.JSON(400, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	err := services.AssignPermissionToRole(assignmentData.RoleID, assignmentData.PermissionID) | ||||
| 	if err != nil { | ||||
| 		c.JSON(500, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 	c.JSON(200, gin.H{"message": "Permission assigned successfully"}) | ||||
| } | ||||
| 
 | ||||
| // GetPermissions 获取所有权限 | ||||
| func GetPermissions(c *gin.Context) { | ||||
| 	permissions, err := services.GetAllPermissions() | ||||
| 	if err != nil { | ||||
| 		c.JSON(500, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 	c.JSON(200, permissions) | ||||
| } | ||||
							
								
								
									
										7
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								go.mod
									
									
									
									
									
								
							| @ -4,19 +4,24 @@ go 1.21 | ||||
| 
 | ||||
| require ( | ||||
| 	github.com/gin-gonic/gin v1.9.1 | ||||
| 	github.com/go-redis/redis/v8 v8.11.5 | ||||
| 	github.com/golang-jwt/jwt/v5 v5.0.0 | ||||
| 	golang.org/x/crypto v0.9.0 | ||||
| 	gorm.io/gorm v1.25.2 | ||||
| 	gorm.io/driver/mysql v1.5.7 | ||||
| 	gorm.io/gorm v1.25.7 | ||||
| ) | ||||
| 
 | ||||
| require ( | ||||
| 	github.com/bytedance/sonic v1.9.1 // indirect | ||||
| 	github.com/cespare/xxhash/v2 v2.1.2 // indirect | ||||
| 	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect | ||||
| 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect | ||||
| 	github.com/gabriel-vasile/mimetype v1.4.2 // indirect | ||||
| 	github.com/gin-contrib/sse v0.1.0 // indirect | ||||
| 	github.com/go-playground/locales v0.14.1 // indirect | ||||
| 	github.com/go-playground/universal-translator v0.18.1 // indirect | ||||
| 	github.com/go-playground/validator/v10 v10.14.0 // indirect | ||||
| 	github.com/go-sql-driver/mysql v1.7.0 // indirect | ||||
| 	github.com/goccy/go-json v0.10.2 // indirect | ||||
| 	github.com/jinzhu/inflection v1.0.0 // indirect | ||||
| 	github.com/jinzhu/now v1.1.5 // indirect | ||||
|  | ||||
							
								
								
									
										26
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,12 +1,18 @@ | ||||
| github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= | ||||
| github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= | ||||
| github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= | ||||
| github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= | ||||
| github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | ||||
| github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= | ||||
| github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= | ||||
| github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= | ||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= | ||||
| github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= | ||||
| github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= | ||||
| github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= | ||||
| github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= | ||||
| github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= | ||||
| github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= | ||||
| @ -21,6 +27,10 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn | ||||
| github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= | ||||
| github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= | ||||
| github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= | ||||
| github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= | ||||
| github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= | ||||
| github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= | ||||
| github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= | ||||
| github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= | ||||
| github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= | ||||
| github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= | ||||
| @ -47,6 +57,12 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w | ||||
| github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||
| github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= | ||||
| github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | ||||
| github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= | ||||
| github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= | ||||
| github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= | ||||
| github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= | ||||
| github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= | ||||
| github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= | ||||
| github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= | ||||
| github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| @ -86,9 +102,15 @@ google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cn | ||||
| google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | ||||
| gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | ||||
| gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= | ||||
| gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= | ||||
| gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho= | ||||
| gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= | ||||
| gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= | ||||
| gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= | ||||
| gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A= | ||||
| gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= | ||||
| rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= | ||||
|  | ||||
| @ -0,0 +1,11 @@ | ||||
| package models | ||||
| 
 | ||||
| import "gorm.io/gorm" | ||||
| 
 | ||||
| type Permission struct { | ||||
| 	gorm.Model | ||||
| 	Name        string `gorm:"unique;not null"` | ||||
| 	Description string | ||||
| 	Resource    string `gorm:"not null"` | ||||
| 	Action      string `gorm:"not null"` | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| package models | ||||
| 
 | ||||
| import "gorm.io/gorm" | ||||
| 
 | ||||
| type Role struct { | ||||
| 	gorm.Model | ||||
| 	Name        string       `gorm:"unique;not null"` | ||||
| 	Permissions []Permission `gorm:"many2many:role_permissions;"` | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| package models | ||||
| 
 | ||||
| import ( | ||||
| 	"gorm.io/gorm" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // UserGroup 表示用户组模型 | ||||
| type UserGroup struct { | ||||
| 	gorm.Model | ||||
| 	Name        string    `json:"name" gorm:"uniqueIndex;not null"`         // 用户组名称 | ||||
| 	Description string    `json:"description"`                              // 用户组描述 | ||||
| 	CreatedAt   time.Time `json:"created_at"`                               // 创建时间 | ||||
| 	UpdatedAt   time.Time `json:"updated_at"`                               // 更新时间 | ||||
| 	Users       []User    `json:"users" gorm:"many2many:user_group_users;"` // 关联的用户 | ||||
| 	Roles       []Role    `json:"roles" gorm:"many2many:user_group_roles;"` // 关联的角色 | ||||
| } | ||||
							
								
								
									
										19
									
								
								repositories/db.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								repositories/db.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/config" | ||||
| 	"gorm.io/driver/mysql" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| var db *gorm.DB | ||||
| 
 | ||||
| func InitDB() error { | ||||
| 	var err error | ||||
| 	dsn := config.AppConfig.DBUser + ":" + config.AppConfig.DBPassword + "@tcp(" + config.AppConfig.DBHost + ":" + strconv.Itoa(config.AppConfig.DBPort) + ")/" + config.AppConfig.DBName + "?charset=utf8mb4&parseTime=True&loc=Local" | ||||
| 	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return db.AutoMigrate(&models.Permission{}, &models.Role{}, &models.UserGroup{}) | ||||
| } | ||||
| @ -0,0 +1,87 @@ | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
|     "gitea.zjmud.xyz/phyer/rbac/models" | ||||
|     "gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreatePermission(permission *models.Permission) (*models.Permission, error) { | ||||
|     result := db.Create(permission) | ||||
|     return permission, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetPermissionByID(id uint) (*models.Permission, error) { | ||||
|     var permission models.Permission | ||||
|     result := db.First(&permission, id) | ||||
|     return &permission, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetPermissions() ([]models.Permission, error) { | ||||
|     var permissions []models.Permission | ||||
|     result := db.Find(&permissions) | ||||
|     return permissions, result.Error | ||||
| } | ||||
| 
 | ||||
| func UpdatePermission(id uint, updateData map[string]interface{}) (*models.Permission, error) { | ||||
|     var permission models.Permission | ||||
|     result := db.Model(&permission).Where("id = ?", id).Updates(updateData) | ||||
|     if result.Error != nil { | ||||
|         return nil, result.Error | ||||
|     } | ||||
|     return GetPermissionByID(id) | ||||
| } | ||||
| 
 | ||||
| func DeletePermission(id uint) error { | ||||
|     result := db.Delete(&models.Permission{}, id) | ||||
|     return result.Error | ||||
| } | ||||
| 
 | ||||
| func CheckPermissionExists(name string) (bool, error) { | ||||
|     var count int64 | ||||
|     result := db.Model(&models.Permission{}).Where("name = ?", name).Count(&count) | ||||
|     return count > 0, result.Error | ||||
| } | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
|     "gitea.zjmud.xyz/phyer/rbac/models" | ||||
|     "gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreatePermission(permission *models.Permission) (*models.Permission, error) { | ||||
|     result := db.Create(permission) | ||||
|     return permission, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetPermissionByID(id uint) (*models.Permission, error) { | ||||
|     var permission models.Permission | ||||
|     result := db.First(&permission, id) | ||||
|     return &permission, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetPermissions() ([]models.Permission, error) { | ||||
|     var permissions []models.Permission | ||||
|     result := db.Find(&permissions) | ||||
|     return permissions, result.Error | ||||
| } | ||||
| 
 | ||||
| func UpdatePermission(id uint, updateData map[string]interface{}) (*models.Permission, error) { | ||||
|     var permission models.Permission | ||||
|     result := db.Model(&permission).Where("id = ?", id).Updates(updateData) | ||||
|     if result.Error != nil { | ||||
|         return nil, result.Error | ||||
|     } | ||||
|     return GetPermissionByID(id) | ||||
| } | ||||
| 
 | ||||
| func DeletePermission(id uint) error { | ||||
|     result := db.Delete(&models.Permission{}, id) | ||||
|     return result.Error | ||||
| } | ||||
| 
 | ||||
| func CheckPermissionExists(name string) (bool, error) { | ||||
|     var count int64 | ||||
|     result := db.Model(&models.Permission{}).Where("name = ?", name).Count(&count) | ||||
|     return count > 0, result.Error | ||||
| } | ||||
| 
 | ||||
| @ -0,0 +1,51 @@ | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreateRole(role *models.Role) (*models.Role, error) { | ||||
| 	result := db.Create(role) | ||||
| 	return role, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetRoleByID(id uint) (*models.Role, error) { | ||||
| 	var role models.Role | ||||
| 	result := db.Preload("Permissions").First(&role, id) | ||||
| 	return &role, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetRoles() ([]models.Role, error) { | ||||
| 	var roles []models.Role | ||||
| 	result := db.Preload("Permissions").Find(&roles) | ||||
| 	return roles, result.Error | ||||
| } | ||||
| 
 | ||||
| func UpdateRole(id uint, updateData map[string]interface{}) (*models.Role, error) { | ||||
| 	var role models.Role | ||||
| 	result := db.Model(&role).Where("id = ?", id).Updates(updateData) | ||||
| 	if result.Error != nil { | ||||
| 		return nil, result.Error | ||||
| 	} | ||||
| 	return GetRoleByID(id) | ||||
| } | ||||
| 
 | ||||
| func DeleteRole(id uint) error { | ||||
| 	result := db.Delete(&models.Role{}, id) | ||||
| 	return result.Error | ||||
| } | ||||
| 
 | ||||
| func CheckRoleExists(name string) (bool, error) { | ||||
| 	var count int64 | ||||
| 	result := db.Model(&models.Role{}).Where("name = ?", name).Count(&count) | ||||
| 	return count > 0, result.Error | ||||
| } | ||||
| 
 | ||||
| func AddPermissionToRole(roleID uint, permissionID uint) error { | ||||
| 	return db.Model(&models.Role{Model: gorm.Model{ID: roleID}}).Association("Permissions").Append(&models.Permission{Model: gorm.Model{ID: permissionID}}) | ||||
| } | ||||
| 
 | ||||
| func RemovePermissionFromRole(roleID uint, permissionID uint) error { | ||||
| 	return db.Model(&models.Role{Model: gorm.Model{ID: roleID}}).Association("Permissions").Delete(&models.Permission{Model: gorm.Model{ID: permissionID}}) | ||||
| } | ||||
| @ -0,0 +1,61 @@ | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreateUserGroup(userGroup *models.UserGroup) (*models.UserGroup, error) { | ||||
| 	result := db.Create(userGroup) | ||||
| 	return userGroup, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetUserGroupByID(id uint) (*models.UserGroup, error) { | ||||
| 	var userGroup models.UserGroup | ||||
| 	result := db.Preload("Users").Preload("Roles").First(&userGroup, id) | ||||
| 	return &userGroup, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetUserGroups() ([]models.UserGroup, error) { | ||||
| 	var userGroups []models.UserGroup | ||||
| 	result := db.Preload("Users").Preload("Roles").Find(&userGroups) | ||||
| 	return userGroups, result.Error | ||||
| } | ||||
| 
 | ||||
| func UpdateUserGroup(id uint, updateData map[string]interface{}) (*models.UserGroup, error) { | ||||
| 	var userGroup models.UserGroup | ||||
| 	result := db.Model(&userGroup).Where("id = ?", id).Updates(updateData) | ||||
| 	if result.Error != nil { | ||||
| 		return nil, result.Error | ||||
| 	} | ||||
| 	return GetUserGroupByID(id) | ||||
| } | ||||
| 
 | ||||
| func DeleteUserGroup(id uint) error { | ||||
| 	result := db.Delete(&models.UserGroup{}, id) | ||||
| 	return result.Error | ||||
| } | ||||
| 
 | ||||
| func AddUserToGroup(userGroupID uint, userID uint) error { | ||||
| 	return db.Model(&models.UserGroup{Model: gorm.Model{ID: userGroupID}}). | ||||
| 		Association("Users"). | ||||
| 		Append(&models.User{Model: gorm.Model{ID: userID}}) | ||||
| } | ||||
| 
 | ||||
| func RemoveUserFromGroup(userGroupID uint, userID uint) error { | ||||
| 	return db.Model(&models.UserGroup{Model: gorm.Model{ID: userGroupID}}). | ||||
| 		Association("Users"). | ||||
| 		Delete(&models.User{Model: gorm.Model{ID: userID}}) | ||||
| } | ||||
| 
 | ||||
| func AddRoleToGroup(userGroupID uint, roleID uint) error { | ||||
| 	return db.Model(&models.UserGroup{Model: gorm.Model{ID: userGroupID}}). | ||||
| 		Association("Roles"). | ||||
| 		Append(&models.Role{Model: gorm.Model{ID: roleID}}) | ||||
| } | ||||
| 
 | ||||
| func RemoveRoleFromGroup(userGroupID uint, roleID uint) error { | ||||
| 	return db.Model(&models.UserGroup{Model: gorm.Model{ID: userGroupID}}). | ||||
| 		Association("Roles"). | ||||
| 		Delete(&models.Role{Model: gorm.Model{ID: roleID}}) | ||||
| } | ||||
							
								
								
									
										110
									
								
								services/rbac.go
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								services/rbac.go
									
									
									
									
									
								
							| @ -0,0 +1,110 @@ | ||||
| package services | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/repositories" | ||||
| ) | ||||
| 
 | ||||
| // AssignRoleToUser 为用户分配角色 | ||||
| func AssignRoleToUser(userID string, roleID uint) error { | ||||
| 	// 检查用户是否存在 | ||||
| 	user, err := repositories.GetUserByID(userID) | ||||
| 	if err != nil { | ||||
| 		return errors.New("user not found") | ||||
| 	} | ||||
| 
 | ||||
| 	// 检查角色是否存在 | ||||
| 	role, err := repositories.GetRoleByID(roleID) | ||||
| 	if err != nil { | ||||
| 		return errors.New("role not found") | ||||
| 	} | ||||
| 
 | ||||
| 	// 分配角色 | ||||
| 	return repositories.AssignRoleToUser(user.ID, role.ID) | ||||
| } | ||||
| 
 | ||||
| // RemoveRoleFromUser 移除用户的角色 | ||||
| func RemoveRoleFromUser(userID string, roleID uint) error { | ||||
| 	// 检查用户是否存在 | ||||
| 	user, err := repositories.GetUserByID(userID) | ||||
| 	if err != nil { | ||||
| 		return errors.New("user not found") | ||||
| 	} | ||||
| 
 | ||||
| 	// 检查角色是否存在 | ||||
| 	role, err := repositories.GetRoleByID(roleID) | ||||
| 	if err != nil { | ||||
| 		return errors.New("role not found") | ||||
| 	} | ||||
| 
 | ||||
| 	// 移除角色 | ||||
| 	return repositories.RemoveRoleFromUser(user.ID, role.ID) | ||||
| } | ||||
| 
 | ||||
| // CreateRoleWithPermissions 创建角色并分配权限 | ||||
| func CreateRoleWithPermissions(roleName string, permissionIDs []uint) (*models.Role, error) { | ||||
| 	// 检查角色是否已存在 | ||||
| 	exists, err := repositories.CheckRoleExists(roleName) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if exists { | ||||
| 		return nil, errors.New("role already exists") | ||||
| 	} | ||||
| 
 | ||||
| 	// 创建角色 | ||||
| 	role := &models.Role{Name: roleName} | ||||
| 	role, err = repositories.CreateRole(role) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// 为角色分配权限 | ||||
| 	for _, permissionID := range permissionIDs { | ||||
| 		err = repositories.AddPermissionToRole(role.ID, permissionID) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return role, nil | ||||
| } | ||||
| 
 | ||||
| // CheckUserPermission 检查用户是否具有特定权限 | ||||
| func CheckUserPermission(userID string, permission string) (bool, error) { | ||||
| 	// 获取用户的所有角色 | ||||
| 	user, err := repositories.GetUserByID(userID) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	// 检查每个角色的权限 | ||||
| 	for _, role := range user.Roles { | ||||
| 		for _, perm := range role.Permissions { | ||||
| 			if perm.Name == permission { | ||||
| 				return true, nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return false, nil | ||||
| } | ||||
| 
 | ||||
| // GetUserPermissions 获取用户的所有权限 | ||||
| func GetUserPermissions(userID string) ([]string, error) { | ||||
| 	var permissions []string | ||||
| 	user, err := repositories.GetUserByID(userID) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// 收集所有角色的权限 | ||||
| 	for _, role := range user.Roles { | ||||
| 		for _, perm := range role.Permissions { | ||||
| 			permissions = append(permissions, perm.Name) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return permissions, nil | ||||
| } | ||||
							
								
								
									
										917
									
								
								sug.md
									
									
									
									
									
								
							
							
						
						
									
										917
									
								
								sug.md
									
									
									
									
									
								
							| @ -1,3 +1,4 @@ | ||||
| 
 | ||||
| - Datetime: 2025-02-16 12:45:39 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| @ -1142,4 +1143,920 @@ func main() { | ||||
| 
 | ||||
| 如果你需要其他模块的实现或有任何问题,请随时告诉我。 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 18:12:44 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - sug.md | ||||
| 
 | ||||
| > models/user_group.go 需要什么内容 | ||||
| >  | ||||
| 
 | ||||
| `models/user_group.go` 文件应该定义用户组模型,用于将用户分组管理。以下是该文件的内容建议: | ||||
| 
 | ||||
| Filepath: models/user_group.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package models | ||||
| 
 | ||||
| import ( | ||||
|     "time" | ||||
|     "gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| // UserGroup 表示用户组模型 | ||||
| type UserGroup struct { | ||||
|     gorm.Model | ||||
|     Name        string    `json:"name" gorm:"uniqueIndex;not null"` // 用户组名称 | ||||
|     Description string    `json:"description"`                     // 用户组描述 | ||||
|     CreatedAt   time.Time `json:"created_at"`                      // 创建时间 | ||||
|     UpdatedAt   time.Time `json:"updated_at"`                      // 更新时间 | ||||
|     Users       []User    `json:"users" gorm:"many2many:user_group_users;"` // 关联的用户 | ||||
|     Roles       []Role    `json:"roles" gorm:"many2many:user_group_roles;"` // 关联的角色 | ||||
| } | ||||
| 
 | ||||
| // UserGroupUser 表示用户和用户组的关联表 | ||||
| type UserGroupUser struct { | ||||
|     UserID      uint `gorm:"primaryKey"` // 用户ID | ||||
|     UserGroupID uint `gorm:"primaryKey"` // 用户组ID | ||||
| } | ||||
| 
 | ||||
| // UserGroupRole 表示用户组和角色的关联表 | ||||
| type UserGroupRole struct { | ||||
|     UserGroupID uint `gorm:"primaryKey"` // 用户组ID | ||||
|     RoleID      uint `gorm:"primaryKey"` // 角色ID | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这个模型包含以下主要部分: | ||||
| 
 | ||||
| 1. `UserGroup` 结构体: | ||||
|    - 包含用户组的基本信息(名称、描述) | ||||
|    - 使用 `gorm.Model` 包含默认字段(ID, CreatedAt, UpdatedAt, DeletedAt) | ||||
|    - 通过 `many2many` 关联用户和角色 | ||||
| 
 | ||||
| 2. `UserGroupUser` 结构体: | ||||
|    - 用于表示用户和用户组的多对多关系 | ||||
|    - 作为关联表,包含复合主键(UserID 和 UserGroupID) | ||||
| 
 | ||||
| 3. `UserGroupRole` 结构体: | ||||
|    - 用于表示用户组和角色的多对多关系 | ||||
|    - 作为关联表,包含复合主键(UserGroupID 和 RoleID) | ||||
| 
 | ||||
| 这个模型设计允许: | ||||
| - 将用户分组管理 | ||||
| - 为整个用户组分配角色 | ||||
| - 灵活地管理用户和用户组之间的关系 | ||||
| - 跟踪用户组的创建和更新时间 | ||||
| 
 | ||||
| 你可以根据需要扩展这个模型,例如添加更多字段或关联关系。如果需要实现具体的业务逻辑,还需要在 repositories 和 services 层添加相应的代码。 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 18:16:15 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - sug.md | ||||
|   - models/permission.go | ||||
| 
 | ||||
| > repositories/permission.go 这个文件用得上吗, 现在有一个 models/permission.gorm  | ||||
| 
 | ||||
| 是的,`repositories/permission.go` 文件是需要的。它负责处理与权限相关的数据库操作,而 `models/permission.go` 只是定义了权限的数据结构。让我们创建 `repositories/permission.go` 文件: | ||||
| 
 | ||||
| Filepath: repositories/permission.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
|     "gitea.zjmud.xyz/phyer/rbac/models" | ||||
|     "gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreatePermission(permission *models.Permission) (*models.Permission, error) { | ||||
|     result := db.Create(permission) | ||||
|     return permission, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetPermissionByID(id uint) (*models.Permission, error) { | ||||
|     var permission models.Permission | ||||
|     result := db.First(&permission, id) | ||||
|     return &permission, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetPermissions() ([]models.Permission, error) { | ||||
|     var permissions []models.Permission | ||||
|     result := db.Find(&permissions) | ||||
|     return permissions, result.Error | ||||
| } | ||||
| 
 | ||||
| func UpdatePermission(id uint, updateData map[string]interface{}) (*models.Permission, error) { | ||||
|     var permission models.Permission | ||||
|     result := db.Model(&permission).Where("id = ?", id).Updates(updateData) | ||||
|     if result.Error != nil { | ||||
|         return nil, result.Error | ||||
|     } | ||||
|     return GetPermissionByID(id) | ||||
| } | ||||
| 
 | ||||
| func DeletePermission(id uint) error { | ||||
|     result := db.Delete(&models.Permission{}, id) | ||||
|     return result.Error | ||||
| } | ||||
| 
 | ||||
| func CheckPermissionExists(name string) (bool, error) { | ||||
|     var count int64 | ||||
|     result := db.Model(&models.Permission{}).Where("name = ?", name).Count(&count) | ||||
|     return count > 0, result.Error | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这个文件实现了以下功能: | ||||
| 
 | ||||
| 1. `CreatePermission`: 创建新的权限 | ||||
| 2. `GetPermissionByID`: 根据ID获取权限 | ||||
| 3. `GetPermissions`: 获取所有权限列表 | ||||
| 4. `UpdatePermission`: 更新权限信息 | ||||
| 5. `DeletePermission`: 删除权限 | ||||
| 6. `CheckPermissionExists`: 检查权限名称是否已存在 | ||||
| 
 | ||||
| 这些方法将与 `models/permission.go` 中定义的 `Permission` 结构体一起工作,为权限管理提供完整的CRUD操作。 | ||||
| 
 | ||||
| 你还需要在 `repositories` 包中初始化数据库连接,可以在 `repositories/db.go` 中添加: | ||||
| 
 | ||||
| Filepath: repositories/db.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
|     "gitea.zjmud.xyz/phyer/rbac/config" | ||||
|     "gorm.io/driver/mysql" | ||||
|     "gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| var db *gorm.DB | ||||
| 
 | ||||
| func InitDB() error { | ||||
|     var err error | ||||
|     dsn := config.AppConfig.DBUser + ":" + config.AppConfig.DBPassword + "@tcp(" + config.AppConfig.DBHost + ":" + strconv.Itoa(config.AppConfig.DBPort) + ")/" + config.AppConfig.DBName + "?charset=utf8mb4&parseTime=True&loc=Local" | ||||
|     db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) | ||||
|     if err != nil { | ||||
|         return err | ||||
|     } | ||||
|     return db.AutoMigrate(&models.Permission{}) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这样,权限相关的数据库操作就完整了。你可以在服务层调用这些方法来处理业务逻辑。 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 18:25:33 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - tree.txt | ||||
| 
 | ||||
| > repositories/role.go 需要吗 | ||||
| 
 | ||||
| 是的,`repositories/role.go` 是需要的。它负责处理与角色相关的数据库操作,与 `models/role.go` 配合使用。让我们创建这个文件: | ||||
| 
 | ||||
| Filepath: repositories/role.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
|     "gitea.zjmud.xyz/phyer/rbac/models" | ||||
|     "gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreateRole(role *models.Role) (*models.Role, error) { | ||||
|     result := db.Create(role) | ||||
|     return role, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetRoleByID(id uint) (*models.Role, error) { | ||||
|     var role models.Role | ||||
|     result := db.Preload("Permissions").First(&role, id) | ||||
|     return &role, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetRoles() ([]models.Role, error) { | ||||
|     var roles []models.Role | ||||
|     result := db.Preload("Permissions").Find(&roles) | ||||
|     return roles, result.Error | ||||
| } | ||||
| 
 | ||||
| func UpdateRole(id uint, updateData map[string]interface{}) (*models.Role, error) { | ||||
|     var role models.Role | ||||
|     result := db.Model(&role).Where("id = ?", id).Updates(updateData) | ||||
|     if result.Error != nil { | ||||
|         return nil, result.Error | ||||
|     } | ||||
|     return GetRoleByID(id) | ||||
| } | ||||
| 
 | ||||
| func DeleteRole(id uint) error { | ||||
|     result := db.Delete(&models.Role{}, id) | ||||
|     return result.Error | ||||
| } | ||||
| 
 | ||||
| func CheckRoleExists(name string) (bool, error) { | ||||
|     var count int64 | ||||
|     result := db.Model(&models.Role{}).Where("name = ?", name).Count(&count) | ||||
|     return count > 0, result.Error | ||||
| } | ||||
| 
 | ||||
| func AddPermissionToRole(roleID uint, permissionID uint) error { | ||||
|     return db.Model(&models.Role{Model: gorm.Model{ID: roleID}}).Association("Permissions").Append(&models.Permission{Model: gorm.Model{ID: permissionID}}) | ||||
| } | ||||
| 
 | ||||
| func RemovePermissionFromRole(roleID uint, permissionID uint) error { | ||||
|     return db.Model(&models.Role{Model: gorm.Model{ID: roleID}}).Association("Permissions").Delete(&models.Permission{Model: gorm.Model{ID: permissionID}}) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这个文件实现了以下功能: | ||||
| 
 | ||||
| 1. `CreateRole`: 创建新角色 | ||||
| 2. `GetRoleByID`: 根据ID获取角色(包含关联的权限) | ||||
| 3. `GetRoles`: 获取所有角色列表(包含关联的权限) | ||||
| 4. `UpdateRole`: 更新角色信息 | ||||
| 5. `DeleteRole`: 删除角色 | ||||
| 6. `CheckRoleExists`: 检查角色名称是否已存在 | ||||
| 7. `AddPermissionToRole`: 为角色添加权限 | ||||
| 8. `RemovePermissionFromRole`: 从角色中移除权限 | ||||
| 
 | ||||
| 这些方法将与 `models/role.go` 中定义的 `Role` 结构体一起工作,为角色管理提供完整的CRUD操作。 | ||||
| 
 | ||||
| 你还需要在 `repositories/db.go` 中添加对 `Role` 模型的自动迁移: | ||||
| 
 | ||||
| Filepath: repositories/db.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
|     "gitea.zjmud.xyz/phyer/rbac/config" | ||||
|     "gorm.io/driver/mysql" | ||||
|     "gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| var db *gorm.DB | ||||
| 
 | ||||
| func InitDB() error { | ||||
|     var err error | ||||
|     dsn := config.AppConfig.DBUser + ":" + config.AppConfig.DBPassword + "@tcp(" + config.AppConfig.DBHost + ":" + strconv.Itoa(config.AppConfig.DBPort) + ")/" + config.AppConfig.DBName + "?charset=utf8mb4&parseTime=True&loc=Local" | ||||
|     db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) | ||||
|     if err != nil { | ||||
|         return err | ||||
|     } | ||||
|     return db.AutoMigrate(&models.Permission{}, &models.Role{}) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这样,角色相关的数据库操作就完整了。你可以在服务层调用这些方法来处理业务逻辑。 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 18:36:07 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - sug.md | ||||
| 
 | ||||
| > repositories/user_group.go 需要什么内容 | ||||
| 
 | ||||
| `repositories/user_group.go` 文件用于处理与用户组相关的数据库操作。以下是该文件的内容建议: | ||||
| 
 | ||||
| Filepath: repositories/user_group.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
|     "gitea.zjmud.xyz/phyer/rbac/models" | ||||
|     "gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreateUserGroup(userGroup *models.UserGroup) (*models.UserGroup, error) { | ||||
|     result := db.Create(userGroup) | ||||
|     return userGroup, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetUserGroupByID(id uint) (*models.UserGroup, error) { | ||||
|     var userGroup models.UserGroup | ||||
|     result := db.Preload("Users").Preload("Roles").First(&userGroup, id) | ||||
|     return &userGroup, result.Error | ||||
| } | ||||
| 
 | ||||
| func GetUserGroups() ([]models.UserGroup, error) { | ||||
|     var userGroups []models.UserGroup | ||||
|     result := db.Preload("Users").Preload("Roles").Find(&userGroups) | ||||
|     return userGroups, result.Error | ||||
| } | ||||
| 
 | ||||
| func UpdateUserGroup(id uint, updateData map[string]interface{}) (*models.UserGroup, error) { | ||||
|     var userGroup models.UserGroup | ||||
|     result := db.Model(&userGroup).Where("id = ?", id).Updates(updateData) | ||||
|     if result.Error != nil { | ||||
|         return nil, result.Error | ||||
|     } | ||||
|     return GetUserGroupByID(id) | ||||
| } | ||||
| 
 | ||||
| func DeleteUserGroup(id uint) error { | ||||
|     result := db.Delete(&models.UserGroup{}, id) | ||||
|     return result.Error | ||||
| } | ||||
| 
 | ||||
| func AddUserToGroup(userGroupID uint, userID uint) error { | ||||
|     return db.Model(&models.UserGroup{Model: gorm.Model{ID: userGroupID}}). | ||||
|         Association("Users"). | ||||
|         Append(&models.User{Model: gorm.Model{ID: userID}}) | ||||
| } | ||||
| 
 | ||||
| func RemoveUserFromGroup(userGroupID uint, userID uint) error { | ||||
|     return db.Model(&models.UserGroup{Model: gorm.Model{ID: userGroupID}}). | ||||
|         Association("Users"). | ||||
|         Delete(&models.User{Model: gorm.Model{ID: userID}}) | ||||
| } | ||||
| 
 | ||||
| func AddRoleToGroup(userGroupID uint, roleID uint) error { | ||||
|     return db.Model(&models.UserGroup{Model: gorm.Model{ID: userGroupID}}). | ||||
|         Association("Roles"). | ||||
|         Append(&models.Role{Model: gorm.Model{ID: roleID}}) | ||||
| } | ||||
| 
 | ||||
| func RemoveRoleFromGroup(userGroupID uint, roleID uint) error { | ||||
|     return db.Model(&models.UserGroup{Model: gorm.Model{ID: userGroupID}}). | ||||
|         Association("Roles"). | ||||
|         Delete(&models.Role{Model: gorm.Model{ID: roleID}}) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这个文件实现了以下功能: | ||||
| 
 | ||||
| 1. `CreateUserGroup`: 创建新用户组 | ||||
| 2. `GetUserGroupByID`: 根据ID获取用户组(包含关联的用户和角色) | ||||
| 3. `GetUserGroups`: 获取所有用户组列表(包含关联的用户和角色) | ||||
| 4. `UpdateUserGroup`: 更新用户组信息 | ||||
| 5. `DeleteUserGroup`: 删除用户组 | ||||
| 6. `AddUserToGroup`: 添加用户到用户组 | ||||
| 7. `RemoveUserFromGroup`: 从用户组中移除用户 | ||||
| 8. `AddRoleToGroup`: 为用户组添加角色 | ||||
| 9. `RemoveRoleFromGroup`: 从用户组中移除角色 | ||||
| 
 | ||||
| 这些方法将与 `models/user_group.go` 中定义的 `UserGroup` 结构体一起工作,为用户组管理提供完整的CRUD操作。 | ||||
| 
 | ||||
| 你还需要在 `repositories/db.go` 中添加对 `UserGroup` 模型的自动迁移: | ||||
| 
 | ||||
| Filepath: repositories/db.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
|     "gitea.zjmud.xyz/phyer/rbac/config" | ||||
|     "gorm.io/driver/mysql" | ||||
|     "gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| var db *gorm.DB | ||||
| 
 | ||||
| func InitDB() error { | ||||
|     var err error | ||||
|     dsn := config.AppConfig.DBUser + ":" + config.AppConfig.DBPassword + "@tcp(" + config.AppConfig.DBHost + ":" + strconv.Itoa(config.AppConfig.DBPort) + ")/" + config.AppConfig.DBName + "?charset=utf8mb4&parseTime=True&loc=Local" | ||||
|     db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) | ||||
|     if err != nil { | ||||
|         return err | ||||
|     } | ||||
|     return db.AutoMigrate(&models.Permission{}, &models.Role{}, &models.UserGroup{}) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这样,用户组相关的数据库操作就完整了。你可以在服务层调用这些方法来处理业务逻辑。 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 18:40:54 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - sug.md | ||||
| 
 | ||||
| > services/rbac.go 需要什么内容 | ||||
| >  | ||||
| 
 | ||||
| `services/rbac.go` 文件应该包含与RBAC(基于角色的访问控制)相关的业务逻辑。以下是该文件的内容建议: | ||||
| 
 | ||||
| Filepath: services/rbac.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package services | ||||
| 
 | ||||
| import ( | ||||
|     "errors" | ||||
|     "gitea.zjmud.xyz/phyer/rbac/models" | ||||
|     "gitea.zjmud.xyz/phyer/rbac/repositories" | ||||
| ) | ||||
| 
 | ||||
| // AssignRoleToUser 为用户分配角色 | ||||
| func AssignRoleToUser(userID string, roleID uint) error { | ||||
|     // 检查用户是否存在 | ||||
|     user, err := repositories.GetUserByID(userID) | ||||
|     if err != nil { | ||||
|         return errors.New("user not found") | ||||
|     } | ||||
| 
 | ||||
|     // 检查角色是否存在 | ||||
|     role, err := repositories.GetRoleByID(roleID) | ||||
|     if err != nil { | ||||
|         return errors.New("role not found") | ||||
|     } | ||||
| 
 | ||||
|     // 分配角色 | ||||
|     return repositories.AssignRoleToUser(user.ID, role.ID) | ||||
| } | ||||
| 
 | ||||
| // RemoveRoleFromUser 移除用户的角色 | ||||
| func RemoveRoleFromUser(userID string, roleID uint) error { | ||||
|     // 检查用户是否存在 | ||||
|     user, err := repositories.GetUserByID(userID) | ||||
|     if err != nil { | ||||
|         return errors.New("user not found") | ||||
|     } | ||||
| 
 | ||||
|     // 检查角色是否存在 | ||||
|     role, err := repositories.GetRoleByID(roleID) | ||||
|     if err != nil { | ||||
|         return errors.New("role not found") | ||||
|     } | ||||
| 
 | ||||
|     // 移除角色 | ||||
|     return repositories.RemoveRoleFromUser(user.ID, role.ID) | ||||
| } | ||||
| 
 | ||||
| // CreateRoleWithPermissions 创建角色并分配权限 | ||||
| func CreateRoleWithPermissions(roleName string, permissionIDs []uint) (*models.Role, error) { | ||||
|     // 检查角色是否已存在 | ||||
|     exists, err := repositories.CheckRoleExists(roleName) | ||||
|     if err != nil { | ||||
|         return nil, err | ||||
|     } | ||||
|     if exists { | ||||
|         return nil, errors.New("role already exists") | ||||
|     } | ||||
| 
 | ||||
|     // 创建角色 | ||||
|     role := &models.Role{Name: roleName} | ||||
|     role, err = repositories.CreateRole(role) | ||||
|     if err != nil { | ||||
|         return nil, err | ||||
|     } | ||||
| 
 | ||||
|     // 为角色分配权限 | ||||
|     for _, permissionID := range permissionIDs { | ||||
|         err = repositories.AddPermissionToRole(role.ID, permissionID) | ||||
|         if err != nil { | ||||
|             return nil, err | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return role, nil | ||||
| } | ||||
| 
 | ||||
| // CheckUserPermission 检查用户是否具有特定权限 | ||||
| func CheckUserPermission(userID string, permission string) (bool, error) { | ||||
|     // 获取用户的所有角色 | ||||
|     user, err := repositories.GetUserByID(userID) | ||||
|     if err != nil { | ||||
|         return false, err | ||||
|     } | ||||
| 
 | ||||
|     // 检查每个角色的权限 | ||||
|     for _, role := range user.Roles { | ||||
|         for _, perm := range role.Permissions { | ||||
|             if perm.Name == permission { | ||||
|                 return true, nil | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false, nil | ||||
| } | ||||
| 
 | ||||
| // GetUserPermissions 获取用户的所有权限 | ||||
| func GetUserPermissions(userID string) ([]string, error) { | ||||
|     var permissions []string | ||||
|     user, err := repositories.GetUserByID(userID) | ||||
|     if err != nil { | ||||
|         return nil, err | ||||
|     } | ||||
| 
 | ||||
|     // 收集所有角色的权限 | ||||
|     for _, role := range user.Roles { | ||||
|         for _, perm := range role.Permissions { | ||||
|             permissions = append(permissions, perm.Name) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return permissions, nil | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这个文件实现了以下主要功能: | ||||
| 
 | ||||
| 1. `AssignRoleToUser`: 为用户分配角色 | ||||
| 2. `RemoveRoleFromUser`: 移除用户的角色 | ||||
| 3. `CreateRoleWithPermissions`: 创建角色并为其分配权限 | ||||
| 4. `CheckUserPermission`: 检查用户是否具有特定权限 | ||||
| 5. `GetUserPermissions`: 获取用户的所有权限 | ||||
| 
 | ||||
| 这些方法将作为RBAC系统的核心业务逻辑,被控制器层调用。它们处理了角色分配、权限检查等关键功能,同时通过调用仓库层的方法与数据库进行交互。 | ||||
| 
 | ||||
| 你可以根据具体需求扩展这个文件,例如添加更多与RBAC相关的业务逻辑,或者优化现有的功能实现。 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 18:43:54 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - sug.md | ||||
| 
 | ||||
| > controllers/rbac.go 需要什么内容 | ||||
| >  | ||||
| 
 | ||||
| `controllers/rbac.go` 文件应该包含与RBAC(基于角色的访问控制)相关的控制器逻辑。以下是该文件的内容建议: | ||||
| 
 | ||||
| Filepath: controllers/rbac.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package controllers | ||||
| 
 | ||||
| import ( | ||||
|     "gitea.zjmud.xyz/phyer/rbac/services" | ||||
|     "github.com/gin-gonic/gin" | ||||
| ) | ||||
| 
 | ||||
| // CreateRole 创建新角色 | ||||
| func CreateRole(c *gin.Context) { | ||||
|     var roleData struct { | ||||
|         Name        string `json:"name" binding:"required"` | ||||
|         Description string `json:"description"` | ||||
|     } | ||||
|     if err := c.ShouldBindJSON(&roleData); err != nil { | ||||
|         c.JSON(400, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
| 
 | ||||
|     role, err := services.CreateRole(roleData.Name, roleData.Description) | ||||
|     if err != nil { | ||||
|         c.JSON(500, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
|     c.JSON(201, role) | ||||
| } | ||||
| 
 | ||||
| // GetRoles 获取所有角色 | ||||
| func GetRoles(c *gin.Context) { | ||||
|     roles, err := services.GetAllRoles() | ||||
|     if err != nil { | ||||
|         c.JSON(500, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
|     c.JSON(200, roles) | ||||
| } | ||||
| 
 | ||||
| // CreatePermission 创建新权限 | ||||
| func CreatePermission(c *gin.Context) { | ||||
|     var permissionData struct { | ||||
|         Name        string `json:"name" binding:"required"` | ||||
|         Description string `json:"description"` | ||||
|         Resource    string `json:"resource" binding:"required"` | ||||
|         Action      string `json:"action" binding:"required"` | ||||
|     } | ||||
|     if err := c.ShouldBindJSON(&permissionData); err != nil { | ||||
|         c.JSON(400, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
| 
 | ||||
|     permission, err := services.CreatePermission(permissionData.Name, permissionData.Description, permissionData.Resource, permissionData.Action) | ||||
|     if err != nil { | ||||
|         c.JSON(500, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
|     c.JSON(201, permission) | ||||
| } | ||||
| 
 | ||||
| // AssignRoleToUser 为用户分配角色 | ||||
| func AssignRoleToUser(c *gin.Context) { | ||||
|     var assignmentData struct { | ||||
|         UserID uint `json:"user_id" binding:"required"` | ||||
|         RoleID uint `json:"role_id" binding:"required"` | ||||
|     } | ||||
|     if err := c.ShouldBindJSON(&assignmentData); err != nil { | ||||
|         c.JSON(400, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
| 
 | ||||
|     err := services.AssignRoleToUser(assignmentData.UserID, assignmentData.RoleID) | ||||
|     if err != nil { | ||||
|         c.JSON(500, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
|     c.JSON(200, gin.H{"message": "Role assigned successfully"}) | ||||
| } | ||||
| 
 | ||||
| // AssignPermissionToRole 为角色分配权限 | ||||
| func AssignPermissionToRole(c *gin.Context) { | ||||
|     var assignmentData struct { | ||||
|         RoleID       uint `json:"role_id" binding:"required"` | ||||
|         PermissionID uint `json:"permission_id" binding:"required"` | ||||
|     } | ||||
|     if err := c.ShouldBindJSON(&assignmentData); err != nil { | ||||
|         c.JSON(400, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
| 
 | ||||
|     err := services.AssignPermissionToRole(assignmentData.RoleID, assignmentData.PermissionID) | ||||
|     if err != nil { | ||||
|         c.JSON(500, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
|     c.JSON(200, gin.H{"message": "Permission assigned successfully"}) | ||||
| } | ||||
| 
 | ||||
| // GetPermissions 获取所有权限 | ||||
| func GetPermissions(c *gin.Context) { | ||||
|     permissions, err := services.GetAllPermissions() | ||||
|     if err != nil { | ||||
|         c.JSON(500, gin.H{"error": err.Error()}) | ||||
|         return | ||||
|     } | ||||
|     c.JSON(200, permissions) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这个控制器文件实现了以下主要功能: | ||||
| 
 | ||||
| 1. `CreateRole`: 创建新角色 | ||||
| 2. `GetRoles`: 获取所有角色列表 | ||||
| 3. `CreatePermission`: 创建新权限 | ||||
| 4. `AssignRoleToUser`: 为用户分配角色 | ||||
| 5. `AssignPermissionToRole`: 为角色分配权限 | ||||
| 6. `GetPermissions`: 获取所有权限列表 | ||||
| 
 | ||||
| 每个控制器方法都: | ||||
| - 解析请求数据 | ||||
| - 调用相应的服务层方法 | ||||
| - 处理错误并返回适当的HTTP响应 | ||||
| 
 | ||||
| 这些控制器方法将与 `services/rbac.go` 中的服务层方法配合使用,完成RBAC系统的核心功能。 | ||||
| 
 | ||||
| 你还需要在 `services/rbac.go` 中实现相应的服务层方法,以及在 `repositories` 包中实现数据库操作。如果需要这些文件的内容,请告诉我。 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 18:47:16 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - sug.md | ||||
| 
 | ||||
| > utils/redis.go 需要什么内容 | ||||
| >  | ||||
| 
 | ||||
| `utils/redis.go` 文件用于初始化和管理 Redis 连接,并提供一些常用的 Redis 操作工具函数。以下是该文件的内容建议: | ||||
| 
 | ||||
| Filepath: utils/redis.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package utils | ||||
| 
 | ||||
| import ( | ||||
|     "context" | ||||
|     "fmt" | ||||
|     "time" | ||||
|     "gitea.zjmud.xyz/phyer/rbac/config" | ||||
|     "github.com/go-redis/redis/v8" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
|     RedisClient *redis.Client | ||||
|     ctx         = context.Background() | ||||
| ) | ||||
| 
 | ||||
| // InitRedis 初始化 Redis 连接 | ||||
| func InitRedis() error { | ||||
|     RedisClient = redis.NewClient(&redis.Options{ | ||||
|         Addr:     fmt.Sprintf("%s:%d", config.AppConfig.RedisHost, config.AppConfig.RedisPort), | ||||
|         Password: config.AppConfig.RedisPassword, | ||||
|         DB:       0, // 使用默认数据库 | ||||
|     }) | ||||
| 
 | ||||
|     // 测试连接 | ||||
|     _, err := RedisClient.Ping(ctx).Result() | ||||
|     if err != nil { | ||||
|         return fmt.Errorf("failed to connect to Redis: %v", err) | ||||
|     } | ||||
| 
 | ||||
|     return nil | ||||
| } | ||||
| 
 | ||||
| // Set 设置键值对,带过期时间 | ||||
| func Set(key string, value interface{}, expiration time.Duration) error { | ||||
|     return RedisClient.Set(ctx, key, value, expiration).Err() | ||||
| } | ||||
| 
 | ||||
| // Get 获取键值 | ||||
| func Get(key string) (string, error) { | ||||
|     return RedisClient.Get(ctx, key).Result() | ||||
| } | ||||
| 
 | ||||
| // Delete 删除键 | ||||
| func Delete(key string) error { | ||||
|     return RedisClient.Del(ctx, key).Err() | ||||
| } | ||||
| 
 | ||||
| // Exists 检查键是否存在 | ||||
| func Exists(key string) (bool, error) { | ||||
|     result, err := RedisClient.Exists(ctx, key).Result() | ||||
|     return result == 1, err | ||||
| } | ||||
| 
 | ||||
| // Incr 自增键值 | ||||
| func Incr(key string) (int64, error) { | ||||
|     return RedisClient.Incr(ctx, key).Result() | ||||
| } | ||||
| 
 | ||||
| // Decr 自减键值 | ||||
| func Decr(key string) (int64, error) { | ||||
|     return RedisClient.Decr(ctx, key).Result() | ||||
| } | ||||
| 
 | ||||
| // HSet 设置哈希字段值 | ||||
| func HSet(key string, field string, value interface{}) error { | ||||
|     return RedisClient.HSet(ctx, key, field, value).Err() | ||||
| } | ||||
| 
 | ||||
| // HGet 获取哈希字段值 | ||||
| func HGet(key string, field string) (string, error) { | ||||
|     return RedisClient.HGet(ctx, key, field).Result() | ||||
| } | ||||
| 
 | ||||
| // HGetAll 获取哈希所有字段值 | ||||
| func HGetAll(key string) (map[string]string, error) { | ||||
|     return RedisClient.HGetAll(ctx, key).Result() | ||||
| } | ||||
| 
 | ||||
| // Expire 设置键的过期时间 | ||||
| func Expire(key string, expiration time.Duration) error { | ||||
|     return RedisClient.Expire(ctx, key, expiration).Err() | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这个文件主要包含以下功能: | ||||
| 
 | ||||
| 1. `InitRedis`: 初始化 Redis 连接,使用配置文件中的 Redis 连接信息 | ||||
| 2. `Set/Get`: 基本的键值对操作 | ||||
| 3. `Delete`: 删除键 | ||||
| 4. `Exists`: 检查键是否存在 | ||||
| 5. `Incr/Decr`: 自增/自减操作 | ||||
| 6. `HSet/HGet/HGetAll`: 哈希表操作 | ||||
| 7. `Expire`: 设置键的过期时间 | ||||
| 
 | ||||
| 使用示例: | ||||
| 
 | ||||
| ```go | ||||
| // 初始化 Redis | ||||
| if err := utils.InitRedis(); err != nil { | ||||
|     log.Fatalf("Failed to initialize Redis: %v", err) | ||||
| } | ||||
| 
 | ||||
| // 设置值 | ||||
| err := utils.Set("mykey", "myvalue", time.Minute*10) | ||||
| if err != nil { | ||||
|     log.Printf("Failed to set Redis key: %v", err) | ||||
| } | ||||
| 
 | ||||
| // 获取值 | ||||
| value, err := utils.Get("mykey") | ||||
| if err != nil { | ||||
|     log.Printf("Failed to get Redis key: %v", err) | ||||
| } else { | ||||
|     log.Printf("Got value: %s", value) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这个 Redis 工具类可以用于缓存、会话管理、限流等场景。你可以根据需要扩展更多 Redis 操作函数。 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 18:51:26 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - sug.md | ||||
| 
 | ||||
| > utils/response.go 这个文件需要吗 | ||||
| >  | ||||
| 
 | ||||
| 是的,`utils/response.go` 文件是很有用的。它可以帮助我们统一 API 的响应格式,使代码更整洁和一致。让我们创建这个文件: | ||||
| 
 | ||||
| Filepath: utils/response.go | ||||
| Replace lines: 1-0 | ||||
| ```go | ||||
| package utils | ||||
| 
 | ||||
| import ( | ||||
|     "github.com/gin-gonic/gin" | ||||
| ) | ||||
| 
 | ||||
| // SuccessResponse 成功响应结构 | ||||
| type SuccessResponse struct { | ||||
|     Code    int         `json:"code"` | ||||
|     Message string      `json:"message"` | ||||
|     Data    interface{} `json:"data"` | ||||
| } | ||||
| 
 | ||||
| // ErrorResponse 错误响应结构 | ||||
| type ErrorResponse struct { | ||||
|     Code    int    `json:"code"` | ||||
|     Message string `json:"message"` | ||||
| } | ||||
| 
 | ||||
| // RespondSuccess 返回成功响应 | ||||
| func RespondSuccess(c *gin.Context, code int, message string, data interface{}) { | ||||
|     c.JSON(code, SuccessResponse{ | ||||
|         Code:    code, | ||||
|         Message: message, | ||||
|         Data:    data, | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| // RespondError 返回错误响应 | ||||
| func RespondError(c *gin.Context, code int, message string) { | ||||
|     c.JSON(code, ErrorResponse{ | ||||
|         Code:    code, | ||||
|         Message: message, | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| // RespondValidationError 返回验证错误响应 | ||||
| func RespondValidationError(c *gin.Context, errors map[string]string) { | ||||
|     c.JSON(400, gin.H{ | ||||
|         "code":    400, | ||||
|         "message": "Validation error", | ||||
|         "errors":  errors, | ||||
|     }) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 这个文件提供了以下功能: | ||||
| 
 | ||||
| 1. `SuccessResponse` 结构体:用于统一成功响应的格式 | ||||
| 2. `ErrorResponse` 结构体:用于统一错误响应的格式 | ||||
| 3. `RespondSuccess` 函数:用于返回成功的 API 响应 | ||||
| 4. `RespondError` 函数:用于返回错误的 API 响应 | ||||
| 5. `RespondValidationError` 函数:专门用于返回验证错误的响应 | ||||
| 
 | ||||
| 使用示例: | ||||
| 
 | ||||
| ```go | ||||
| // 成功响应 | ||||
| utils.RespondSuccess(c, http.StatusOK, "User created successfully", user) | ||||
| 
 | ||||
| // 错误响应 | ||||
| utils.RespondError(c, http.StatusBadRequest, "Invalid input data") | ||||
| 
 | ||||
| // 验证错误响应 | ||||
| utils.RespondValidationError(c, map[string]string{ | ||||
|     "username": "Username is required", | ||||
|     "email":    "Invalid email format", | ||||
| }) | ||||
| ``` | ||||
| 
 | ||||
| 这个工具文件可以帮助我们: | ||||
| 1. 保持 API 响应格式的一致性 | ||||
| 2. 减少重复代码 | ||||
| 3. 更容易维护和修改响应格式 | ||||
| 4. 提供更清晰的错误信息 | ||||
| 
 | ||||
| 建议在控制器中统一使用这些响应函数,而不是直接使用 `c.JSON()`,这样可以确保整个项目的 API 响应格式一致。 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -0,0 +1,82 @@ | ||||
| package utils | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/config" | ||||
| 	"github.com/go-redis/redis/v8" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	RedisClient *redis.Client | ||||
| 	ctx         = context.Background() | ||||
| ) | ||||
| 
 | ||||
| // InitRedis 初始化 Redis 连接 | ||||
| func InitRedis() error { | ||||
| 	RedisClient = redis.NewClient(&redis.Options{ | ||||
| 		Addr:     fmt.Sprintf("%s:%d", config.AppConfig.RedisHost, config.AppConfig.RedisPort), | ||||
| 		Password: config.AppConfig.RedisPassword, | ||||
| 		DB:       0, // 使用默认数据库 | ||||
| 	}) | ||||
| 
 | ||||
| 	// 测试连接 | ||||
| 	_, err := RedisClient.Ping(ctx).Result() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to connect to Redis: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Set 设置键值对,带过期时间 | ||||
| func Set(key string, value interface{}, expiration time.Duration) error { | ||||
| 	return RedisClient.Set(ctx, key, value, expiration).Err() | ||||
| } | ||||
| 
 | ||||
| // Get 获取键值 | ||||
| func Get(key string) (string, error) { | ||||
| 	return RedisClient.Get(ctx, key).Result() | ||||
| } | ||||
| 
 | ||||
| // Delete 删除键 | ||||
| func Delete(key string) error { | ||||
| 	return RedisClient.Del(ctx, key).Err() | ||||
| } | ||||
| 
 | ||||
| // Exists 检查键是否存在 | ||||
| func Exists(key string) (bool, error) { | ||||
| 	result, err := RedisClient.Exists(ctx, key).Result() | ||||
| 	return result == 1, err | ||||
| } | ||||
| 
 | ||||
| // Incr 自增键值 | ||||
| func Incr(key string) (int64, error) { | ||||
| 	return RedisClient.Incr(ctx, key).Result() | ||||
| } | ||||
| 
 | ||||
| // Decr 自减键值 | ||||
| func Decr(key string) (int64, error) { | ||||
| 	return RedisClient.Decr(ctx, key).Result() | ||||
| } | ||||
| 
 | ||||
| // HSet 设置哈希字段值 | ||||
| func HSet(key string, field string, value interface{}) error { | ||||
| 	return RedisClient.HSet(ctx, key, field, value).Err() | ||||
| } | ||||
| 
 | ||||
| // HGet 获取哈希字段值 | ||||
| func HGet(key string, field string) (string, error) { | ||||
| 	return RedisClient.HGet(ctx, key, field).Result() | ||||
| } | ||||
| 
 | ||||
| // HGetAll 获取哈希所有字段值 | ||||
| func HGetAll(key string) (map[string]string, error) { | ||||
| 	return RedisClient.HGetAll(ctx, key).Result() | ||||
| } | ||||
| 
 | ||||
| // Expire 设置键的过期时间 | ||||
| func Expire(key string, expiration time.Duration) error { | ||||
| 	return RedisClient.Expire(ctx, key, expiration).Err() | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| package utils | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
| 
 | ||||
| // SuccessResponse 成功响应结构 | ||||
| type SuccessResponse struct { | ||||
| 	Code    int         `json:"code"` | ||||
| 	Message string      `json:"message"` | ||||
| 	Data    interface{} `json:"data"` | ||||
| } | ||||
| 
 | ||||
| // ErrorResponse 错误响应结构 | ||||
| type ErrorResponse struct { | ||||
| 	Code    int    `json:"code"` | ||||
| 	Message string `json:"message"` | ||||
| } | ||||
| 
 | ||||
| // RespondSuccess 返回成功响应 | ||||
| func RespondSuccess(c *gin.Context, code int, message string, data interface{}) { | ||||
| 	c.JSON(code, SuccessResponse{ | ||||
| 		Code:    code, | ||||
| 		Message: message, | ||||
| 		Data:    data, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // RespondError 返回错误响应 | ||||
| func RespondError(c *gin.Context, code int, message string) { | ||||
| 	c.JSON(code, ErrorResponse{ | ||||
| 		Code:    code, | ||||
| 		Message: message, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // RespondValidationError 返回验证错误响应 | ||||
| func RespondValidationError(c *gin.Context, errors map[string]string) { | ||||
| 	c.JSON(400, gin.H{ | ||||
| 		"code":    400, | ||||
| 		"message": "Validation error", | ||||
| 		"errors":  errors, | ||||
| 	}) | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zhangkun9038@dingtalk.com
						zhangkun9038@dingtalk.com