2025-04-29 06:03:47 +02:00
|
|
|
package domain
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2025-05-08 07:42:53 +02:00
|
|
|
|
|
|
|
"github.com/zitadel/zitadel/backend/v3/storage/eventstore"
|
2025-04-29 06:03:47 +02:00
|
|
|
)
|
|
|
|
|
2025-05-08 19:01:55 +02:00
|
|
|
// AddOrgCommand adds a new organization.
|
|
|
|
// I'm unsure if we should add the Admins here or if this should be a separate command.
|
2025-04-29 06:03:47 +02:00
|
|
|
type AddOrgCommand struct {
|
2025-05-08 07:42:53 +02:00
|
|
|
ID string `json:"id"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
Admins []*AddMemberCommand `json:"admins"`
|
2025-04-29 06:03:47 +02:00
|
|
|
}
|
|
|
|
|
2025-05-08 07:42:53 +02:00
|
|
|
func NewAddOrgCommand(name string, admins ...*AddMemberCommand) *AddOrgCommand {
|
2025-04-29 06:03:47 +02:00
|
|
|
return &AddOrgCommand{
|
|
|
|
Name: name,
|
|
|
|
Admins: admins,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-08 15:30:06 +02:00
|
|
|
// String implements [Commander].
|
|
|
|
func (cmd *AddOrgCommand) String() string {
|
|
|
|
return "AddOrgCommand"
|
|
|
|
}
|
|
|
|
|
2025-04-29 06:03:47 +02:00
|
|
|
// Execute implements Commander.
|
|
|
|
func (cmd *AddOrgCommand) Execute(ctx context.Context, opts *CommandOpts) (err error) {
|
|
|
|
if len(cmd.Admins) == 0 {
|
|
|
|
return ErrNoAdminSpecified
|
|
|
|
}
|
|
|
|
if err = cmd.ensureID(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
close, err := opts.EnsureTx(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer func() { err = close(ctx, err) }()
|
|
|
|
err = orgRepo(opts.DB).Create(ctx, &Org{
|
|
|
|
ID: cmd.ID,
|
|
|
|
Name: cmd.Name,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2025-05-08 07:42:53 +02:00
|
|
|
for _, admin := range cmd.Admins {
|
|
|
|
admin.orgID = cmd.ID
|
|
|
|
if err = opts.Invoke(ctx, admin); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-08 15:30:06 +02:00
|
|
|
orgCache.Set(ctx, &Org{
|
|
|
|
ID: cmd.ID,
|
|
|
|
Name: cmd.Name,
|
|
|
|
})
|
|
|
|
|
2025-04-29 06:03:47 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2025-05-08 07:42:53 +02:00
|
|
|
// Events implements [eventer].
|
|
|
|
func (cmd *AddOrgCommand) Events() []*eventstore.Event {
|
|
|
|
return []*eventstore.Event{
|
|
|
|
{
|
|
|
|
AggregateType: "org",
|
|
|
|
AggregateID: cmd.ID,
|
|
|
|
Type: "org.added",
|
|
|
|
Payload: cmd,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-29 06:03:47 +02:00
|
|
|
var (
|
|
|
|
_ Commander = (*AddOrgCommand)(nil)
|
2025-05-08 07:42:53 +02:00
|
|
|
_ eventer = (*AddOrgCommand)(nil)
|
2025-04-29 06:03:47 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func (cmd *AddOrgCommand) ensureID() (err error) {
|
|
|
|
if cmd.ID != "" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
cmd.ID, err = generateID()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2025-05-08 19:01:55 +02:00
|
|
|
// AddMemberCommand adds a new member to an organization.
|
|
|
|
// I'm not sure if we should make it more generic to also use it for instances.
|
2025-05-08 07:42:53 +02:00
|
|
|
type AddMemberCommand struct {
|
|
|
|
orgID string
|
2025-04-29 06:03:47 +02:00
|
|
|
UserID string `json:"userId"`
|
|
|
|
Roles []string `json:"roles"`
|
|
|
|
}
|
|
|
|
|
2025-05-08 15:30:06 +02:00
|
|
|
func NewAddMemberCommand(userID string, roles ...string) *AddMemberCommand {
|
|
|
|
return &AddMemberCommand{
|
|
|
|
UserID: userID,
|
|
|
|
Roles: roles,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// String implements [Commander].
|
|
|
|
func (cmd *AddMemberCommand) String() string {
|
|
|
|
return "AddMemberCommand"
|
|
|
|
}
|
|
|
|
|
2025-04-29 06:03:47 +02:00
|
|
|
// Execute implements Commander.
|
2025-05-08 07:42:53 +02:00
|
|
|
func (a *AddMemberCommand) Execute(ctx context.Context, opts *CommandOpts) (err error) {
|
2025-04-29 06:03:47 +02:00
|
|
|
close, err := opts.EnsureTx(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer func() { err = close(ctx, err) }()
|
2025-05-08 07:42:53 +02:00
|
|
|
|
|
|
|
return orgRepo(opts.DB).Member().AddMember(ctx, a.orgID, a.UserID, a.Roles)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Events implements [eventer].
|
|
|
|
func (a *AddMemberCommand) Events() []*eventstore.Event {
|
|
|
|
return []*eventstore.Event{
|
|
|
|
{
|
|
|
|
AggregateType: "org",
|
|
|
|
AggregateID: a.UserID,
|
|
|
|
Type: "member.added",
|
|
|
|
Payload: a,
|
|
|
|
},
|
|
|
|
}
|
2025-04-29 06:03:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
2025-05-08 07:42:53 +02:00
|
|
|
_ Commander = (*AddMemberCommand)(nil)
|
|
|
|
_ eventer = (*AddMemberCommand)(nil)
|
2025-04-29 06:03:47 +02:00
|
|
|
)
|