rbac/sug.md
zhangkun9038@dingtalk.com ae75582d11 up
2025-02-16 18:55:51 +08:00

52 KiB
Raw Blame History

  • Datetime: 2025-02-16 12:45:39

  • Model: alidsv3/deepseek-v3

  • Selected files:

    • tree.txt

我需要创建一饿go语言gin框架的api后端项目,项目名字叫 gitea.zjmud.xyz/phyer/rbac, 需要创建一个用户账号系统, 包括基础的用户验证功能和鉴权,鉴权依照rbac模式,管理员可以创建角色、用户、定义资源、资源组、和动作,管理员可以委派某个用户,对特定资源组和用户组进行动作定义, 请把go文件根据逻辑,放置到不同的模块中,不要都放到main 模块下

那么当前目录结构是否需要调整, 请给出每个文件的内容

根据你的需求,我们需要创建一个基于 Gin 框架的 RBAC 系统。当前的目录结构基本合理,但需要做一些调整和补充。以下是建议的目录结构和每个文件的内容:

  1. 首先,我们需要调整目录结构,添加一些必要的文件和目录:

Filepath: tree.txt Replace lines: 1-31

.
├── api
│   └── routes.go
├── config
│   └── config.go
├── controllers
│   ├── auth.go
│   ├── rbac.go
│   └── user.go
├── go.mod
├── go.sum
├── main.go
├── middleware
│   ├── auth.go
│   └── rbac.go
├── models
│   ├── permission.go
│   ├── role.go
│   ├── user.go
│   └── user_group.go
├── repositories
│   ├── permission.go
│   ├── role.go
│   ├── user.go
│   └── user_group.go
├── server
│   └── server.go
├── services
│   ├── auth.go
│   ├── rbac.go
│   └── user.go
├── utils
│   ├── jwt.go
│   └── response.go
├── sug.md
└── tree.txt

10 directories, 26 files
  1. 现在让我们创建每个文件的内容。由于内容较多,我将分多次提供。首先从核心文件开始:

Filepath: go.mod Replace lines: 1-0

module gitea.zjmud.xyz/phyer/rbac

go 1.21

require (
    github.com/gin-gonic/gin v1.9.1
    github.com/golang-jwt/jwt/v5 v5.0.0
    gorm.io/driver/mysql v1.5.1
    gorm.io/gorm v1.25.2
)

Filepath: main.go Replace lines: 1-0

package main

import (
    "gitea.zjmud.xyz/phyer/rbac/config"
    "gitea.zjmud.xyz/phyer/rbac/server"
)

func main() {
    // 初始化配置
    config.Init()
    
    // 启动服务器
    server.Start()
}

Filepath: config/config.go Replace lines: 1-0

package config

import (
    "os"
    "strconv"
)

type Config struct {
    DBHost     string
    DBPort     int
    DBUser     string
    DBPassword string
    DBName     string
    JWTSecret  string
}

var AppConfig Config

func Init() {
    AppConfig = Config{
        DBHost:     getEnv("DB_HOST", "localhost"),
        DBPort:     getEnvAsInt("DB_PORT", 3306),
        DBUser:     getEnv("DB_USER", "root"),
        DBPassword: getEnv("DB_PASSWORD", ""),
        DBName:     getEnv("DB_NAME", "rbac"),
        JWTSecret:  getEnv("JWT_SECRET", "secret"),
    }
}

func getEnv(key, defaultValue string) string {
    if value, exists := os.LookupEnv(key); exists {
        return value
    }
    return defaultValue
}

func getEnvAsInt(key string, defaultValue int) int {
    valueStr := getEnv(key, "")
    if value, err := strconv.Atoi(valueStr); err == nil {
        return value
    }
    return defaultValue
}

Filepath: server/server.go Replace lines: 1-0

package server

