mirror of https://github.com/chaitin/PandaWiki.git
Compare commits
2 Commits
704f5fd4f6
...
2f706a6100
| Author | SHA1 | Date |
|---|---|---|
|
|
2f706a6100 | |
|
|
febcb06654 |
|
|
@ -1,8 +1,6 @@
|
|||
package consts
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
|
|
@ -19,106 +17,7 @@ const (
|
|||
LicenseEditionBusiness LicenseEdition = 3 // 商业版
|
||||
)
|
||||
|
||||
type EditionLimitation struct {
|
||||
MaxKb int `json:"max_kb"` // 知识库站点数量
|
||||
MaxNode int `json:"max_node"` // 单个知识库下文档数量
|
||||
MaxSSOUser int `json:"max_sso_users"` // SSO认证用户数量
|
||||
MaxAdmin int64 `json:"max_admin"` // 后台管理员数量
|
||||
AllowAdminPerm bool `json:"allow_admin_perm"` // 支持管理员分权控制
|
||||
AllowCustomCopyright bool `json:"allow_custom_copyright"` // 支持自定义版权信息
|
||||
AllowAdvancedStats bool `json:"allow_advanced_stats"` // 支持高级访问流量分析
|
||||
AllowCustomPrompt bool `json:"allow_custom_prompt"` // 支持自定义AI提示词
|
||||
AllowContribute bool `json:"allow_contribute"` // 支持文档贡献
|
||||
AllowCommentAudit bool `json:"allow_comment_audit"` // 支持评论审核
|
||||
AllowAdvancedBot bool `json:"allow_advanced_bot"` // 支持高级机器人配置
|
||||
|
||||
AllowSSOAuth bool `json:"allow_sso_auth"` // 支持SSO登录
|
||||
AllowNodeUserPerm bool `json:"allow_node_user_perm"` // 支持文档访客权限控制
|
||||
AllowWatermark bool `json:"allow_watermark"` // 支持水印
|
||||
AllowCopyProtection bool `json:"allow_copy_protection"` // 支持内容复制保护
|
||||
AllowSensitiveFilter bool `json:"allow_sensitive_filter"` // 支持敏感内容过滤
|
||||
AllowNodeHistory bool `json:"allow_node_history"` // 支持管理文档历史版本数量
|
||||
AllowAPI bool `json:"allow_api"` // 支持api调用
|
||||
}
|
||||
|
||||
func GetLicenseEdition(c echo.Context) LicenseEdition {
|
||||
edition, _ := c.Get("edition").(LicenseEdition)
|
||||
return edition
|
||||
}
|
||||
|
||||
// GetLimitation 获取版本对应限制
|
||||
func (e LicenseEdition) GetLimitation() EditionLimitation {
|
||||
switch e {
|
||||
case LicenseEditionProfession:
|
||||
return EditionLimitation{
|
||||
MaxSSOUser: 0,
|
||||
MaxNode: 10000,
|
||||
MaxKb: 10,
|
||||
MaxAdmin: 20,
|
||||
AllowAdminPerm: true,
|
||||
AllowCustomCopyright: true,
|
||||
AllowAdvancedStats: true,
|
||||
AllowCustomPrompt: true,
|
||||
AllowCommentAudit: true,
|
||||
AllowContribute: true,
|
||||
AllowAdvancedBot: true,
|
||||
AllowSSOAuth: false,
|
||||
AllowNodeUserPerm: false,
|
||||
AllowWatermark: false,
|
||||
AllowCopyProtection: false,
|
||||
AllowSensitiveFilter: false,
|
||||
AllowNodeHistory: false,
|
||||
AllowAPI: false,
|
||||
}
|
||||
case LicenseEditionBusiness:
|
||||
return EditionLimitation{
|
||||
MaxSSOUser: 2000,
|
||||
MaxNode: 10000,
|
||||
MaxKb: 10,
|
||||
MaxAdmin: 50,
|
||||
AllowAdminPerm: true,
|
||||
AllowCustomCopyright: true,
|
||||
AllowAdvancedStats: true,
|
||||
AllowCustomPrompt: true,
|
||||
AllowCommentAudit: true,
|
||||
AllowContribute: true,
|
||||
AllowAdvancedBot: true,
|
||||
AllowSSOAuth: true,
|
||||
AllowNodeUserPerm: true,
|
||||
AllowWatermark: true,
|
||||
AllowCopyProtection: true,
|
||||
AllowSensitiveFilter: true,
|
||||
AllowNodeHistory: true,
|
||||
AllowAPI: true,
|
||||
}
|
||||
case LicenseEditionEnterprise:
|
||||
return EditionLimitation{
|
||||
MaxSSOUser: math.MaxInt,
|
||||
MaxNode: math.MaxInt,
|
||||
MaxKb: math.MaxInt,
|
||||
MaxAdmin: math.MaxInt,
|
||||
AllowAdminPerm: true,
|
||||
AllowCustomCopyright: true,
|
||||
AllowAdvancedStats: true,
|
||||
AllowCustomPrompt: true,
|
||||
AllowCommentAudit: true,
|
||||
AllowContribute: true,
|
||||
AllowAdvancedBot: true,
|
||||
AllowSSOAuth: true,
|
||||
AllowNodeUserPerm: true,
|
||||
AllowWatermark: true,
|
||||
AllowCopyProtection: true,
|
||||
AllowSensitiveFilter: true,
|
||||
AllowNodeHistory: true,
|
||||
AllowAPI: true,
|
||||
}
|
||||
default:
|
||||
// LicenseEditionFree
|
||||
return EditionLimitation{
|
||||
MaxSSOUser: 0,
|
||||
MaxNode: 300,
|
||||
MaxKb: 1,
|
||||
MaxAdmin: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
const ContextKeyEditionLimitation contextKey = "edition_limitation"
|
||||
|
||||
type BaseEditionLimitation struct {
|
||||
MaxKb int `json:"max_kb"` // 知识库站点数量
|
||||
MaxNode int `json:"max_node"` // 单个知识库下文档数量
|
||||
MaxSSOUser int `json:"max_sso_users"` // SSO认证用户数量
|
||||
MaxAdmin int64 `json:"max_admin"` // 后台管理员数量
|
||||
AllowAdminPerm bool `json:"allow_admin_perm"` // 支持管理员分权控制
|
||||
AllowCustomCopyright bool `json:"allow_custom_copyright"` // 支持自定义版权信息
|
||||
AllowCommentAudit bool `json:"allow_comment_audit"` // 支持评论审核
|
||||
AllowAdvancedBot bool `json:"allow_advanced_bot"` // 支持高级机器人配置
|
||||
AllowWatermark bool `json:"allow_watermark"` // 支持水印
|
||||
AllowCopyProtection bool `json:"allow_copy_protection"` // 支持内容复制保护
|
||||
AllowOpenAIBotSettings bool `json:"allow_open_ai_bot_settings"` // 支持问答机器人
|
||||
}
|
||||
|
||||
var baseEditionLimitationDefault = BaseEditionLimitation{
|
||||
MaxKb: 1,
|
||||
MaxAdmin: 1,
|
||||
MaxNode: 300,
|
||||
}
|
||||
|
||||
func GetBaseEditionLimitation(c context.Context) BaseEditionLimitation {
|
||||
|
||||
edition, ok := c.Value(ContextKeyEditionLimitation).([]byte)
|
||||
if !ok {
|
||||
return baseEditionLimitationDefault
|
||||
}
|
||||
|
||||
var editionLimitation BaseEditionLimitation
|
||||
if err := json.Unmarshal(edition, &editionLimitation); err != nil {
|
||||
return baseEditionLimitationDefault
|
||||
}
|
||||
|
||||
return editionLimitation
|
||||
}
|
||||
|
|
@ -6,7 +6,6 @@ import (
|
|||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"github.com/chaitin/panda-wiki/consts"
|
||||
"github.com/chaitin/panda-wiki/domain"
|
||||
"github.com/chaitin/panda-wiki/handler"
|
||||
"github.com/chaitin/panda-wiki/log"
|
||||
|
|
@ -157,7 +156,7 @@ func (h *ShareCommentHandler) GetCommentList(c echo.Context) error {
|
|||
}
|
||||
|
||||
// 查询数据库获取所有评论-->0 所有, 1,2 为需要审核的评论
|
||||
commentsList, err := h.usecase.GetCommentListByNodeID(ctx, nodeID, consts.GetLicenseEdition(c))
|
||||
commentsList, err := h.usecase.GetCommentListByNodeID(ctx, nodeID)
|
||||
if err != nil {
|
||||
return h.NewResponseWithError(c, "failed to get comment list", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
v1 "github.com/chaitin/panda-wiki/api/kb/v1"
|
||||
"github.com/chaitin/panda-wiki/consts"
|
||||
"github.com/chaitin/panda-wiki/domain"
|
||||
)
|
||||
|
||||
// KBUserList
|
||||
|
|
@ -55,7 +56,7 @@ func (h *KnowledgeBaseHandler) KBUserInvite(c echo.Context) error {
|
|||
return h.NewResponseWithError(c, "validate request failed", err)
|
||||
}
|
||||
|
||||
if !consts.GetLicenseEdition(c).GetLimitation().AllowAdminPerm && req.Perm != consts.UserKBPermissionFullControl {
|
||||
if !domain.GetBaseEditionLimitation(c.Request().Context()).AllowAdminPerm && req.Perm != consts.UserKBPermissionFullControl {
|
||||
return h.NewResponseWithError(c, "当前版本不支持管理员分权控制", nil)
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +88,7 @@ func (h *KnowledgeBaseHandler) KBUserUpdate(c echo.Context) error {
|
|||
return h.NewResponseWithError(c, "validate request failed", err)
|
||||
}
|
||||
|
||||
if !consts.GetLicenseEdition(c).GetLimitation().AllowAdminPerm && req.Perm != consts.UserKBPermissionFullControl {
|
||||
if !domain.GetBaseEditionLimitation(c.Request().Context()).AllowAdminPerm && req.Perm != consts.UserKBPermissionFullControl {
|
||||
return h.NewResponseWithError(c, "当前版本不支持管理员分权控制", nil)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ func (h *KnowledgeBaseHandler) CreateKnowledgeBase(c echo.Context) error {
|
|||
return h.NewResponseWithError(c, "ports is required", nil)
|
||||
}
|
||||
|
||||
req.MaxKB = consts.GetLicenseEdition(c).GetLimitation().MaxKb
|
||||
req.MaxKB = domain.GetBaseEditionLimitation(c.Request().Context()).MaxKb
|
||||
|
||||
did, err := h.usecase.CreateKnowledgeBase(c.Request().Context(), &req)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ func (h *NodeHandler) CreateNode(c echo.Context) error {
|
|||
return h.NewResponseWithError(c, "validate request body failed", err)
|
||||
}
|
||||
|
||||
req.MaxNode = consts.GetLicenseEdition(c).GetLimitation().MaxNode
|
||||
req.MaxNode = domain.GetBaseEditionLimitation(ctx).MaxNode
|
||||
|
||||
id, err := h.usecase.Create(c.Request().Context(), req, authInfo.UserId)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ type AuthMiddleware interface {
|
|||
ValidateUserRole(role consts.UserRole) echo.MiddlewareFunc
|
||||
ValidateKBUserPerm(role consts.UserKBPermission) echo.MiddlewareFunc
|
||||
ValidateLicenseEdition(edition ...consts.LicenseEdition) echo.MiddlewareFunc
|
||||
ValidateLicenseEditionLimitation(f func(consts.EditionLimitation) bool) echo.MiddlewareFunc
|
||||
MustGetUserID(c echo.Context) (string, bool)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -219,20 +219,6 @@ func (m *JWTMiddleware) ValidateLicenseEdition(needEditions ...consts.LicenseEdi
|
|||
}
|
||||
}
|
||||
|
||||
func (m *JWTMiddleware) ValidateLicenseEditionLimitation(f func(consts.EditionLimitation) bool) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
if !f(consts.GetLicenseEdition(c).GetLimitation()) {
|
||||
return c.JSON(http.StatusForbidden, domain.PWResponse{
|
||||
Success: false,
|
||||
Message: "Validate EditionLimitation Failed",
|
||||
})
|
||||
}
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *JWTMiddleware) MustGetUserID(c echo.Context) (string, bool) {
|
||||
user, ok := c.Get("user").(*jwt.Token)
|
||||
if !ok || user == nil {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 7db7fe94c7a7511f5c7415b4776bf76d826e58bb
|
||||
Subproject commit bcf7e0f0bedb18f43cf36463ddb45ace6c1dbab9
|
||||
|
|
@ -300,8 +300,8 @@ func (r *AuthRepo) GetOrCreateAuth(ctx context.Context, auth *domain.Auth, sourc
|
|||
return err
|
||||
}
|
||||
|
||||
if int(count) >= licenseEdition.GetLimitation().MaxSSOUser {
|
||||
return fmt.Errorf("exceed max auth limit for kb %s, current count: %d, max limit: %d", auth.KBID, count, licenseEdition.GetLimitation().MaxSSOUser)
|
||||
if int(count) >= domain.GetBaseEditionLimitation(ctx).MaxSSOUser {
|
||||
return fmt.Errorf("exceed max auth limit for kb %s, current count: %d, max limit: %d", auth.KBID, count, domain.GetBaseEditionLimitation(ctx).MaxSSOUser)
|
||||
}
|
||||
|
||||
auth.LastLoginTime = time.Now()
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ func (r *CommentRepository) CreateComment(ctx context.Context, comment *domain.C
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *CommentRepository) GetCommentList(ctx context.Context, nodeID string, edition consts.LicenseEdition) ([]*domain.ShareCommentListItem, int64, error) {
|
||||
func (r *CommentRepository) GetCommentList(ctx context.Context, nodeID string) ([]*domain.ShareCommentListItem, int64, error) {
|
||||
// 按照时间排序来查询node_id的comments
|
||||
var comments []*domain.ShareCommentListItem
|
||||
query := r.db.WithContext(ctx).Model(&domain.Comment{}).Where("node_id = ?", nodeID)
|
||||
|
||||
if edition.GetLimitation().AllowCommentAudit {
|
||||
if domain.GetBaseEditionLimitation(ctx).AllowCommentAudit {
|
||||
query = query.Where("status = ?", domain.CommentStatusAccepted) //accepted
|
||||
}
|
||||
|
||||
|
|
@ -50,14 +50,14 @@ func (r *CommentRepository) GetCommentList(ctx context.Context, nodeID string, e
|
|||
|
||||
func (r *CommentRepository) GetCommentListByKbID(ctx context.Context, req *domain.CommentListReq, edition consts.LicenseEdition) ([]*domain.CommentListItem, int64, error) {
|
||||
comments := []*domain.CommentListItem{}
|
||||
query := r.db.Model(&domain.Comment{}).Where("comments.kb_id = ?", req.KbID)
|
||||
query := r.db.WithContext(ctx).Model(&domain.Comment{}).Where("comments.kb_id = ?", req.KbID)
|
||||
var count int64
|
||||
if req.Status == nil {
|
||||
if err := query.Count(&count).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
} else {
|
||||
if edition != consts.LicenseEditionFree {
|
||||
if domain.GetBaseEditionLimitation(ctx).AllowCommentAudit {
|
||||
query = query.Where("comments.status = ?", *req.Status)
|
||||
}
|
||||
// 按照时间排序来查询kb_id的comments ->reject pending accepted
|
||||
|
|
@ -84,7 +84,7 @@ func (r *CommentRepository) GetCommentListByKbID(ctx context.Context, req *domai
|
|||
|
||||
func (r *CommentRepository) DeleteCommentList(ctx context.Context, commentID []string) error {
|
||||
// 批量删除指定id的comment,获取删除的总的数量、
|
||||
query := r.db.Model(&domain.Comment{}).Where("id IN (?)", commentID)
|
||||
query := r.db.WithContext(ctx).Model(&domain.Comment{}).Where("id IN (?)", commentID)
|
||||
|
||||
if err := query.Delete(&domain.Comment{}).Error; err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -683,7 +683,7 @@ func (r *NodeRepository) GetNodeReleaseListByKBID(ctx context.Context, kbID stri
|
|||
Where("kb_release_node_releases.kb_id = ?", kbID).
|
||||
Where("kb_release_node_releases.release_id = ?", kbRelease.ID).
|
||||
Where("nodes.permissions->>'visible' != ?", consts.NodeAccessPermClosed).
|
||||
Select("node_releases.node_id as id, node_releases.name, node_releases.type, node_releases.parent_id, node_releases.position, node_releases.meta->>'emoji' as emoji, node_releases.updated_at, nodes.permissions").
|
||||
Select("node_releases.node_id as id, node_releases.name, node_releases.type, node_releases.parent_id, nodes.position, node_releases.meta->>'emoji' as emoji, node_releases.updated_at, nodes.permissions").
|
||||
Find(&nodes).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ func (r *UserRepository) CreateUser(ctx context.Context, user *domain.User, edit
|
|||
if err := tx.Model(&domain.User{}).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if count >= edition.GetLimitation().MaxAdmin {
|
||||
return fmt.Errorf("exceed max admin limit, current count: %d, max limit: %d", count, edition.GetLimitation().MaxAdmin)
|
||||
if count >= domain.GetBaseEditionLimitation(ctx).MaxAdmin {
|
||||
return fmt.Errorf("exceed max admin limit, current count: %d, max limit: %d", count, domain.GetBaseEditionLimitation(ctx).MaxAdmin)
|
||||
}
|
||||
|
||||
if err := tx.Create(user).Error; err != nil {
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ func (u *AppUsecase) ValidateUpdateApp(ctx context.Context, id string, req *doma
|
|||
return err
|
||||
}
|
||||
|
||||
limitation := edition.GetLimitation()
|
||||
limitation := domain.GetBaseEditionLimitation(ctx)
|
||||
if !limitation.AllowCopyProtection && app.Settings.CopySetting != req.Settings.CopySetting {
|
||||
return domain.ErrPermissionDenied
|
||||
}
|
||||
|
|
@ -104,10 +104,6 @@ func (u *AppUsecase) ValidateUpdateApp(ctx context.Context, id string, req *doma
|
|||
}
|
||||
}
|
||||
|
||||
if !limitation.AllowContribute && app.Settings.ContributeSettings != req.Settings.ContributeSettings {
|
||||
return domain.ErrPermissionDenied
|
||||
}
|
||||
|
||||
if !limitation.AllowAdvancedBot {
|
||||
if !slices.Equal(app.Settings.WechatServiceContainKeywords, req.Settings.WechatServiceContainKeywords) ||
|
||||
!slices.Equal(app.Settings.WechatServiceEqualKeywords, req.Settings.WechatServiceEqualKeywords) {
|
||||
|
|
@ -119,6 +115,11 @@ func (u *AppUsecase) ValidateUpdateApp(ctx context.Context, id string, req *doma
|
|||
return domain.ErrPermissionDenied
|
||||
}
|
||||
|
||||
if !limitation.AllowOpenAIBotSettings {
|
||||
if app.Settings.OpenAIAPIBotSettings.IsEnabled != req.Settings.OpenAIAPIBotSettings.IsEnabled || app.Settings.OpenAIAPIBotSettings.SecretKey != req.Settings.OpenAIAPIBotSettings.SecretKey {
|
||||
return domain.ErrPermissionDenied
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -621,9 +622,8 @@ func (u *AppUsecase) ShareGetWebAppInfo(ctx context.Context, kbID string, authId
|
|||
}
|
||||
showBrand := true
|
||||
defaultDisclaimer := "本回答由 PandaWiki 基于 AI 生成,仅供参考。"
|
||||
licenseEdition, _ := ctx.Value(consts.ContextKeyEdition).(consts.LicenseEdition)
|
||||
|
||||
if !licenseEdition.GetLimitation().AllowCustomCopyright {
|
||||
if !domain.GetBaseEditionLimitation(ctx).AllowCustomCopyright {
|
||||
appInfo.Settings.WebAppCustomSettings.ShowBrandInfo = &showBrand
|
||||
appInfo.Settings.DisclaimerSettings.Content = &defaultDisclaimer
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ func (u *CommentUsecase) CreateComment(ctx context.Context, commentReq *domain.C
|
|||
return CommentStr, nil
|
||||
}
|
||||
|
||||
func (u *CommentUsecase) GetCommentListByNodeID(ctx context.Context, nodeID string, edition consts.LicenseEdition) (*domain.PaginatedResult[[]*domain.ShareCommentListItem], error) {
|
||||
comments, total, err := u.CommentRepo.GetCommentList(ctx, nodeID, edition)
|
||||
func (u *CommentUsecase) GetCommentListByNodeID(ctx context.Context, nodeID string) (*domain.PaginatedResult[[]*domain.ShareCommentListItem], error) {
|
||||
comments, total, err := u.CommentRepo.GetCommentList(ctx, nodeID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue