Skip to content

Commit

Permalink
chore(boards2): remove permission handlers (#3449)
Browse files Browse the repository at this point in the history
This approach doesn't make a lot of sense for the current
implementation, we can use default permissions methods instead.
  • Loading branch information
jeronimoalbi authored Jan 7, 2025
1 parent efbfd00 commit 3c41887
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 75 deletions.
4 changes: 1 addition & 3 deletions examples/gno.land/r/demo/boards2/board.gno
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,12 @@ func (board *Board) GetPostFormURL() string {

// TODO: This is a temporary implementation until the permissions and DAO mecahnics are defined
func createDefaultBoardPermissions(owner std.Address) *DefaultPermissions {
perms := NewDefaultPermissions(
return NewDefaultPermissions(
admindao.New(admindao.WithMember(owner)),
WithSuperRole(RoleOwner),
WithRole(RoleAdmin, PermissionMemberInvite),
// TODO: Finish assigning all roles and permissions
// WithRole(RoleModerator, permissions...),
WithUser(owner, RoleOwner),
)
perms.HandleFunc(PermissionMemberInvite, handleMemberInvite)
return perms
}
84 changes: 50 additions & 34 deletions examples/gno.land/r/demo/boards2/permission_default.gno
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,25 @@ import (

"gno.land/p/demo/avl"
"gno.land/p/demo/boards2/admindao"
)

type (
// PermissionsHandlerFunc defines a function to handle permission callbacks.
// Handlers are called by the `WithPermission()` method to execute callbacks
// when users have the permission assigned.
PermissionsHandlerFunc func(Permissions, Args, func(Args))

// DefaultPermissions manages users, roles and permissions.
DefaultPermissions struct {
superRole Role
dao *admindao.AdminDAO
handlers *avl.Tree // string(permission) -> PermissionsHandlerFunc
users *avl.Tree // string(std.Address) -> []Role
roles *avl.Tree // string(role) -> []Permission
}
"gno.land/r/demo/users"
)

// DefaultPermissions manages users, roles and permissions.
type DefaultPermissions struct {
superRole Role
dao *admindao.AdminDAO
users *avl.Tree // string(std.Address) -> []Role
roles *avl.Tree // string(role) -> []Permission
}

// NewDefaultPermissions creates a new permissions type.
// This type is a default implementation to handle users, roles and permissions.
func NewDefaultPermissions(dao *admindao.AdminDAO, options ...DefaultPermissionsOption) *DefaultPermissions {
dp := &DefaultPermissions{
dao: dao,
handlers: avl.NewTree(),
roles: avl.NewTree(),
users: avl.NewTree(),
dao: dao,
roles: avl.NewTree(),
users: avl.NewTree(),
}
for _, apply := range options {
apply(dp)
Expand Down Expand Up @@ -124,11 +117,6 @@ func (dp *DefaultPermissions) RemoveUser(user std.Address) bool {
return removed
}

// HandleFunc registers a handler function for a permission.
func (dp *DefaultPermissions) HandleFunc(p Permission, fn PermissionsHandlerFunc) {
dp.handlers.Set(string(p), fn)
}

// WithPermission calls a callback when a user has a specific permission.
// It panics on error or when a handler panics.
// Callbacks are by default called when there is no handle registered for the permission.
Expand All @@ -137,28 +125,56 @@ func (dp *DefaultPermissions) WithPermission(user std.Address, perm Permission,
panic("unauthorized")
}

h, found := dp.handlers.Get(string(perm))
if !found {
cb(args) // TODO: Should we fail instead?
return
switch perm {
case PermissionBoardCreate:
dp.handleBoardCreate(args, cb)
case PermissionMemberInvite:
dp.handleMemberInvite(args, cb)
default:
cb(args)
}
}

func (DefaultPermissions) handleBoardCreate(args Args, cb func(Args)) {
// TODO: This way of dealing with arguments is delicate, ideally types should be used
name := args[0].(string)
if std.Address(name).IsValid() {
panic("addresses are not allowed as board name")
}

// When the board name is the name of a registered user
// check that caller is the owner of the name.
caller := std.GetOrigCaller()
user := users.GetUserByName(name)
if user != nil && user.Address != caller {
panic("board name is a user name registered to a different user")
}

cb(args)
}

func (dp DefaultPermissions) handleMemberInvite(args Args, cb func(Args)) {
// Make sure that only owners invite other owners
role := args[1].(Role)
if role == RoleOwner {
caller := std.GetOrigCaller()
if !dp.HasRole(caller, RoleOwner) {
panic("only owners are allowed to invite other owners")
}
}

fn := h.(PermissionsHandlerFunc)
fn(dp, args, cb)
cb(args)
}

func createDefaultPermissions(owner std.Address) *DefaultPermissions {
// TODO: DAO should be a different realm or proposal and voting functions should be part of boards realm?
// Permissions and DAO mechanics should be discussed and improved. Add `GetDAO()` to `Permissions`??
perms := NewDefaultPermissions(
return NewDefaultPermissions(
admindao.New(admindao.WithMember(owner)),
WithSuperRole(RoleOwner),
WithRole(RoleAdmin, PermissionBoardCreate, PermissionMemberInvite),
// TODO: Finish assigning all roles and permissions
// WithRole(RoleModerator, permissions...),
WithUser(owner, RoleOwner),
)
perms.HandleFunc(PermissionBoardCreate, handleBoardCreate)
perms.HandleFunc(PermissionMemberInvite, handleMemberInvite)
return perms
}
38 changes: 0 additions & 38 deletions examples/gno.land/r/demo/boards2/permission_handlers.gno

This file was deleted.

0 comments on commit 3c41887

Please sign in to comment.