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