feat: user migration
This commit is contained in:
@@ -33,6 +33,9 @@ func main() {
|
||||
&models.MqttGatewayStatusRecord{},
|
||||
&models.MqttTrainingSessionRecord{},
|
||||
)
|
||||
if err := models.BackfillLegacyUserPermissions(config.DB); err != nil {
|
||||
log.Printf("legacy user permission backfill failed: %v", err)
|
||||
}
|
||||
|
||||
if err := mqtt.Start(config.DB, config.App.MQTT); err != nil {
|
||||
log.Printf("mqtt listener start failed: %v", err)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"hr_receiver/config"
|
||||
"hr_receiver/models"
|
||||
"hr_receiver/util"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -33,12 +35,33 @@ func JWTAuth() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
role := claims.Role
|
||||
flavorType := claims.FlavorType
|
||||
regionIDs := claims.RegionIDs
|
||||
|
||||
if role == "" || flavorType == "" {
|
||||
var user models.User
|
||||
if err := config.DB.Preload("Regions").First(&user, claims.UserID).Error; err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not found"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if !user.IsActive {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "User is disabled"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
role = user.Role
|
||||
flavorType = user.FlavorType
|
||||
regionIDs = user.RegionIDs()
|
||||
}
|
||||
|
||||
// 将用户信息存入上下文
|
||||
c.Set("userID", claims.UserID)
|
||||
c.Set("username", claims.Username)
|
||||
c.Set("role", claims.Role)
|
||||
c.Set("flavorType", claims.FlavorType)
|
||||
c.Set("regionIDs", claims.RegionIDs)
|
||||
c.Set("role", role)
|
||||
c.Set("flavorType", flavorType)
|
||||
c.Set("regionIDs", regionIDs)
|
||||
|
||||
c.Next()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"hr_receiver/models"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func RequireStepTrainingAccess() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
roleValue, exists := c.Get("role")
|
||||
if !exists {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "missing user role"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
role, ok := roleValue.(models.UserRole)
|
||||
if !ok {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "invalid user role"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if role != models.UserRoleSuperAdmin &&
|
||||
role != models.UserRoleRegionAdmin &&
|
||||
role != models.UserRoleOperator {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "insufficient role permissions"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
flavorValue, exists := c.Get("flavorType")
|
||||
if !exists {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "missing user flavor"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
flavorType, ok := flavorValue.(models.UserFlavorType)
|
||||
if !ok {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "invalid user flavor"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if flavorType != models.UserFlavorAll &&
|
||||
flavorType != models.UserFlavorFlink {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "insufficient flavor permissions"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ type UserFlavorType string
|
||||
|
||||
const (
|
||||
UserFlavorAll UserFlavorType = "all"
|
||||
UserFlavorFlink UserFlavorType = "flink"
|
||||
UserFlavorFull UserFlavorType = "full"
|
||||
UserFlavorLight UserFlavorType = "light"
|
||||
UserFlavorHeartRate UserFlavorType = "heartrate"
|
||||
@@ -87,6 +88,9 @@ func (u *User) SupportsFlavor(flavor string) bool {
|
||||
if u.FlavorType == UserFlavorAll {
|
||||
return true
|
||||
}
|
||||
if u.FlavorType == UserFlavorFlink {
|
||||
return flavor == string(UserFlavorFlink) || flavor == string(UserFlavorFull) || flavor == string(UserFlavorLight)
|
||||
}
|
||||
return string(u.FlavorType) == flavor
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package models
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func BackfillLegacyUserPermissions(db *gorm.DB) error {
|
||||
if err := db.Model(&User{}).
|
||||
Where("role IS NULL OR role = '' OR role = ?", UserRoleViewer).
|
||||
Update("role", UserRoleOperator).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.Model(&User{}).
|
||||
Where("flavor_type IS NULL OR flavor_type = '' OR flavor_type = ?", UserFlavorAll).
|
||||
Update("flavor_type", UserFlavorFlink).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.Model(&User{}).
|
||||
Where("is_active IS NULL").
|
||||
Update("is_active", true).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+1
-1
@@ -23,7 +23,7 @@ func SetupRouter() *gin.Engine {
|
||||
records.POST("/analysis-by-ai", trainingController.AnalyzeByAI)
|
||||
// 可扩展其他路由:GET, PUT, DELETE等
|
||||
}
|
||||
steps := v1.Group("/step").Use(middleware.JWTAuth())
|
||||
steps := v1.Group("/step").Use(middleware.JWTAuth(), middleware.RequireStepTrainingAccess())
|
||||
{
|
||||
steps.POST("", stepTrainController.CreateTrainingRecord)
|
||||
steps.GET("train-records", stepTrainController.GetTrainingRecords)
|
||||
|
||||
Reference in New Issue
Block a user