import (
    "gitea.zjmud.xyz/phyer/rbac/api"
    "gitea.zjmud.xyz/phyer/rbac/config"
    "gitea.zjmud.xyz/phyer/rbac/middleware"
    "github.com/gin-gonic/gin"
)

func Start() {
    r := gin.Default()
    
    // 全局中间件
    r.Use(middleware.CORS())
    
    // 初始化路由
    api.InitRoutes(r)
    
    // 启动服务器
    r.Run(":8080")
}

Filepath: api/routes.go Replace lines: 1-0

package api

import (
    "gitea.zjmud.xyz/phyer/rbac/controllers"
    "gitea.zjmud.xyz/phyer/rbac/middleware"
    "github.com/gin-gonic/gin"
)

func InitRoutes(r *gin.Engine) {
    // 公共路由
    public := r.Group("/api")
    {
        public.POST("/login", controllers.Login)
        public.POST("/register", controllers.Register)
    }

    // 需要认证的路由
    auth := r.Group("/api")
    auth.Use(middleware.JWTAuth())
    {
        // 用户管理
        auth.GET("/users", controllers.GetUsers)
        auth.GET("/users/:id", controllers.GetUser)
        auth.PUT("/users/:id", controllers.UpdateUser)
        auth.DELETE("/users/:id", controllers.DeleteUser)

        // RBAC 管理
        auth.POST("/roles", controllers.CreateRole)
        auth.GET("/roles", controllers.GetRoles)
        auth.POST("/permissions", controllers.CreatePermission)
        auth.GET("/permissions", controllers.GetPermissions)
        auth.POST("/assign-role", controllers.AssignRoleToUser)
        auth.POST("/assign-permission", controllers.AssignPermissionToRole)
    }
}

由于内容较多,我将继续在下一个回复中提供其他文件的内容。请让我知道是否要继续。


  • Datetime: 2025-02-16 12:50:02

  • Model: alidsv3/deepseek-v3

  • Selected files:

    • tree.txt

我重新定义一下需求: 我需要创建一饿go语言gin框架的api后端项目,项目名字叫 gitea.zjmud.xyz/phyer/rbac, 需要创建一个用户账号系统, 包括基础的用户验证功能和鉴权,鉴权依照rbac模式,管理员可以创建角色、用户、定义资源、资源组、和动作,管理员可以委派某个用户,对特定资源组和用户组进行动作定义, 请把go文件根据逻辑,放置到不同的模块中,不要都放到main 模块下 , 数据库使用mysql,如果有必要的话在加上redis 那么当前目录结构是否需要调整, 请给出每个文件的内容

根据你的新需求,我会调整目录结构并添加 Redis 支持。以下是新的目录结构和文件内容:

  1. 首先,更新目录结构:

Filepath: tree.txt Replace lines: 1-0

.
├── api
│   └── routes.go
├── config
│   └── config.go
├── controllers
│   ├── auth.go
│   ├── rbac.go
│   └── user.go
├── go.mod
├── go.sum
├── main.go
├── middleware
│   ├── auth.go
│   └── rbac.go
├── models
│   ├── permission.go
│   ├── role.go
│   ├── user.go
│   └── user_group.go
├── repositories
│   ├── permission.go
│   ├── role.go
│   ├── user.go
│   └── user_group.go
├── server
│   └── server.go
├── services
│   ├── auth.go
│   ├── rbac.go
│   └── user.go
├── utils
│   ├── jwt.go
│   ├── redis.go
│   └── response.go
├── sug.md
└── tree.txt

10 directories, 27 files
  1. 更新 go.mod 文件,添加 Redis 依赖:

Filepath: go.mod Replace lines: 1-0

module gitea.zjmud.xyz/phyer/rbac

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
    gorm.io/driver/mysql v1.5.1
    gorm.io/gorm v1.25.2
)
  1. 更新 config.go 添加 Redis 配置:

Filepath: config/config.go Replace lines: 1-0

package config

import (
    "os"
    "strconv"
)

