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}