完善角色权限与数据隔离

This commit is contained in:
yml2213
2026-07-26 14:00:50 +08:00
parent b483cbc26d
commit 16d9ab0e5e
38 changed files with 2847 additions and 292 deletions
+18 -13
View File
@@ -35,8 +35,8 @@ type QuickReplyHandler struct{}
func NewQuickReplyHandler() *QuickReplyHandler { return &QuickReplyHandler{} }
func requireTeamQuickReplyManager(c *gin.Context) bool {
if middleware.HasAnyRole(c, "admin", "supervisor") {
func requireTeamQuickReplyPermission(c *gin.Context, code string) bool {
if middleware.HasPermission(c, code) {
return true
}
c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": "仅管理员或主管可管理团队快捷回复"})
@@ -81,7 +81,7 @@ func loadQuickReply(c *gin.Context, id uint) (*model.QuickReply, bool) {
func canEditQuickReply(c *gin.Context, item *model.QuickReply) bool {
uid := middleware.GetUserID(c)
if item.Scope == quickReplyScopeTeam {
return middleware.HasAnyRole(c, "admin", "supervisor")
return middleware.HasPermission(c, "quick_reply.team_edit")
}
return item.OwnerUserID != nil && *item.OwnerUserID == uid
}
@@ -171,7 +171,7 @@ func (h *QuickReplyHandler) List(c *gin.Context) {
case quickReplyScopeTeam:
db = db.Where("scope = ?", quickReplyScopeTeam)
// 非管理端:工作台只看已发布;管理页可传 status
if !middleware.HasAnyRole(c, "admin", "supervisor") {
if !middleware.HasAnyPermission(c, "quick_reply.team_create", "quick_reply.team_edit") {
db = db.Where("status = ?", quickReplyStatusPub)
} else if status != "" {
db = db.Where("status = ?", status)
@@ -316,7 +316,7 @@ func (h *QuickReplyHandler) Create(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "scope 无效"})
return
}
if scope == quickReplyScopeTeam && !requireTeamQuickReplyManager(c) {
if scope == quickReplyScopeTeam && !requireTeamQuickReplyPermission(c, "quick_reply.team_create") {
return
}
@@ -441,7 +441,7 @@ func (h *QuickReplyHandler) Delete(c *gin.Context) {
// Publish POST /api/quick-replies/:id/publish 团队:暂存 → 发布同步
func (h *QuickReplyHandler) Publish(c *gin.Context) {
if !requireTeamQuickReplyManager(c) {
if !requireTeamQuickReplyPermission(c, "quick_reply.team_edit") {
return
}
id64, _ := strconv.ParseUint(c.Param("id"), 10, 64)
@@ -463,7 +463,7 @@ func (h *QuickReplyHandler) Publish(c *gin.Context) {
// Unpublish POST /api/quick-replies/:id/unpublish
func (h *QuickReplyHandler) Unpublish(c *gin.Context) {
if !requireTeamQuickReplyManager(c) {
if !requireTeamQuickReplyPermission(c, "quick_reply.team_edit") {
return
}
id64, _ := strconv.ParseUint(c.Param("id"), 10, 64)
@@ -494,7 +494,7 @@ func (h *QuickReplyHandler) Use(c *gin.Context) {
uid := middleware.GetUserID(c)
tenantID := middleware.GetTenantID(c)
if item.Scope == quickReplyScopeTeam && item.Status != quickReplyStatusPub {
if !middleware.HasAnyRole(c, "admin", "supervisor") {
if !middleware.HasAnyPermission(c, "quick_reply.team_create", "quick_reply.team_edit") {
c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": "该话术尚未发布"})
return
}
@@ -590,7 +590,7 @@ func (h *QuickReplyHandler) Export(c *gin.Context) {
db := model.DB.Where("tenant_id = ?", tenantID)
switch scope {
case quickReplyScopeTeam:
if !requireTeamQuickReplyManager(c) {
if !requireTeamQuickReplyPermission(c, "quick_reply.team_edit") {
return
}
db = db.Where("scope = ?", quickReplyScopeTeam)
@@ -646,14 +646,15 @@ func (h *QuickReplyHandler) Import(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "scope 无效"})
return
}
if defaultScope == quickReplyScopeTeam && !requireTeamQuickReplyManager(c) {
if defaultScope == quickReplyScopeTeam && !requireTeamQuickReplyPermission(c, "quick_reply.team_create") {
return
}
onConflict := strings.TrimSpace(c.DefaultPostForm("on_conflict", "skip"))
if onConflict != "skip" && onConflict != "overwrite" {
onConflict = "skip"
}
canManageTeam := middleware.HasAnyRole(c, "admin", "supervisor")
canCreateTeam := middleware.HasPermission(c, "quick_reply.team_create")
canEditTeam := middleware.HasPermission(c, "quick_reply.team_edit")
file, _, err := c.Request.FormFile("file")
if err != nil {
@@ -721,7 +722,7 @@ func (h *QuickReplyHandler) Import(c *gin.Context) {
rowScope = parsed
}
if rowScope == quickReplyScopeTeam && !canManageTeam {
if rowScope == quickReplyScopeTeam && !canCreateTeam {
skipped++
errors = append(errors, fmt.Sprintf("第 %d 行:无权限导入团队快捷回复", lineNo))
continue
@@ -775,6 +776,11 @@ func (h *QuickReplyHandler) Import(c *gin.Context) {
skipped++
continue
}
if rowScope == quickReplyScopeTeam && !canEditTeam {
skipped++
errors = append(errors, fmt.Sprintf("第 %d 行:无权限覆盖团队快捷回复", lineNo))
continue
}
if err := model.DB.Model(&existing).Updates(map[string]interface{}{
"title": title, "content": content, "shortcut": shortcut,
}).Error; err != nil {
@@ -813,4 +819,3 @@ func (h *QuickReplyHandler) Import(c *gin.Context) {
"errors": errors,
})
}