public_invite.gno

3.60 Kb ยท 151 lines
  1package boards2
  2
  3import (
  4	"chain"
  5	"chain/runtime"
  6	"time"
  7
  8	"gno.land/p/nt/avl"
  9)
 10
 11// InviteMember adds a member to the realm or to a boards.
 12//
 13// A role can optionally be specified to be assigned to the new member.
 14// Board ID is only required when inviting a member to a board.
 15func InviteMember(_ realm, boardID BoardID, user address, role Role) {
 16	assertUserAddressIsValid(user)
 17	assertMembersUpdateIsEnabled(boardID)
 18
 19	perms := mustGetPermissions(boardID)
 20	if perms.HasUser(user) {
 21		panic("user is already a member")
 22	}
 23
 24	caller := runtime.PreviousRealm().Address()
 25	args := Args{boardID, user, role}
 26	perms.WithPermission(caller, PermissionMemberInvite, args, func(Args) {
 27		assertMembersUpdateIsEnabled(boardID)
 28
 29		if perms.HasUser(user) {
 30			panic("user is already a member")
 31		}
 32
 33		if err := perms.SetUserRoles(user, role); err != nil {
 34			panic(err)
 35		}
 36
 37		chain.Emit(
 38			"MemberInvited",
 39			"invitedBy", caller.String(),
 40			"boardID", boardID.String(),
 41			"user", user.String(),
 42			"role", string(role),
 43		)
 44	})
 45}
 46
 47// RequestInvite request to be invited to a board.
 48func RequestInvite(_ realm, boardID BoardID) {
 49	assertMembersUpdateIsEnabled(boardID)
 50
 51	if !runtime.PreviousRealm().IsUser() {
 52		panic("caller must be user")
 53	}
 54
 55	// TODO: Request a fee (returned on accept) or registered user to avoid spam?
 56
 57	board := mustGetBoard(boardID)
 58	user := runtime.PreviousRealm().Address()
 59	if board.perms.HasUser(user) {
 60		panic("caller is already a member")
 61	}
 62
 63	invitee := user.String()
 64	requests, found := getInviteRequests(boardID)
 65	if !found {
 66		requests = avl.NewTree()
 67		requests.Set(invitee, time.Now())
 68		gInviteRequests.Set(boardID.Key(), requests)
 69		return
 70	}
 71
 72	if requests.Has(invitee) {
 73		panic("invite request already exists")
 74	}
 75
 76	requests.Set(invitee, time.Now())
 77}
 78
 79// AcceptInvite accepts a board invite request.
 80func AcceptInvite(_ realm, boardID BoardID, user address) {
 81	assertMembersUpdateIsEnabled(boardID)
 82	assertInviteRequestExists(boardID, user)
 83
 84	board := mustGetBoard(boardID)
 85	if board.perms.HasUser(user) {
 86		panic("user is already a member")
 87	}
 88
 89	caller := runtime.PreviousRealm().Address()
 90	args := Args{boardID, user, RoleGuest}
 91	board.perms.WithPermission(caller, PermissionMemberInvite, args, func(Args) {
 92		assertMembersUpdateIsEnabled(boardID)
 93
 94		invitee := user.String()
 95		requests, found := getInviteRequests(boardID)
 96		if !found || !requests.Has(invitee) {
 97			panic("invite request not found")
 98		}
 99
100		board := mustGetBoard(boardID)
101		if board.perms.HasUser(user) {
102			panic("user is already a member")
103		}
104
105		if err := board.perms.SetUserRoles(user); err != nil {
106			panic(err)
107		}
108
109		requests.Remove(invitee)
110
111		chain.Emit(
112			"MemberInvited",
113			"invitedBy", caller.String(),
114			"boardID", boardID.String(),
115			"user", user.String(),
116		)
117	})
118}
119
120// RevokeInvite revokes a board invite request.
121func RevokeInvite(_ realm, boardID BoardID, user address) {
122	assertInviteRequestExists(boardID, user)
123
124	board := mustGetBoard(boardID)
125	caller := runtime.PreviousRealm().Address()
126	args := Args{boardID, user, RoleGuest}
127	board.perms.WithPermission(caller, PermissionMemberInviteRevoke, args, func(Args) {
128		invitee := user.String()
129		requests, found := getInviteRequests(boardID)
130		if !found || !requests.Has(invitee) {
131			panic("invite request not found")
132		}
133
134		requests.Remove(invitee)
135
136		chain.Emit(
137			"InviteRevoked",
138			"revokedBy", caller.String(),
139			"boardID", boardID.String(),
140			"user", user.String(),
141		)
142	})
143}
144
145func assertInviteRequestExists(boardID BoardID, user address) {
146	invitee := user.String()
147	requests, found := getInviteRequests(boardID)
148	if !found || !requests.Has(invitee) {
149		panic("invite request not found")
150	}
151}