Identity
Overview
The Identity domain is a default domain in comby. Identities can be linked to accounts, associated with groups, and assigned tokens for secure interactions. The Identity aggregate is at the core of this domain, handling events and maintaining consistency across identity-related operations.
Concept
What is an Identity?
An Identity is the tenant-specific representation of a user. While an Account handles authentication (login/credentials), an Identity handles authorization (permissions/groups) within a specific tenant. A single account can have multiple identities across different tenants.
Key Characteristics:
- Account-Tenant Bridge: Links an account to a tenant with specific permissions
- Multi-Tenant Support: One account can have multiple identities in different tenants
- Profile Information: Each identity has its own profile (name, email, title, avatar)
- Group Membership: Identities belong to groups that define their permissions
- Service Account Tokens: Identities can have API tokens for programmatic access
Account (Authentication)
└── Identity 1 (Tenant A)
├── Profile (Name, Email, Title, Avatar)
├── Groups [Admin, Developer]
└── Tokens [API Token 1, API Token 2]
└── Identity 2 (Tenant B)
├── Profile (Different Name, Email)
├── Groups [Viewer]
└── Tokens []Architecture
Hierarchy
System
└── Tenant
└── Identities
├── AccountUuid (Link to Account)
├── Profile (Name, Email, Title, Avatar)
├── GroupUuids (List of assigned groups)
└── Tokens (Service account tokens)Location in Codebase
Domain:
/domain/identity/aggregate/- Identity aggregatecommand/- Identity commandsquery/- Identity queriesreadmodel/- Identity readmodel
API:
/api/identity/- REST API handlers for identity management
Related Entities
Identity is connected to:
- Account: One-to-many relationship (one account, many identities)
- Tenant: Each identity belongs to exactly one tenant
- Group: Identities are assigned to groups for permissions
- Auth: Auth domain consumes identity events for authorization
- Workspace: Identities can be workspace members
Domain Model
type Identity struct {
AggregateUuid string
// References
AccountUuid string
GroupUuids []string
// Entities
Profile *Profile
Tokens []*Token
}
type Profile struct {
Name string
Email string
Title string
Avatar string
}
type Token struct {
TokenUuid string
Name string
Description string
TokenValue string // Hashed
ExpiredAt int64
}An Identity can only be associated with a single Tenant. However, an account can have multiple identities, each linked to a different Tenant. This design allows a user to log in to multiple Tenants using a single account.
Account vs Identity
Account
- Purpose: Authentication (login, sessions, passwords)
- Scope: System-wide, tenant-independent
- Stored in: Anonymous tenant
- One per user: A user has one account
Identity
- Purpose: Authorization (permissions, groups, roles)
- Scope: Tenant-specific
- Stored in: Specific tenant
- Multiple per user: A user can have identities in multiple tenants
Example Flow
User → Registers → Creates Account
→ Invited to Tenant A → Creates Identity A (with Groups: [Admin])
→ Invited to Tenant B → Creates Identity B (with Groups: [Viewer])Service Account Tokens
Identities can have service account tokens for programmatic API access:
Characteristics:
- API Authentication: Use tokens instead of session-based auth
- Long-lived: Configurable expiration (default: 10 years)
- Named & Described: Each token has a name and description
- Hashed Storage: Token values are hashed before storage
- Multiple per Identity: Each identity can have multiple tokens
Use Cases:
- CI/CD pipelines
- Automated scripts
- Third-party integrations
- Microservice authentication
Structure
The Identity aggregate extends the BaseAggregate, inheriting core event-sourcing capabilities like event tracking and versioning. It includes fields to represent the identity's relationships, attributes, and associated entities:
The Identity is an aggregate that represents a user within a system holding entities Profile and Token. Profile contains information about the user, such as their name, email address, title, and avatar. Token represents API tokens associated with the identity, each containing a unique UUID, name, description, token value, and expiration. An identity can act as an Service Account - without an associated account.
References:
- AccountUuid: Link the identity to an existing account in the Account domain (optional).
- GroupUuids: Tracks the groups to which the identity belongs.
Entities:
- Profile: Captures personal information about the identity, such as name, email, title, and avatar.
- Tokens: Represents authentication or API tokens associated with the identity, each containing a unique UUID, name, description, token value, and expiration.
Usage
1. Register Domain
import "github.com/gradientzero/comby/v2/domain/identity"
// In application initialization
identity.Register(ctx, facade)2. Create Identity
cmd, _ := comby.NewCommand("Identity", &command.IdentityCommandCreate{
IdentityUuid: uuid.New().String(),
AccountUuid: "account-uuid",
GroupUuids: []string{
"developers-group-uuid",
"viewers-group-uuid",
},
})
cmd.SetTenantUuid("tenant-uuid")
facade.DispatchCommand(ctx, cmd)3. Create Identity without Account
// For service accounts or system identities
cmd, _ := comby.NewCommand("Identity", &command.IdentityCommandCreate{
IdentityUuid: uuid.New().String(),
GroupUuids: []string{
"service-accounts-group-uuid",
},
})
cmd.SetTenantUuid("tenant-uuid")
facade.DispatchCommand(ctx, cmd)4. Update Identity Profile
cmd, _ := comby.NewCommand("Identity", &command.IdentityCommandUpdateProfile{
IdentityUuid: "identity-uuid",
Name: "John Doe",
Email: "john.doe@example.com",
Title: "Senior Developer",
Avatar: "https://example.com/avatars/johndoe.jpg",
PatchedFields: []string{"name", "email", "title", "avatar"},
})
facade.DispatchCommand(ctx, cmd)5. Add Group to Identity
cmd, _ := comby.NewCommand("Identity", &command.IdentityCommandAddGroup{
IdentityUuid: "identity-uuid",
GroupUuid: "administrators-group-uuid",
})
facade.DispatchCommand(ctx, cmd)6. Remove Group from Identity
cmd, _ := comby.NewCommand("Identity", &command.IdentityCommandRemoveGroup{
IdentityUuid: "identity-uuid",
GroupUuid: "viewers-group-uuid",
})
facade.DispatchCommand(ctx, cmd)7. Add Service Account Token
cmd, _ := comby.NewCommand("Identity", &command.IdentityCommandAddToken{
IdentityUuid: "identity-uuid",
TokenUuid: uuid.New().String(),
TokenValue: "generated-secure-token",
Name: "CI/CD Pipeline Token",
Description: "Token for automated deployments",
ExpiredAt: time.Now().Add(365 * 24 * time.Hour).UnixNano(), // 1 year
})
facade.DispatchCommand(ctx, cmd)8. Remove Token
cmd, _ := comby.NewCommand("Identity", &command.IdentityCommandRemoveToken{
IdentityUuid: "identity-uuid",
TokenUuid: "token-uuid",
})
facade.DispatchCommand(ctx, cmd)9. List Identities
// List all identities in tenant
qry, _ := comby.NewQuery("Identity", &query.IdentityQueryList{
TenantUuid: "tenant-uuid",
Page: 0,
PageSize: 100,
})
res, _ := facade.DispatchQuery(ctx, qry)
identities := res.(*query.IdentityQueryListResponse).Items10. List Identities for Account
// List all identities for a specific account
qry, _ := comby.NewQuery("Identity", &query.IdentityQueryListForAccount{
AccountUuid: "account-uuid",
TenantUuid: "tenant-uuid",
})
res, _ := facade.DispatchQuery(ctx, qry)
identities := res.(*query.IdentityQueryListResponse).Items11. Get Identity
qry, _ := comby.NewQuery("Identity", &query.IdentityQueryGet{
IdentityUuid: "identity-uuid",
})
res, _ := facade.DispatchQuery(ctx, qry)
identity := res.(*query.IdentityQueryItemResponse).Item12. Delete Identity
cmd, _ := comby.NewCommand("Identity", &command.IdentityCommandRemove{
IdentityUuid: "identity-uuid",
})
facade.DispatchCommand(ctx, cmd)13. Set Identity Attribute
cmd, _ := comby.NewCommand("Identity", &command.IdentityCommandSetAttribute{
IdentityUuid: "identity-uuid",
Key: "department",
Value: "engineering",
})
facade.DispatchCommand(ctx, cmd)API Endpoints
Identity Management
POST /api/tenants/{tenantUuid}/identities - Create new identity
GET /api/tenants/{tenantUuid}/identities - List all identities
GET /api/tenants/{tenantUuid}/identities/{identityUuid} - Get specific identity
PATCH /api/tenants/{tenantUuid}/identities/{identityUuid} - Update identity
DELETE /api/tenants/{tenantUuid}/identities/{identityUuid} - Delete identityProfile Management
PATCH /api/tenants/{tenantUuid}/identities/{identityUuid}/profile - Update profileGroup Management
POST /api/tenants/{tenantUuid}/identities/{identityUuid}/add_group - Add group
POST /api/tenants/{tenantUuid}/identities/{identityUuid}/remove_group - Remove groupToken Management
POST /api/tenants/{tenantUuid}/identities/{identityUuid}/add_token - Add service account token
POST /api/tenants/{tenantUuid}/identities/{identityUuid}/remove_token - Remove tokenQuery by Account
GET /api/tenants/{tenantUuid}/identities/account/{accountUuid} - List identities for accountAttributes
POST /api/tenants/{tenantUuid}/identities/{identityUuid}/attributes - Set attribute
DELETE /api/tenants/{tenantUuid}/identities/{identityUuid}/attributes/{key} - Remove attributeAPI Example: Create Identity
POST /api/tenants/{tenantUuid}/identities
Content-Type: application/json
{
"identityUuid": "550e8400-e29b-41d4-a716-446655440001",
"accountUuid": "account-uuid",
"groupUuids": [
"developers-group-uuid",
"viewers-group-uuid"
]
}API Example: Update Profile
PATCH /api/tenants/{tenantUuid}/identities/{identityUuid}/profile
Content-Type: application/json
{
"name": "John Doe",
"email": "john.doe@example.com",
"title": "Senior Developer",
"avatar": "https://example.com/avatars/johndoe.jpg",
"patchedFields": ["name", "email", "title", "avatar"]
}API Example: Add Service Account Token
POST /api/tenants/{tenantUuid}/identities/{identityUuid}/add_token
Content-Type: application/json
{
"tokenUuid": "token-uuid",
"tokenValue": "generated-secure-token",
"name": "CI/CD Pipeline Token",
"description": "Token for automated deployments",
"expiredAt": 1735689600000000000
}Use Cases
1. Multi-Tenant SaaS User
User: john@example.com
└── Account: john-account-uuid
├── Identity in Tenant A (Company A)
│ ├── Profile: John Doe (CTO)
│ ├── Groups: [Administrators, Developers]
│ └── Tokens: []
└── Identity in Tenant B (Company B)
├── Profile: John D. (Consultant)
├── Groups: [Consultants, Viewers]
└── Tokens: []2. Service Account Integration
Service: CI/CD Pipeline
└── Identity (No Account)
├── Profile: CI/CD Service
├── Groups: [Service Accounts, Deployers]
└── Tokens: [Deploy Token (expires: never)]3. User Joining Multiple Organizations
User Registration Flow:
1. User registers → Account created
2. User accepts invite from Org A → Identity A created (Groups: [Members])
3. User accepts invite from Org B → Identity B created (Groups: [Admins])
4. User switches between orgs → Uses different identities with different permissions4. Role Changes Over Time
User Career Progression:
Identity: jane-identity-uuid
├── Year 1: Groups [Junior Developers]
├── Year 2: Groups [Developers, Team Leads] (add group)
├── Year 3: Groups [Senior Developers, Team Leads] (remove Junior, add Senior)
└── Year 4: Groups [Engineering Managers] (new role)Features
- ✅ Multi-tenant identity support
- ✅ Account-identity separation
- ✅ Profile management per identity
- ✅ Group-based permissions
- ✅ Service account token support
- ✅ Token expiration management
- ✅ Multiple tokens per identity
- ✅ Custom attributes support
- ✅ Cross-tenant identity queries
Best Practices
Identity Creation
✅ Always link identities to accounts for human users ✅ Create identities without accounts for service accounts ✅ Assign initial groups during creation ✅ Set meaningful profile information
Profile Management
✅ Keep profiles up-to-date with user information ✅ Use consistent email addresses across tenants when appropriate ✅ Use professional titles that reflect role ✅ Store avatar URLs, not binary data
Group Assignment
✅ Assign minimal required groups (principle of least privilege) ✅ Review group assignments regularly ✅ Remove unnecessary groups promptly ✅ Use group membership to control access, not individual permissions
Service Account Tokens
✅ Use descriptive names for tokens ✅ Set appropriate expiration times ✅ Rotate tokens regularly ✅ Delete unused tokens immediately ✅ Never log or expose token values ✅ Use separate tokens for different purposes
Token Security
// ✅ Good: Generate secure random tokens
tokenValue := generateSecureRandomToken(32)
// ✅ Good: Set reasonable expiration
expiredAt := time.Now().Add(90 * 24 * time.Hour).UnixNano() // 90 days
// ❌ Bad: Use predictable tokens
tokenValue := "token-123"
// ❌ Bad: Never expire tokens (for regular use)
expiredAt := 0Troubleshooting
Identity not found after creation
Check:
- Is the identity in the correct tenant?
- Was the command successfully dispatched?
- Check event store for IdentityCreatedEvent
Debug:
// List all identities in tenant
identities, _ := GetIdentityReadmodel().GetModelList(
readmodel.ListWithTenantUuid(tenantUuid),
)
for _, identity := range identities {
fmt.Printf("Identity: %s, Account: %s\n", identity.IdentityUuid, identity.AccountUuid)
}Group assignment not working
Cause: Group doesn't exist in the tenant or invalid group UUID.
Solution: Verify group exists before adding:
// Check if group exists in tenant
group, err := GetGroupReadmodel().GetModel(groupUuid)
if err != nil {
// Group not found
}Token authentication fails
Check:
- Is the token expired?
- Is the token value correct (hashed comparison)?
- Is the identity active?
- Does the identity have required permissions?
Debug:
// Validate token via Auth readmodel
tokenCtx, err := auth.GetAuthReadmodel().GetServiceAccount(tokenUuid, tokenValue)
if err != nil {
// Token not found or invalid
}
if time.Now().Unix() > tokenCtx.ExpiredAt {
// Token expired
}Multiple identities causing confusion
Cause: User has multiple identities and doesn't understand context switching.
Solution:
- Clearly indicate which tenant/identity is active in UI
- Provide easy tenant switching mechanism
- Show identity-specific information (profile, groups)
Profile not updating
Cause: Missing fields in PatchedFields parameter.
Solution:
// ✅ Correct: Specify which fields to update
cmd := &command.IdentityCommandUpdateProfile{
IdentityUuid: "identity-uuid",
Name: "New Name",
Email: "new@email.com",
PatchedFields: []string{"name", "email"}, // Required!
}Integration with Other Domains
Account Domain
// After account registration, create identity
accountRegistered := // from account event
cmd := &command.IdentityCommandCreate{
IdentityUuid: uuid.New().String(),
AccountUuid: accountRegistered.AccountUuid,
GroupUuids: []string{defaultGroupUuid},
}Tenant Domain
When a tenant is created, you may want to create an initial identity:
// Create first identity (owner) for new tenant
cmd := &command.IdentityCommandCreate{
IdentityUuid: uuid.New().String(),
AccountUuid: ownerAccountUuid,
GroupUuids: []string{adminGroupUuid},
}
cmd.SetTenantUuid(newTenantUuid)Auth Domain
The Auth domain consumes identity events:
IdentityCreatedEvent→ Builds authorization contextIdentityAddedGroupEvent→ Updates permissionsIdentityRemovedGroupEvent→ Revokes permissionsIdentityAddedTokenEvent→ Enables token-based auth
Invitation Domain
Invitations often trigger identity creation:
// When invitation is accepted
cmd := &command.IdentityCommandCreate{
IdentityUuid: uuid.New().String(),
AccountUuid: invitation.AccountUuid,
GroupUuids: invitation.GroupUuids,
}
cmd.SetTenantUuid(invitation.TenantUuid)Security Considerations
Token Management
- Always hash token values before storage
- Validate token expiration before authentication
- Implement token rotation policies
- Monitor token usage for anomalies
Profile Information
- Validate email addresses
- Sanitize profile inputs to prevent XSS
- Don't store sensitive information in profiles
- Use HTTPS for avatar URLs
Permission Isolation
- Ensure identities can only access their tenant's resources
- Validate group memberships before granting permissions
- Audit identity permission changes
- Implement multi-factor authentication for sensitive operations
Commands
- IdentityCommandAddGroup
- IdentityCommandAddToken
- IdentityCommandCreate
- IdentityCommandRemove
- IdentityCommandRemoveAttribute
- IdentityCommandRemoveGroup
- IdentityCommandRemoveToken
- IdentityCommandSetAttribute
- IdentityCommandUpdate
- IdentityCommandUpdateProfile
IdentityCommandAddGroup
Domain Command Struct:
type IdentityCommandAddGroup struct {
IdentityUuid string `json:"identityUuid"`
GroupUuid string `json:"groupUuid"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandAddGroup(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandAddGroup) ([]comby.Event, error)IdentityCommandAddToken
Domain Command Struct:
type IdentityCommandAddToken struct {
IdentityUuid string `json:"identityUuid"`
TokenUuid string `json:"tokenUuid"`
TokenValue string `json:"tokenValue"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
ExpiredAt int64 `json:"expiredAt,omitempty"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandAddToken(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandAddToken) ([]comby.Event, error)IdentityCommandCreate
Domain Command Struct:
type IdentityCommandCreate struct {
IdentityUuid string `json:"identityUuid"`
AccountUuid string `json:"accountUuid,omitempty"`
GroupUuids []string `json:"groupUuids"`
Attributes string `json:"attributes,omitempty"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandCreate(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandCreate) ([]comby.Event, error)IdentityCommandRemove
Domain Command Struct:
type IdentityCommandRemove struct {
IdentityUuid string `json:"identityUuid"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandRemove(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandRemove) ([]comby.Event, error)IdentityCommandRemoveAttribute
Domain Command Struct:
type IdentityCommandRemoveAttribute struct {
IdentityUuid string `json:"identityUuid"`
Key string `json:"key"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandRemoveAttribute(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandRemoveAttribute) ([]comby.Event, error)IdentityCommandRemoveGroup
Domain Command Struct:
type IdentityCommandRemoveGroup struct {
IdentityUuid string `json:"identityUuid"`
GroupUuid string `json:"groupUuid"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandRemoveGroup(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandRemoveGroup) ([]comby.Event, error)IdentityCommandRemoveToken
Domain Command Struct:
type IdentityCommandRemoveToken struct {
IdentityUuid string `json:"identityUuid"`
TokenUuid string `json:"tokenUuid"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandRemoveToken(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandRemoveToken) ([]comby.Event, error)IdentityCommandSetAttribute
Domain Command Struct:
type IdentityCommandSetAttribute struct {
IdentityUuid string `json:"identityUuid"`
Key string `json:"key"`
Value any `json:"value"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandSetAttribute(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandSetAttribute) ([]comby.Event, error)IdentityCommandUpdate
Domain Command Struct:
type IdentityCommandUpdate struct {
IdentityUuid string `json:"identityUuid"`
Attributes string `json:"attributes,omitempty"`
PatchedFields []string `json:"patchedFields"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandUpdate(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandUpdate) ([]comby.Event, error)IdentityCommandUpdateProfile
Domain Command Struct:
type IdentityCommandUpdateProfile struct {
IdentityUuid string `json:"identityUuid"`
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
Title string `json:"title,omitempty"`
Avatar string `json:"avatar,omitempty"`
PatchedFields []string `json:"patchedFields" doc:"list of fields that should be patched - comma separated" example:"field1,field2"`
}Domain Command Handling Method:
func (cs *commandHandler) IdentityCommandUpdateProfile(ctx context.Context, cmd comby.Command, domainCmd *IdentityCommandUpdateProfile) ([]comby.Event, error)Queries
Domain Query Structs:
- IdentityQueryListByAccountUuid
- IdentityQueryListByAccountTenantUuid
- IdentityQueryList
- IdentityQueryModel
Domain Query Responses:
IdentityQueryListByAccountUuid
Domain Query Struct:
type IdentityQueryListByAccountUuid struct {
AccountUuid string `json:"accountUuid"`
Page int64 `json:"page,omitempty"`
PageSize int64 `json:"pageSize,omitempty"`
OrderBy string `json:"orderBy,omitempty"`
}Domain Query Handling Method:
func (qs *queryHandler) IdentityQueryListByAccountUuid(ctx context.Context, qry comby.Query, domainQry *IdentityQueryListByAccountUuid) (*IdentityQueryListResponse, error)IdentityQueryListByAccountTenantUuid
Domain Query Struct:
type IdentityQueryListByAccountTenantUuid struct {
TenantUuid string `json:"tenantUuid"`
AccountUuid string `json:"accountUuid"`
Page int64 `json:"page,omitempty"`
PageSize int64 `json:"pageSize,omitempty"`
OrderBy string `json:"orderBy,omitempty"`
}Domain Query Handling Method:
func (qs *queryHandler) IdentityQueryListByAccountTenantUuid(ctx context.Context, qry comby.Query, domainQry *IdentityQueryListByAccountTenantUuid) (*IdentityQueryListResponse, error)IdentityQueryList
Domain Query Struct:
type IdentityQueryList 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"`
IncludeHistory bool `json:"includeHistory,omitempty"`
}Domain Query Handling Method:
func (qs *queryHandler) IdentityQueryList(ctx context.Context, qry comby.Query, domainQry *IdentityQueryList) (*IdentityQueryListResponse, error)IdentityQueryModel
Domain Query Struct:
type IdentityQueryModel struct {
IdentityUuid string `json:"identityUuid"`
IncludeHistory bool `json:"includeHistory,omitempty"`
}Domain Query Handling Method:
func (qs *queryHandler) IdentityQueryModel(ctx context.Context, qry comby.Query, domainQry *IdentityQueryModel) (*IdentityQueryItemResponse, error)IdentityQueryListResponse
type IdentityQueryListResponse struct {
Items []*readmodel.IdentityModel `json:"items,omitempty"`
Total int64 `json:"total,omitempty"`
Page int64 `json:"page,omitempty"`
PageSize int64 `json:"pageSize,omitempty"`
}IdentityQueryItemResponse
type IdentityQueryItemResponse struct {
Item *readmodel.IdentityModel `json:"item,omitempty"`
}Events
- IdentityAddedGroupEvent
- IdentityAddedTokenEvent
- IdentityCreatedEvent
- IdentityRemovedEvent
- IdentityAttributeRemovedEvent
- IdentityRemovedGroupEvent
- IdentityRemovedTokenEvent
- IdentityAttributeSetEvent
- IdentityUpdatedEvent
- IdentityProfileUpdatedEvent
IdentityAddedGroupEvent
Domain Event Struct:
type IdentityAddedGroupEvent struct {
GroupUuid string `json:"groupUuid"`
}Domain Event Handling Method:
func (agg *Identity) IdentityAddedGroupEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityAddedGroupEvent) (error)IdentityAddedTokenEvent
Domain Event Struct:
type IdentityAddedTokenEvent struct {
TokenUuid string `json:"tokenUuid"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
TokenValue string `json:"tokenValue"`
ExpiredAt int64 `json:"expiredAt,omitempty"`
}Domain Event Handling Method:
func (agg *Identity) IdentityAddedTokenEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityAddedTokenEvent) (error)IdentityCreatedEvent
Domain Event Struct:
type IdentityCreatedEvent struct {
AccountUuid string `json:"accountUuid,omitempty"`
Attributes string `json:"attributes,omitempty"`
}Domain Event Handling Method:
func (agg *Identity) IdentityCreatedEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityCreatedEvent) (error)IdentityRemovedEvent
Domain Event Struct:
type IdentityRemovedEvent struct {
Reason string `json:"reason,omitempty"`
}Domain Event Handling Method:
func (agg *Identity) IdentityRemovedEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityRemovedEvent) (error)IdentityAttributeRemovedEvent
Domain Event Struct:
type IdentityAttributeRemovedEvent struct {
Key string `json:"key"`
}Domain Event Handling Method:
func (agg *Identity) IdentityAttributeRemovedEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityAttributeRemovedEvent) (error)IdentityRemovedGroupEvent
Domain Event Struct:
type IdentityRemovedGroupEvent struct {
GroupUuid string `json:"groupUuid"`
}Domain Event Handling Method:
func (agg *Identity) IdentityRemovedGroupEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityRemovedGroupEvent) (error)IdentityRemovedTokenEvent
Domain Event Struct:
type IdentityRemovedTokenEvent struct {
TokenUuid string `json:"tokenUuid"`
}Domain Event Handling Method:
func (agg *Identity) IdentityRemovedTokenEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityRemovedTokenEvent) (error)IdentityAttributeSetEvent
Domain Event Struct:
type IdentityAttributeSetEvent struct {
Key string `json:"key"`
Value any `json:"value"`
}Domain Event Handling Method:
func (agg *Identity) IdentityAttributesSetEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityAttributeSetEvent) (error)IdentityUpdatedEvent
Domain Event Struct:
type IdentityUpdatedEvent struct {
Attributes string `json:"attributes,omitempty"`
}Domain Event Handling Method:
func (agg *Identity) IdentityUpdatedEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityUpdatedEvent) (error)IdentityProfileUpdatedEvent
Domain Event Struct:
type IdentityProfileUpdatedEvent struct {
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
Title string `json:"title,omitempty"`
Avatar string `json:"avatar,omitempty"`
}Domain Event Handling Method:
func (agg *Identity) IdentityProfileUpdatedEvent(ctx context.Context, evt comby.Event, domainEvt *IdentityProfileUpdatedEvent) (error)Aggregate
Aggregate Struct:
type Identity struct {
*comby.BaseAggregate
// References
AccountUuid string
GroupUuids []string
// Entities
Profile *Profile
Tokens []*Token
}Methods
AddGroup
func (agg *Identity) AddGroup(opts ) (error)AddToken
func (agg *Identity) AddToken(opts ) (error)Add
func (agg *Identity) Add(opts ) (error)Remove
func (agg *Identity) Remove(opts ) (error)RemoveAttribute
func (agg *Identity) RemoveAttribute(opts ) (error)RemoveGroup
func (agg *Identity) RemoveGroup(opts ) (error)RemoveToken
func (agg *Identity) RemoveToken(opts ) (error)SetAttribute
func (agg *Identity) SetAttribute(opts ) (error)Update
func (agg *Identity) Update(opts ) (error)UpdateProfile
func (agg *Identity) UpdateProfile(opts ) (error)Event Handlers
IdentityReadmodel
| Domain Event | Method |
|---|---|
tenantAggregate.TenantCreatedEvent | TenantCreatedEvent |
tenantAggregate.TenantAttributeRemovedEvent | TenantAttributeRemovedEvent |
tenantAggregate.TenantAttributeSetEvent | TenantAttributeSetEvent |
tenantAggregate.TenantUpdatedEvent | TenantUpdatedEvent |
tenantAggregate.TenantRemovedEvent | TenantRemovedEvent |
identityAggregate.IdentityAttributeRemovedEvent | IdentityAttributeRemovedEvent |
identityAggregate.IdentityRemovedTokenEvent | IdentityRemovedTokenEvent |
identityAggregate.IdentityUpdatedEvent | IdentityUpdatedEvent |
identityAggregate.IdentityRemovedEvent | IdentityRemovedEvent |
identityAggregate.IdentityAddedGroupEvent | IdentityAddedGroupEvent |
identityAggregate.IdentityRemovedGroupEvent | IdentityRemovedGroupEvent |
identityAggregate.IdentityAddedTokenEvent | IdentityAddedTokenEvent |
identityAggregate.IdentityCreatedEvent | IdentityCreatedEvent |
identityAggregate.IdentityProfileUpdatedEvent | IdentityProfileUpdatedEvent |
identityAggregate.IdentityAttributeSetEvent | IdentityAttributeSetEvent |
groupAggregate.GroupUpdatedEvent | GroupUpdatedEvent |
groupAggregate.GroupRemovedEvent | GroupRemovedEvent |
groupAggregate.GroupAddedEvent | GroupAddedEvent |
assetAggregate.AssetAddedEvent | AssetAddedEvent |
assetAggregate.AssetRemovedEvent | AssetRemovedEvent |
assetAggregate.AssetUpdatedEvent | AssetUpdatedEvent |
Custom Permissions
| Name | Type | Comment |
|---|---|---|
| IdentityCommandAddToken | Command | Add token for any other identity |
| IdentityCommandRemoveToken | Command | Remove token of any other identity |
| IdentityCommandUpdateProfile | Command | Update profile of any other identity |
| IdentityCommandSetAttribute | Command | Set attributes of any other identity |
| IdentityQueryModel | Query | Get identity model of any identity |