type Config struct {
    DBHost     string
    DBPort     int
    DBUser     string
    DBPassword string
    DBName     string
    JWTSecret  string
    RedisHost  string
    RedisPort  int
    RedisPassword string
}

var AppConfig Config

func Init() {
    AppConfig = Config{
        DBHost:       getEnv("DB_HOST", "localhost"),
        DBPort:       getEnvAsInt("DB_PORT", 3306),
        DBUser:       getEnv("DB_USER", "root"),
        DBPassword:   getEnv("DB_PASSWORD", ""),
        DBName:       getEnv("DB_NAME", "rbac"),
        JWTSecret:    getEnv("JWT_SECRET", "secret"),
        RedisHost:    getEnv("REDIS_HOST", "localhost"),
        RedisPort:    getEnvAsInt("REDIS_PORT", 6379),
        RedisPassword: getEnv("REDIS_PASSWORD", ""),
    }
}

func getEnv(key, defaultValue string) string {
    if value, exists := os.LookupEnv(key); exists {
        return value
    }
    return defaultValue
}

func getEnvAsInt(key string, defaultValue int) int {
    valueStr := getEnv(key, "")
    if value, err := strconv.Atoi(valueStr); err == nil {
        return value
    }
    return defaultValue
}
  1. 添加 Redis 工具类:

Filepath: utils/redis.go Replace lines: 1-0

package main

import (
    "gitea.zjmud.xyz/phyer/rbac/config"
    "gitea.zjmud.xyz/phyer/rbac/server"
    "gitea.zjmud.xyz/phyer/rbac/utils"
)

func main() {
    // 初始化配置
    config.Init()
    
    // 初始化 Redis
    utils.InitRedis()
    
    // 启动服务器
    server.Start()
}
  1. 更新 models 文件,添加 RBAC 相关模型:

Filepath: models/user.go

package models

import "gorm.io/gorm"

type User struct { gorm.Model Username string gorm:"unique;not null" Password string gorm:"not null" Email string gorm:"unique;not null" Roles []Role gorm:"many2many:user_roles;" IsActive bool gorm:"default:true" }


Filepath: models/role.go
<SEARCH>
package models

import "gorm.io/gorm"

type Role struct {
    gorm.Model
    Name        string       `gorm:"unique;not null"`
    Permissions []Permission `gorm:"many2many:role_permissions;"`
}

Filepath: models/permission.go

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


Filepath: models/user_group.go

---

- Datetime: 2025-02-16 13:25:47

- Model: alidsv3/deepseek-v3

- Selected files:
  - neo-tree filesystem [1]

> 给出创建此目录结构的shell语句
> 
> .
> ├── api
> │   └── routes.go
> ├── config
> │   └── config.go
> ├── controllers
> │   ├── auth.go
> │   ├── rbac.go
> │   └── user.go
> ├── go.mod
> ├── go.sum
> ├── main.go
> ├── middleware
> │   ├── auth.go
> │   └── rbac.go
> ├── models
> │   ├── permission.go
> │   ├── role.go
> │   ├── user.go
> │   └── user_group.go
> ├── repositories
> │   ├── permission.go
> │   ├── role.go
> │   ├── user.go
> │   └── user_group.go
> ├── server
> │   └── server.go
> ├── services
> │   ├── auth.go
> │   ├── rbac.go
> │   └── user.go
> ├── utils
> │   ├── jwt.go
> │   ├── redis.go
> │   └── response.go
> ├── sug.md
> └── tree.txt
> 

以下是在当前目录下创建所需目录结构的 shell 命令:

