Skip to content

Tenant

Overview

The Tenant domain is a default domain in comby, designed to represent an organization that can manage identities. These identities may be linked to existing accounts, creating a structured relationship between organizations and individual users. The domain is implemented through the Tenant aggregate, which models the organization, manages associated metadata, and reacts to domain events.

The Tenant serves as the central hub for all aggregates. While each aggregate operates independently, all comby default aggregates reference the Tenant by default to support a multi-tenancy system.

Structure

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

  • Name: The name of the tenant or organization.
  • Secrets: A map for storing sensitive information, such as API keys or other credentials linked to the tenant.

A Tenant does not reference other aggregates, as it serves as the central entity. All other aggregates refer to the Tenant instead. In comby, multiple Tenants can be created and managed. The framework ensures that Tenants are isolated, and no data is shared between them.

Commands

TenantCommandCreate

Domain Command Struct:

go
type TenantCommandCreate struct {
	TenantUuid string `json:"tenantUuid"`
	Name       string `json:"name"`
	Attributes string `json:"attributes,omitempty"`
}

Domain Command Handling Method:

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

TenantCommandRemove

Domain Command Struct:

go
type TenantCommandRemove struct {
	TenantUuid string `json:"tenantUuid"`
}

Domain Command Handling Method:

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

TenantCommandRemoveAttribute

Domain Command Struct:

go
type TenantCommandRemoveAttribute struct {
	TenantUuid string `json:"tenantUuid"`
	Key        string `json:"key"`
}

Domain Command Handling Method:

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

TenantCommandRemoveSecret

Domain Command Struct:

go
type TenantCommandRemoveSecret struct {
	TenantUuid string `json:"tenantUuid"`
	SecretKey  string `json:"secretKey"`
}

Domain Command Handling Method:

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

TenantCommandSetAttribute

Domain Command Struct:

go
type TenantCommandSetAttribute struct {
	TenantUuid string `json:"tenantUuid"`
	Key        string `json:"key"`
	Value      any    `json:"value"`
}

Domain Command Handling Method:

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

TenantCommandSetSecret

Domain Command Struct:

go
type TenantCommandSetSecret struct {
	TenantUuid  string `json:"tenantUuid"`
	SecretKey   string `json:"secretKey"`
	SecretValue string `json:"secretValue,omitempty"`
}

Domain Command Handling Method:

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

TenantCommandUpdate

Domain Command Struct:

go
type TenantCommandUpdate struct {
	TenantUuid    string   `json:"tenantUuid"`
	Name          string   `json:"name,omitempty"`
	Attributes    string   `json:"attributes,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) TenantCommandUpdate(ctx context.Context, cmd comby.Command, domainCmd *TenantCommandUpdate) ([]comby.Event, error)

Queries

Domain Query Structs:

Domain Query Responses:

TenantQueryList

TenantQueryList returns a list of tenants based on the context of the requestor.

This query determines the list of tenants a requestor is allowed to access, with behavior depending on the requestor's context. The query outcome is classified into two distinct cases:

  1. System Tenant Context:
  • When the requestor represents the system tenant, the query retrieves a complete list of all tenants.
  • This includes tenants from all contexts, providing global visibility for the system tenant.
  1. Specific Tenant Context:
  • If the requestor represents a specific tenant, the query returns a list containing only the tenant associated with the requestor.
  • This ensures that the tenant has access only to its own information, adhering to strict isolation principles in a multi-tenant architecture.

Domain Query Struct:

go
type TenantQueryList struct {
	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) TenantQueryList(ctx context.Context, qry comby.Query, domainQry *TenantQueryList) (*TenantQueryListResponse, error)

TenantQueryModelByName

Domain Query Struct:

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

Domain Query Handling Method:

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

TenantQueryModel

Domain Query Struct:

go
type TenantQueryModel struct {
	TenantUuid string `json:"tenantUuid"`
}

Domain Query Handling Method:

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

TenantQueryListResponse

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

TenantQueryItemResponse

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

Events

TenantCreatedEvent

Domain Event Struct:

go
type TenantCreatedEvent struct {
	Name       string `json:"name"`
	Attributes string `json:"attributes,omitempty"`
}

Domain Event Handling Method:

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

TenantRemovedEvent

Domain Event Struct:

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

Domain Event Handling Method:

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

TenantAttributeRemovedEvent

Domain Event Struct:

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

Domain Event Handling Method:

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

TenantSecretRemovedEvent

Domain Event Struct:

go
type TenantSecretRemovedEvent struct {
	SecretKey string `json:"secretKey"`
}

Domain Event Handling Method:

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

TenantAttributeSetEvent

Domain Event Struct:

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

Domain Event Handling Method:

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

TenantSecretSetEvent

Domain Event Struct:

go
type TenantSecretSetEvent struct {
	SecretKey   string `json:"SecretKey"`
	SecretValue string `json:"SecretValue,omitempty"`
}

Domain Event Handling Method:

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

TenantUpdatedEvent

Domain Event Struct:

go
type TenantUpdatedEvent struct {
	Name       string `json:"name,omitempty"`
	Attributes string `json:"attributes,omitempty"`
}

Domain Event Handling Method:

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

Aggregate

Aggregate Struct:

go
type Tenant struct {
	*comby.BaseAggregate
	// Value Objects
	Name    string
	Secrets *comby.Attributes
}

Methods

Create

go
func (agg *Tenant) Create(name, attributes string) (error)

Remove

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

RemoveAttribute

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

RemoveSecret

go
func (agg *Tenant) RemoveSecret(key string) (error)

SetAttribute

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

SetSecret

go
func (agg *Tenant) SetSecret(key, value string) (error)

Update

go
func (agg *Tenant) Update(name, attributes string) (error)

Event Handlers

TenantReadmodel

Domain EventMethod
webhookAggregate.WebhookRemovedEventWebhookRemovedEvent
webhookAggregate.WebhookAddedEventWebhookAddedEvent
tenantAggregate.TenantCreatedEventTenantCreatedEvent
tenantAggregate.TenantSecretRemovedEventTenantSecretRemovedEvent
tenantAggregate.TenantSecretSetEventTenantSecretSetEvent
tenantAggregate.TenantAttributeRemovedEventTenantAttributeRemovedEvent
tenantAggregate.TenantAttributeSetEventTenantAttributeSetEvent
tenantAggregate.TenantUpdatedEventTenantUpdatedEvent
tenantAggregate.TenantRemovedEventTenantRemovedEvent
invitationAggregate.InvitationCreatedEventInvitationCreatedEvent
invitationAggregate.InvitationRemovedEventInvitationRemovedEvent
identityAggregate.IdentityProfileUpdatedEventIdentityProfileUpdatedEvent
identityAggregate.IdentityRemovedEventIdentityRemovedEvent
identityAggregate.IdentityCreatedEventIdentityCreatedEvent
groupAggregate.GroupUpdatedEventGroupUpdatedEvent
groupAggregate.GroupRemovedEventGroupRemovedEvent
groupAggregate.GroupAddedEventGroupAddedEvent
assetAggregate.AssetAddedEventAssetAddedEvent
assetAggregate.AssetRemovedEventAssetRemovedEvent