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