package controller import ( "errors" "net/http" "regexp" "strconv" "strings" "ezops/model" "ezops/pkg/logaccess" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // LogScopeRoleHandler 日志查询权限 // Logan.Li type LogScopeRoleHandler struct { db *gorm.DB } func NewLogScopeRoleHandler(db *gorm.DB) *LogScopeRoleHandler { return &LogScopeRoleHandler{db: db} } // ListLogScopeRoles GET /log-scope-roles func (h *LogScopeRoleHandler) ListLogScopeRoles(c *gin.Context) { var roles []model.LogScopeRole h.db.Order("created_at DESC").Find(&roles) c.JSON(http.StatusOK, model.Response{Code: 200, Data: model.ListResponse{List: roles, Total: int64(len(roles))}}) } // CreateLogScopeRole POST /log-scope-roles func (h *LogScopeRoleHandler) CreateLogScopeRole(c *gin.Context) { var req model.CreateLogScopeRoleRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: err.Error()}) return } if _, err := regexp.Compile(req.Pattern); err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "正则表达式无效: " + err.Error()}) return } engine := strings.TrimSpace(req.Engine) if engine == "" { engine = "*" } role := req.Role if role == "" { role = "viewer" } var dup int64 h.db.Model(&model.LogScopeRole{}).Where("name = ? OR code = ?", req.Name, req.Code).Count(&dup) if dup > 0 { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "名称或编码已存在"}) return } item := model.LogScopeRole{ Name: req.Name, Code: req.Code, Engine: engine, MatchField: req.MatchField, Pattern: req.Pattern, DatasourceID: req.DatasourceID, Role: role, Description: req.Description, Status: 1, } if err := h.db.Create(&item).Error; err != nil { c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "创建失败"}) return } c.JSON(http.StatusOK, model.Response{Code: 200, Message: "创建成功", Data: item}) } // UpdateLogScopeRole PUT /log-scope-roles/:id func (h *LogScopeRoleHandler) UpdateLogScopeRole(c *gin.Context) { id, _ := strconv.ParseUint(c.Param("id"), 10, 64) var item model.LogScopeRole if err := h.db.First(&item, id).Error; err != nil { c.JSON(http.StatusNotFound, model.Response{Code: 404, Message: "策略不存在"}) return } var req model.UpdateLogScopeRoleRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: err.Error()}) return } updates := map[string]interface{}{} if req.Name != "" { updates["name"] = req.Name } if req.Code != "" { updates["code"] = req.Code } if req.Engine != "" { updates["engine"] = req.Engine } if req.MatchField != "" { updates["match_field"] = req.MatchField } if req.Pattern != "" { if _, err := regexp.Compile(req.Pattern); err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "正则无效"}) return } updates["pattern"] = req.Pattern } if req.DatasourceID != nil { updates["datasource_id"] = req.DatasourceID } if req.Role != "" { updates["role"] = req.Role } if req.Description != "" { updates["description"] = req.Description } if req.Status != nil { updates["status"] = *req.Status } if len(updates) > 0 { h.db.Model(&item).Updates(updates) } h.db.First(&item, id) c.JSON(http.StatusOK, model.Response{Code: 200, Message: "更新成功", Data: item}) } // DeleteLogScopeRole DELETE /log-scope-roles/:id func (h *LogScopeRoleHandler) DeleteLogScopeRole(c *gin.Context) { id, _ := strconv.ParseUint(c.Param("id"), 10, 64) h.db.Where("log_scope_role_id = ?", id).Delete(&model.UserLogScopeRole{}) if err := h.db.Delete(&model.LogScopeRole{}, id).Error; err != nil { c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "删除失败"}) return } c.JSON(http.StatusOK, model.Response{Code: 200, Message: "删除成功"}) } // ListUserLogScopeRoles GET /log-scope-roles/users/:id func (h *LogScopeRoleHandler) ListUserLogScopeRoles(c *gin.Context) { uid, _ := strconv.ParseUint(c.Param("id"), 10, 64) var rows []model.UserLogScopeRole h.db.Preload("LogScopeRole").Where("user_id = ?", uid).Find(&rows) c.JSON(http.StatusOK, model.Response{Code: 200, Data: model.ListResponse{List: rows, Total: int64(len(rows))}}) } // AssignLogScopeRole POST /log-scope-roles/users/:id func (h *LogScopeRoleHandler) AssignLogScopeRole(c *gin.Context) { uid, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || uid == 0 { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "无效的用户 ID"}) return } var req model.AssignLogScopeRoleRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "请求参数错误: " + err.Error()}) return } var role model.LogScopeRole if err := h.db.First(&role, req.LogScopeRoleID).Error; err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "策略不存在"}) return } var existing model.UserLogScopeRole if err := h.db.Where("user_id = ? AND log_scope_role_id = ?", uid, req.LogScopeRoleID).Take(&existing).Error; err == nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "已分配该策略"}) return } else if !errors.Is(err, gorm.ErrRecordNotFound) { c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "查询失败: " + err.Error()}) return } row := model.UserLogScopeRole{UserID: uint(uid), LogScopeRoleID: req.LogScopeRoleID} if err := h.db.Create(&row).Error; err != nil { c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "分配失败: " + err.Error()}) return } h.db.Preload("LogScopeRole").Take(&row, row.ID) c.JSON(http.StatusOK, model.Response{Code: 200, Message: "分配成功", Data: row}) } // RemoveLogScopeRole DELETE /log-scope-roles/users/:userId/:assignId func (h *LogScopeRoleHandler) RemoveLogScopeRole(c *gin.Context) { assignID, _ := strconv.ParseUint(c.Param("assignId"), 10, 64) h.db.Delete(&model.UserLogScopeRole{}, assignID) c.JSON(http.StatusOK, model.Response{Code: 200, Message: "已撤销"}) } // PreviewLogScope POST /log-scope-roles/preview func (h *LogScopeRoleHandler) PreviewLogScope(c *gin.Context) { var req model.PreviewLogScopeRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: err.Error()}) return } var roles []model.LogScopeRole h.db.Where("status = 1").Find(&roles) qc := logaccess.QueryContext{ Engine: req.Engine, DatasourceID: req.DatasourceID, Index: req.Index, Query: req.Query, } matched := logaccess.MatchRolesForPreview(roles, qc, req.SampleValue) c.JSON(http.StatusOK, model.Response{Code: 200, Data: gin.H{ "allowed": len(matched) > 0, "matched": matched, "total": len(matched), }}) }