Files
zitadel/apps/api/internal/command/web_key_model.go
2025-08-05 15:20:32 -07:00

132 lines
3.3 KiB
Go

package command
import (
"github.com/go-jose/go-jose/v4"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/webkey"
)
type WebKeyWriteModel struct {
eventstore.WriteModel
State domain.WebKeyState
PrivateKey *crypto.CryptoValue
PublicKey *jose.JSONWebKey
}
func NewWebKeyWriteModel(keyID, resourceOwner string) *WebKeyWriteModel {
return &WebKeyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: keyID,
ResourceOwner: resourceOwner,
},
}
}
func (wm *WebKeyWriteModel) AppendEvents(events ...eventstore.Event) {
wm.WriteModel.AppendEvents(events...)
}
func (wm *WebKeyWriteModel) Reduce() error {
for _, event := range wm.Events {
if event.Aggregate().ID != wm.AggregateID {
continue
}
switch e := event.(type) {
case *webkey.AddedEvent:
wm.State = domain.WebKeyStateInitial
wm.PrivateKey = e.PrivateKey
wm.PublicKey = e.PublicKey
case *webkey.ActivatedEvent:
wm.State = domain.WebKeyStateActive
case *webkey.DeactivatedEvent:
wm.State = domain.WebKeyStateInactive
case *webkey.RemovedEvent:
wm.State = domain.WebKeyStateRemoved
wm.PrivateKey = nil
wm.PublicKey = nil
}
}
return wm.WriteModel.Reduce()
}
func (wm *WebKeyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
ResourceOwner(wm.ResourceOwner).
AddQuery().
AggregateTypes(webkey.AggregateType).
AggregateIDs(wm.AggregateID).
EventTypes(
webkey.AddedEventType,
webkey.ActivatedEventType,
webkey.DeactivatedEventType,
webkey.RemovedEventType,
).
Builder()
}
type webKeyWriteModels struct {
resourceOwner string
events []eventstore.Event
keys map[string]*WebKeyWriteModel
activeID string
}
func newWebKeyWriteModels(resourceOwner string) *webKeyWriteModels {
return &webKeyWriteModels{
resourceOwner: resourceOwner,
keys: make(map[string]*WebKeyWriteModel),
}
}
func (models *webKeyWriteModels) AppendEvents(events ...eventstore.Event) {
models.events = append(models.events, events...)
}
func (models *webKeyWriteModels) Reduce() error {
for _, event := range models.events {
aggregate := event.Aggregate()
if models.keys[aggregate.ID] == nil {
models.keys[aggregate.ID] = NewWebKeyWriteModel(aggregate.ID, aggregate.ResourceOwner)
}
switch event.(type) {
case *webkey.AddedEvent:
break
case *webkey.ActivatedEvent:
models.activeID = aggregate.ID
case *webkey.DeactivatedEvent:
if models.activeID == aggregate.ID {
models.activeID = ""
}
case *webkey.RemovedEvent:
delete(models.keys, aggregate.ID)
continue
}
model := models.keys[aggregate.ID]
model.AppendEvents(event)
if err := model.Reduce(); err != nil {
return err
}
}
models.events = models.events[0:0]
return nil
}
func (models *webKeyWriteModels) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
ResourceOwner(models.resourceOwner).
AddQuery().
AggregateTypes(webkey.AggregateType).
EventTypes(
webkey.AddedEventType,
webkey.ActivatedEventType,
webkey.DeactivatedEventType,
webkey.RemovedEventType,
).
Builder()
}