This commit is contained in:
zhangkun9038@dingtalk.com 2025-02-16 18:55:51 +08:00
parent af4d55d0d1
commit ae75582d11
14 changed files with 1542 additions and 3 deletions

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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"`
}

View File

@ -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;"`
}

View File

@ -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
View 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{})
}

View File

@ -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
}

View File

@ -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}})
}

View File

@ -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}})
}

View File

@ -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
View File

@ -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 响应格式一致。

View File

@ -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()
}

View File

@ -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,
})
}