mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:17:32 +00:00
feat: limit audit trail (#6744)
* feat: enable limiting audit trail * support AddExclusiveQuery * fix invalid condition * register event mappers * fix NullDuration validity * test query side for limits * lint * acceptance test audit trail limit * fix acceptance test * translate limits not found * update tests * fix linting * add audit log retention to default instance * fix tests * update docs * remove todo * improve test name
This commit is contained in:
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/idpintent"
|
||||
instance_repo "github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/keypair"
|
||||
"github.com/zitadel/zitadel/internal/repository/limits"
|
||||
"github.com/zitadel/zitadel/internal/repository/milestone"
|
||||
"github.com/zitadel/zitadel/internal/repository/oidcsession"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
@@ -150,6 +151,7 @@ func StartCommands(
|
||||
keypair.RegisterEventMappers(repo.eventstore)
|
||||
action.RegisterEventMappers(repo.eventstore)
|
||||
quota.RegisterEventMappers(repo.eventstore)
|
||||
limits.RegisterEventMappers(repo.eventstore)
|
||||
session.RegisterEventMappers(repo.eventstore)
|
||||
idpintent.RegisterEventMappers(repo.eventstore)
|
||||
authrequest.RegisterEventMappers(repo.eventstore)
|
||||
|
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/repository/feature"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/limits"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/repository/project"
|
||||
"github.com/zitadel/zitadel/internal/repository/quota"
|
||||
@@ -114,6 +115,9 @@ type InstanceSetup struct {
|
||||
Items []*SetQuota
|
||||
}
|
||||
Features map[domain.Feature]any
|
||||
Limits *struct {
|
||||
AuditLogRetention *time.Duration
|
||||
}
|
||||
}
|
||||
|
||||
type SecretGenerators struct {
|
||||
@@ -135,6 +139,7 @@ type ZitadelConfig struct {
|
||||
adminAppID string
|
||||
authAppID string
|
||||
consoleAppID string
|
||||
limitsID string
|
||||
}
|
||||
|
||||
func (s *InstanceSetup) generateIDs(idGenerator id.Generator) (err error) {
|
||||
@@ -159,7 +164,10 @@ func (s *InstanceSetup) generateIDs(idGenerator id.Generator) (err error) {
|
||||
}
|
||||
|
||||
s.zitadel.consoleAppID, err = idGenerator.Next()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.zitadel.limitsID, err = idGenerator.Next()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -190,6 +198,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
|
||||
orgAgg := org.NewAggregate(orgID)
|
||||
userAgg := user.NewAggregate(userID, orgID)
|
||||
projectAgg := project.NewAggregate(setup.zitadel.projectID, orgID)
|
||||
limitsAgg := limits.NewAggregate(setup.zitadel.limitsID, instanceID, instanceID)
|
||||
|
||||
validations := []preparation.Validation{
|
||||
prepareAddInstance(instanceAgg, setup.InstanceName, setup.DefaultLanguage),
|
||||
@@ -441,6 +450,12 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
|
||||
}
|
||||
}
|
||||
|
||||
if setup.Limits != nil {
|
||||
validations = append(validations, c.SetLimitsCommand(limitsAgg, &limitsWriteModel{}, &SetLimits{
|
||||
AuditLogRetention: setup.Limits.AuditLogRetention,
|
||||
}))
|
||||
}
|
||||
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validations...)
|
||||
if err != nil {
|
||||
return "", "", nil, nil, err
|
||||
|
105
internal/command/limits.go
Normal file
105
internal/command/limits.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/limits"
|
||||
)
|
||||
|
||||
type SetLimits struct {
|
||||
AuditLogRetention *time.Duration `json:"AuditLogRetention,omitempty"`
|
||||
}
|
||||
|
||||
// SetLimits creates new limits or updates existing limits.
|
||||
func (c *Commands) SetLimits(
|
||||
ctx context.Context,
|
||||
resourceOwner string,
|
||||
setLimits *SetLimits,
|
||||
) (*domain.ObjectDetails, error) {
|
||||
instanceId := authz.GetInstance(ctx).InstanceID()
|
||||
wm, err := c.getLimitsWriteModel(ctx, instanceId, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aggregateId := wm.AggregateID
|
||||
if aggregateId == "" {
|
||||
aggregateId, err = c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
createCmds, err := c.SetLimitsCommand(limits.NewAggregate(aggregateId, instanceId, resourceOwner), wm, setLimits)()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmds, err := createCmds(ctx, nil)
|
||||
if len(cmds) > 0 {
|
||||
events, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(wm, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return writeModelToObjectDetails(&wm.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ResetLimits(ctx context.Context, resourceOwner string) (*domain.ObjectDetails, error) {
|
||||
instanceId := authz.GetInstance(ctx).InstanceID()
|
||||
wm, err := c.getLimitsWriteModel(ctx, instanceId, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if wm.AggregateID == "" {
|
||||
return nil, errors.ThrowNotFound(nil, "COMMAND-9JToT", "Errors.Limits.NotFound")
|
||||
}
|
||||
aggregate := limits.NewAggregate(wm.AggregateID, instanceId, resourceOwner)
|
||||
events := []eventstore.Command{limits.NewResetEvent(ctx, &aggregate.Aggregate)}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(wm, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&wm.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) getLimitsWriteModel(ctx context.Context, instanceId, resourceOwner string) (*limitsWriteModel, error) {
|
||||
wm := newLimitsWriteModel(instanceId, resourceOwner)
|
||||
return wm, c.eventstore.FilterToQueryReducer(ctx, wm)
|
||||
}
|
||||
|
||||
func (c *Commands) SetLimitsCommand(a *limits.Aggregate, wm *limitsWriteModel, setLimits *SetLimits) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if setLimits == nil || setLimits.AuditLogRetention == nil {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "COMMAND-4M9vs", "Errors.Limits.NoneSpecified")
|
||||
}
|
||||
return func(ctx context.Context, _ preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
changes := wm.NewChanges(setLimits)
|
||||
if len(changes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return []eventstore.Command{limits.NewSetEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
limits.SetEventType,
|
||||
),
|
||||
changes...,
|
||||
)}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
73
internal/command/limits_model.go
Normal file
73
internal/command/limits_model.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/limits"
|
||||
)
|
||||
|
||||
type limitsWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
rollingAggregateID string
|
||||
auditLogRetention *time.Duration
|
||||
}
|
||||
|
||||
// newLimitsWriteModel aggregateId is filled by reducing unit matching events
|
||||
func newLimitsWriteModel(instanceId, resourceOwner string) *limitsWriteModel {
|
||||
return &limitsWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
InstanceID: instanceId,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *limitsWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
InstanceID(wm.InstanceID).
|
||||
AddQuery().
|
||||
AggregateTypes(limits.AggregateType).
|
||||
EventTypes(
|
||||
limits.SetEventType,
|
||||
limits.ResetEventType,
|
||||
)
|
||||
|
||||
return query.Builder()
|
||||
}
|
||||
|
||||
func (wm *limitsWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
wm.ChangeDate = event.CreatedAt()
|
||||
switch e := event.(type) {
|
||||
case *limits.SetEvent:
|
||||
wm.rollingAggregateID = e.Aggregate().ID
|
||||
if e.AuditLogRetention != nil {
|
||||
wm.auditLogRetention = e.AuditLogRetention
|
||||
}
|
||||
case *limits.ResetEvent:
|
||||
wm.rollingAggregateID = ""
|
||||
wm.auditLogRetention = nil
|
||||
}
|
||||
}
|
||||
if err := wm.WriteModel.Reduce(); err != nil {
|
||||
return err
|
||||
}
|
||||
// wm.WriteModel.Reduce() sets the aggregateID to the first event's aggregateID, but we need the last one
|
||||
wm.AggregateID = wm.rollingAggregateID
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewChanges returns all changes that need to be applied to the aggregate.
|
||||
// nil properties in setLimits are ignored
|
||||
func (wm *limitsWriteModel) NewChanges(setLimits *SetLimits) (changes []limits.LimitsChange) {
|
||||
if setLimits == nil {
|
||||
return nil
|
||||
}
|
||||
changes = make([]limits.LimitsChange, 0, 1)
|
||||
if setLimits.AuditLogRetention != nil && (wm.auditLogRetention == nil || *wm.auditLogRetention != *setLimits.AuditLogRetention) {
|
||||
changes = append(changes, limits.ChangeAuditLogRetention(setLimits.AuditLogRetention))
|
||||
}
|
||||
return changes
|
||||
}
|
313
internal/command/limits_test.go
Normal file
313
internal/command/limits_test.go
Normal file
@@ -0,0 +1,313 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
caos_errors "github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/id"
|
||||
id_mock "github.com/zitadel/zitadel/internal/id/mock"
|
||||
"github.com/zitadel/zitadel/internal/repository/limits"
|
||||
)
|
||||
|
||||
func TestLimits_SetLimits(t *testing.T) {
|
||||
type fields func(*testing.T) (*eventstore.Eventstore, id.Generator)
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
setLimits *SetLimits
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "create limits, ok",
|
||||
fields: func(*testing.T) (*eventstore.Eventstore, id.Generator) {
|
||||
return eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
eventFromEventPusherWithInstanceID(
|
||||
"instance1",
|
||||
limits.NewSetEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
context.Background(),
|
||||
&limits.NewAggregate("limits1", "instance1", "instance1").Aggregate,
|
||||
limits.SetEventType,
|
||||
),
|
||||
limits.ChangeAuditLogRetention(gu.Ptr(time.Hour)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
id_mock.NewIDGeneratorExpectIDs(t, "limits1")
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
resourceOwner: "instance1",
|
||||
setLimits: &SetLimits{
|
||||
AuditLogRetention: gu.Ptr(time.Hour),
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update limits, ok",
|
||||
fields: func(*testing.T) (*eventstore.Eventstore, id.Generator) {
|
||||
return eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
limits.NewSetEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
context.Background(),
|
||||
&limits.NewAggregate("limits1", "instance1", "instance1").Aggregate,
|
||||
limits.SetEventType,
|
||||
),
|
||||
limits.ChangeAuditLogRetention(gu.Ptr(time.Minute)),
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
eventFromEventPusherWithInstanceID(
|
||||
"instance1",
|
||||
limits.NewSetEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
context.Background(),
|
||||
&limits.NewAggregate("limits1", "instance1", "instance1").Aggregate,
|
||||
limits.SetEventType,
|
||||
),
|
||||
limits.ChangeAuditLogRetention(gu.Ptr(time.Hour)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
nil
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
resourceOwner: "instance1",
|
||||
setLimits: &SetLimits{
|
||||
AuditLogRetention: gu.Ptr(time.Hour),
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set limits after resetting limits, ok",
|
||||
fields: func(*testing.T) (*eventstore.Eventstore, id.Generator) {
|
||||
return eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
limits.NewSetEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
context.Background(),
|
||||
&limits.NewAggregate("limits1", "instance1", "instance1").Aggregate,
|
||||
limits.SetEventType,
|
||||
),
|
||||
limits.ChangeAuditLogRetention(gu.Ptr(time.Hour)),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
limits.NewResetEvent(
|
||||
context.Background(),
|
||||
&limits.NewAggregate("limits1", "instance1", "instance1").Aggregate,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
eventFromEventPusherWithInstanceID(
|
||||
"instance1",
|
||||
limits.NewSetEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
context.Background(),
|
||||
&limits.NewAggregate("limits2", "instance1", "instance1").Aggregate,
|
||||
limits.SetEventType,
|
||||
),
|
||||
limits.ChangeAuditLogRetention(gu.Ptr(time.Hour)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
id_mock.NewIDGeneratorExpectIDs(t, "limits2")
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
resourceOwner: "instance1",
|
||||
setLimits: &SetLimits{
|
||||
AuditLogRetention: gu.Ptr(time.Hour),
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := new(Commands)
|
||||
r.eventstore, r.idGenerator = tt.fields(t)
|
||||
got, err := r.SetLimits(tt.args.ctx, tt.args.resourceOwner, tt.args.setLimits)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLimits_ResetLimits(t *testing.T) {
|
||||
type fields func(*testing.T) *eventstore.Eventstore
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "not found",
|
||||
fields: func(tt *testing.T) *eventstore.Eventstore {
|
||||
return eventstoreExpect(
|
||||
tt,
|
||||
expectFilter(),
|
||||
)
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
resourceOwner: "instance1",
|
||||
},
|
||||
res: res{
|
||||
err: func(err error) bool {
|
||||
return errors.Is(err, caos_errors.ThrowNotFound(nil, "COMMAND-9JToT", "Errors.Limits.NotFound"))
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "already removed",
|
||||
fields: func(tt *testing.T) *eventstore.Eventstore {
|
||||
return eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
limits.NewSetEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
context.Background(),
|
||||
&limits.NewAggregate("limits1", "instance1", "instance1").Aggregate,
|
||||
limits.SetEventType,
|
||||
),
|
||||
limits.ChangeAuditLogRetention(gu.Ptr(time.Hour)),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
limits.NewResetEvent(context.Background(),
|
||||
&limits.NewAggregate("limits1", "instance1", "instance1").Aggregate,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
resourceOwner: "instance1",
|
||||
},
|
||||
res: res{
|
||||
err: func(err error) bool {
|
||||
return errors.Is(err, caos_errors.ThrowNotFound(nil, "COMMAND-9JToT", "Errors.Limits.NotFound"))
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reset limits, ok",
|
||||
fields: func(tt *testing.T) *eventstore.Eventstore {
|
||||
return eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
limits.NewSetEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
context.Background(),
|
||||
&limits.NewAggregate("limits1", "instance1", "instance1").Aggregate,
|
||||
limits.SetEventType,
|
||||
),
|
||||
limits.ChangeAuditLogRetention(gu.Ptr(time.Hour)),
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
eventFromEventPusherWithInstanceID(
|
||||
"instance1",
|
||||
limits.NewResetEvent(context.Background(),
|
||||
&limits.NewAggregate("limits1", "instance1", "instance1").Aggregate,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
resourceOwner: "instance1",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields(t),
|
||||
}
|
||||
got, err := r.ResetLimits(tt.args.ctx, tt.args.resourceOwner)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/idpintent"
|
||||
iam_repo "github.com/zitadel/zitadel/internal/repository/instance"
|
||||
key_repo "github.com/zitadel/zitadel/internal/repository/keypair"
|
||||
"github.com/zitadel/zitadel/internal/repository/limits"
|
||||
"github.com/zitadel/zitadel/internal/repository/oidcsession"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
proj_repo "github.com/zitadel/zitadel/internal/repository/project"
|
||||
@@ -58,6 +59,7 @@ func eventstoreExpect(t *testing.T, expects ...expect) *eventstore.Eventstore {
|
||||
authrequest.RegisterEventMappers(es)
|
||||
oidcsession.RegisterEventMappers(es)
|
||||
quota_repo.RegisterEventMappers(es)
|
||||
limits.RegisterEventMappers(es)
|
||||
feature.RegisterEventMappers(es)
|
||||
return es
|
||||
}
|
||||
|
Reference in New Issue
Block a user