permissions_validators_open.gno
4.04 Kb · 164 lines
1package boards2
2
3import (
4 "chain/banker"
5 "errors"
6
7 "gno.land/p/gnoland/boards"
8 "gno.land/p/nt/ufmt/v0"
9)
10
11// validateOpenBoardRename validates PermissionBoardRename.
12//
13// Expected `args` values:
14// 1. Caller address
15// 2. Board ID
16// 3. Current board name
17// 4. New board name
18func validateOpenBoardRename(_ boards.Permissions, args boards.Args) error {
19 caller, ok := args[0].(address)
20 if !ok {
21 return errors.New("expected a valid caller address")
22 }
23
24 newName, ok := args[3].(string)
25 if !ok {
26 return errors.New("expected new board name to be a string")
27 }
28
29 if err := checkBoardNameIsNotAddress(newName); err != nil {
30 return err
31 }
32
33 if err := checkBoardNameBelongsToAddress(caller, newName); err != nil {
34 return err
35 }
36 return nil
37}
38
39// validateOpenMemberInvite validates PermissionMemberInvite.
40//
41// Expected `args` values:
42// 1. Caller address
43// 2. Board ID
44// 3. Invites
45func validateOpenMemberInvite(perms boards.Permissions, args boards.Args) error {
46 caller, ok := args[0].(address)
47 if !ok {
48 return errors.New("expected a valid caller address")
49 }
50
51 invites, ok := args[2].([]Invite)
52 if !ok {
53 return errors.New("expected valid user invites")
54 }
55
56 // Make sure that only owners invite other owners
57 callerIsOwner := perms.HasRole(caller, RoleOwner)
58 for _, v := range invites {
59 if v.Role == RoleOwner && !callerIsOwner {
60 return errors.New("only owners are allowed to invite other owners")
61 }
62 }
63 return nil
64}
65
66// validateOpenRoleChange validates PermissionRoleChange.
67//
68// Expected `args` values:
69// 1. Caller address
70// 2. Board ID
71// 3. Member address
72// 4. Role
73func validateOpenRoleChange(perms boards.Permissions, args boards.Args) error {
74 caller, ok := args[0].(address)
75 if !ok {
76 return errors.New("expected a valid caller address")
77 }
78
79 // Owners and Admins can change roles.
80 // Admins should not be able to assign or remove the Owner role from members.
81 if perms.HasRole(caller, RoleAdmin) {
82 role, ok := args[3].(boards.Role)
83 if !ok {
84 return errors.New("expected a valid member role")
85 }
86
87 if role == RoleOwner {
88 return errors.New("admins are not allowed to promote members to Owner")
89 } else {
90 member, ok := args[2].(address)
91 if !ok {
92 return errors.New("expected a valid member address")
93 }
94
95 if perms.HasRole(member, RoleOwner) {
96 return errors.New("admins are not allowed to remove the Owner role")
97 }
98 }
99 }
100 return nil
101}
102
103// validateOpenThreadCreate validates PermissionThreadCreate.
104//
105// Expected `args` values:
106// 1. Caller address
107// 2. Board ID
108// 3. Thread ID
109// 4. Title
110// 5. Body
111func validateOpenThreadCreate(perms boards.Permissions, args boards.Args) error {
112 caller, ok := args[0].(address)
113 if !ok {
114 return errors.New("expected a valid caller address")
115 }
116
117 // Owners and admins can create threads without special requirements
118 if perms.HasRole(caller, RoleOwner) || perms.HasRole(caller, RoleAdmin) {
119 return nil
120 }
121
122 // Require non members to have some GNOT in their accounts
123 if err := checkAccountHasAmount(caller, gOpenAccountAmount); err != nil {
124 return ufmt.Errorf("caller is not allowed to create threads: %s", err)
125 }
126 return nil
127}
128
129// validateOpenReplyCreate validates PermissionReplyCreate.
130//
131// Expected `args` values:
132// 1. Caller address
133// 2. Board ID
134// 3. Thread ID
135// 4. Parent ID
136// 5. Reply ID
137// 6. Body
138func validateOpenReplyCreate(perms boards.Permissions, args boards.Args) error {
139 caller, ok := args[0].(address)
140 if !ok {
141 return errors.New("expected a valid caller address")
142 }
143
144 // All board members can reply
145 if perms.HasUser(caller) {
146 return nil
147 }
148
149 // Require non members to have some GNOT in their accounts
150 if err := checkAccountHasAmount(caller, gOpenAccountAmount); err != nil {
151 return ufmt.Errorf("caller is not allowed to comment: %s", err)
152 }
153 return nil
154}
155
156func checkAccountHasAmount(addr address, amount int64) error {
157 bnk := banker.NewBanker(banker.BankerTypeReadonly)
158 coins := bnk.GetCoins(addr)
159 if coins.AmountOf("ugnot") < gOpenAccountAmount {
160 amount = amount / 1_000_000 // ugnot -> GNOT
161 return ufmt.Errorf("account amount is lower than %d GNOT", amount)
162 }
163 return nil
164}