Search Apps Documentation Source Content File Folder Download Copy Actions Download

permissions_validators_open.gno

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