package accesspolicy import ( "context" "github.com/Tencent/WeKnora/internal/types" ) // Snapshot is loaded from the active workspace on each authenticated request. // An absent snapshot preserves native service behavior for background jobs. type Snapshot struct { Restricted bool Permissions map[string]bool Publications map[string]bool Grants map[string]bool Hidden map[string]bool NoExport map[string]bool } func WithSnapshot(ctx context.Context, snapshot *Snapshot) context.Context { return context.WithValue(ctx, types.AccessPolicySnapshotContextKey, snapshot) } func FromContext(ctx context.Context) *Snapshot { value, _ := ctx.Value(types.AccessPolicySnapshotContextKey).(*Snapshot) return value } func Allowed(ctx context.Context, permission string) bool { s := FromContext(ctx) return s == nil || !s.Restricted || s.Permissions[permission] } // WorkbenchActionPermission is shared by request and queued-job authorization. func WorkbenchActionPermission(kind, action string) string { if kind == "flows" { return "flows.write" } if kind == "training-maps" { return "content.maps" } if kind == "content-tasks" && (action == "accept" || action == "skip" || action == "review" || action == "review-settings" || action == "compose") { return "content.review" } return "content.generate" } func Readable(ctx context.Context, kind, id string, owned, nativePublic bool) bool { if Hidden(ctx, kind, id) { return false } if owned { return true } s := FromContext(ctx) if s == nil { return nativePublic } resource := kind + ":" + id if global, managed := s.Publications[resource]; managed { return global || s.Grants[resource] } return nativePublic || s.Grants[resource] } func SharedIDs(ctx context.Context, kind string) []string { s := FromContext(ctx) if s == nil { return nil } ids := map[string]bool{} prefix := kind + ":" for key, enabled := range s.Publications { if enabled && len(key) > len(prefix) && key[:len(prefix)] == prefix { ids[key[len(prefix):]] = true } } for key, enabled := range s.Grants { if enabled && len(key) > len(prefix) && key[:len(prefix)] == prefix { ids[key[len(prefix):]] = true } } out := make([]string, 0, len(ids)) for id := range ids { if !s.Hidden[prefix+id] { out = append(out, id) } } return out } func Hidden(ctx context.Context, kind, id string) bool { s := FromContext(ctx) return s != nil && s.Hidden[kind+":"+id] } func HiddenIDs(ctx context.Context, kind string) []string { s := FromContext(ctx) if s == nil { return nil } result := []string{} prefix := kind + ":" for key, hidden := range s.Hidden { if hidden && len(key) > len(prefix) && key[:len(prefix)] == prefix { result = append(result, key[len(prefix):]) } } return result }