```zsh
mkdir -p api config controllers middleware models repositories server services utils
touch api/routes.go config/config.go controllers/{auth.go,rbac.go,user.go} go.mod go.sum main.go middleware/{auth.go,rbac.go} models/{permission.go,role.go,user.go,user_group.go} repositories/{permission.go,role.go,user.go,user_group.go} server/server.go services/{auth.go,rbac.go,user.go} utils/{jwt.go,redis.go,response.go} sug.md tree.txt

这个命令会:

  1. 使用 mkdir -p 递归创建所有需要的目录
  2. 使用 touch 创建所有需要的空文件
  3. 使用花括号 {} 来批量创建同一目录下的多个文件

执行这个命令后,你将得到所需的完整目录结构,所有文件都会被创建为空文件,等待后续填充内容。


  • Datetime: 2025-02-16 13:27:57

  • Model: alidsv3/deepseek-v3

  • Selected files:

    • tree.txt

我需要创建一个go语言gin框架的api后端项目,项目名字叫 gitea.zjmud.xyz/phyer/rbac, 需要创建一个用户账号系统, 包括基础的用户验证功能和鉴权,鉴权依照rbac模式,管理员可以创建角色、用户、定义资源、资源组、和动作,管理员可以委派某个用户,对特定资源组和用户组进行动作定义, 请把go文件根据逻辑,放置到不同的模块中,不要都放到main 模块下, 数据库使用mysql,如果有必要的话在加上redis, 根据如下目录结构来实现上诉诉求, 然后 给出分别每个文件的内容.

根据你的需求我将按照提供的目录结构实现RBAC系统。以下是各个文件的内容

  1. 首先初始化项目并添加依赖:

Filepath: go.mod Replace lines: 1-0

module gitea.zjmud.xyz/phyer/rbac

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
    gorm.io/driver/mysql v1.5.1
    gorm.io/gorm v1.25.2
)
  1. 配置文件:

Filepath: config/config.go Replace lines: 1-0

package config

import (
    "os"
    "strconv"
)

type Config struct {
    DBHost     string
    DBPort     int
    DBUser     string
    DBPassword string
    DBName     string
    JWTSecret  string
    RedisHost  string
    RedisPort  int
    RedisPassword string
}

var AppConfig Config

func Init() {
    AppConfig = Config{
        DBHost:       getEnv("DB_HOST", "localhost"),
        DBPort:       getEnvAsInt("DB_PORT", 3306),
        DBUser:       getEnv("DB_USER", "root"),
        DBPassword:   getEnv("DB_PASSWORD", ""),
        DBName:       getEnv("DB_NAME", "rbac"),
        JWTSecret:    getEnv("JWT_SECRET", "secret"),
        RedisHost:    getEnv("REDIS_HOST", "localhost"),
        RedisPort:    getEnvAsInt("REDIS_PORT", 6379),
        RedisPassword: getEnv("REDIS_PASSWORD", ""),
    }
}

func getEnv(key, defaultValue string) string {
    if value, exists := os.LookupEnv(key); exists {
        return value
    }
    return defaultValue
}

func getEnvAsInt(key string, defaultValue int) int {
    valueStr := getEnv(key, "")
    if value, err := strconv.Atoi(valueStr); err == nil {
        return value
    }
    return defaultValue
}
  1. 主程序入口:

Filepath: main.go Replace lines: 1-0

package main

import (
    "gitea.zjmud.xyz/phyer/rbac/config"
    "gitea.zjmud.xyz/phyer/rbac/server"
    "gitea.zjmud.xyz/phyer/rbac/utils"
)

func main() {
    // 初始化配置
    config.Init()
    
    // 初始化 Redis
    utils.InitRedis()
    
    // 启动服务器
    server.Start()
}
  1. 服务器启动文件:

Filepath: server/server.go Replace lines: 1-0

package server

import (
    "gitea.zjmud.xyz/phyer/rbac/api"
    "github.com/gin-gonic/gin"
)

func Start() {
    r := gin.Default()
    
    // 初始化路由
    api.SetupRoutes(r)
    
    // 启动服务器
    r.Run(":8080")
}
  1. 路由配置:

Filepath: api/routes.go Replace lines: 1-0

package api

import (
    "gitea.zjmud.xyz/phyer/rbac/controllers"
    "gitea.zjmud.xyz/phyer/rbac/middleware"
    "github.com/gin-gonic/gin"
)

func SetupRoutes(r *gin.Engine) {
    // 认证相关路由
    auth := r.Group("/auth")
    {
        auth.POST("/register", controllers.Register)
        auth.POST("/login", controllers.Login)
    }

    // 需要认证的路由
    api := r.Group("/api")
    api.Use(middleware.JWTAuth())
    {
        // 用户管理
        users := api.Group("/users")
        {
            users.GET("/", controllers.GetUsers)
            users.GET("/:id", controllers.GetUser)
            users.PUT("/:id", controllers.UpdateUser)
            users.DELETE("/:id", controllers.DeleteUser)
        }

        // 角色管理
        roles := api.Group("/roles")
        {
            roles.POST("/", controllers.CreateRole)
            roles.GET("/", controllers.GetRoles)
            roles.GET("/:id", controllers.GetRole)
            roles.PUT("/:id", controllers.UpdateRole)
            roles.DELETE("/:id", controllers.DeleteRole)
        }

        // 权限管理
        permissions := api.Group("/permissions")
        {
            permissions.POST("/", controllers.CreatePermission)
            permissions.GET("/", controllers.GetPermissions)
            permissions.GET("/:id", controllers.GetPermission)
            permissions.PUT("/:id", controllers.UpdatePermission)
            permissions.DELETE("/:id", controllers.DeletePermission)
        }
    }
}

由于内容较多,我将继续在下一个回复中提供控制器、服务层、仓库层和中间件的实现。请让我知道是否要继续。


  • Datetime: 2025-02-16 17:36:11

  • Model: alidsv3/deepseek-v3

  • Selected files:

    • config/config.go
    • tree.txt

好的,请继续

好的,我将继续提供其他模块的实现代码。以下是控制器、服务层、仓库层和中间件的实现:

  1. 用户控制器:

Filepath: controllers/user.go Replace lines: 1-0

package controllers

import (
    "gitea.zjmud.xyz/phyer/rbac/services"
    "github.com/gin-gonic/gin"
)

func GetUsers(c *gin.Context) {
    users, err := services.GetAllUsers()
    if err != nil {
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, users)
}

func GetUser(c *gin.Context) {
    id := c.Param("id")
    user, err := services.GetUserByID(id)
    if err != nil {
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, user)
}

func UpdateUser(c *gin.Context) {
    id := c.Param("id")
    var updateData map[string]interface{}
    if err := c.ShouldBindJSON(&updateData); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    user, err := services.UpdateUser(id, updateData)
    if err != nil {
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, user)
}

func DeleteUser(c *gin.Context) {
    id := c.Param("id")
    err := services.DeleteUser(id)
    if err != nil {
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, gin.H{"message": "User deleted successfully"})
}
  1. 认证控制器:

Filepath: controllers/auth.go Replace lines: 1-0

package controllers

import (
    "gitea.zjmud.xyz/phyer/rbac/services"
    "github.com/gin-gonic/gin"
)

func Register(c *gin.Context) {
    var registerData struct {
        Username string `json:"username"`
        Password string `json:"password"`
        Email    string `json:"email"`
    }
    if err := c.ShouldBindJSON(&registerData); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    user, err := services.RegisterUser(registerData.Username, registerData.Password, registerData.Email)
    if err != nil {
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }
    c.JSON(201, user)
}

func Login(c *gin.Context) {
    var loginData struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    if err := c.ShouldBindJSON(&loginData); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    token, err := services.Login(loginData.Username, loginData.Password)
    if err != nil {
        c.JSON(401, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, gin.H{"token": token})
}
  1. 用户服务层:

Filepath: services/user.go Replace lines: 1-0

package services

import (
    "gitea.zjmud.xyz/phyer/rbac/models"
    "gitea.zjmud.xyz/phyer/rbac/repositories"
    "gitea.zjmud.xyz/phyer/rbac/utils"
    "golang.org/x/crypto/bcrypt"
)

func GetAllUsers() ([]models.User, error) {
    return repositories.GetAllUsers()
}

func GetUserByID(id string) (*models.User, error) {
    return repositories.GetUserByID(id)
}

func UpdateUser(id string, updateData map[string]interface{}) (*models.User, error) {
    if password, ok := updateData["password"]; ok {
        hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password.(string)), bcrypt.DefaultCost)
        if err != nil {
            return nil, err
        }
        updateData["password"] = string(hashedPassword)
    }
    return repositories.UpdateUser(id, updateData)
}

func DeleteUser(id string) error {
    return repositories.DeleteUser(id)
}

func RegisterUser(username, password, email string) (*models.User, error) {
    hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    if err != nil {
        return nil, err
    }
    user := &models.User{
        Username: username,
        Password: string(hashedPassword),
        Email:    email,
    }
    return repositories.CreateUser(user)
}
  1. 认证服务层:

Filepath: services/auth.go Replace lines: 1-0

package services

import (
    "errors"
    "gitea.zjmud.xyz/phyer/rbac/models"
    "gitea.zjmud.xyz/phyer/rbac/repositories"
    "gitea.zjmud.xyz/phyer/rbac/utils"
    "golang.org/x/crypto/bcrypt"
)

func Login(username, password string) (string, error) {
    user, err := repositories.GetUserByUsername(username)
    if err != nil {
        return "", errors.New("invalid credentials")
    }
    err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
    if err != nil {
        return "", errors.New("invalid credentials")
    }
    token, err := utils.GenerateJWT(user.ID)
    if err != nil {
        return "", err
    }
    return token, nil
}
  1. JWT工具类

Filepath: utils/jwt.go Replace lines: 1-0

package utils

import (
    "time"
    "gitea.zjmud.xyz/phyer/rbac/config"
    "github.com/golang-jwt/jwt/v5"
)

func GenerateJWT(userID string) (string, error) {
    claims := jwt.MapClaims{
        "user_id": userID,
        "exp":     time.Now().Add(time.Hour * 24).Unix(),
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString([]byte(config.AppConfig.JWTSecret))
}

func ParseJWT(tokenString string) (jwt.MapClaims, error) {
    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        return []byte(config.AppConfig.JWTSecret), nil
    })
    if err != nil {
        return nil, err
    }
    if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
        return claims, nil
    }
    return nil, errors.New("invalid token")
}

由于内容较多,我将继续在下一个回复中提供模型、仓库层和中间件的实现。请让我知道是否要继续。


  • Datetime: 2025-02-16 17:48:07

  • Model: alidsv3/deepseek-v3

  • Selected files:

    • config/config.go
    • tree.txt

好的,请继续

好的,我将继续提供模型、仓库层和中间件的实现代码:

  1. 用户模型:

Filepath: models/user.go Replace lines: 1-0

package models

import (
    "time"
)

type User struct {
    ID        string    `json:"id" gorm:"primaryKey"`
    Username  string    `json:"username" gorm:"uniqueIndex;not null"`
    Password  string    `json:"-" gorm:"not null"`
    Email     string    `json:"email" gorm:"uniqueIndex;not null"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
    Roles     []Role    `json:"roles" gorm:"many2many:user_roles;"`
}
  1. 用户仓库层:

Filepath: repositories/user.go Replace lines: 1-0

package repositories

import (
    "gitea.zjmud.xyz/phyer/rbac/config"
    "gitea.zjmud.xyz/phyer/rbac/models"
    "gorm.io/gorm"
)

var db *gorm.DB

func InitDB() error {
    var err error
    db, err = gorm.Open(mysql.Open(config.GetDSN()), &gorm.Config{})
    if err != nil {
        return err
    }
    return db.AutoMigrate(&models.User{})
}

func GetAllUsers() ([]models.User, error) {
    var users []models.User
    result := db.Find(&users)
    return users, result.Error
}

func GetUserByID(id string) (*models.User, error) {
    var user models.User
    result := db.First(&user, "id = ?", id)
    return &user, result.Error
}

func GetUserByUsername(username string) (*models.User, error) {
    var user models.User
    result := db.First(&user, "username = ?", username)
    return &user, result.Error
}

func CreateUser(user *models.User) (*models.User, error) {
    result := db.Create(user)
    return user, result.Error
}

func UpdateUser(id string, updateData map[string]interface{}) (*models.User, error) {
    var user models.User
    result := db.Model(&user).Where("id = ?", id).Updates(updateData)
    if result.Error != nil {
        return nil, result.Error
    }
    return GetUserByID(id)
}

