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

permissions_validators_open.gno

4.78 Kb · 191 lines
  1package boards2
  2
  3import (
  4	"chain/banker"
  5	"errors"
  6
  7	"gno.land/p/gnoland/boards/v0"
  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, RequiredAccountAmount); err != nil {
124		return ufmt.Errorf("caller is not allowed to create threads: %s", err)
125	}
126	return nil
127}
128
129// validateOpenThreadRepost validates PermissionThreadRepost.
130//
131// Expected `args` values:
132// 1. Caller address
133// 2. Board ID
134// 3. Thread ID
135// 4. Destination board ID
136// 5. Repost ID
137// 6. Title
138// 7. Body
139func validateOpenThreadRepost(perms boards.Permissions, args boards.Args) error {
140	caller, ok := args[0].(address)
141	if !ok {
142		return errors.New("expected a valid caller address")
143	}
144
145	// Owners and admins can repost threads without special requirements
146	if perms.HasRole(caller, RoleOwner) || perms.HasRole(caller, RoleAdmin) {
147		return nil
148	}
149
150	// Require non members to have some GNOT in their accounts
151	if err := checkAccountHasAmount(caller, RequiredAccountAmount); err != nil {
152		return ufmt.Errorf("caller is not allowed to repost threads: %s", err)
153	}
154	return nil
155}
156
157// validateOpenReplyCreate validates PermissionReplyCreate.
158//
159// Expected `args` values:
160// 1. Caller address
161// 2. Board ID
162// 3. Thread ID
163// 4. Parent ID
164// 5. Reply ID
165// 6. Body
166func validateOpenReplyCreate(perms boards.Permissions, args boards.Args) error {
167	caller, ok := args[0].(address)
168	if !ok {
169		return errors.New("expected a valid caller address")
170	}
171
172	// All board members can reply
173	if perms.HasUser(caller) {
174		return nil
175	}
176
177	// Require non members to have some GNOT in their accounts
178	if err := checkAccountHasAmount(caller, RequiredAccountAmount); err != nil {
179		return ufmt.Errorf("caller is not allowed to comment: %s", err)
180	}
181	return nil
182}
183
184func checkAccountHasAmount(addr address, amount int64) error {
185	bnk := banker.NewReadonlyBanker()
186	if bnk.GetCoin(addr, "ugnot") < RequiredAccountAmount {
187		amount = amount / 1_000_000 // ugnot -> GNOT
188		return ufmt.Errorf("account amount is lower than %d GNOT", amount)
189	}
190	return nil
191}