Files
xinmi/internal/accesscontrol/resource_version_knowledge_review.go
T

92 lines
3.5 KiB
Go
Raw Normal View History

package accesscontrol
import (
"context"
"fmt"
"strconv"
"github.com/Tencent/WeKnora/internal/types"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type knowledgeReviewDocument struct {
ID string `json:"id"`
Title string `json:"title"`
Type string `json:"type"`
}
type knowledgeReviewChunk struct {
ID string `json:"id"`
Content string `json:"content"`
ChunkType string `json:"chunk_type"`
ChunkIndex int `json:"chunk_index"`
IsEnabled bool `json:"is_enabled"`
}
type knowledgeReviewPage struct {
Documents []knowledgeReviewDocument `json:"documents,omitempty"`
Document *knowledgeReviewDocument `json:"document,omitempty"`
Chunks []knowledgeReviewChunk `json:"chunks,omitempty"`
Page int `json:"page"`
PageSize int `json:"page_size"`
Total int64 `json:"total"`
}
func (s *Service) GetKnowledgeVersionReview(c *gin.Context) {
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
if err != nil || page < 1 || page > 100000 {
versionResult(c, errInvalid, nil)
return
}
result, err := s.knowledgeVersionReview(c.Request.Context(), c.Param("id"), c.Query("document_id"), page)
versionResult(c, err, result)
}
// Review reads only an immutable stage, without granting ordinary KB access or
// exposing file handles, provider configuration, or download URLs.
func (s *Service) knowledgeVersionReview(ctx context.Context, id, document string, page int) (*knowledgeReviewPage, error) {
if err := versionPermission(ctx, "knowledge", false); err != nil {
return nil, err
}
tenant, user := identity(ctx)
result := &knowledgeReviewPage{Page: page, PageSize: 20}
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
var submission ResourceSubmission
q := tx.Clauses(clause.Locking{Strength: "SHARE"}).Where("tenant_id=? AND id=? AND kind='knowledge'", tenant, id)
if !administrator(ctx) {
q = q.Where("owner_id=?", user)
}
if err := q.First(&submission).Error; err != nil {
return err
}
if submission.SnapshotID == "" || (submission.Status != "pending" && submission.Status != "rejected" && submission.Status != "withdrawn") {
return fmt.Errorf("%w: 当前记录没有可查看的只读知识快照;已批准记录请查看已发布知识库", errConflict)
}
var kb types.KnowledgeBase
if err := tx.Clauses(clause.Locking{Strength: "SHARE"}).Where("tenant_id=? AND id=? AND is_temporary=true AND version_state='snapshot'", tenant, submission.SnapshotID).First(&kb).Error; err != nil {
return err
}
docs := tx.Model(&types.Knowledge{}).Where("tenant_id=? AND knowledge_base_id=?", tenant, kb.ID)
if document == "" {
if err := docs.Count(&result.Total).Error; err != nil {
return err
}
result.Documents = []knowledgeReviewDocument{}
return docs.Select("id,title,type").Order("title,id").Offset((page - 1) * result.PageSize).Limit(result.PageSize).Find(&result.Documents).Error
}
result.Document = &knowledgeReviewDocument{}
if err := docs.Select("id,title,type").Where("id=?", document).Take(result.Document).Error; err != nil {
return err
}
chunks := tx.Model(&types.Chunk{}).Where("tenant_id=? AND knowledge_base_id=? AND knowledge_id=?", tenant, kb.ID, document)
if err := chunks.Count(&result.Total).Error; err != nil {
return err
}
result.Chunks = []knowledgeReviewChunk{}
return chunks.Select("id,content,chunk_type,chunk_index,is_enabled").Order("chunk_index,id").Offset((page - 1) * result.PageSize).Limit(result.PageSize).Find(&result.Chunks).Error
})
return result, err
}