WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s

This commit is contained in:
yawan
2026-09-22 16:19:06 +08:00
commit f7fc992f57
3929 changed files with 1006607 additions and 0 deletions
@@ -0,0 +1,85 @@
package service
import (
"context"
"github.com/Tencent/WeKnora/internal/accesspolicy"
apperrors "github.com/Tencent/WeKnora/internal/errors"
"github.com/Tencent/WeKnora/internal/types"
)
func assetAdministrator(ctx context.Context) bool {
return types.IsSystemAdminFromContext(ctx) || types.TenantRoleFromContext(ctx).HasPermission(types.TenantRoleAdmin)
}
func assetOwnedByCaller(ctx context.Context, tenant uint64, owner string) bool {
current, ok := types.TenantIDFromContext(ctx)
if !ok || current == 0 || current != tenant {
return false
}
if assetAdministrator(ctx) {
return true
}
user, ok := types.UserIDFromContext(ctx)
return ok && user != "" && !types.IsSyntheticUserID(user) && owner != "" && owner == user
}
// CheckKnowledgeBaseCopyPermission is used before enqueueing and again by the
// worker. Jobs without a human initiator retain their internal tenant scope.
func CheckKnowledgeBaseCopyPermission(ctx context.Context, kb *types.KnowledgeBase) error {
tenant, ok := types.TenantIDFromContext(ctx)
if kb == nil || !ok || tenant == 0 || kb.TenantID != tenant {
return apperrors.NewForbiddenError("没有此知识库的复制权限")
}
if assetAdministrator(ctx) {
return nil
}
user, hasUser := types.UserIDFromContext(ctx)
if _, apiKey := types.TenantAPIKeyScopeFromContext(ctx); apiKey {
return types.AuthorizeTenantAPIKeyKnowledgeBases(ctx, kb.ID)
}
if !hasUser && accesspolicy.FromContext(ctx) == nil {
return nil
}
if user == "" || types.IsSyntheticUserID(user) || user != kb.CreatorID {
return apperrors.NewForbiddenError("共享知识库仅支持查看和使用,不能复制")
}
if snapshot := accesspolicy.FromContext(ctx); snapshot != nil && snapshot.NoExport["knowledge:"+kb.ID] {
return apperrors.NewForbiddenError("此知识库不允许复制或导出")
}
return nil
}
func nativeAgentReadable(ctx context.Context, agent *types.CustomAgent) bool {
if agent == nil {
return false
}
agent.EnsureDefaults()
tenant, ok := types.TenantIDFromContext(ctx)
if !agent.Enabled && !assetOwnedByCaller(ctx, agent.TenantID, agent.CreatedBy) {
return false
}
return ok && tenant != 0 && tenant == agent.TenantID &&
accesspolicy.Allowed(ctx, "agents.read") && accesspolicy.Readable(ctx, "agents", agent.ID, assetOwnedByCaller(ctx, tenant, agent.CreatedBy), agent.Visibility == "global" && agent.Enabled)
}
func nativeAgentExecutableDependency(ctx context.Context, agent *types.CustomAgent) bool {
if agent == nil {
return false
}
agent.EnsureDefaults()
return agent.Enabled && accesspolicy.CanExecuteDependency(ctx, agent.TenantID, "agents", agent.ID, agent.CreatedBy)
}
func instructionSkillReadable(ctx context.Context, skill *types.TenantSkillCatalogEntity) bool {
if skill == nil || !skill.InstructionOnly {
return false
}
skill.EnsureInstructionDefaults()
tenant, ok := types.TenantIDFromContext(ctx)
if !skill.Enabled && !assetOwnedByCaller(ctx, skill.TenantID, skill.CreatedBy) {
return false
}
return ok && tenant != 0 && tenant == skill.TenantID &&
accesspolicy.Allowed(ctx, "agents.read") && accesspolicy.Readable(ctx, "skills", skill.ID, assetOwnedByCaller(ctx, tenant, skill.CreatedBy), skill.Visibility == "global" && skill.Enabled)
}