tinyrelayfile
tinyrelay/internal/policy/access.go/

internal/policy/access.go raw
1package policy
2
3import (
4 "strings"
5
6 "github.com/FelineStateMachine/tinyrelay/internal/event"
7)
8
9type Access struct {
10 PubKeys []string
11 Role string
12 Member bool
13 Owner bool
14}
15
16// CanRead applies the read rule, kind blocks, private repository rules and
17// recipient addressing to one event.
18func CanRead(p Policy, e event.Event, a Access) bool {
19 if containsInt(p.BlockedKinds, e.Kind) {
20 return false
21 }
22 if !readRule(p, a) {
23 return false
24 }
25 if IsPrivateRepository(e) && (!p.Features.Grasp08 || p.Reads != "members") {
26 return false
27 }
28 if privateKind(e.Kind) {
29 return addressed(e, a)
30 }
31 return true
32}
33
34// IsPrivateRepository identifies a GRASP repository announcement carrying the
35// private=true marker. State events are associated with their announcement by
36// owner and identifier at the storage boundary.
37func IsPrivateRepository(e event.Event) bool {
38 if e.Kind != 30617 {
39 return false
40 }
41 for _, tag := range e.Tags {
42 if len(tag) >= 2 && tag[0] == "private" && strings.EqualFold(tag[1], "true") {
43 return true
44 }
45 }
46 return false
47}
48
49// CanWrite applies kind blocks, allowlists and the tenant write rule to one
50// event.
51func CanWrite(p Policy, e event.Event, a Access) bool {
52 if containsInt(p.BlockedKinds, e.Kind) {
53 return false
54 }
55 if len(p.AllowedKinds) > 0 && !containsInt(p.AllowedKinds, e.Kind) {
56 return false
57 }
58 switch p.Writes {
59 case "open":
60 return true
61 case "owner":
62 return a.Owner || (p.Owner != "" && e.PubKey == p.Owner)
63 case "allowlist":
64 return a.Member || a.Owner
65 case "wot":
66 return a.Member || a.Owner
67 default:
68 return false
69 }
70}
71
72func readRule(p Policy, a Access) bool {
73 switch p.Reads {
74 case "open":
75 return true
76 case "auth":
77 return len(a.PubKeys) > 0 || a.Owner
78 case "members":
79 return a.Member || a.Owner
80 default:
81 return false
82 }
83}
84
85func privateKind(kind int) bool { return kind == 4 || kind == 1059 }
86
87func addressed(e event.Event, a Access) bool {
88 if hasKey(a, e.PubKey) {
89 return true
90 }
91 for _, tag := range e.Tags {
92 if len(tag) >= 2 && strings.EqualFold(tag[0], "p") && hasKey(a, tag[1]) {
93 return true
94 }
95 }
96 return false
97}
98
99func hasKey(a Access, key string) bool {
100 for _, candidate := range a.PubKeys {
101 if candidate == key {
102 return true
103 }
104 }
105 return false
106}
107func containsInt(values []int, wanted int) bool {
108 for _, value := range values {
109 if value == wanted {
110 return true
111 }
112 }
113 return false
114}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs