Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

boards.gno

4.49 Kb · 154 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/g1gsarxwyhnxfuug3lsys58rcpg7myrgmw3wuc2u/boards2/v1"
 13	gRealmPath   = "/r/g1gsarxwyhnxfuug3lsys58rcpg7myrgmw3wuc2u/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(
 48		"g1rp7cmetn27eqlpjpc4vuusf8kaj746tysc0qgh", // GovDAO T1 multisig
 49		"g1gsarxwyhnxfuug3lsys58rcpg7myrgmw3wuc2u",
 50	)
 51)
 52
 53// initRealmPermissions returns the default realm permissions.
 54func initRealmPermissions(owners ...address) boards.Permissions {
 55	perms := permissions.New(
 56		permissions.UseSingleUserRole(),
 57		permissions.WithSuperRole(RoleOwner),
 58	)
 59	perms.AddRole(RoleAdmin, PermissionBoardCreate)
 60	for _, owner := range owners {
 61		perms.SetUserRoles(owner, RoleOwner)
 62	}
 63
 64	perms.ValidateFunc(PermissionBoardCreate, validateBasicBoardCreate)
 65	perms.ValidateFunc(PermissionMemberInvite, validateBasicMemberInvite)
 66	perms.ValidateFunc(PermissionRoleChange, validateBasicRoleChange)
 67	return perms
 68}
 69
 70// getInviteRequests returns invite requests for a board.
 71func getInviteRequests(boardID boards.ID) (_ *bptree.BPTree, found bool) {
 72	v := gInviteRequests.Get(boardID.Key())
 73	if v == nil {
 74		return nil, false
 75	}
 76	return v.(*bptree.BPTree), true
 77}
 78
 79// getBannedUsers returns banned users within a board.
 80func getBannedUsers(boardID boards.ID) (_ *bptree.BPTree, found bool) {
 81	v := gBannedUsers.Get(boardID.Key())
 82	if v == nil {
 83		return nil, false
 84	}
 85	return v.(*bptree.BPTree), true
 86}
 87
 88// mustGetBoardByName returns a board or panics when it's not found.
 89func mustGetBoardByName(name string) *boards.Board {
 90	board, found := gBoards.GetByName(name)
 91	if !found {
 92		panic("board does not exist with name: " + name)
 93	}
 94	return board
 95}
 96
 97// mustGetBoard returns a board or panics when it's not found.
 98func mustGetBoard(id boards.ID) *boards.Board {
 99	board, found := gBoards.Get(id)
100	if !found {
101		panic("board does not exist with ID: " + id.String())
102	}
103	return board
104}
105
106// getThread returns a board thread.
107func getThread(board *boards.Board, threadID boards.ID) (*boards.Post, bool) {
108	thread, found := board.Threads.Get(threadID)
109	if !found {
110		// When thread is not found search it within hidden threads
111		meta := board.Meta.(*BoardMeta)
112		thread, found = meta.HiddenThreads.Get(threadID)
113	}
114	return thread, found
115}
116
117// getReply returns a thread comment or reply.
118func getReply(thread *boards.Post, replyID boards.ID) (*boards.Post, bool) {
119	meta := thread.Meta.(*ThreadMeta)
120	return meta.AllReplies.Get(replyID)
121}
122
123// mustGetThread returns a thread or panics when it's not found.
124func mustGetThread(board *boards.Board, threadID boards.ID) *boards.Post {
125	thread, found := getThread(board, threadID)
126	if !found {
127		panic("thread does not exist with ID: " + threadID.String())
128	}
129	return thread
130}
131
132// mustGetReply returns a reply or panics when it's not found.
133func mustGetReply(thread *boards.Post, replyID boards.ID) *boards.Post {
134	reply, found := getReply(thread, replyID)
135	if !found {
136		panic("reply does not exist with ID: " + replyID.String())
137	}
138	return reply
139}
140
141func mustGetPermissions(bid boards.ID) boards.Permissions {
142	if bid != 0 {
143		board := mustGetBoard(bid)
144		return board.Permissions
145	}
146	return gPerms
147}
148
149func parseRealmPath(path string) *realmpath.Request {
150	// Make sure request is using current realm path so paths can be parsed during Render
151	r := realmpath.Parse(path)
152	r.Realm = string(RealmLink)
153	return r
154}