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

boards.gno

4.39 Kb · 151 lines
  1package boards2
  2
  3import (
  4	"gno.land/p/gnoland/boards/exts/permissions/v0"
  5	"gno.land/p/gnoland/boards/v0"
  6	"gno.land/p/moul/realmpath/v0"
  7	"gno.land/p/moul/txlink/v0"
  8	"gno.land/p/nt/bptree/v0"
  9)
 10
 11const (
 12	realmPkgPath = "gno.land/r/gnoland/boards2/v0"
 13	gRealmPath   = "/r/gnoland/boards2/v0"
 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("g1skl80cuz8zq3lul9pgz5pc35l2pfzgxgfpsqkx") // 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 := gInviteRequests.Get(boardID.Key())
 70	if v == nil {
 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 := gBannedUsers.Get(boardID.Key())
 79	if v == nil {
 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}