Skip to content

Group

Overview

The Group domain in comby is designed to manage groups within a tenant. Groups act as organizational units that can hold runtime permissions and serve as collections for identities. Each group belongs to a specific tenant and provides a structured way to manage permissions and membership. The domain is implemented through the Group aggregate, which models groups, handles domain events, and enforces business rules.

A Group always references only one Tenant; it is neither possible nor intended for a Group to be shared across multiple Tenants. In the comby default setup, the system Tenant always includes a System Group (named "system-admin"). This System Group is implemented with full rights across the system.

If an identity in the system Tenant is assigned to this Group, it can perform all actions and access all permissions within the system. This is also the reason why the System Group cannot be deleted.

Structure

The structure of a Group is simple and consists of the following elements:

  • Name: The name of the group, serving as a human-readable identifier.
  • Description: Additional context or information about the group.
  • Attributes: A map for storing additional metadata associated with the group.
  • Permissions: A list of runtime permissions assigned to the group, defining its access and capabilities.

Permissions are simple strings that can, for example, be assigned to a Group through the Admin Dashboard. comby automatically generates permissions for all commands and queries, ensuring seamless integration. If needed, these permissions can be overridden with custom logic. Example: Allowing user logins for anonymous users.

Commands

GroupCommandCreate

Domain Command Struct:

go
type GroupCommandCreate struct {
	GroupUuid   string   `json:"groupUuid"`
	Name        string   `json:"name"`
	Description string   `json:"description,omitempty"`
	Attributes  string   `json:"attributes,omitempty"`
	Permissions []string `json:"permissions,omitempty"`
}

Domain Command Handling Method:

go
func (cs *commandHandler) GroupCommandCreate(ctx context.Context, cmd comby.Command, domainCmd *GroupCommandCreate) ([]comby.Event, error)

GroupCommandRemove

Domain Command Struct:

go
type GroupCommandRemove struct {
	GroupUuid string `json:"groupUuid"`
}

Domain Command Handling Method:

go
func (cs *commandHandler) GroupCommandRemove(ctx context.Context, cmd comby.Command, domainCmd *GroupCommandRemove) ([]comby.Event, error)

GroupCommandRemoveAttribute

Domain Command Struct:

go
type GroupCommandRemoveAttribute struct {
	GroupUuid string `json:"groupUuid"`
	Key       string `json:"key"`
}

Domain Command Handling Method:

go
func (cs *commandHandler) GroupCommandRemoveAttribute(ctx context.Context, cmd comby.Command, domainCmd *GroupCommandRemoveAttribute) ([]comby.Event, error)

GroupCommandSetAttribute

Domain Command Struct:

go
type GroupCommandSetAttribute struct {
	GroupUuid string `json:"groupUuid"`
	Key       string `json:"key"`
	Value     any    `json:"value"`
}

Domain Command Handling Method:

go
func (cs *commandHandler) GroupCommandSetAttribute(ctx context.Context, cmd comby.Command, domainCmd *GroupCommandSetAttribute) ([]comby.Event, error)

GroupCommandUpdate

Domain Command Struct:

go
type GroupCommandUpdate struct {
	GroupUuid     string   `json:"groupUuid"`
	Name          string   `json:"name,omitempty"`
	Description   string   `json:"description,omitempty"`
	Attributes    string   `json:"attributes,omitempty"`
	Permissions   []string `json:"permissions,omitempty"`
	PatchedFields []string `json:"patchedFields" doc:"list of fields that should be patched - comma separated" example:"field1,field2"`
}

Domain Command Handling Method:

go
func (cs *commandHandler) GroupCommandUpdate(ctx context.Context, cmd comby.Command, domainCmd *GroupCommandUpdate) ([]comby.Event, error)

Queries

Domain Query Structs:

Domain Query Responses:

GroupQueryList

Domain Query Struct:

go
type GroupQueryList struct {
	TenantUuid string `json:"tenantUuid"`
	Page       int64  `json:"page,omitempty"`
	PageSize   int64  `json:"pageSize,omitempty"`
	OrderBy    string `json:"orderBy,omitempty"`
	Attributes string `json:"attributes,omitempty"`
}

Domain Query Handling Method:

go
func (qs *queryHandler) GroupQueryList(ctx context.Context, qry comby.Query, domainQry *GroupQueryList) (*GroupQueryListResponse, error)

GroupQueryModelByName

Domain Query Struct:

go
type GroupQueryModelByName struct {
	Name string `json:"name"`
}

Domain Query Handling Method:

