Search Apps Documentation Source Content File Folder Download Copy Actions Download

boards.gno

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