up
This commit is contained in:
		
							parent
							
								
									fb86af7a77
								
							
						
					
					
						commit
						6669be1923
					
				| @ -3,25 +3,75 @@ 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("/login", controllers.Login) | ||||
|         auth.POST("/register", controllers.Register) | ||||
|         auth.POST("/login", controllers.Login) | ||||
|     } | ||||
| 
 | ||||
| 	admin := r.Group("/admin") | ||||
| 	admin.Use(middleware.RBACMiddleware("admin", "full-access")) | ||||
|     api := r.Group("/api") | ||||
|     api.Use(middleware.AuthMiddleware()) | ||||
|     { | ||||
| 		admin.POST("/roles", controllers.CreateRole) | ||||
| 		admin.POST("/users", controllers.CreateUser) | ||||
| 		admin.POST("/permissions", controllers.CreatePermission) | ||||
| 		admin.POST("/user-groups", controllers.CreateUserGroup) | ||||
| 		admin.POST("/assign-role", controllers.AssignRoleToUser) | ||||
| 		admin.POST("/assign-permission", controllers.AssignPermissionToRole) | ||||
|         users := api.Group("/users") | ||||
|         { | ||||
|             users.GET("/", controllers.GetUsers) | ||||
|             users.GET("/:id", controllers.GetUser) | ||||
|             users.PUT("/:id", controllers.UpdateUser) | ||||
|             users.DELETE("/:id", controllers.DeleteUser) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 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) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -1,57 +1,49 @@ | ||||
| package controllers | ||||
| package config | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/services" | ||||
| 	"net/http" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/golang-jwt/jwt/v5" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| func Login(c *gin.Context) { | ||||
| 	var loginData struct { | ||||
| 		Username string `json:"username"` | ||||
| 		Password string `json:"password"` | ||||
| type Config struct { | ||||
| 	DBHost        string | ||||
| 	DBPort        int | ||||
| 	DBUser        string | ||||
| 	DBPassword    string | ||||
| 	DBName        string | ||||
| 	JWTSecret     string | ||||
| 	RedisHost     string | ||||
| 	RedisPort     int | ||||
| 	RedisPassword string | ||||
| } | ||||
| 
 | ||||
| 	if err := c.ShouldBindJSON(&loginData); err != nil { | ||||
| 		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 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", ""), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	user, err := services.Authenticate(loginData.Username, loginData.Password) | ||||
| 	if err != nil { | ||||
| 		c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"}) | ||||
| 		return | ||||
| func getEnv(key, defaultValue string) string { | ||||
| 	if value, exists := os.LookupEnv(key); exists { | ||||
| 		return value | ||||
| 	} | ||||
| 	return defaultValue | ||||
| } | ||||
| 
 | ||||
| 	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ | ||||
| 		"sub": user.ID, | ||||
| 		"exp": time.Now().Add(time.Hour * 24).Unix(), | ||||
| 	}) | ||||
| 
 | ||||
| 	tokenString, err := token.SignedString([]byte("your-256-bit-secret")) | ||||
| 	if err != nil { | ||||
| 		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"}) | ||||
| 		return | ||||
| func getEnvAsInt(key string, defaultValue int) int { | ||||
| 	valueStr := getEnv(key, "") | ||||
| 	if value, err := strconv.Atoi(valueStr); err == nil { | ||||
| 		return value | ||||
| 	} | ||||
| 
 | ||||
| 	c.JSON(http.StatusOK, gin.H{"token": tokenString}) | ||||
| } | ||||
| 
 | ||||
| func Register(c *gin.Context) { | ||||
| 	var user models.User | ||||
| 	if err := c.ShouldBindJSON(&user); err != nil { | ||||
| 		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if err := services.CreateUser(&user); err != nil { | ||||
| 		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c.JSON(http.StatusCreated, user) | ||||
| 	return defaultValue | ||||
| } | ||||
|  | ||||
| @ -1,57 +1,41 @@ | ||||
| package controllers | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/services" | ||||
| 	"net/http" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/golang-jwt/jwt/v5" | ||||
| ) | ||||
| 
 | ||||
| func Register(c *gin.Context) { | ||||
| 	var registerData struct { | ||||
| 		Username string `json:"username"` | ||||
| 		Password string `json:"password"` | ||||
| 		Email    string `json:"email"` | ||||
| 	} | ||||
| 	if err := c.ShouldBindJSON(®isterData); 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(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||||
| 		c.JSON(400, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	user, err := services.Authenticate(loginData.Username, loginData.Password) | ||||
| 	token, err := services.Login(loginData.Username, loginData.Password) | ||||
| 	if err != nil { | ||||
| 		c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"}) | ||||
| 		c.JSON(401, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ | ||||
| 		"sub": user.ID, | ||||
| 		"exp": time.Now().Add(time.Hour * 24).Unix(), | ||||
| 	}) | ||||
| 
 | ||||
| 	tokenString, err := token.SignedString([]byte("your-256-bit-secret")) | ||||
| 	if err != nil { | ||||
| 		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c.JSON(http.StatusOK, gin.H{"token": tokenString}) | ||||
| } | ||||
| 
 | ||||
| func Register(c *gin.Context) { | ||||
| 	var user models.User | ||||
| 	if err := c.ShouldBindJSON(&user); err != nil { | ||||
| 		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if err := services.CreateUser(&user); err != nil { | ||||
| 		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c.JSON(http.StatusCreated, user) | ||||
| 	c.JSON(200, gin.H{"token": token}) | ||||
| } | ||||
|  | ||||
| @ -1,24 +0,0 @@ | ||||
| package controllers | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/services" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
| 
 | ||||
| func CreateRole(c *gin.Context) { | ||||
| 	var role models.Role | ||||
| 	if err := c.ShouldBindJSON(&role); err != nil { | ||||
| 		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if err := services.CreateRole(&role); err != nil { | ||||
| 		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c.JSON(http.StatusCreated, role) | ||||
| } | ||||
| @ -1,24 +1,50 @@ | ||||
| package controllers | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/services" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
| 
 | ||||
| func CreateUser(c *gin.Context) { | ||||
| 	var user models.User | ||||
| 	if err := c.ShouldBindJSON(&user); err != nil { | ||||
| 		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||||
| 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) | ||||
| } | ||||
| 
 | ||||
| 	if err := services.CreateUser(&user); err != nil { | ||||
| 		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) | ||||
| 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(http.StatusCreated, user) | ||||
| 	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"}) | ||||
| } | ||||
|  | ||||
							
								
								
									
										37
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								go.mod
									
									
									
									
									
								
							| @ -4,39 +4,8 @@ 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/sqlite v1.5.4 | ||||
| 	gorm.io/gorm v1.25.5 | ||||
| 	github.com/caarlos0/env/v10 v10.0.0 | ||||
| ) | ||||
| 
 | ||||
| require ( | ||||
| 	github.com/bytedance/sonic v1.11.6 // indirect | ||||
| 	github.com/bytedance/sonic/loader v0.1.1 // indirect | ||||
| 	github.com/cloudwego/base64x v0.1.4 // indirect | ||||
| 	github.com/cloudwego/iasm v0.2.0 // indirect | ||||
| 	github.com/gabriel-vasile/mimetype v1.4.3 // 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.20.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 | ||||
| 	github.com/json-iterator/go v1.1.12 // indirect | ||||
| 	github.com/klauspost/cpuid/v2 v2.2.7 // indirect | ||||
| 	github.com/leodido/go-urn v1.4.0 // indirect | ||||
| 	github.com/mattn/go-isatty v0.0.20 // indirect | ||||
| 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | ||||
| 	github.com/modern-go/reflect2 v1.0.2 // indirect | ||||
| 	github.com/pelletier/go-toml/v2 v2.2.2 // indirect | ||||
| 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect | ||||
| 	github.com/ugorji/go/codec v1.2.12 // indirect | ||||
| 	golang.org/x/arch v0.8.0 // indirect | ||||
| 	golang.org/x/crypto v0.23.0 // indirect | ||||
| 	golang.org/x/net v0.25.0 // indirect | ||||
| 	golang.org/x/sys v0.20.0 // indirect | ||||
| 	golang.org/x/text v0.15.0 // indirect | ||||
| 	google.golang.org/protobuf v1.34.1 // indirect | ||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||
| 	gorm.io/driver/mysql v1.5.1 | ||||
| 	gorm.io/gorm v1.25.2 | ||||
| ) | ||||
|  | ||||
							
								
								
									
										97
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										97
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,97 +0,0 @@ | ||||
| github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= | ||||
| github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= | ||||
| github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= | ||||
| github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= | ||||
| github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= | ||||
| github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= | ||||
| github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= | ||||
| github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= | ||||
| 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/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= | ||||
| github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= | ||||
| github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= | ||||
| github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= | ||||
| github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= | ||||
| github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= | ||||
| github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= | ||||
| github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= | ||||
| github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= | ||||
| github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= | ||||
| github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= | ||||
| github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= | ||||
| github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= | ||||
| github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= | ||||
| 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.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= | ||||
| github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= | ||||
| github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= | ||||
| github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||||
| github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= | ||||
| github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= | ||||
| github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= | ||||
| github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= | ||||
| github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= | ||||
| github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= | ||||
| github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | ||||
| github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= | ||||
| github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= | ||||
| github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= | ||||
| github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= | ||||
| github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= | ||||
| github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= | ||||
| github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | ||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||
| github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= | ||||
| 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/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= | ||||
| github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||||
| github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||||
| github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= | ||||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | ||||
| github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||||
| github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||||
| github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||||
| github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||
| github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= | ||||
| github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= | ||||
| github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= | ||||
| github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= | ||||
| golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= | ||||
| golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= | ||||
| golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= | ||||
| golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= | ||||
| golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= | ||||
| golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= | ||||
| golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= | ||||
| golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= | ||||
| golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||
| golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= | ||||
| golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= | ||||
| google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= | ||||
| 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/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.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= | ||||
| gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= | ||||
| nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= | ||||
| rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= | ||||
							
								
								
									
										31
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								main.go
									
									
									
									
									
								
							| @ -1,7 +1,34 @@ | ||||
| package main | ||||
| 
 | ||||
| import "gitea.zjmud.xyz/phyer/rbac/server" | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/api" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/config" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/server" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
| 	server.Start() | ||||
| 	config.Init() | ||||
| 	server.InitDB() | ||||
| 	r := server.NewServer() | ||||
| 	api.SetupRoutes(r) | ||||
| 	r.Run(":8080") | ||||
| } | ||||
| 
 | ||||
| // 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,42 +1,26 @@ | ||||
| package middleware | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/config" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/utils" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/golang-jwt/jwt/v5" | ||||
| ) | ||||
| 
 | ||||
| func JWTAuthMiddleware() gin.HandlerFunc { | ||||
| 	cfg := config.LoadConfig() | ||||
| func AuthMiddleware() gin.HandlerFunc { | ||||
| 	return func(c *gin.Context) { | ||||
| 		tokenString := c.GetHeader("Authorization") | ||||
| 		if tokenString == "" { | ||||
| 			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Authorization header missing"}) | ||||
| 		token := c.GetHeader("Authorization") | ||||
| 		if token == "" { | ||||
| 			c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"}) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { | ||||
| 			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { | ||||
| 				return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) | ||||
| 			} | ||||
| 			return []byte(cfg.JWTSecret), nil | ||||
| 		}) | ||||
| 
 | ||||
| 		if err != nil || !token.Valid { | ||||
| 			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"}) | ||||
| 		claims, err := utils.ParseJWT(token) | ||||
| 		if err != nil { | ||||
| 			c.AbortWithStatusJSON(401, gin.H{"error": "Invalid token"}) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		claims, ok := token.Claims.(jwt.MapClaims) | ||||
| 		if !ok { | ||||
| 			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token claims"}) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		c.Set("userID", claims["sub"]) | ||||
| 		userID := claims["user_id"].(string) | ||||
| 		c.Set("userID", userID) | ||||
| 		c.Next() | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										24
									
								
								middleware/rbac.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								middleware/rbac.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| 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,28 +0,0 @@ | ||||
| package models | ||||
| 
 | ||||
| import "gorm.io/gorm" | ||||
| 
 | ||||
| type User struct { | ||||
| 	gorm.Model | ||||
| 	Username string `gorm:"unique"` | ||||
| 	Password string | ||||
| 	Roles    []Role `gorm:"many2many:user_roles;"` | ||||
| } | ||||
| 
 | ||||
| type Role struct { | ||||
| 	gorm.Model | ||||
| 	Name        string `gorm:"unique"` | ||||
| 	Permissions []Permission `gorm:"many2many:role_permissions;"` | ||||
| } | ||||
| 
 | ||||
| type Permission struct { | ||||
| 	gorm.Model | ||||
| 	Name string `gorm:"unique"` | ||||
| } | ||||
| 
 | ||||
| type UserGroup struct { | ||||
| 	gorm.Model | ||||
| 	Name  string `gorm:"unique"` | ||||
| 	Users []User `gorm:"many2many:user_group_users;"` | ||||
| } | ||||
| ` | ||||
							
								
								
									
										0
									
								
								models/permission.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								models/permission.go
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								models/role.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								models/role.go
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										15
									
								
								models/user.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								models/user.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| 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;"` | ||||
| } | ||||
							
								
								
									
										0
									
								
								models/user_group.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								models/user_group.go
									
									
									
									
									
										Normal file
									
								
							| @ -1,10 +0,0 @@ | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreatePermission(permission *models.Permission) error { | ||||
| 	return db.Create(permission).Error | ||||
| } | ||||
| @ -1,10 +0,0 @@ | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreateRole(role *models.Role) error { | ||||
| 	return db.Create(role).Error | ||||
| } | ||||
| @ -1,16 +1,55 @@ | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/config" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func GetUserByUsername(username string) (*models.User, error) { | ||||
| 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.Where("username = ?", username).First(&user) | ||||
| 	result := db.First(&user, "id = ?", id) | ||||
| 	return &user, result.Error | ||||
| } | ||||
| 
 | ||||
| func CreateUser(user *models.User) error { | ||||
| 	return db.Create(user).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,10 +0,0 @@ | ||||
| package repositories | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| func CreateUserGroup(group *models.UserGroup) error { | ||||
| 	return db.Create(group).Error | ||||
| } | ||||
| @ -2,17 +2,15 @@ package server | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/api" | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/config" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
| 
 | ||||
| func Start() { | ||||
| 	cfg := config.LoadConfig() | ||||
| 
 | ||||
| 	r := gin.Default() | ||||
| 
 | ||||
| 	// 初始化路由 | ||||
| 	api.SetupRoutes(r) | ||||
| 
 | ||||
| 	r.Run(":" + cfg.ServerPort) | ||||
| 	// 启动服务器 | ||||
| 	r.Run(":8080") | ||||
| } | ||||
|  | ||||
| @ -4,29 +4,22 @@ 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 Authenticate(username, password string) (*models.User, error) { | ||||
| func Login(username, password string) (string, error) { | ||||
| 	user, err := repositories.GetUserByUsername(username) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.New("user not found") | ||||
| 		return "", errors.New("invalid credentials") | ||||
| 	} | ||||
| 
 | ||||
| 	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil { | ||||
| 		return nil, errors.New("invalid password") | ||||
| 	} | ||||
| 
 | ||||
| 	return user, nil | ||||
| } | ||||
| 
 | ||||
| func CreateUser(user *models.User) error { | ||||
| 	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) | ||||
| 	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return "", errors.New("invalid credentials") | ||||
| 	} | ||||
| 
 | ||||
| 	user.Password = string(hashedPassword) | ||||
| 	return repositories.CreateUser(user) | ||||
| 	token, err := utils.GenerateJWT(user.ID) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return token, nil | ||||
| } | ||||
|  | ||||
| @ -1,12 +0,0 @@ | ||||
| package services | ||||
| 
 | ||||
| import "gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 
 | ||||
| func CreateRole(role *models.Role) error { | ||||
| 	return repositories.CreateRole(role) | ||||
| } | ||||
| 
 | ||||
| func AssignRoleToUser(userID uint, roleID uint) error { | ||||
| 	// 实现角色分配逻辑 | ||||
| 	return nil | ||||
| } | ||||
| @ -1,7 +1,44 @@ | ||||
| package services | ||||
| 
 | ||||
| import "gitea.zjmud.xyz/phyer/rbac/models" | ||||
| 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 CreateUser(user *models.User) error { | ||||
| 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) | ||||
| } | ||||
|  | ||||
							
								
								
									
										475
									
								
								sug.md
									
									
									
									
									
								
							
							
						
						
									
										475
									
								
								sug.md
									
									
									
									
									
								
							| @ -1,475 +0,0 @@ | ||||
| Filepath: api/admin.go | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 02:30:16 | ||||
| 
 | ||||
| - Model: ollamav3/chsword/DeepSeek-V3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - main.go | ||||
|   - api/routes.go | ||||
|   - middleware/auth.go | ||||
|   - config/config.go | ||||
|   - models/models.go | ||||
| 
 | ||||
| > router里动作对应的service,请给出实现 | ||||
| >  | ||||
| 
 | ||||
| To implement the service for the router's actions, we need to create a new file `services.py` in the project root directory `/Users/zhangkun/data/go/test/testai`.  | ||||
| 
 | ||||
| Here are the *SEARCH/REPLACE* blocks: | ||||
| 
 | ||||
| Filepath: main.go | ||||
| Replace lines: 0-0 | ||||
| ```go | ||||
| import "services" | ||||
| 
 | ||||
| router.HandleFunc("/action1", services.action1Handler) | ||||
| router.HandleFunc("/action2", services.action2Handler) | ||||
| ``` | ||||
| 
 | ||||
| Filepath: services.go | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 02:32:35 | ||||
| 
 | ||||
| - Model: ollamav3/chsword/DeepSeek-V3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - main.go | ||||
|   - api/routes.go | ||||
|   - middleware/auth.go | ||||
|   - config/config.go | ||||
|   - models/models.go | ||||
| 
 | ||||
| > 		admin.POST("/roles", CreateRole) | ||||
| > 		admin.POST("/users", CreateUser) | ||||
| > 		admin.POST("/permissions", CreatePermission) | ||||
| > 		admin.POST("/user-groups", CreateUserGroup) | ||||
| > 		admin.POST("/assign-role", AssignRoleToUser) | ||||
| > 		admin.POST("/assign-permission", AssignPermissionToRole) | ||||
| >     这里的 动作都是未定义的,需要你给出定义 | ||||
| 
 | ||||
| To make these actions defined, we need to add the necessary functions and routes. Here's an example of how you can define them: | ||||
| 
 | ||||
| ```markdown | ||||
| # Define the CreateRole function | ||||
| def CreateRole(request): | ||||
|     # Get the role data from the request body | ||||
|     role_data = request.get_json() | ||||
|      | ||||
|     # Create a new Role object with the provided data | ||||
|     role = Role(name=role_data['name'], description=role_data['description']) | ||||
|      | ||||
|     # Save the role to the database | ||||
|     db.session.add(role) | ||||
|     db.session.commit() | ||||
|      | ||||
|     # Return the created role as JSON | ||||
|     return jsonify({'id': role.id, 'name': role.name, 'description': role.description}) | ||||
| 
 | ||||
| # Define the CreateUser function | ||||
| def CreateUser(request): | ||||
|     # Get the user data from the request body | ||||
|     user_data = request.get_json() | ||||
|      | ||||
|     # Create a new User object with the provided data | ||||
|     user = User(username=user_data['username'], email=user_data['email']) | ||||
|      | ||||
|     # Hash the password using bcrypt | ||||
|     user.password = bcrypt.hashpw(user.password.encode('utf-8'), bcrypt.gensalt()) | ||||
|      | ||||
|     # Save the user to the database | ||||
|     db.session.add(user) | ||||
|     db.session.commit() | ||||
|      | ||||
|     # Return the created user as JSON | ||||
|     return jsonify({'id': user.id, 'username': user.username, 'email': user.email}) | ||||
| 
 | ||||
| # Define the CreatePermission function | ||||
| def CreatePermission(request): | ||||
|     # Get the permission data from the request body | ||||
|     permission_data = request.get_json() | ||||
|      | ||||
|     # Create a new Permission object with the provided data | ||||
|     permission = Permission(name=permission_data['name'], description=permission_data['description']) | ||||
|      | ||||
|     # Save the permission to the database | ||||
|     db.session.add(permission) | ||||
|     db.session.commit() | ||||
|      | ||||
|     # Return the created permission as JSON | ||||
|     return jsonify({'id': permission.id, 'name': permission.name, 'description': permission.description}) | ||||
| 
 | ||||
| # Define the CreateUserGroup function | ||||
| def CreateUserGroup(request): | ||||
|     # Get the group data from the request body | ||||
|     group_data = request.get_json() | ||||
|      | ||||
|     # Create a new Group object with the provided data | ||||
|     group = Group(name=group_data['name'], description=group_data['description']) | ||||
|      | ||||
|     # Save the group to the database | ||||
|     db.session.add(group) | ||||
|     db.session.commit() | ||||
|      | ||||
|     # Return the created group as JSON | ||||
|     return jsonify({'id': group.id, 'name': group.name, 'description': group.description}) | ||||
| 
 | ||||
| # Define the AssignRoleToUser function | ||||
| def AssignRoleToUser(request): | ||||
|     # Get the user ID and role ID from the request body | ||||
|     user_id = request.get_json()['user_id'] | ||||
|     role_id = request.get_json()['role_id'] | ||||
|      | ||||
|     # Find the user and role objects in the database | ||||
|     user = User.query.get(user_id) | ||||
|     role = Role.query.get(role_id) | ||||
|      | ||||
|     # Assign the role to the user | ||||
|     user.roles.append(role) | ||||
|      | ||||
|     # Save the changes to the database | ||||
|     db.session.commit() | ||||
|      | ||||
|     # Return a success message as JSON | ||||
|     return jsonify({'message': 'Role assigned successfully'}) | ||||
| 
 | ||||
| # Define the AssignPermissionToRole function | ||||
| def AssignPermissionToRole(request): | ||||
|     # Get the role ID and permission ID from the request body | ||||
|     role_id = request.get_json()['role_id'] | ||||
|     permission_id = request.get_json()['permission_id'] | ||||
|      | ||||
|     # Find the role and permission objects in the database | ||||
|     role = Role.query.get(role_id) | ||||
|     permission = Permission.query.get(permission_id) | ||||
|      | ||||
|     # Assign the permission to the role | ||||
|     role.permissions.append(permission) | ||||
|      | ||||
|     # Save the changes to the database | ||||
|     db.session.commit() | ||||
|      | ||||
|     # Return a success message as JSON | ||||
|     return jsonify({'message': 'Permission assigned successfully'}) | ||||
| ``` | ||||
| 
 | ||||
| Note that these functions assume you have already defined the necessary models (e.g. `User`, `Role`, `Group`, etc.) and database sessions. | ||||
| 
 | ||||
| Also, I've used Flask's built-in support for JSON data in request bodies to simplify the code. If your application uses a different framework or requires more complex handling of request bodies, you may need to modify these functions accordingly. | ||||
| 
 | ||||
| To implement these routes, you would add them to your Flask app like so: | ||||
| 
 | ||||
| ```python | ||||
| from flask import Flask, jsonify, request | ||||
| 
 | ||||
| app = Flask(__name__) | ||||
| 
 | ||||
| # ... (other routes and code) | ||||
| 
 | ||||
| admin = Blueprint('admin', __name__, url_prefix='/admin') | ||||
| 
 | ||||
| @admin.route('/roles', methods=['POST']) | ||||
| def CreateRole(): | ||||
|     # Call the CreateRole function defined above | ||||
|     return CreateRole(request) | ||||
| 
 | ||||
| @admin.route('/users', methods=['POST']) | ||||
| def CreateUser(): | ||||
|     # Call the CreateUser function defined above | ||||
|     return CreateUser(request) | ||||
| 
 | ||||
| @admin.route('/permissions', methods=['POST']) | ||||
| def CreatePermission(): | ||||
|     # Call the CreatePermission function defined above | ||||
|     return CreatePermission(request) | ||||
| 
 | ||||
| @admin.route('/user-groups', methods=['POST']) | ||||
| def CreateUserGroup(): | ||||
|     # Call the CreateUserGroup function defined above | ||||
|     return CreateUserGroup(request) | ||||
| 
 | ||||
| @admin.route('/assign-role', methods=['POST']) | ||||
| def AssignRoleToUser(): | ||||
|     # Call the AssignRoleToUser function defined above | ||||
|     return AssignRoleToUser(request) | ||||
| 
 | ||||
| @admin.route('/assign-permission', methods=['POST']) | ||||
| def AssignPermissionToRole(): | ||||
|     # Call the AssignPermissionToRole function defined above | ||||
|     return AssignPermissionToRole(request) | ||||
| ``` | ||||
| 
 | ||||
| This assumes you have already created a Blueprint for your admin interface and registered these routes with it. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 02:34:18 | ||||
| 
 | ||||
| - Model: ollamav3/chsword/DeepSeek-V3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - main.go | ||||
|   - api/routes.go | ||||
|   - middleware/auth.go | ||||
|   - config/config.go | ||||
|   - models/models.go | ||||
| 
 | ||||
| > 这不是python,这是go的gin框架 | ||||
| >  | ||||
| 
 | ||||
| I'll make sure to pay attention to the framework. | ||||
| 
 | ||||
| So, you want me to modify the `mathweb/flask/app.go` file in the Go Gin framework instead of Python Flask. | ||||
| 
 | ||||
| Please confirm if I should proceed with the changes. If so, please provide more details about what changes are needed. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| - Datetime: 2025-02-16 02:38:40 | ||||
| 
 | ||||
| - Model: alidsv3/deepseek-v3 | ||||
| 
 | ||||
| - Selected files: | ||||
|   - tree.txt | ||||
|   - api/routes.go | ||||
|   - config/config.go | ||||
|   - middleware/auth.go | ||||
|   - models/models.go | ||||
|   - server/server.go | ||||
|   - main.go | ||||
| 
 | ||||
| > 我在一个空目录下, 我需要创建一饿go语言gin框架的api后端项目,项目名字叫   zjmud.xyz/phyer/rbac, 需要帮我生成 go.mod的内容,  | ||||
| > > 然后需要创建一个用户账号系统, 包括基础的用户验证功能和鉴权,鉴权依照rbac模式,管理员可以创建角色、用户、定义资源、资源组、和动作,管理员可以委派某个用户,对特定资源组和用户组进行动作定义, 请把go文件根据逻辑,放置到不同的模块中,不要都放到main 模块下 | ||||
| >  | ||||
| > 那么当前目录结构是否在正确的方向上, 每个文件是否有需要改动的地方 | ||||
| 
 | ||||
| 根据你的需求,当前目录结构已经在一个很好的方向上,但还需要做一些调整和补充。让我们一步一步来: | ||||
| 
 | ||||
| 1. 首先,创建 `go.mod` 文件: | ||||
| 
 | ||||
| Filepath: go.mod | ||||
| Replace lines: 1-0 | ||||
| ```unknown | ||||
| module 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/sqlite v1.5.4 | ||||
|     gorm.io/gorm v1.25.5 | ||||
|     github.com/caarlos0/env/v10 v10.0.0 | ||||
| ) | ||||
| ``` | ||||
| 
 | ||||
| 2. 当前目录结构基本合理,但建议做一些调整: | ||||
| 
 | ||||
| ``` | ||||
| . | ||||
| ├── api | ||||
| │   └── routes.go | ||||
| ├── config | ||||
| │   └── config.go | ||||
| ├── controllers | ||||
| │   ├── auth.go | ||||
| │   ├── rbac.go | ||||
| │   └── user.go | ||||
| ├── go.mod | ||||
| ├── go.sum | ||||
| ├── main.go | ||||
| ├── middleware | ||||
| │   └── auth.go | ||||
| ├── models | ||||
| │   └── models.go | ||||
| ├── repositories | ||||
| │   ├── permission.go | ||||
| │   ├── role.go | ||||
| │   ├── user.go | ||||
| │   └── user_group.go | ||||
| ├── server | ||||
| │   └── server.go | ||||
| └── services | ||||
|     ├── auth.go | ||||
|     ├── rbac.go | ||||
|     └── user.go | ||||
| ``` | ||||
| 
 | ||||
| 3. 需要修改和补充的文件: | ||||
| 
 | ||||
| Filepath: api/routes.go | ||||
| Replace lines: 9-26 | ||||
| ```go | ||||
| func SetupRoutes(r *gin.Engine) { | ||||
| 	auth := r.Group("/auth") | ||||
| 	{ | ||||
| 		auth.POST("/login", controllers.Login) | ||||
| 		auth.POST("/register", controllers.Register) | ||||
| 	} | ||||
| 
 | ||||
| 	admin := r.Group("/admin") | ||||
| 	admin.Use(middleware.RBACMiddleware("admin", "full-access")) | ||||
| 	{ | ||||
| 		admin.POST("/roles", controllers.CreateRole) | ||||
| 		admin.POST("/users", controllers.CreateUser) | ||||
| 		admin.POST("/permissions", controllers.CreatePermission) | ||||
| 		admin.POST("/user-groups", controllers.CreateUserGroup) | ||||
| 		admin.POST("/assign-role", controllers.AssignRoleToUser) | ||||
| 		admin.POST("/assign-permission", controllers.AssignPermissionToRole) | ||||
| 	} | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Filepath: config/config.go | ||||
| Replace lines: 15-19 | ||||
| ```go | ||||
| func LoadConfig() *Config { | ||||
| 	cfg := &Config{} | ||||
| 	if err := env.Parse(cfg); err != nil { | ||||
| 		panic("Failed to load config: " + err.Error()) | ||||
| 	} | ||||
| 	return cfg | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Filepath: middleware/auth.go | ||||
| Replace lines: 8-13 | ||||
| ```go | ||||
| func JWTAuthMiddleware(secret string) gin.HandlerFunc { | ||||
| 	return func(c *gin.Context) { | ||||
| 		tokenString := c.GetHeader("Authorization") | ||||
| 		if tokenString == "" { | ||||
| 			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Authorization header missing"}) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { | ||||
| 			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { | ||||
| 				return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) | ||||
| 			} | ||||
| 			return []byte(secret), nil | ||||
| 		}) | ||||
| 
 | ||||
| 		if err != nil || !token.Valid { | ||||
| 			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"}) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		claims, ok := token.Claims.(jwt.MapClaims) | ||||
| 		if !ok { | ||||
| 			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token claims"}) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		c.Set("userID", claims["sub"]) | ||||
| 		c.Next() | ||||
| 	} | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 4. 需要创建的新文件: | ||||
| 
 | ||||
| Filepath: controllers/auth.go | ||||
| <SEARCH> | ||||
| package controllers | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"time" | ||||
| 	"zjmud.xyz/phyer/rbac/models" | ||||
| 	"zjmud.xyz/phyer/rbac/services" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/golang-jwt/jwt/v5" | ||||
| ) | ||||
| 
 | ||||
| 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(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	user, err := services.Authenticate(loginData.Username, loginData.Password) | ||||
| 	if err != nil { | ||||
| 		c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ | ||||
| 		"sub": user.ID, | ||||
| 		"exp": time.Now().Add(time.Hour * 24).Unix(), | ||||
| 	}) | ||||
| 
 | ||||
| 	tokenString, err := token.SignedString([]byte("your-256-bit-secret")) | ||||
| 	if err != nil { | ||||
| 		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c.JSON(http.StatusOK, gin.H{"token": tokenString}) | ||||
| } | ||||
| 
 | ||||
| func Register(c *gin.Context) { | ||||
| 	var user models.User | ||||
| 	if err := c.ShouldBindJSON(&user); err != nil { | ||||
| 		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if err := services.CreateUser(&user); err != nil { | ||||
| 		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c.JSON(http.StatusCreated, user) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Filepath: services/auth.go | ||||
| <SEARCH> | ||||
| package services | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"zjmud.xyz/phyer/rbac/models" | ||||
| 	"zjmud.xyz/phyer/rbac/repositories" | ||||
| 
 | ||||
| 	"golang.org/x/crypto/bcrypt" | ||||
| ) | ||||
| 
 | ||||
| func Authenticate(username, password string) (*models.User, error) { | ||||
| 	user, err := repositories.GetUserByUsername(username) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.New("user not found") | ||||
| 	} | ||||
| 
 | ||||
| 	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil { | ||||
| 		return nil, errors.New("invalid password") | ||||
| 	} | ||||
| 
 | ||||
| 	return user, nil | ||||
| } | ||||
| 
 | ||||
| func CreateUser(user *models.User) error { | ||||
| 	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	user.Password = string(hashedPassword) | ||||
| 	return repositories.CreateUser(user) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Filepath: repositories/user.go | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										34
									
								
								tree.txt
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								tree.txt
									
									
									
									
									
								
							| @ -1,17 +1,37 @@ | ||||
| . | ||||
| ├── api | ||||
| │   └── routes.go | ||||
| │   └── routes.go | ||||
| ├── config | ||||
| │   └── config.go | ||||
| │   └── config.go | ||||
| ├── controllers | ||||
| │   ├── auth.go | ||||
| │   ├── rbac.go | ||||
| │   └── user.go | ||||
| ├── go.mod | ||||
| ├── go.sum | ||||
| ├── main.go | ||||
| ├── middleware | ||||
| │   └── auth.go | ||||
| │   ├── auth.go | ||||
| │   └── rbac.go | ||||
| ├── models | ||||
| │   └── models.go | ||||
| │   ├── permission.go | ||||
| │   ├── role.go | ||||
| │   ├── user.go | ||||
| │   └── user_group.go | ||||
| ├── repositories | ||||
| │   ├── permission.go | ||||
| │   ├── role.go | ||||
| │   ├── user.go | ||||
| │   └── user_group.go | ||||
| ├── server | ||||
| │   └── server.go | ||||
| │   └── server.go | ||||
| ├── services | ||||
| │   ├── auth.go | ||||
| │   ├── rbac.go | ||||
| │   └── user.go | ||||
| ├── utils | ||||
| │   ├── jwt.go | ||||
| │   ├── redis.go | ||||
| │   └── response.go | ||||
| ├── sug.md | ||||
| └── tree.txt | ||||
| 
 | ||||
| 6 directories, 9 files | ||||
|  | ||||
							
								
								
									
										29
									
								
								utils/jwt.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								utils/jwt.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| package utils | ||||
| 
 | ||||
| import ( | ||||
| 	"gitea.zjmud.xyz/phyer/rbac/config" | ||||
| 	"github.com/golang-jwt/jwt/v5" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| 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") | ||||
| } | ||||
							
								
								
									
										0
									
								
								utils/redis.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								utils/redis.go
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								utils/response.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								utils/response.go
									
									
									
									
									
										Normal file
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zhangkun9038@dingtalk.com
						zhangkun9038@dingtalk.com