From a3b36a0138d184293a79e3e4a2b24bbed1962926 Mon Sep 17 00:00:00 2001 From: Silvan Date: Fri, 17 Mar 2023 10:14:06 +0100 Subject: [PATCH] refactor(changes): use `queries.SearchEvents` (#5388) * refactor(changes): use `queries.SearchEvents` --------- Co-authored-by: Livio Spring --- cmd/defaults.yaml | 2 + cmd/start/start.go | 2 +- internal/api/grpc/admin/event.go | 2 +- internal/api/grpc/admin/server.go | 33 ++-- internal/api/grpc/auth/user.go | 33 +++- internal/api/grpc/change/changes.go | 27 ++-- internal/api/grpc/management/org.go | 32 +++- internal/api/grpc/management/project.go | 67 +++++++- .../grpc/management/project_application.go | 36 ++++- internal/api/grpc/management/user.go | 33 +++- internal/query/changes.go | 145 ------------------ internal/query/event.go | 64 +++++--- 12 files changed, 261 insertions(+), 215 deletions(-) delete mode 100644 internal/query/changes.go diff --git a/cmd/defaults.yaml b/cmd/defaults.yaml index 13d8940d87..b7b7275a26 100644 --- a/cmd/defaults.yaml +++ b/cmd/defaults.yaml @@ -656,6 +656,8 @@ DefaultInstance: # # CallURL is called when a relative amount of the quota is used. # CallURL: "https://httpbin.org/post" +AuditLogRetention: 0s + InternalAuthZ: RolePermissionMappings: - Role: "IAM_OWNER" diff --git a/cmd/start/start.go b/cmd/start/start.go index c5153a3ffc..10c60303ad 100644 --- a/cmd/start/start.go +++ b/cmd/start/start.go @@ -235,7 +235,7 @@ func startAPIs( if err := apis.RegisterServer(ctx, system.CreateServer(commands, queries, adminRepo, config.Database.DatabaseName(), config.DefaultInstance, config.ExternalDomain)); err != nil { return err } - if err := apis.RegisterServer(ctx, admin.CreateServer(config.Database.DatabaseName(), commands, queries, config.SystemDefaults, adminRepo, config.ExternalSecure, keys.User)); err != nil { + if err := apis.RegisterServer(ctx, admin.CreateServer(config.Database.DatabaseName(), commands, queries, config.SystemDefaults, adminRepo, config.ExternalSecure, keys.User, config.AuditLogRetention)); err != nil { return err } if err := apis.RegisterServer(ctx, management.CreateServer(commands, queries, config.SystemDefaults, keys.User, config.ExternalSecure, config.AuditLogRetention)); err != nil { diff --git a/internal/api/grpc/admin/event.go b/internal/api/grpc/admin/event.go index 28f9578c46..04f7026fb3 100644 --- a/internal/api/grpc/admin/event.go +++ b/internal/api/grpc/admin/event.go @@ -17,7 +17,7 @@ func (s *Server) ListEvents(ctx context.Context, in *admin_pb.ListEventsRequest) if err != nil { return nil, err } - events, err := s.query.SearchEvents(ctx, filter) + events, err := s.query.SearchEvents(ctx, filter, s.auditLogRetention) if err != nil { return nil, err } diff --git a/internal/api/grpc/admin/server.go b/internal/api/grpc/admin/server.go index 60808f5b90..42429cb124 100644 --- a/internal/api/grpc/admin/server.go +++ b/internal/api/grpc/admin/server.go @@ -2,6 +2,8 @@ package admin import ( "context" + "time" + "google.golang.org/grpc" "github.com/zitadel/zitadel/internal/admin/repository" @@ -24,13 +26,14 @@ var _ admin.AdminServiceServer = (*Server)(nil) type Server struct { admin.UnimplementedAdminServiceServer - database string - command *command.Commands - query *query.Queries - administrator repository.AdministratorRepository - assetsAPIDomain func(context.Context) string - userCodeAlg crypto.EncryptionAlgorithm - passwordHashAlg crypto.HashAlgorithm + database string + command *command.Commands + query *query.Queries + administrator repository.AdministratorRepository + assetsAPIDomain func(context.Context) string + userCodeAlg crypto.EncryptionAlgorithm + passwordHashAlg crypto.HashAlgorithm + auditLogRetention time.Duration } type Config struct { @@ -45,15 +48,17 @@ func CreateServer( repo repository.Repository, externalSecure bool, userCodeAlg crypto.EncryptionAlgorithm, + auditLogRetention time.Duration, ) *Server { return &Server{ - database: database, - command: command, - query: query, - administrator: repo, - assetsAPIDomain: assets.AssetAPI(externalSecure), - userCodeAlg: userCodeAlg, - passwordHashAlg: crypto.NewBCrypt(sd.SecretGenerators.PasswordSaltCost), + database: database, + command: command, + query: query, + administrator: repo, + assetsAPIDomain: assets.AssetAPI(externalSecure), + userCodeAlg: userCodeAlg, + passwordHashAlg: crypto.NewBCrypt(sd.SecretGenerators.PasswordSaltCost), + auditLogRetention: auditLogRetention, } } diff --git a/internal/api/grpc/auth/user.go b/internal/api/grpc/auth/user.go index 1f15a721b5..41a7fee19f 100644 --- a/internal/api/grpc/auth/user.go +++ b/internal/api/grpc/auth/user.go @@ -11,8 +11,10 @@ import ( user_grpc "github.com/zitadel/zitadel/internal/api/grpc/user" "github.com/zitadel/zitadel/internal/command" "github.com/zitadel/zitadel/internal/domain" + "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore/v1/models" "github.com/zitadel/zitadel/internal/query" + "github.com/zitadel/zitadel/internal/repository/user" auth_pb "github.com/zitadel/zitadel/pkg/grpc/auth" ) @@ -56,13 +58,38 @@ func (s *Server) RemoveMyUser(ctx context.Context, _ *auth_pb.RemoveMyUserReques } func (s *Server) ListMyUserChanges(ctx context.Context, req *auth_pb.ListMyUserChangesRequest) (*auth_pb.ListMyUserChangesResponse, error) { - sequence, limit, asc := change.ChangeQueryToQuery(req.Query) - changes, err := s.query.UserChanges(ctx, authz.GetCtxData(ctx).UserID, sequence, limit, asc, s.auditLogRetention) + var ( + limit uint64 + sequence uint64 + asc bool + ) + if req.Query != nil { + limit = uint64(req.Query.Limit) + sequence = req.Query.Sequence + asc = req.Query.Asc + } + + query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). + AllowTimeTravel(). + Limit(limit). + OrderDesc(). + ResourceOwner(authz.GetCtxData(ctx).ResourceOwner). + AddQuery(). + SequenceGreater(sequence). + AggregateTypes(user.AggregateType). + AggregateIDs(authz.GetCtxData(ctx).UserID). + Builder() + if asc { + query.OrderAsc() + } + + changes, err := s.query.SearchEvents(ctx, query, s.auditLogRetention) if err != nil { return nil, err } + return &auth_pb.ListMyUserChangesResponse{ - Result: change.ChangesToPb(changes.Changes, s.assetsAPIDomain(ctx)), + Result: change.EventsToChangesPb(changes, s.assetsAPIDomain(ctx)), }, nil } diff --git a/internal/api/grpc/change/changes.go b/internal/api/grpc/change/changes.go index a3a35bde1f..2205d89544 100644 --- a/internal/api/grpc/change/changes.go +++ b/internal/api/grpc/change/changes.go @@ -10,30 +10,23 @@ import ( "github.com/zitadel/zitadel/pkg/grpc/message" ) -func ChangeQueryToQuery(query *change_pb.ChangeQuery) (sequence uint64, limit uint64, asc bool) { - if query == nil { - return 0, 0, false - } - return query.Sequence, uint64(query.Limit), query.Asc -} - -func ChangesToPb(changes []*query.Change, assetAPIPrefix string) []*change_pb.Change { +func EventsToChangesPb(changes []*query.Event, assetAPIPrefix string) []*change_pb.Change { c := make([]*change_pb.Change, len(changes)) for i, change := range changes { - c[i] = ChangeToPb(change, assetAPIPrefix) + c[i] = EventToChangePb(change, assetAPIPrefix) } return c } -func ChangeToPb(change *query.Change, assetAPIPrefix string) *change_pb.Change { +func EventToChangePb(change *query.Event, assetAPIPrefix string) *change_pb.Change { return &change_pb.Change{ - ChangeDate: timestamppb.New(change.ChangeDate), - EventType: message.NewLocalizedEventType(change.EventType), + ChangeDate: timestamppb.New(change.CreationDate), + EventType: message.NewLocalizedEventType(change.Type), Sequence: change.Sequence, - EditorId: change.ModifierId, - EditorDisplayName: change.ModifierName, - EditorPreferredLoginName: change.ModifierLoginName, - EditorAvatarUrl: domain.AvatarURL(assetAPIPrefix, change.ModifierResourceOwner, change.ModifierAvatarKey), - ResourceOwnerId: change.ResourceOwner, + EditorId: change.Editor.ID, + EditorDisplayName: change.Editor.DisplayName, + EditorPreferredLoginName: change.Editor.PreferedLoginName, + EditorAvatarUrl: domain.AvatarURL(assetAPIPrefix, change.Aggregate.ResourceOwner, change.Editor.AvatarKey), + ResourceOwnerId: change.Aggregate.ResourceOwner, } } diff --git a/internal/api/grpc/management/org.go b/internal/api/grpc/management/org.go index 138ee752f5..1627530e6c 100644 --- a/internal/api/grpc/management/org.go +++ b/internal/api/grpc/management/org.go @@ -12,8 +12,10 @@ import ( org_grpc "github.com/zitadel/zitadel/internal/api/grpc/org" policy_grpc "github.com/zitadel/zitadel/internal/api/grpc/policy" "github.com/zitadel/zitadel/internal/domain" + "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore/v1/models" "github.com/zitadel/zitadel/internal/query" + "github.com/zitadel/zitadel/internal/repository/org" mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management" ) @@ -35,13 +37,37 @@ func (s *Server) GetOrgByDomainGlobal(ctx context.Context, req *mgmt_pb.GetOrgBy } func (s *Server) ListOrgChanges(ctx context.Context, req *mgmt_pb.ListOrgChangesRequest) (*mgmt_pb.ListOrgChangesResponse, error) { - sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query) - response, err := s.query.OrgChanges(ctx, authz.GetCtxData(ctx).OrgID, sequence, limit, asc, s.auditLogRetention) + var ( + limit uint64 + sequence uint64 + asc bool + ) + if req.Query != nil { + limit = uint64(req.Query.Limit) + sequence = req.Query.Sequence + asc = req.Query.Asc + } + + query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). + AllowTimeTravel(). + Limit(limit). + OrderDesc(). + ResourceOwner(authz.GetCtxData(ctx).OrgID). + AddQuery(). + SequenceGreater(sequence). + AggregateTypes(org.AggregateType). + AggregateIDs(authz.GetCtxData(ctx).OrgID). + Builder() + if asc { + query.OrderAsc() + } + + response, err := s.query.SearchEvents(ctx, query, s.auditLogRetention) if err != nil { return nil, err } return &mgmt_pb.ListOrgChangesResponse{ - Result: change_grpc.ChangesToPb(response.Changes, s.assetAPIPrefix(ctx)), + Result: change_grpc.EventsToChangesPb(response, s.assetAPIPrefix(ctx)), }, nil } diff --git a/internal/api/grpc/management/project.go b/internal/api/grpc/management/project.go index 4ad7ffe97a..f0c1f6cc68 100644 --- a/internal/api/grpc/management/project.go +++ b/internal/api/grpc/management/project.go @@ -8,7 +8,9 @@ import ( member_grpc "github.com/zitadel/zitadel/internal/api/grpc/member" object_grpc "github.com/zitadel/zitadel/internal/api/grpc/object" project_grpc "github.com/zitadel/zitadel/internal/api/grpc/project" + "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/query" + "github.com/zitadel/zitadel/internal/repository/project" mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management" ) @@ -56,13 +58,41 @@ func (s *Server) ListProjects(ctx context.Context, req *mgmt_pb.ListProjectsRequ } func (s *Server) ListProjectGrantChanges(ctx context.Context, req *mgmt_pb.ListProjectGrantChangesRequest) (*mgmt_pb.ListProjectGrantChangesResponse, error) { - sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query) - res, err := s.query.ProjectGrantChanges(ctx, req.ProjectId, req.GrantId, sequence, limit, asc, s.auditLogRetention) + var ( + limit uint64 + sequence uint64 + asc bool + ) + if req.Query != nil { + limit = uint64(req.Query.Limit) + sequence = req.Query.Sequence + asc = req.Query.Asc + } + + query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). + AllowTimeTravel(). + Limit(limit). + OrderDesc(). + ResourceOwner(authz.GetCtxData(ctx).OrgID). + AddQuery(). + SequenceGreater(sequence). + AggregateTypes(project.AggregateType). + AggregateIDs(req.ProjectId). + EventData(map[string]interface{}{ + "grantId": req.GrantId, + }). + Builder() + if asc { + query.OrderAsc() + } + + changes, err := s.query.SearchEvents(ctx, query, s.auditLogRetention) if err != nil { return nil, err } + return &mgmt_pb.ListProjectGrantChangesResponse{ - Result: change_grpc.ChangesToPb(res.Changes, s.assetAPIPrefix(ctx)), + Result: change_grpc.EventsToChangesPb(changes, s.assetAPIPrefix(ctx)), }, nil } @@ -109,13 +139,38 @@ func (s *Server) ListGrantedProjectRoles(ctx context.Context, req *mgmt_pb.ListG } func (s *Server) ListProjectChanges(ctx context.Context, req *mgmt_pb.ListProjectChangesRequest) (*mgmt_pb.ListProjectChangesResponse, error) { - sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query) - res, err := s.query.ProjectChanges(ctx, req.ProjectId, sequence, limit, asc, s.auditLogRetention) + var ( + limit uint64 + sequence uint64 + asc bool + ) + if req.Query != nil { + limit = uint64(req.Query.Limit) + sequence = req.Query.Sequence + asc = req.Query.Asc + } + + query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). + AllowTimeTravel(). + Limit(limit). + OrderDesc(). + ResourceOwner(authz.GetCtxData(ctx).OrgID). + AddQuery(). + SequenceGreater(sequence). + AggregateTypes(project.AggregateType). + AggregateIDs(req.ProjectId). + Builder() + if asc { + query.OrderAsc() + } + + changes, err := s.query.SearchEvents(ctx, query, s.auditLogRetention) if err != nil { return nil, err } + return &mgmt_pb.ListProjectChangesResponse{ - Result: change_grpc.ChangesToPb(res.Changes, s.assetAPIPrefix(ctx)), + Result: change_grpc.EventsToChangesPb(changes, s.assetAPIPrefix(ctx)), }, nil } diff --git a/internal/api/grpc/management/project_application.go b/internal/api/grpc/management/project_application.go index 422f2bf4b7..a6b5841c5e 100644 --- a/internal/api/grpc/management/project_application.go +++ b/internal/api/grpc/management/project_application.go @@ -9,7 +9,9 @@ import ( object_grpc "github.com/zitadel/zitadel/internal/api/grpc/object" project_grpc "github.com/zitadel/zitadel/internal/api/grpc/project" "github.com/zitadel/zitadel/internal/domain" + "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/query" + "github.com/zitadel/zitadel/internal/repository/project" mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management" ) @@ -39,13 +41,41 @@ func (s *Server) ListApps(ctx context.Context, req *mgmt_pb.ListAppsRequest) (*m } func (s *Server) ListAppChanges(ctx context.Context, req *mgmt_pb.ListAppChangesRequest) (*mgmt_pb.ListAppChangesResponse, error) { - sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query) - res, err := s.query.ApplicationChanges(ctx, req.ProjectId, req.AppId, sequence, limit, asc, s.auditLogRetention) + var ( + limit uint64 + sequence uint64 + asc bool + ) + if req.Query != nil { + limit = uint64(req.Query.Limit) + sequence = req.Query.Sequence + asc = req.Query.Asc + } + + query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). + AllowTimeTravel(). + Limit(limit). + OrderDesc(). + ResourceOwner(authz.GetCtxData(ctx).OrgID). + AddQuery(). + SequenceGreater(sequence). + AggregateTypes(project.AggregateType). + AggregateIDs(req.ProjectId). + EventData(map[string]interface{}{ + "appId": req.AppId, + }). + Builder() + if asc { + query.OrderAsc() + } + + changes, err := s.query.SearchEvents(ctx, query, s.auditLogRetention) if err != nil { return nil, err } + return &mgmt_pb.ListAppChangesResponse{ - Result: change_grpc.ChangesToPb(res.Changes, s.assetAPIPrefix(ctx)), + Result: change_grpc.EventsToChangesPb(changes, s.assetAPIPrefix(ctx)), }, nil } diff --git a/internal/api/grpc/management/user.go b/internal/api/grpc/management/user.go index 035e9e833d..58092dc739 100644 --- a/internal/api/grpc/management/user.go +++ b/internal/api/grpc/management/user.go @@ -20,7 +20,9 @@ import ( "github.com/zitadel/zitadel/internal/api/ui/login" "github.com/zitadel/zitadel/internal/command" "github.com/zitadel/zitadel/internal/domain" + "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/query" + "github.com/zitadel/zitadel/internal/repository/user" mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management" ) @@ -73,13 +75,38 @@ func (s *Server) ListUsers(ctx context.Context, req *mgmt_pb.ListUsersRequest) ( } func (s *Server) ListUserChanges(ctx context.Context, req *mgmt_pb.ListUserChangesRequest) (*mgmt_pb.ListUserChangesResponse, error) { - sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query) - res, err := s.query.UserChanges(ctx, req.UserId, sequence, limit, asc, s.auditLogRetention) + var ( + limit uint64 + sequence uint64 + asc bool + ) + if req.Query != nil { + limit = uint64(req.Query.Limit) + sequence = req.Query.Sequence + asc = req.Query.Asc + } + + query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). + AllowTimeTravel(). + Limit(limit). + OrderDesc(). + ResourceOwner(authz.GetCtxData(ctx).OrgID). + AddQuery(). + SequenceGreater(sequence). + AggregateTypes(user.AggregateType). + AggregateIDs(req.UserId). + Builder() + if asc { + query.OrderAsc() + } + + changes, err := s.query.SearchEvents(ctx, query, s.auditLogRetention) if err != nil { return nil, err } + return &mgmt_pb.ListUserChangesResponse{ - Result: change_grpc.ChangesToPb(res.Changes, s.assetAPIPrefix(ctx)), + Result: change_grpc.EventsToChangesPb(changes, s.assetAPIPrefix(ctx)), }, nil } diff --git a/internal/query/changes.go b/internal/query/changes.go deleted file mode 100644 index 43669f3d32..0000000000 --- a/internal/query/changes.go +++ /dev/null @@ -1,145 +0,0 @@ -package query - -import ( - "context" - "time" - - "github.com/zitadel/logging" - - "github.com/zitadel/zitadel/internal/errors" - "github.com/zitadel/zitadel/internal/eventstore" - "github.com/zitadel/zitadel/internal/repository/org" - "github.com/zitadel/zitadel/internal/repository/project" - "github.com/zitadel/zitadel/internal/repository/user" - "github.com/zitadel/zitadel/internal/telemetry/tracing" -) - -type Changes struct { - Changes []*Change -} - -type Change struct { - ChangeDate time.Time - EventType string - Sequence uint64 - ResourceOwner string - ModifierId string - ModifierName string - ModifierLoginName string - ModifierResourceOwner string - ModifierAvatarKey string -} - -func (q *Queries) OrgChanges(ctx context.Context, orgID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (_ *Changes, err error) { - ctx, span := tracing.NewSpan(ctx) - defer func() { span.EndWithError(err) }() - - query := func(query *eventstore.SearchQuery) { - query.AggregateTypes(org.AggregateType). - AggregateIDs(orgID) - } - return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention) - -} - -func (q *Queries) ProjectChanges(ctx context.Context, projectID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (_ *Changes, err error) { - ctx, span := tracing.NewSpan(ctx) - defer func() { span.EndWithError(err) }() - - query := func(query *eventstore.SearchQuery) { - query.AggregateTypes(project.AggregateType). - AggregateIDs(projectID) - } - return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention) -} - -func (q *Queries) ProjectGrantChanges(ctx context.Context, projectID, grantID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (_ *Changes, err error) { - ctx, span := tracing.NewSpan(ctx) - defer func() { span.EndWithError(err) }() - - query := func(query *eventstore.SearchQuery) { - query.AggregateTypes(project.AggregateType). - AggregateIDs(projectID). - EventData(map[string]interface{}{ - "grantId": grantID, - }) - } - return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention) -} - -func (q *Queries) ApplicationChanges(ctx context.Context, projectID, appID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (_ *Changes, err error) { - ctx, span := tracing.NewSpan(ctx) - defer func() { span.EndWithError(err) }() - - query := func(query *eventstore.SearchQuery) { - query.AggregateTypes(project.AggregateType). - AggregateIDs(projectID). - EventData(map[string]interface{}{ - "appId": appID, - }) - } - return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention) -} - -func (q *Queries) UserChanges(ctx context.Context, userID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (_ *Changes, err error) { - ctx, span := tracing.NewSpan(ctx) - defer func() { span.EndWithError(err) }() - - query := func(query *eventstore.SearchQuery) { - query.AggregateTypes(user.AggregateType). - AggregateIDs(userID) - } - return q.changes(ctx, query, lastSequence, limit, sortAscending, auditLogRetention) -} - -func (q *Queries) changes(ctx context.Context, query func(query *eventstore.SearchQuery), lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) { - builder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(limit).AllowTimeTravel() - if !sortAscending { - builder.OrderDesc() - } - search := builder.AddQuery().SequenceGreater(lastSequence) //always use greater (less is done automatically by sorting desc) - query(search) - - events, err := q.eventstore.Filter(ctx, builder) - if err != nil { - logging.Log("QUERY-ZRffs").WithError(err).Warn("eventstore unavailable") - return nil, errors.ThrowInternal(err, "QUERY-328b1", "Errors.Internal") - } - if len(events) == 0 { - return nil, errors.ThrowNotFound(nil, "QUERY-FpQqK", "Errors.Changes.NotFound") - } - changes := make([]*Change, 0, len(events)) - for _, event := range events { - if auditLogRetention != 0 && event.CreationDate().Before(time.Now().Add(-auditLogRetention)) { - continue - } - change := &Change{ - ChangeDate: event.CreationDate(), - EventType: string(event.Type()), - Sequence: event.Sequence(), - ResourceOwner: event.Aggregate().ResourceOwner, - ModifierId: event.EditorUser(), - ModifierName: event.EditorUser(), - ModifierLoginName: event.EditorUser(), - } - editor, _ := q.GetUserByID(ctx, false, change.ModifierId, false) - if editor != nil { - change.ModifierLoginName = editor.PreferredLoginName - change.ModifierResourceOwner = editor.ResourceOwner - if editor.Human != nil { - change.ModifierName = editor.Human.DisplayName - change.ModifierAvatarKey = editor.Human.AvatarKey - } - if editor.Machine != nil { - change.ModifierName = editor.Machine.Name - } - } - changes = append(changes, change) - } - if len(changes) == 0 { - return nil, errors.ThrowPreconditionFailed(nil, "QUERY-DEGS2", "Errors.Changes.AuditRetention") - } - return &Changes{ - Changes: changes, - }, nil -} diff --git a/internal/query/event.go b/internal/query/event.go index d5c4462a63..6d238ebabe 100644 --- a/internal/query/event.go +++ b/internal/query/event.go @@ -4,6 +4,7 @@ import ( "context" "time" + "github.com/zitadel/zitadel/internal/api/call" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/telemetry/tracing" ) @@ -18,12 +19,14 @@ type Event struct { } type EventEditor struct { - ID string - DisplayName string - Service string + ID string + DisplayName string + Service string + PreferedLoginName string + AvatarKey string } -func (q *Queries) SearchEvents(ctx context.Context, query *eventstore.SearchQueryBuilder) (_ []*Event, err error) { +func (q *Queries) SearchEvents(ctx context.Context, query *eventstore.SearchQueryBuilder, auditLogRetention time.Duration) (_ []*Event, err error) { ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() events, err := q.eventstore.Filter(ctx, query.AllowTimeTravel()) @@ -31,7 +34,18 @@ func (q *Queries) SearchEvents(ctx context.Context, query *eventstore.SearchQuer return nil, err } - return q.convertEvents(ctx, events), nil + callTime := call.FromContext(ctx) + if callTime.IsZero() { + callTime = time.Now() + } + for i, event := range events { + if event.CreationDate().Before(callTime.Add(-auditLogRetention)) { + events = events[:i] + break + } + } + + return q.convertEvents(ctx, events, auditLogRetention), nil } func (q *Queries) SearchEventTypes(ctx context.Context) []string { @@ -42,31 +56,33 @@ func (q *Queries) SearchAggregateTypes(ctx context.Context) []string { return q.eventstore.AggregateTypes() } -func (q *Queries) convertEvents(ctx context.Context, events []eventstore.Event) []*Event { +func (q *Queries) convertEvents(ctx context.Context, events []eventstore.Event, auditLogRetention time.Duration) []*Event { result := make([]*Event, len(events)) - users := make(map[string]string) + users := make(map[string]*EventEditor) for i, event := range events { result[i] = q.convertEvent(ctx, event, users) } return result } -func (q *Queries) convertEvent(ctx context.Context, event eventstore.Event, users map[string]string) *Event { +func (q *Queries) convertEvent(ctx context.Context, event eventstore.Event, users map[string]*EventEditor) *Event { ctx, span := tracing.NewSpan(ctx) var err error defer func() { span.EndWithError(err) }() - displayName, ok := users[event.EditorUser()] + editor, ok := users[event.EditorUser()] if !ok { - displayName = q.editorUserByID(ctx, event.EditorUser()) - users[event.EditorUser()] = displayName + editor = q.editorUserByID(ctx, event.EditorUser()) + users[event.EditorUser()] = editor } return &Event{ Editor: &EventEditor{ - ID: event.EditorUser(), - Service: event.EditorService(), - DisplayName: displayName, + ID: event.EditorUser(), + Service: event.EditorService(), + DisplayName: editor.DisplayName, + PreferedLoginName: editor.PreferedLoginName, + AvatarKey: editor.AvatarKey, }, Aggregate: event.Aggregate(), Sequence: event.Sequence(), @@ -76,15 +92,25 @@ func (q *Queries) convertEvent(ctx context.Context, event eventstore.Event, user } } -func (q *Queries) editorUserByID(ctx context.Context, userID string) string { +func (q *Queries) editorUserByID(ctx context.Context, userID string) *EventEditor { user, err := q.GetUserByID(ctx, false, userID, false) if err != nil { - return userID + return &EventEditor{ID: userID} } + if user.Human != nil { - return user.Human.DisplayName + return &EventEditor{ + ID: user.ID, + DisplayName: user.Human.DisplayName, + PreferedLoginName: user.PreferredLoginName, + AvatarKey: user.Human.AvatarKey, + } } else if user.Machine != nil { - return user.Machine.Name + return &EventEditor{ + ID: user.ID, + DisplayName: user.Machine.Name, + PreferedLoginName: user.PreferredLoginName, + } } - return userID + return &EventEditor{ID: userID} }