-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathwhitelist.go
127 lines (104 loc) · 2.73 KB
/
whitelist.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main
import (
"encoding/json"
"errors"
"fmt"
"os"
"github.com/nbd-wtf/go-nostr"
)
type Whitelist map[string]string // { [user_pubkey]: [invited_by] }
func addToWhitelist(pubkey string, inviter string) error {
if !isPublicKeyInWhitelist(inviter) {
return fmt.Errorf("pubkey %s doesn't have permission to invite", inviter)
}
if !nostr.IsValidPublicKey(pubkey) {
return fmt.Errorf("pubkey invalid: %s", pubkey)
}
if isPublicKeyInWhitelist(pubkey) {
return fmt.Errorf("pubkey already in whitelist: %s", pubkey)
}
whitelist[pubkey] = inviter
return saveWhitelist()
}
func isPublicKeyInWhitelist(pubkey string) bool {
_, ok := whitelist[pubkey]
return ok
}
func hasInvitedAtLeast(ancestor string, target int) bool {
count := 0
for _, inviter := range whitelist {
if inviter == ancestor {
count++
}
if count >= target {
return true
}
}
return false
}
func isAncestorOf(ancestor string, target string) bool {
parent, ok := whitelist[target]
if !ok {
// parent is not in whitelist, this means this is a top-level user and can
// only be deleted by manually editing the users.json file
return false
}
if parent == ancestor {
// if the pubkey is the parent, that means it is an ancestor
return true
}
// otherwise we climb one degree up and test with the parent of the target
return isAncestorOf(ancestor, parent)
}
func removeFromWhitelist(target string, deleter string) error {
// check if this user is a descendant of the user who issued the delete command
if !isAncestorOf(deleter, target) {
return fmt.Errorf("insufficient permissions to delete this")
}
// if we got here that means we have permission to delete the target
delete(whitelist, target)
// delete all people who were invited by the target
removeDescendantsFromWhitelist(target)
return saveWhitelist()
}
func removeDescendantsFromWhitelist(ancestor string) {
for pubkey, inviter := range whitelist {
if inviter == ancestor {
delete(whitelist, pubkey)
removeDescendantsFromWhitelist(pubkey)
}
}
}
func loadWhitelist() error {
b, err := os.ReadFile(s.UserdataPath)
if err != nil {
// If the whitelist file does not exist, with RELAY_PUBKEY
if errors.Is(err, os.ErrNotExist) {
whitelist[s.RelayPubkey] = ""
jsonBytes, err := json.Marshal(&whitelist)
if err != nil {
return err
}
if err := os.WriteFile(s.UserdataPath, jsonBytes, 0644); err != nil {
return err
}
return nil
} else {
return err
}
}
if err := json.Unmarshal(b, &whitelist); err != nil {
return err
}
return nil
}
func saveWhitelist() error {
jsonBytes, err := json.Marshal(whitelist)
if err != nil {
return err
}
if err := os.WriteFile(s.UserdataPath, jsonBytes, 0644); err != nil {
return err
}
return nil
}