完善角色权限与数据隔离
This commit is contained in:
@@ -15,14 +15,18 @@ type KnowledgeHandler struct{}
|
||||
|
||||
func NewKnowledgeHandler() *KnowledgeHandler { return &KnowledgeHandler{} }
|
||||
|
||||
func requireKnowledgeManager(c *gin.Context) bool {
|
||||
if middleware.HasAnyRole(c, "admin", "supervisor") {
|
||||
func requireKnowledgePermission(c *gin.Context, code string) bool {
|
||||
if middleware.HasPermission(c, code) {
|
||||
return true
|
||||
}
|
||||
c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": "仅主管或管理员可管理知识库"})
|
||||
c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": "无权执行该知识库操作"})
|
||||
return false
|
||||
}
|
||||
|
||||
func canDeleteKnowledge(c *gin.Context, createdBy uint) bool {
|
||||
return middleware.GetRole(c) == "admin" || (createdBy != 0 && createdBy == middleware.GetUserID(c))
|
||||
}
|
||||
|
||||
func hasKnowledgeCapacity(tenantID uint) (bool, error) {
|
||||
var tenant model.Tenant
|
||||
if err := model.DB.First(&tenant, tenantID).Error; err != nil {
|
||||
@@ -139,7 +143,7 @@ var (
|
||||
|
||||
type catError string
|
||||
|
||||
func errCat(s string) catError { return catError(s) }
|
||||
func errCat(s string) catError { return catError(s) }
|
||||
func (e catError) Error() string { return string(e) }
|
||||
|
||||
func isCategoryNameTaken(tenantID uint, name string, parentID *uint, excludeID uint) bool {
|
||||
@@ -158,7 +162,7 @@ func isCategoryNameTaken(tenantID uint, name string, parentID *uint, excludeID u
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) CreateCategory(c *gin.Context) {
|
||||
if !requireKnowledgeManager(c) {
|
||||
if !requireKnowledgePermission(c, "knowledge.create") {
|
||||
return
|
||||
}
|
||||
var req CategoryReq
|
||||
@@ -181,9 +185,10 @@ func (h *KnowledgeHandler) CreateCategory(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
category := model.Category{
|
||||
TenantID: tenantID,
|
||||
Name: name,
|
||||
ParentID: req.ParentID,
|
||||
TenantID: tenantID,
|
||||
CreatedBy: middleware.GetUserID(c),
|
||||
Name: name,
|
||||
ParentID: req.ParentID,
|
||||
}
|
||||
if err := model.DB.Create(&category).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "创建失败"})
|
||||
@@ -193,7 +198,7 @@ func (h *KnowledgeHandler) CreateCategory(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) UpdateCategory(c *gin.Context) {
|
||||
if !requireKnowledgeManager(c) {
|
||||
if !requireKnowledgePermission(c, "knowledge.edit") {
|
||||
return
|
||||
}
|
||||
tenantID := middleware.GetTenantID(c)
|
||||
@@ -248,7 +253,7 @@ func (h *KnowledgeHandler) UpdateCategory(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) DeleteCategory(c *gin.Context) {
|
||||
if !requireKnowledgeManager(c) {
|
||||
if !requireKnowledgePermission(c, "knowledge.delete") {
|
||||
return
|
||||
}
|
||||
tenantID := middleware.GetTenantID(c)
|
||||
@@ -258,6 +263,10 @@ func (h *KnowledgeHandler) DeleteCategory(c *gin.Context) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"code": 404, "message": "分类不存在"})
|
||||
return
|
||||
}
|
||||
if !canDeleteKnowledge(c, category.CreatedBy) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": "主管仅可删除自己创建的分类"})
|
||||
return
|
||||
}
|
||||
var childCnt int64
|
||||
model.DB.Model(&model.Category{}).Where("parent_id = ? AND tenant_id = ?", category.ID, tenantID).Count(&childCnt)
|
||||
if childCnt > 0 {
|
||||
@@ -364,7 +373,7 @@ func (h *KnowledgeHandler) ListEntries(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) CreateEntry(c *gin.Context) {
|
||||
if !requireKnowledgeManager(c) {
|
||||
if !requireKnowledgePermission(c, "knowledge.create") {
|
||||
return
|
||||
}
|
||||
var entry model.KnowledgeEntry
|
||||
@@ -373,6 +382,11 @@ func (h *KnowledgeHandler) CreateEntry(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
entry.TenantID = middleware.GetTenantID(c)
|
||||
entry.CreatedBy = middleware.GetUserID(c)
|
||||
if entry.Status == "published" && !middleware.HasPermission(c, "knowledge.publish") {
|
||||
c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": "无权直接发布知识条目"})
|
||||
return
|
||||
}
|
||||
available, err := hasKnowledgeCapacity(entry.TenantID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "校验知识库容量失败"})
|
||||
@@ -397,7 +411,7 @@ func (h *KnowledgeHandler) CreateEntry(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) UpdateEntry(c *gin.Context) {
|
||||
if !requireKnowledgeManager(c) {
|
||||
if !requireKnowledgePermission(c, "knowledge.edit") {
|
||||
return
|
||||
}
|
||||
tenantID := middleware.GetTenantID(c)
|
||||
@@ -432,6 +446,10 @@ func (h *KnowledgeHandler) UpdateEntry(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "没有可更新字段"})
|
||||
return
|
||||
}
|
||||
if status, exists := updates["status"]; exists && status != entry.Status && !middleware.HasPermission(c, "knowledge.publish") {
|
||||
c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": "无权发布或下架知识条目"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := model.DB.Model(&entry).Updates(updates).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "更新失败"})
|
||||
@@ -442,13 +460,22 @@ func (h *KnowledgeHandler) UpdateEntry(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) DeleteEntry(c *gin.Context) {
|
||||
if !requireKnowledgeManager(c) {
|
||||
if !requireKnowledgePermission(c, "knowledge.delete") {
|
||||
return
|
||||
}
|
||||
tenantID := middleware.GetTenantID(c)
|
||||
id := c.Param("id")
|
||||
|
||||
result := model.DB.Where("id = ? AND tenant_id = ?", id, tenantID).Delete(&model.KnowledgeEntry{})
|
||||
var entry model.KnowledgeEntry
|
||||
if err := model.DB.Where("id = ? AND tenant_id = ?", id, tenantID).First(&entry).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"code": 404, "message": "条目不存在"})
|
||||
return
|
||||
}
|
||||
if !canDeleteKnowledge(c, entry.CreatedBy) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": "主管仅可删除自己创建的知识条目"})
|
||||
return
|
||||
}
|
||||
result := model.DB.Delete(&entry)
|
||||
if result.RowsAffected == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"code": 404, "message": "条目不存在"})
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user