go
func (qs *queryHandler) GroupQueryModelByName(ctx context.Context, qry comby.Query, domainQry *GroupQueryModelByName) (*GroupQueryItemResponse, error)

GroupQueryModel

Domain Query Struct:

go
type GroupQueryModel struct {
	GroupUuid string `json:"groupUuid"`
}

Domain Query Handling Method:

go
func (qs *queryHandler) GroupQueryModel(ctx context.Context, qry comby.Query, domainQry *GroupQueryModel) (*GroupQueryItemResponse, error)

GroupQueryListResponse

go
type GroupQueryListResponse struct {
	Items    []*readmodel.GroupModel `json:"items,omitempty"`
	Total    int64                   `json:"total,omitempty"`
	Page     int64                   `json:"page,omitempty"`
	PageSize int64                   `json:"pageSize,omitempty"`
}

GroupQueryItemResponse

go
type GroupQueryItemResponse struct {
	Item *readmodel.GroupModel `json:"item,omitempty"`
}

Events

GroupAddedEvent

Domain Event Struct:

go
type GroupAddedEvent struct {
	Name        string   `json:"name"`
	Description string   `json:"description,omitempty"`
	Attributes  string   `json:"attributes,omitempty"`
	Permissions []string `json:"permissions,omitempty"`
}

Domain Event Handling Method:

go
func (agg *Group) GroupAddedEvent(ctx context.Context, evt comby.Event, domainEvt *GroupAddedEvent) (error)

GroupRemovedEvent

Domain Event Struct:

go
type GroupRemovedEvent struct {
	Reason string `json:"reason,omitempty"`
}

Domain Event Handling Method:

go
func (agg *Group) GroupRemovedEvent(ctx context.Context, evt comby.Event, domainEvt *GroupRemovedEvent) (error)

GroupAttributeRemovedEvent

Domain Event Struct:

go
type GroupAttributeRemovedEvent struct {
	Key string `json:"key"`
}

Domain Event Handling Method:

go
func (agg *Group) GroupAttributeRemovedEvent(ctx context.Context, evt comby.Event, domainEvt *GroupAttributeRemovedEvent) (error)

GroupAttributeSetEvent

Domain Event Struct:

go
type GroupAttributeSetEvent struct {
	Key   string `json:"key"`
	Value any    `json:"value"`
}

Domain Event Handling Method:

go
func (agg *Group) GroupAttributeSetEvent(ctx context.Context, evt comby.Event, domainEvt *GroupAttributeSetEvent) (error)

GroupUpdatedEvent

Domain Event Struct:

go
type GroupUpdatedEvent struct {
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Attributes  string   `json:"attributes,omitempty"`
	Permissions []string `json:"permissions,omitempty"`
}

Domain Event Handling Method:

go
func (agg *Group) GroupUpdatedEvent(ctx context.Context, evt comby.Event, domainEvt *GroupUpdatedEvent) (error)

Aggregate

Aggregate Struct:

go
type Group struct {
	*comby.BaseAggregate
	// Value Objects
	Permissions []string
	Name        string
	Description string
}

Methods

Add

go
func (agg *Group) Add(name, description, attributes string, permissions []string) (error)

Remove

go
func (agg *Group) Remove() (error)

RemoveAttribute

go
func (agg *Group) RemoveAttribute(key string) (error)

SetAttribute

go
func (agg *Group) SetAttribute(key string, value any) (error)

Update

go
func (agg *Group) Update(name, description, attributes string, permissions []string) (error)

Event Handlers

GroupReadmodel

Domain EventMethod
tenantAggregate.TenantCreatedEventTenantCreatedEvent
tenantAggregate.TenantRemovedEventTenantRemovedEvent
tenantAggregate.TenantUpdatedEventTenantUpdatedEvent
groupAggregate.GroupAddedEventGroupAddedEvent
groupAggregate.GroupUpdatedEventGroupUpdatedEvent
groupAggregate.GroupRemovedEventGroupRemovedEvent
groupAggregate.GroupAttributeSetEventGroupAttributeSetEvent
groupAggregate.GroupAttributeRemovedEventGroupAttributeRemovedEvent

Custom Permissions

NameTypeComment
GroupCommandCreateCommandCreate new group
GroupCommandUpdateCommandUpdate existing group
GroupCommandRemoveCommandRemove existing group
GroupCommandSetAttributeCommandSet single attribute of existing group
GroupCommandRemoveAttributeCommandRemove single attribute from existing group
GroupQueryListQueryList groups
GroupQueryModelQueryGet group by id
GroupQueryModelByNameQueryGet group by name