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

wip: implements r/sys/teams #3568

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions examples/gno.land/r/sys/teams/cmd.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package teams

import (
"errors"
"std"
"strings"
)

// XXX: Improve errors
var ErrAlreadyExist = errors.New("already exists")
var ErrDoesNotExist = errors.New("does not exist")

// Cmd represents a command that can be executed on a team.
type Cmd interface {
Name() string
}

type Cmds []Cmd

func (cmds Cmds) Name() string {
var str strings.Builder
str.WriteRune('[')
for i, cmd := range cmds {
if i > 0 {
str.WriteRune(',')
}

str.WriteString(cmd.Name())
}
str.WriteRune(']')
return str.String()
}

// AddMemberCmd represents a command to add a member to the team.
type AddMemberCmd struct {
Member std.Address
}

func (cmd AddMemberCmd) Name() string { return "AddMember" }

// AddMemberTask creates a task to add a member to the team.
func AddMemberTask(member std.Address) Task {
return CreateTask(func(t *Team) Cmd {
// Cannot add team address as a member
if t.IsTeamAddress(member) {
panic("cannot add team address as a member")
}

if t.members.Has(member.String()) {
panic(ErrAlreadyExist)
}
t.members.Set(member.String(), struct{}{})
return nil
})
}

// RemoveMemberCmd represents a command to remove a member from the team.
type RemoveMemberCmd struct {
Member std.Address
}

func (cmd RemoveMemberCmd) Name() string { return "RemoveMember" }

// RemoveMemberTask creates a task to remove a member from the team.
func RemoveMemberTask(member std.Address) Task {
return CreateTask(func(t *Team) Cmd {
if !t.members.Has(member.String()) {
panic(ErrDoesNotExist)
}
t.members.Remove(member.String())
return nil
})
}

// The command bellow should be use with precaution

// UpdateAccessControllerCmd represents a command to update the team's access controller.
type UpdateAccessControllerCmd struct {
AccessController
}

func (cmd UpdateAccessControllerCmd) Name() string { return "UpdateAccessController" }

// UpdateAccessControllerTask creates a task to update the team's access controller.
func UpdateAccessControllerTask(ac AccessController) Task {
return CreateTask(func(t *Team) Cmd {
t.AccessController = ac
return nil
})
}

// UpdateLifecycleCmd represents a command to update the team's access controller.
type UpdateLifecycleCmd struct {
Lifecycle
}

func (cmd UpdateLifecycleCmd) Name() string { return "UpdateLifecycle" }

// UpdateLifecycleTask creates a task to update the team's access controller.
func UpdateLifecycleTask(ac Lifecycle) Task {
return CreateTask(func(t *Team) Cmd {
t.Lifecycle = ac
return nil
})
}

// BurnTeamAddressCmd represents a command to burn the team's address.
type BurnTeamAddressCmd struct{}

func (cmd BurnTeamAddressCmd) Name() string { return "BurnTeamAddress" }

var BurnTeamAddressTask = CreateTaskCmd(BurnTeamAddressCmd{})

// AddPackageCmd represents a command to add a package to the team.
type AddPackageCmd struct {
Path string
}

func (cmd AddPackageCmd) Name() string { return "AddPackage" }
1 change: 1 addition & 0 deletions examples/gno.land/r/sys/teams/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/r/sys/teams
85 changes: 85 additions & 0 deletions examples/gno.land/r/sys/teams/task.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package teams

// TaskFunc defines a function type that takes a Team and returns a Cmd.
// It represents the executable logic that can be performed on a team.
type TaskFunc func(t *Team) Cmd

// Task represents a unit of work that can be executed to apply a command.
// Tasks encapsulate the execution logic of commands, ensuring that operations
// are performed with the correct permissions and in a specified order.
//
// Tasks are used to execute commands that modify the team's state, ensuring
// that these modifications adhere to the permissions set by the access control
// mechanisms and are executed in a controlled sequence.
type Task interface {
call(t *Team) Cmd
}

type task struct {
actionFunc TaskFunc
}

func (a task) call(t *Team) Cmd {
return a.actionFunc(t)
}

// CreateTaskCmd creates a Task from one or more commands.
func CreateTaskCmd(cmd ...Cmd) Task {
switch len(cmd) {
case 0:
return nil
case 1:
return CreateTask(func(_ *Team) Cmd {
return cmd[0]
})
default:
// Handle multiple commands
}

fns := make([]TaskFunc, len(cmd))
for i, m := range cmd {
fns[i] = func(_ *Team) Cmd {
return m
}
}
return CreateTask(fns...)
}

// CreateTask creates a Task from one or more TaskFuncs.
func CreateTask(fn ...TaskFunc) Task {
switch len(fn) {
case 0:
return nil
case 1:
return &task{actionFunc: fn[0]}
default:
// Handle multiple functions
}

actions := make([]Task, len(fn))
for i, f := range fn {
actions[i] = &task{actionFunc: f}
}
return ChainTasks(actions...)
}

// ChainTasks creates a single Task that executes a series of tasks in sequence.
// It combines multiple tasks into one.
func ChainTasks(actions ...Task) Task {
switch len(actions) {
case 0:
return nil
case 1:
return actions[0]
default:
// Handle chaining of multiple tasks
}

return CreateTask(func(t *Team) Cmd {
cmds := make([]Cmd, len(actions))
for i, action := range actions {
cmds[i] = action.call(t)
}
return Cmds(cmds)
})
}
Loading
Loading