Files

86 lines
3.2 KiB
Go
Raw Permalink Normal View History

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)
}