Search Apps Documentation Source Content File Folder Download Copy Actions Download

boards.gno

4.39 Kb · 151 lines
  1package boards2
  2
  3import (
  4	"gno.land/p/gnoland/boards"
  5	"gno.land/p/gnoland/boards/exts/permissions"
  6	"gno.land/p/moul/realmpath"
  7	"gno.land/p/moul/txlink"
  8	"gno.land/p/nt/bptree/v0"
  9)
 10
 11const (
 12	realmPkgPath = "gno.land/r/gnoland/boards2/v1"
 13	gRealmPath   = "/r/gnoland/boards2/v1"
 14)
 15
 16var (
 17	// RealmLink contains Boards2 realm link.
 18	// It can be used to generate board TX links from other realms.
 19	RealmLink = txlink.Realm(realmPkgPath)
 20
 21	// RequiredAccountAmount contains the required account amount for open board interactions.
 22	// The amount requirement is not applied to members that were invited to an open board.
 23	// Amount is defined as ugnot.
 24	RequiredAccountAmount = int64(3_000_000_000)
 25
 26	// Notice contains an optional message that is displayed globally within the realm.
 27	Notice string
 28
 29	// Help contains optional Markdown with Boards2 realm help.
 30	Help string
 31)
 32
 33// TODO: Refactor globals in favor of a cleaner pattern
 34var (
 35	gListedBoardsByID bptree.BPTree // string(id) -> *boards.Board
 36	gInviteRequests   bptree.BPTree // string(board id) -> *bptree.BPTree(address -> time.Time)
 37	gBannedUsers      bptree.BPTree // string(board id) -> *bptree.BPTree(address -> time.Time)
 38	gLocked           struct {
 39		realm        bool
 40		realmMembers bool
 41	}
 42)
 43
 44var (
 45	gBoards         = boards.NewStorage()
 46	gBoardsSequence = boards.NewIdentifierGenerator()
 47	gPerms          = initRealmPermissions("g1rp7cmetn27eqlpjpc4vuusf8kaj746tysc0qgh") // GovDAO T1 multisig
 48)
 49
 50// initRealmPermissions returns the default realm permissions.
 51func initRealmPermissions(owners ...address) boards.Permissions {
 52	perms := permissions.New(
 53		permissions.UseSingleUserRole(),
 54		permissions.WithSuperRole(RoleOwner),
 55	)
 56	perms.AddRole(RoleAdmin, PermissionBoardCreate)
 57	for _, owner := range owners {
 58		perms.SetUserRoles(owner, RoleOwner)
 59	}
 60
 61	perms.ValidateFunc(PermissionBoardCreate, validateBasicBoardCreate)
 62	perms.ValidateFunc(PermissionMemberInvite, validateBasicMemberInvite)
 63	perms.ValidateFunc(PermissionRoleChange, validateBasicRoleChange)
 64	return perms
 65}
 66
 67// getInviteRequests returns invite requests for a board.
 68func getInviteRequests(boardID boards.ID) (_ *bptree.BPTree, found bool) {
 69	v, exists := gInviteRequests.Get(boardID.Key())
 70	if !exists {
 71		return nil, false
 72	}
 73	return v.(*bptree.BPTree), true
 74}
 75
 76// getBannedUsers returns banned users within a board.
 77func getBannedUsers(boardID boards.ID) (_ *bptree.BPTree, found bool) {
 78	v, exists := gBannedUsers.Get(boardID.Key())
 79	if !exists {
 80		return nil, false
 81	}
 82	return v.(*bptree.BPTree), true
 83}
 84
 85// mustGetBoardByName returns a board or panics when it's not found.
 86func mustGetBoardByName(name string) *boards.Board {
 87	board, found := gBoards.GetByName(name)
 88	if !found {
 89		panic("board does not exist with name: " + name)
 90	}
 91	return board
 92}
 93
 94// mustGetBoard returns a board or panics when it's not found.
 95func mustGetBoard(id boards.ID) *boards.Board {
 96	board, found := gBoards.Get(id)
 97	if !found {
 98		panic("board does not exist with ID: " + id.String())
 99	}
100	return board
101}
102
103// getThread returns a board thread.
104func getThread(board *boards.Board, threadID boards.ID) (*boards.Post, bool) {
105	thread, found := board.Threads.Get(threadID)
106	if !found {
107		// When thread is not found search it within hidden threads
108		meta := board.Meta.(*BoardMeta)
109		thread, found = meta.HiddenThreads.Get(threadID)
110	}
111	return thread, found
112}
113
114// getReply returns a thread comment or reply.
115func getReply(thread *boards.Post, replyID boards.ID) (*boards.Post, bool) {
116	meta := thread.Meta.(*ThreadMeta)
117	return meta.AllReplies.Get(replyID)
118}
119
120// mustGetThread returns a thread or panics when it's not found.
121func mustGetThread(board *boards.Board, threadID boards.ID) *boards.Post {
122	thread, found := getThread(board, threadID)
123	if !found {
124		panic("thread does not exist with ID: " + threadID.String())
125	}
126	return thread
127}
128
129// mustGetReply returns a reply or panics when it's not found.
130func mustGetReply(thread *boards.Post, replyID boards.ID) *boards.Post {
131	reply, found := getReply(thread, replyID)
132	if !found {
133		panic("reply does not exist with ID: " + replyID.String())
134	}
135	return reply
136}
137
138func mustGetPermissions(bid boards.ID) boards.Permissions {
139	if bid != 0 {
140		board := mustGetBoard(bid)
141		return board.Permissions
142	}
143	return gPerms
144}
145
146func parseRealmPath(path string) *realmpath.Request {
147	// Make sure request is using current realm path so paths can be parsed during Render
148	r := realmpath.Parse(path)
149	r.Realm = string(RealmLink)
150	return r
151}