boards.gno
3.85 Kb ยท 142 lines
1package boards2
2
3import (
4 "chain/runtime"
5 "strings"
6
7 "gno.land/p/moul/realmpath"
8 "gno.land/p/moul/txlink"
9 "gno.land/p/nt/avl"
10)
11
12// TODO: Refactor globals in favor of a cleaner pattern
13var (
14 gPerms Permissions
15 gRealmLink txlink.Realm
16 gNotice string
17 gHelp string
18 gLastReservedID BoardID
19 gBoardsByID avl.Tree // string(id) -> *Board
20 gListedBoardsByID avl.Tree // string(id) -> *Board
21 gBoardsByName avl.Tree // string(lowercase name) -> *Board
22 gInviteRequests avl.Tree // string(board id) -> *avl.Tree(address -> time.Time)
23 gBannedUsers avl.Tree // string(board id) -> *avl.Tree(address -> time.Time)
24 gLocked struct {
25 realm bool
26 realmMembers bool
27 }
28)
29
30func init() {
31 // Save current realm path so it's available during render calls
32 gRealmLink = txlink.Realm(runtime.CurrentRealm().PkgPath())
33
34 // Initialize default realm permissions
35 gPerms = initRealmPermissions(
36 "g16jpf0puufcpcjkph5nxueec8etpcldz7zwgydq", // @devx
37 "g1manfred47kzduec920z88wfr64ylksmdcedlf5", // @moul
38 )
39}
40
41// initRealmPermissions returns the default realm permissions.
42func initRealmPermissions(owners ...address) *BasicPermissions {
43 perms := createBasicPermissions(owners...)
44 perms.ValidateFunc(PermissionBoardCreate, validateBoardCreate)
45 perms.ValidateFunc(PermissionMemberInvite, validateMemberInvite)
46 perms.ValidateFunc(PermissionRoleChange, validateRoleChange)
47 return perms
48}
49
50// reserveBoardID returns a new board ID which won't be used by another board.
51// Reserving IDs is necessary because boards can be created asynchronically.
52func reserveBoardID() BoardID {
53 gLastReservedID++
54 return gLastReservedID
55}
56
57// getBoard returns a board for a specific ID.
58func getBoard(id BoardID) (_ *Board, found bool) {
59 v, exists := gBoardsByID.Get(id.Key())
60 if !exists {
61 return nil, false
62 }
63 return v.(*Board), true
64}
65
66// getInvitesRequests returns invite requests for a board.
67func getInviteRequests(boardID BoardID) (_ *avl.Tree, found bool) {
68 v, exists := gInviteRequests.Get(boardID.Key())
69 if !exists {
70 return nil, false
71 }
72 return v.(*avl.Tree), true
73}
74
75// getBannedUsers returns banned users within a board.
76func getBannedUsers(boardID BoardID) (_ *avl.Tree, found bool) {
77 v, exists := gBannedUsers.Get(boardID.Key())
78 if !exists {
79 return nil, false
80 }
81 return v.(*avl.Tree), true
82}
83
84// getBoardByName returns a board that matches a name.
85func getBoardByName(name string) (_ *Board, found bool) {
86 name = strings.ToLower(name)
87 if v, found := gBoardsByName.Get(name); found {
88 return v.(*Board), true
89 }
90 return nil, false
91}
92
93// mustGetBoardByName returns a board or panics when it's not found.
94func mustGetBoardByName(name string) *Board {
95 board, found := getBoardByName(name)
96 if !found {
97 panic("board does not exist with name: " + name)
98 }
99 return board
100}
101
102// mustGetBoard returns a board or panics when it's not found.
103func mustGetBoard(id BoardID) *Board {
104 board, found := getBoard(id)
105 if !found {
106 panic("board does not exist with ID: " + id.String())
107 }
108 return board
109}
110
111// mustGetThread returns a thread or panics when it's not found.
112func mustGetThread(board *Board, threadID PostID) *Post {
113 thread, found := board.GetThread(threadID)
114 if !found {
115 panic("thread does not exist with ID: " + threadID.String())
116 }
117 return thread
118}
119
120// mustGetReply returns a reply or panics when it's not found.
121func mustGetReply(thread *Post, replyID PostID) *Post {
122 reply, found := thread.GetReply(replyID)
123 if !found {
124 panic("reply does not exist with ID: " + replyID.String())
125 }
126 return reply
127}
128
129func mustGetPermissions(bid BoardID) Permissions {
130 if bid != 0 {
131 board := mustGetBoard(bid)
132 return board.perms
133 }
134 return gPerms
135}
136
137func parseRealmPath(path string) *realmpath.Request {
138 // Make sure request is using current realm path so paths can be parsed during Render
139 r := realmpath.Parse(path)
140 r.Realm = string(gRealmLink)
141 return r
142}