func DeleteUser(id string) error {
    result := db.Delete(&models.User{}, "id = ?", id)
    return result.Error
}
  1. 认证中间件:

Filepath: middleware/auth.go Replace lines: 1-0

package middleware

import (
    "gitea.zjmud.xyz/phyer/rbac/utils"
    "github.com/gin-gonic/gin"
)

func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("Authorization")
        if token == "" {
            c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
            return
        }

        claims, err := utils.ParseJWT(token)
        if err != nil {
            c.AbortWithStatusJSON(401, gin.H{"error": "Invalid token"})
            return
        }

        userID := claims["user_id"].(string)
        c.Set("userID", userID)
        c.Next()
    }
}
  1. RBAC中间件

Filepath: middleware/rbac.go Replace lines: 1-0

package middleware

import (
    "gitea.zjmud.xyz/phyer/rbac/repositories"
    "github.com/gin-gonic/gin"
)

func RBACMiddleware(permission string) gin.HandlerFunc {
    return func(c *gin.Context) {
        userID := c.GetString("userID")
        if userID == "" {
            c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
            return
        }

        hasPermission, err := repositories.CheckUserPermission(userID, permission)
        if err != nil || !hasPermission {
            c.AbortWithStatusJSON(403, gin.H{"error": "Forbidden"})
            return
        }

        c.Next()
    }
}
  1. 路由配置:

Filepath: api/routes.go Replace lines: 1-0

package api

import (
    "gitea.zjmud.xyz/phyer/rbac/controllers"
    "gitea.zjmud.xyz/phyer/rbac/middleware"
    "github.com/gin-gonic/gin"
)

func SetupRoutes(r *gin.Engine) {
    auth := r.Group("/auth")
    {
        auth.POST("/register", controllers.Register)
        auth.POST("/login", controllers.Login)
    }

    api := r.Group("/api")
    api.Use(middleware.AuthMiddleware())
    {
        users := api.Group("/users")
        {
            users.GET("/", controllers.GetUsers)
            users.GET("/:id", controllers.GetUser)
            users.PUT("/:id", controllers.UpdateUser)
            users.DELETE("/:id", controllers.DeleteUser)
        }
    }
}
  1. 主程序入口:

Filepath: main.go Replace lines: 1-0

package main

import (
    "gitea.zjmud.xyz/phyer/rbac/api"
    "gitea.zjmud.xyz/phyer/rbac/config"
    "gitea.zjmud.xyz/phyer/rbac/server"
)

func main() {
    config.Init()
    server.InitDB()
    r := server.NewServer()
    api.SetupRoutes(r)
    r.Run(":8080")
}

这些代码实现了RBAC系统的主要功能模块。请注意这只是一个基础实现实际生产环境中可能需要添加更多功能如日志记录、错误处理、性能优化等。同时数据库连接和配置管理部分可能需要根据具体环境进行调整。

如果你需要其他模块的实现或有任何问题,请随时告诉我。


  • 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

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

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

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

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

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

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

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

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

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

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: 设置键的过期时间

使用示例:

// 初始化 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

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 函数:专门用于返回验证错误的响应

使用示例:

// 成功响应
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 响应格式一致。