package middleware import ( "net/http" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "chaitin.cn/patronus/safeline-2/management/webserver/api/response" "chaitin.cn/patronus/safeline-2/management/webserver/model" "chaitin.cn/patronus/safeline-2/management/webserver/pkg/constants" "chaitin.cn/patronus/safeline-2/management/webserver/pkg/database" ) func AuthRequired(c *gin.Context) { session := sessions.Default(c) user := session.Get(constants.DefaultSessionUserKey) if user == nil { response.Error(c, response.ErrorLoginRequired, http.StatusUnauthorized) c.Abort() return } // Load user from database to get current role/status db := database.GetDB() var userModel model.User res := db.First(&userModel, user) if res.RowsAffected == 0 { response.Error(c, response.ErrorLoginRequired, http.StatusUnauthorized) c.Abort() return } // Check if user is still enabled if !userModel.IsEnabled { session.Clear() session.Save() response.Error(c, response.JSONBody{Err: "account_disabled", Msg: "Account has been disabled"}, http.StatusForbidden) c.Abort() return } // Store user info in context for downstream handlers c.Set("user_id", int(userModel.ID)) c.Set("user_role", userModel.Role) c.Set("username", userModel.Username) // extend session expired time session.Options(sessions.Options{ Path: "/", MaxAge: 3600 * 24 * 7, }) if err := session.Save(); err != nil { response.Error(c, response.JSONBody{Err: response.ErrInternalError, Msg: "Error occurred when creating sessions"}, http.StatusInternalServerError) return } c.Next() } // RequireRole returns a middleware that checks if the user has one of the required roles. func RequireRole(roles ...string) gin.HandlerFunc { roleSet := make(map[string]bool) for _, r := range roles { roleSet[r] = true } return func(c *gin.Context) { userRole, exists := c.Get("user_role") if !exists { response.Error(c, response.ErrorLoginRequired, http.StatusUnauthorized) c.Abort() return } role, ok := userRole.(string) if !ok || !roleSet[role] { response.Error(c, response.JSONBody{Err: "forbidden", Msg: "Insufficient permissions"}, http.StatusForbidden) c.Abort() return } c.Next() } } func ReadOnly(c *gin.Context) { if c.Request.Method != "GET" && c.Request.Method != "HEAD" && c.Request.Method != "OPTIONS" { response.Error(c, response.ErrorReadOnly, http.StatusBadRequest) c.Abort() } }