Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(examples): finalize acl package #2987

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
206 changes: 194 additions & 12 deletions examples/gno.land/p/demo/acl/acl.gno
Original file line number Diff line number Diff line change
Expand Up @@ -56,47 +56,229 @@ func (d *Directory) HasRole(addr std.Address, role string) bool {
return d.HasPerm(addr, "role", role)
}

func (d *Directory) AddUserPerm(addr std.Address, verb, resource string) {
func (d *Directory) AddUserPerm(addr std.Address, verb, resource string) bool {
bucket := "u:" + addr.String()
p := perm{
verbs: []string{verb},
resources: []string{resource},
}
d.addPermToBucket(bucket, p)
d.addPermsToBucket(bucket, []perm{p})
return true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useless returned value

}

func (d *Directory) AddGroupPerm(name string, verb, resource string) {
func (d *Directory) AddUserPerms(addr std.Address, verbs []string, resource string) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this helper should take multiple verbs AND resources, or multiple structs, not just multiple verbs.

bucket := "u:" + addr.String()
var ps perms
for _, verb := range verbs {
p := perm{
verbs: []string{verb},
resources: []string{resource},
}
ps = append(ps, p)
}
d.addPermsToBucket(bucket, ps)
return true
}

func (d *Directory) AddGroupPerm(name string, verb, resource string) bool {
bucket := "g:" + name
p := perm{
verbs: []string{verb},
resources: []string{resource},
}
d.addPermToBucket(bucket, p)
d.addPermsToBucket(bucket, []perm{p})
return true
}

func (d *Directory) addPermToBucket(bucket string, p perm) {
func (d *Directory) AddGroupPerms(name string, verbs []string, resource string) bool {
bucket := "g:" + name
var ps perms
for _, verb := range verbs {
p := perm{
verbs: []string{verb},
resources: []string{resource},
}
ps = append(ps, p)
}
d.addPermsToBucket(bucket, ps)
return true
}

func (d *Directory) addPermsToBucket(bucket string, p perms) {
var ps perms

existing, ok := d.permBuckets.Get(bucket)
if ok {
ps = existing.(perms)
}
ps = append(ps, p)
ps = ps.appendWithoutDuplicates(p)

d.permBuckets.Set(bucket, ps)
}

func (d *Directory) AddUserToGroup(user std.Address, group string) {
func (d *Directory) AddUserToGroup(user std.Address, group string) bool {
existing, ok := d.userGroups.Get(user.String())
var groups []string
if ok {
groups = existing.([]string)
}
groups = appendGroupsWithoutDuplicates(groups, []string{group})
d.userGroups.Set(user.String(), groups)
return true
}

func (d *Directory) AddUserToGroups(user std.Address, newGroups []string) bool {
existing, ok := d.userGroups.Get(user.String())
var groups []string
if ok {
groups = existing.([]string)
}
groups = append(groups, group)
groups = appendGroupsWithoutDuplicates(groups, newGroups)
d.userGroups.Set(user.String(), groups)
return true
}

func (d *Directory) RemoveUserFromGroup(user std.Address, group string) bool {
existing, ok := d.userGroups.Get(user.String())
if !ok {
return false
}
found := false
groups := existing.([]string)
for i, g := range groups {
if g == group {
groups = append(groups[:i], groups[i+1:]...)
found = true
break
}
}

if !found {
return false
}
if len(groups) == 0 {
d.userGroups.Remove(user.String())
} else {
d.userGroups.Set(user.String(), groups)
}
return true
}

func (d *Directory) RemoveUserFromGroups(user std.Address, groups []string) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this helper, just call RemoveUserFromGroup several times.

existing, ok := d.userGroups.Get(user.String())
if !ok {
return false
}
existingGroups := existing.([]string)

foundGroups := 0
for _, group := range groups {
for i, g := range existingGroups {
if g == group {
existingGroups = append(existingGroups[:i], existingGroups[i+1:]...)
foundGroups++
break
}
}
}

if foundGroups == 0 {
return false
}
if len(existingGroups) == 0 {
d.userGroups.Remove(user.String())
} else {
d.userGroups.Set(user.String(), existingGroups)
}
return foundGroups == len(groups)
}

func (d *Directory) removePermsFromBucket(bucket string, p []perm) bool {
Copy link
Member

@moul moul Feb 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should switch to a map or a tree instead of a slice.
most of the code is hard to read and gas inefficient. let's just change how we store the data.

edit: let's use a tree directly.

existing, ok := d.permBuckets.Get(bucket)
if !ok {
return false
}
ps := existing.(perms)

foundPerms := 0
for _, perm := range p {
for i, existingPerm := range ps {
if perm.Equal(existingPerm) {
ps = append(ps[:i], ps[i+1:]...)
foundPerms++
break
}
}
}

if foundPerms == 0 {
return false
}
if len(ps) == 0 {
d.permBuckets.Remove(bucket)
} else {
d.permBuckets.Set(bucket, ps)
}
return foundPerms == len(p)
}

func (d *Directory) RemoveUserPerm(addr std.Address, verb, resource string) bool {
bucket := "u:" + addr.String()
p := perm{
verbs: []string{verb},
resources: []string{resource},
}
return d.removePermsFromBucket(bucket, []perm{p})
}

func (d *Directory) RemoveUserPerms(addr std.Address, verbs []string, resource string) bool {
bucket := "u:" + addr.String()
var ps perms
for _, verb := range verbs {
p := perm{
verbs: []string{verb},
resources: []string{resource},
}
ps = append(ps, p)
}
return d.removePermsFromBucket(bucket, ps)
}

// TODO: helpers to remove permissions.
// TODO: helpers to adds multiple permissions at once -> {verbs: []string{"read","write"}}.
// TODO: helpers to delete users from gorups.
// TODO: helpers to quickly reset states.
func (d *Directory) RemoveGroupPerm(name string, verb, resource string) bool {
bucket := "g:" + name
p := perm{
verbs: []string{verb},
resources: []string{resource},
}
return d.removePermsFromBucket(bucket, []perm{p})
}

func (d *Directory) RemoveGroupPerms(name string, verbs []string, resource string) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bucket := "g:" + name
var ps perms
for _, verb := range verbs {
p := perm{
verbs: []string{verb},
resources: []string{resource},
}
ps = append(ps, p)
}
return d.removePermsFromBucket(bucket, ps)
}

func (d *Directory) ResetGroupPerms(name string) bool {
bucket := "g:" + name
d.permBuckets.Remove(bucket)
return true
}

func (d *Directory) ResetUserPerms(addr std.Address) bool {
bucket := "u:" + addr.String()
d.permBuckets.Remove(bucket)
return true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useless returned value

}

func (d *Directory) ResetUserGroups(addr std.Address) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invalid function name, the code isn't resetting a user group,but removing a specific address from a group

d.userGroups.Remove(addr.String())
return true
}
Loading
Loading