mirror of https://github.com/chaitin/PandaWiki.git
Compare commits
2 Commits
bec070786d
...
0624cfc340
| Author | SHA1 | Date |
|---|---|---|
|
|
0624cfc340 | |
|
|
29ccdad483 |
|
|
@ -13,17 +13,23 @@ type GetNodeDetailReq struct {
|
|||
}
|
||||
|
||||
type NodeDetailResp struct {
|
||||
ID string `json:"id"`
|
||||
KbID string `json:"kb_id"`
|
||||
Type domain.NodeType `json:"type"`
|
||||
Status domain.NodeStatus `json:"status"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
Meta domain.NodeMeta `json:"meta"`
|
||||
ParentID string `json:"parent_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Permissions domain.NodePermissions `json:"permissions"`
|
||||
ID string `json:"id"`
|
||||
KbID string `json:"kb_id"`
|
||||
Type domain.NodeType `json:"type"`
|
||||
Status domain.NodeStatus `json:"status"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
Meta domain.NodeMeta `json:"meta"`
|
||||
ParentID string `json:"parent_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Permissions domain.NodePermissions `json:"permissions"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
EditorId string `json:"editor_id"`
|
||||
PublisherId string `json:"publisher_id" gorm:"-"`
|
||||
CreatorAccount string `json:"creator_account"`
|
||||
EditorAccount string `json:"editor_account"`
|
||||
PublisherAccount string `json:"publisher_account" gorm:"-"`
|
||||
}
|
||||
|
||||
type NodePermissionReq struct {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/chaitin/panda-wiki/domain"
|
||||
)
|
||||
|
||||
type ShareNodeDetailResp struct {
|
||||
ID string `json:"id"`
|
||||
KbID string `json:"kb_id"`
|
||||
Type domain.NodeType `json:"type"`
|
||||
Status domain.NodeStatus `json:"status"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
Meta domain.NodeMeta `json:"meta"`
|
||||
ParentID string `json:"parent_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Permissions domain.NodePermissions `json:"permissions"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
EditorId string `json:"editor_id"`
|
||||
PublisherId string `json:"publisher_id"`
|
||||
CreatorAccount string `json:"creator_account"`
|
||||
EditorAccount string `json:"editor_account"`
|
||||
PublisherAccount string `json:"publisher_account"`
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ func createApp() (*App, error) {
|
|||
return nil, err
|
||||
}
|
||||
authRepo := pg2.NewAuthRepo(db, logger, cacheCache)
|
||||
nodeUsecase := usecase.NewNodeUsecase(nodeRepository, appRepository, ragRepository, knowledgeBaseRepository, llmUsecase, ragService, logger, minioClient, modelRepository, authRepo)
|
||||
nodeUsecase := usecase.NewNodeUsecase(nodeRepository, appRepository, ragRepository, userRepository, knowledgeBaseRepository, llmUsecase, ragService, logger, minioClient, modelRepository, authRepo)
|
||||
nodeHandler := v1.NewNodeHandler(baseHandler, echo, nodeUsecase, authMiddleware, logger)
|
||||
geoRepo := cache2.NewGeoCache(cacheCache, db, logger)
|
||||
ipdbIPDB, err := ipdb.NewIPDB(configConfig, logger)
|
||||
|
|
|
|||
|
|
@ -76,11 +76,12 @@ func createApp() (*App, error) {
|
|||
return nil, err
|
||||
}
|
||||
ragRepository := mq3.NewRAGRepository(mqProducer)
|
||||
userRepository := pg2.NewUserRepository(db, logger)
|
||||
minioClient, err := s3.NewMinioClient(configConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodeUsecase := usecase.NewNodeUsecase(nodeRepository, appRepository, ragRepository, knowledgeBaseRepository, llmUsecase, ragService, logger, minioClient, modelRepository, authRepo)
|
||||
nodeUsecase := usecase.NewNodeUsecase(nodeRepository, appRepository, ragRepository, userRepository, knowledgeBaseRepository, llmUsecase, ragService, logger, minioClient, modelRepository, authRepo)
|
||||
cronHandler, err := mq2.NewStatCronHandler(logger, statRepository, statUseCase, nodeUsecase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ func createApp() (*App, error) {
|
|||
return nil, err
|
||||
}
|
||||
ragRepository := mq2.NewRAGRepository(mqProducer)
|
||||
userRepository := pg2.NewUserRepository(db, logger)
|
||||
ragService, err := rag.NewRAGService(configConfig, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -59,8 +60,7 @@ func createApp() (*App, error) {
|
|||
return nil, err
|
||||
}
|
||||
authRepo := pg2.NewAuthRepo(db, logger, cacheCache)
|
||||
nodeUsecase := usecase.NewNodeUsecase(nodeRepository, appRepository, ragRepository, knowledgeBaseRepository, llmUsecase, ragService, logger, minioClient, modelRepository, authRepo)
|
||||
userRepository := pg2.NewUserRepository(db, logger)
|
||||
nodeUsecase := usecase.NewNodeUsecase(nodeRepository, appRepository, ragRepository, userRepository, knowledgeBaseRepository, llmUsecase, ragService, logger, minioClient, modelRepository, authRepo)
|
||||
kbRepo := cache2.NewKBRepo(cacheCache)
|
||||
knowledgeBaseUsecase, err := usecase.NewKnowledgeBaseUsecase(knowledgeBaseRepository, nodeRepository, ragRepository, userRepository, ragService, kbRepo, logger, configConfig)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -3616,7 +3616,19 @@ const docTemplate = `{
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/v1.ShareNodeDetailResp"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7379,6 +7391,18 @@ const docTemplate = `{
|
|||
"is_open": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"recommend_node_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"recommend_questions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"theme_mode": {
|
||||
"type": "string"
|
||||
}
|
||||
|
|
@ -8058,6 +8082,18 @@ const docTemplate = `{
|
|||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"editor_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"editor_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -8076,6 +8112,12 @@ const docTemplate = `{
|
|||
"permissions": {
|
||||
"$ref": "#/definitions/domain.NodePermissions"
|
||||
},
|
||||
"publisher_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"publisher_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/domain.NodeStatus"
|
||||
},
|
||||
|
|
@ -8180,6 +8222,62 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"v1.ShareNodeDetailResp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"editor_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"editor_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"kb_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/domain.NodeMeta"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"$ref": "#/definitions/domain.NodePermissions"
|
||||
},
|
||||
"publisher_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"publisher_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/domain.NodeStatus"
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/definitions/domain.NodeType"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1.StatCountResp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -3609,7 +3609,19 @@
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/v1.ShareNodeDetailResp"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7372,6 +7384,18 @@
|
|||
"is_open": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"recommend_node_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"recommend_questions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"theme_mode": {
|
||||
"type": "string"
|
||||
}
|
||||
|
|
@ -8051,6 +8075,18 @@
|
|||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"editor_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"editor_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -8069,6 +8105,12 @@
|
|||
"permissions": {
|
||||
"$ref": "#/definitions/domain.NodePermissions"
|
||||
},
|
||||
"publisher_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"publisher_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/domain.NodeStatus"
|
||||
},
|
||||
|
|
@ -8173,6 +8215,62 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"v1.ShareNodeDetailResp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"editor_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"editor_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"kb_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/domain.NodeMeta"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"$ref": "#/definitions/domain.NodePermissions"
|
||||
},
|
||||
"publisher_account": {
|
||||
"type": "string"
|
||||
},
|
||||
"publisher_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/domain.NodeStatus"
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/definitions/domain.NodeType"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1.StatCountResp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -2407,6 +2407,14 @@ definitions:
|
|||
type: string
|
||||
is_open:
|
||||
type: boolean
|
||||
recommend_node_ids:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
recommend_questions:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
theme_mode:
|
||||
type: string
|
||||
type: object
|
||||
|
|
@ -2852,6 +2860,14 @@ definitions:
|
|||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
creator_account:
|
||||
type: string
|
||||
creator_id:
|
||||
type: string
|
||||
editor_account:
|
||||
type: string
|
||||
editor_id:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
kb_id:
|
||||
|
|
@ -2864,6 +2880,10 @@ definitions:
|
|||
type: string
|
||||
permissions:
|
||||
$ref: '#/definitions/domain.NodePermissions'
|
||||
publisher_account:
|
||||
type: string
|
||||
publisher_id:
|
||||
type: string
|
||||
status:
|
||||
$ref: '#/definitions/domain.NodeStatus'
|
||||
type:
|
||||
|
|
@ -2935,6 +2955,43 @@ definitions:
|
|||
- id
|
||||
- new_password
|
||||
type: object
|
||||
v1.ShareNodeDetailResp:
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
creator_account:
|
||||
type: string
|
||||
creator_id:
|
||||
type: string
|
||||
editor_account:
|
||||
type: string
|
||||
editor_id:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
kb_id:
|
||||
type: string
|
||||
meta:
|
||||
$ref: '#/definitions/domain.NodeMeta'
|
||||
name:
|
||||
type: string
|
||||
parent_id:
|
||||
type: string
|
||||
permissions:
|
||||
$ref: '#/definitions/domain.NodePermissions'
|
||||
publisher_account:
|
||||
type: string
|
||||
publisher_id:
|
||||
type: string
|
||||
status:
|
||||
$ref: '#/definitions/domain.NodeStatus'
|
||||
type:
|
||||
$ref: '#/definitions/domain.NodeType'
|
||||
updated_at:
|
||||
type: string
|
||||
type: object
|
||||
v1.StatCountResp:
|
||||
properties:
|
||||
conversation_count:
|
||||
|
|
@ -5208,7 +5265,12 @@ paths:
|
|||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/domain.Response'
|
||||
allOf:
|
||||
- $ref: '#/definitions/domain.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/v1.ShareNodeDetailResp'
|
||||
type: object
|
||||
summary: GetNodeDetail
|
||||
tags:
|
||||
- share_node
|
||||
|
|
|
|||
|
|
@ -380,10 +380,12 @@ type FooterSettings struct {
|
|||
}
|
||||
|
||||
type WidgetBotSettings struct {
|
||||
IsOpen bool `json:"is_open,omitempty"`
|
||||
ThemeMode string `json:"theme_mode,omitempty"`
|
||||
BtnText string `json:"btn_text,omitempty"`
|
||||
BtnLogo string `json:"btn_logo,omitempty"`
|
||||
IsOpen bool `json:"is_open,omitempty"`
|
||||
ThemeMode string `json:"theme_mode,omitempty"`
|
||||
BtnText string `json:"btn_text,omitempty"`
|
||||
BtnLogo string `json:"btn_logo,omitempty"`
|
||||
RecommendQuestions []string `json:"recommend_questions,omitempty"`
|
||||
RecommendNodeIDs []string `json:"recommend_node_ids,omitempty"`
|
||||
}
|
||||
|
||||
type BrandGroup struct {
|
||||
|
|
|
|||
|
|
@ -129,6 +129,10 @@ type KBReleaseNodeRelease struct {
|
|||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
func (KBReleaseNodeRelease) TableName() string {
|
||||
return "kb_release_node_releases"
|
||||
}
|
||||
|
||||
type CreateKBReleaseReq struct {
|
||||
KBID string `json:"kb_id" validate:"required"`
|
||||
Message string `json:"message" validate:"required"`
|
||||
|
|
|
|||
|
|
@ -279,10 +279,12 @@ type GetRecommendNodeListReq struct {
|
|||
|
||||
// table: node_releases
|
||||
type NodeRelease struct {
|
||||
ID string `json:"id" gorm:"primaryKey"`
|
||||
KBID string `json:"kb_id" gorm:"index"`
|
||||
NodeID string `json:"node_id" gorm:"index"`
|
||||
DocID string `json:"doc_id" gorm:"index"` // for rag service
|
||||
ID string `json:"id" gorm:"primaryKey"`
|
||||
KBID string `json:"kb_id" gorm:"index"`
|
||||
PublisherId string `json:"publisher_id"`
|
||||
EditorId string `json:"editor_id"`
|
||||
NodeID string `json:"node_id" gorm:"index"`
|
||||
DocID string `json:"doc_id" gorm:"index"` // for rag service
|
||||
|
||||
Type NodeType `json:"type"`
|
||||
|
||||
|
|
@ -312,3 +314,15 @@ type BatchMoveReq struct {
|
|||
KBID string `json:"kb_id" validate:"required"`
|
||||
ParentID string `json:"parent_id"`
|
||||
}
|
||||
|
||||
type NodeCreateInfo struct {
|
||||
ID string `json:"id"`
|
||||
Account string `json:"account"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
}
|
||||
|
||||
type NodeReleaseWithPublisher struct {
|
||||
ID string `json:"id" gorm:"primaryKey"`
|
||||
PublisherId string `json:"publisher_id"`
|
||||
PublisherAccount string `json:"publisher_account"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func (h *ShareNodeHandler) GetNodeList(c echo.Context) error {
|
|||
// @Param X-KB-ID header string true "kb id"
|
||||
// @Param id query string true "node id"
|
||||
// @Param format query string true "format"
|
||||
// @Success 200 {object} domain.Response
|
||||
// @Success 200 {object} domain.Response{data=v1.ShareNodeDetailResp}
|
||||
// @Router /share/v1/node/detail [get]
|
||||
func (h *ShareNodeHandler) GetNodeDetail(c echo.Context) error {
|
||||
kbID := c.Request().Header.Get("X-KB-ID")
|
||||
|
|
|
|||
|
|
@ -244,6 +244,12 @@ func (h *KnowledgeBaseHandler) DeleteKnowledgeBase(c echo.Context) error {
|
|||
// @Success 200 {object} domain.Response
|
||||
// @Router /api/v1/knowledge_base/release [post]
|
||||
func (h *KnowledgeBaseHandler) CreateKBRelease(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
authInfo := domain.GetAuthInfoFromCtx(ctx)
|
||||
if authInfo == nil {
|
||||
return h.NewResponseWithError(c, "authInfo not found in context", nil)
|
||||
}
|
||||
|
||||
req := &domain.CreateKBReleaseReq{}
|
||||
if err := c.Bind(req); err != nil {
|
||||
return h.NewResponseWithError(c, "request body is invalid", err)
|
||||
|
|
@ -252,7 +258,7 @@ func (h *KnowledgeBaseHandler) CreateKBRelease(c echo.Context) error {
|
|||
return h.NewResponseWithError(c, "validate request body failed", err)
|
||||
}
|
||||
|
||||
id, err := h.usecase.CreateKBRelease(c.Request().Context(), req)
|
||||
id, err := h.usecase.CreateKBRelease(ctx, req, authInfo.UserId)
|
||||
if err != nil {
|
||||
return h.NewResponseWithError(c, "create kb release failed", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ func (m *MigrationNodeVersion) Execute(tx *gorm.DB) error {
|
|||
Message: "release all old nodes",
|
||||
Tag: "init",
|
||||
NodeIDs: nodeIDs,
|
||||
})
|
||||
}, "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("create kb release failed: %w", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit e7bf0a030242425c83291b369770c113fd503a5a
|
||||
Subproject commit 1b0bb2ce039ac1d8352be941380872fcede5bf7a
|
||||
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/samber/lo/mutable"
|
||||
|
||||
v1 "github.com/chaitin/panda-wiki/api/node/v1"
|
||||
shareV1 "github.com/chaitin/panda-wiki/api/share/v1"
|
||||
"github.com/chaitin/panda-wiki/consts"
|
||||
"github.com/chaitin/panda-wiki/domain"
|
||||
"github.com/chaitin/panda-wiki/log"
|
||||
|
|
@ -258,8 +259,11 @@ func (r *NodeRepository) GetByID(ctx context.Context, id, kbId string) (*v1.Node
|
|||
var node *v1.NodeDetailResp
|
||||
if err := r.db.WithContext(ctx).
|
||||
Model(&domain.Node{}).
|
||||
Where("id = ?", id).
|
||||
Where("kb_id = ?", kbId).
|
||||
Select("nodes.*, creator.id as creator_id, creator.account as creator_account, editor.id as editor_id, editor.account as editor_account").
|
||||
Joins("left join users creator on creator.id = nodes.creator_id").
|
||||
Joins("left join users editor on editor.id = nodes.editor_id").
|
||||
Where("nodes.id = ?", id).
|
||||
Where("nodes.kb_id = ?", kbId).
|
||||
First(&node).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -425,6 +429,20 @@ func (r *NodeRepository) GetLatestNodeReleaseByNodeID(ctx context.Context, nodeI
|
|||
return nodeRelease, nil
|
||||
}
|
||||
|
||||
func (r *NodeRepository) GetLatestNodeReleaseWithPublishAccount(ctx context.Context, nodeID string) (*domain.NodeReleaseWithPublisher, error) {
|
||||
var nodeRelease *domain.NodeReleaseWithPublisher
|
||||
if err := r.db.WithContext(ctx).
|
||||
Model(&domain.NodeRelease{}).Debug().
|
||||
Select("node_releases.id, node_releases.publisher_id, users.account as publisher_account").
|
||||
Joins("left join users on users.id = node_releases.publisher_id").
|
||||
Where("node_releases.node_id = ?", nodeID).
|
||||
Order("node_releases.updated_at DESC").
|
||||
Find(&nodeRelease).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nodeRelease, nil
|
||||
}
|
||||
|
||||
// GetNodeReleaseWithDirPathByID gets a node release by ID and includes its directory path
|
||||
func (r *NodeRepository) GetNodeReleaseWithDirPathByID(ctx context.Context, id string) (*domain.NodeReleaseWithDirPath, error) {
|
||||
// First get the node release
|
||||
|
|
@ -672,7 +690,7 @@ func (r *NodeRepository) GetNodeReleaseListByKBID(ctx context.Context, kbID stri
|
|||
return nodes, nil
|
||||
}
|
||||
|
||||
func (r *NodeRepository) GetNodeReleaseDetailByKBIDAndID(ctx context.Context, kbID, id string) (*v1.NodeDetailResp, error) {
|
||||
func (r *NodeRepository) GetNodeReleaseDetailByKBIDAndID(ctx context.Context, kbID, id string) (*shareV1.ShareNodeDetailResp, error) {
|
||||
// get kb release
|
||||
var kbRelease *domain.KBRelease
|
||||
if err := r.db.WithContext(ctx).
|
||||
|
|
@ -683,16 +701,16 @@ func (r *NodeRepository) GetNodeReleaseDetailByKBIDAndID(ctx context.Context, kb
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var node *v1.NodeDetailResp
|
||||
var node *shareV1.ShareNodeDetailResp
|
||||
if err := r.db.WithContext(ctx).
|
||||
Model(&domain.KBReleaseNodeRelease{}).
|
||||
Select("node_releases.*, nodes.permissions, nodes.creator_id").
|
||||
Joins("LEFT JOIN node_releases ON node_releases.id = kb_release_node_releases.node_release_id").
|
||||
Joins("LEFT JOIN nodes ON nodes.id = kb_release_node_releases.node_id").
|
||||
Where("kb_release_node_releases.release_id = ?", kbRelease.ID).
|
||||
Where("node_releases.node_id = ?", id).
|
||||
Where("node_releases.kb_id = ?", kbID).
|
||||
Where("nodes.permissions->>'visitable' != ?", consts.NodeAccessPermClosed).
|
||||
Select("node_releases.*, nodes.permissions").
|
||||
First(&node).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -810,7 +828,7 @@ func (r *NodeRepository) TraverseNodesByCursor(ctx context.Context, callback fun
|
|||
}
|
||||
|
||||
// CreateNodeReleases create node releases
|
||||
func (r *NodeRepository) CreateNodeReleases(ctx context.Context, kbID string, nodeIDs []string) ([]string, error) {
|
||||
func (r *NodeRepository) CreateNodeReleases(ctx context.Context, kbID, userId string, nodeIDs []string) ([]string, error) {
|
||||
releaseIDs := make([]string, 0)
|
||||
if err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
// update node status to published and return node ids
|
||||
|
|
@ -829,17 +847,19 @@ func (r *NodeRepository) CreateNodeReleases(ctx context.Context, kbID string, no
|
|||
for i, updatedNode := range updatedNodes {
|
||||
// create node release
|
||||
nodeRelease := &domain.NodeRelease{
|
||||
ID: uuid.New().String(),
|
||||
KBID: kbID,
|
||||
NodeID: updatedNode.ID,
|
||||
Type: updatedNode.Type,
|
||||
Name: updatedNode.Name,
|
||||
Meta: updatedNode.Meta,
|
||||
Content: updatedNode.Content,
|
||||
ParentID: updatedNode.ParentID,
|
||||
Position: updatedNode.Position,
|
||||
CreatedAt: updatedNode.CreatedAt,
|
||||
UpdatedAt: time.Now(),
|
||||
ID: uuid.New().String(),
|
||||
KBID: kbID,
|
||||
PublisherId: userId,
|
||||
EditorId: updatedNode.EditorId,
|
||||
NodeID: updatedNode.ID,
|
||||
Type: updatedNode.Type,
|
||||
Name: updatedNode.Name,
|
||||
Meta: updatedNode.Meta,
|
||||
Content: updatedNode.Content,
|
||||
ParentID: updatedNode.ParentID,
|
||||
Position: updatedNode.Position,
|
||||
CreatedAt: updatedNode.CreatedAt,
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
nodeReleases[i] = nodeRelease
|
||||
releaseIDs = append(releaseIDs, nodeRelease.ID)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
|
||||
|
|
@ -113,6 +114,22 @@ func (r *UserRepository) ListUsers(ctx context.Context) ([]v1.UserListItemResp,
|
|||
return users, nil
|
||||
}
|
||||
|
||||
func (r *UserRepository) GetUsersAccountMap(ctx context.Context) (map[string]string, error) {
|
||||
var users []v1.UserListItemResp
|
||||
err := r.db.WithContext(ctx).
|
||||
Model(&domain.User{}).
|
||||
Find(&users).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := lo.SliceToMap(users, func(user v1.UserListItemResp) (string, string) {
|
||||
return user.ID, user.Account
|
||||
})
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (r *UserRepository) UpdateUserPassword(ctx context.Context, userID string, newPassword string) error {
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE node_releases DROP COLUMN IF EXISTS publisher_id;
|
||||
ALTER TABLE node_releases DROP COLUMN IF EXISTS editor_id;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE node_releases ADD COLUMN IF NOT EXISTS publisher_id text default '';
|
||||
ALTER TABLE node_releases ADD COLUMN IF NOT EXISTS editor_id text default '';
|
||||
|
|
@ -642,14 +642,14 @@ func (u *AppUsecase) GetWidgetAppInfo(ctx context.Context, kbID string) (*domain
|
|||
Icon: webApp.Settings.Icon,
|
||||
WelcomeStr: webApp.Settings.WelcomeStr,
|
||||
SearchPlaceholder: webApp.Settings.SearchPlaceholder,
|
||||
RecommendQuestions: webApp.Settings.RecommendQuestions,
|
||||
RecommendQuestions: widgetApp.Settings.WidgetBotSettings.RecommendQuestions,
|
||||
WidgetBotSettings: widgetApp.Settings.WidgetBotSettings,
|
||||
},
|
||||
}
|
||||
if len(webApp.Settings.RecommendNodeIDs) > 0 {
|
||||
if len(widgetApp.Settings.WidgetBotSettings.RecommendNodeIDs) > 0 {
|
||||
nodes, err := u.nodeUsecase.GetRecommendNodeList(ctx, &domain.GetRecommendNodeListReq{
|
||||
KBID: kbID,
|
||||
NodeIDs: webApp.Settings.RecommendNodeIDs,
|
||||
NodeIDs: widgetApp.Settings.WidgetBotSettings.RecommendNodeIDs,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -146,10 +146,10 @@ func (u *KnowledgeBaseUsecase) DeleteKnowledgeBase(ctx context.Context, kbID str
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *KnowledgeBaseUsecase) CreateKBRelease(ctx context.Context, req *domain.CreateKBReleaseReq) (string, error) {
|
||||
func (u *KnowledgeBaseUsecase) CreateKBRelease(ctx context.Context, req *domain.CreateKBReleaseReq, userId string) (string, error) {
|
||||
if len(req.NodeIDs) > 0 {
|
||||
// create published nodes
|
||||
releaseIDs, err := u.nodeRepo.CreateNodeReleases(ctx, req.KBID, req.NodeIDs)
|
||||
releaseIDs, err := u.nodeRepo.CreateNodeReleases(ctx, req.KBID, userId, req.NodeIDs)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create published nodes: %w", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
"gorm.io/gorm"
|
||||
|
||||
v1 "github.com/chaitin/panda-wiki/api/node/v1"
|
||||
shareV1 "github.com/chaitin/panda-wiki/api/share/v1"
|
||||
"github.com/chaitin/panda-wiki/consts"
|
||||
"github.com/chaitin/panda-wiki/domain"
|
||||
"github.com/chaitin/panda-wiki/log"
|
||||
|
|
@ -31,6 +32,7 @@ type NodeUsecase struct {
|
|||
ragRepo *mq.RAGRepository
|
||||
kbRepo *pg.KnowledgeBaseRepository
|
||||
modelRepo *pg.ModelRepository
|
||||
userRepo *pg.UserRepository
|
||||
authRepo *pg.AuthRepo
|
||||
llmUsecase *LLMUsecase
|
||||
logger *log.Logger
|
||||
|
|
@ -42,6 +44,7 @@ func NewNodeUsecase(
|
|||
nodeRepo *pg.NodeRepository,
|
||||
appRepo *pg.AppRepository,
|
||||
ragRepo *mq.RAGRepository,
|
||||
userRepo *pg.UserRepository,
|
||||
kbRepo *pg.KnowledgeBaseRepository,
|
||||
llmUsecase *LLMUsecase,
|
||||
ragService rag.RAGService,
|
||||
|
|
@ -57,6 +60,7 @@ func NewNodeUsecase(
|
|||
ragRepo: ragRepo,
|
||||
kbRepo: kbRepo,
|
||||
authRepo: authRepo,
|
||||
userRepo: userRepo,
|
||||
llmUsecase: llmUsecase,
|
||||
modelRepo: modelRepo,
|
||||
logger: logger.WithModule("usecase.node"),
|
||||
|
|
@ -87,6 +91,16 @@ func (u *NodeUsecase) GetNodeByKBID(ctx context.Context, id, kbId, format string
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeRelease, err := u.nodeRepo.GetLatestNodeReleaseWithPublishAccount(ctx, node.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if nodeRelease != nil {
|
||||
node.PublisherId = nodeRelease.PublisherId
|
||||
node.PublisherAccount = nodeRelease.PublisherAccount
|
||||
}
|
||||
|
||||
if node.Meta.ContentType == domain.ContentTypeMD {
|
||||
return node, nil
|
||||
}
|
||||
|
|
@ -169,11 +183,26 @@ func (u *NodeUsecase) ValidateNodePerm(ctx context.Context, kbID, nodeId string,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *NodeUsecase) GetNodeReleaseDetailByKBIDAndID(ctx context.Context, kbID, nodeId, format string) (*v1.NodeDetailResp, error) {
|
||||
func (u *NodeUsecase) GetNodeReleaseDetailByKBIDAndID(ctx context.Context, kbID, nodeId, format string) (*shareV1.ShareNodeDetailResp, error) {
|
||||
node, err := u.nodeRepo.GetNodeReleaseDetailByKBIDAndID(ctx, kbID, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userMap, err := u.userRepo.GetUsersAccountMap(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if account, ok := userMap[node.CreatorId]; ok {
|
||||
node.CreatorAccount = account
|
||||
}
|
||||
if account, ok := userMap[node.EditorId]; ok {
|
||||
node.EditorAccount = account
|
||||
}
|
||||
if account, ok := userMap[node.PublisherId]; ok {
|
||||
node.PublisherAccount = account
|
||||
}
|
||||
|
||||
if node.Meta.ContentType == domain.ContentTypeMD {
|
||||
return node, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue