From 1b6e3dcf2723ff77b3df9a8c59e2d5bdad99e015 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Fri, 3 Nov 2023 15:52:48 +0100 Subject: [PATCH] fix: creation date argument in search events filters (#6855) * fix: creation date filter in event queries * fix: creation date with ordering filter * simplify code * simplify review --------- Co-authored-by: Livio Spring --- internal/api/grpc/admin/event.go | 6 ++++-- internal/eventstore/repository/search_query.go | 16 +++++++++++++--- internal/eventstore/repository/sql/query.go | 9 ++++++++- internal/eventstore/search_query.go | 14 ++++++++++++++ internal/query/event.go | 8 +++++++- proto/zitadel/admin.proto | 2 +- 6 files changed, 47 insertions(+), 8 deletions(-) diff --git a/internal/api/grpc/admin/event.go b/internal/api/grpc/admin/event.go index 434290d8e..72adfa015 100644 --- a/internal/api/grpc/admin/event.go +++ b/internal/api/grpc/admin/event.go @@ -60,7 +60,6 @@ func eventRequestToFilter(ctx context.Context, req *admin_pb.ListEventsRequest) AwaitOpenTransactions(). ResourceOwner(req.ResourceOwner). EditorUser(req.EditorUserId). - CreationDateAfter(req.CreationDate.AsTime()). SequenceGreater(req.Sequence) if len(aggregateIDs) > 0 || len(aggregateTypes) > 0 || len(eventTypes) > 0 { @@ -71,8 +70,11 @@ func eventRequestToFilter(ctx context.Context, req *admin_pb.ListEventsRequest) Builder() } - if req.Asc { + if req.GetAsc() { builder.OrderAsc() + builder.CreationDateAfter(req.CreationDate.AsTime()) + } else { + builder.CreationDateBefore(req.CreationDate.AsTime()) } return builder, nil diff --git a/internal/eventstore/repository/search_query.go b/internal/eventstore/repository/search_query.go index 7c2ff31eb..aa1068c1f 100644 --- a/internal/eventstore/repository/search_query.go +++ b/internal/eventstore/repository/search_query.go @@ -25,7 +25,8 @@ type SearchQuery struct { Owner *Filter Position *Filter Sequence *Filter - CreatedAt *Filter + CreatedAfter *Filter + CreatedBefore *Filter } // Filter represents all fields needed to compare a field of an event with a value @@ -136,6 +137,7 @@ func QueryFromBuilder(builder *eventstore.SearchQueryBuilder) (*SearchQuery, err positionAfterFilter, eventSequenceGreaterFilter, creationDateAfterFilter, + creationDateBeforeFilter, } { filter := f(builder, query) if filter == nil { @@ -191,8 +193,16 @@ func creationDateAfterFilter(builder *eventstore.SearchQueryBuilder, query *Sear if builder.GetCreationDateAfter().IsZero() { return nil } - query.CreatedAt = NewFilter(FieldCreationDate, builder.GetCreationDateAfter(), OperationGreater) - return query.CreatedAt + query.CreatedAfter = NewFilter(FieldCreationDate, builder.GetCreationDateAfter(), OperationGreater) + return query.CreatedAfter +} + +func creationDateBeforeFilter(builder *eventstore.SearchQueryBuilder, query *SearchQuery) *Filter { + if builder.GetCreationDateBefore().IsZero() { + return nil + } + query.CreatedBefore = NewFilter(FieldCreationDate, builder.GetCreationDateBefore(), OperationLess) + return query.CreatedBefore } func resourceOwnerFilter(builder *eventstore.SearchQueryBuilder, query *SearchQuery) *Filter { diff --git a/internal/eventstore/repository/sql/query.go b/internal/eventstore/repository/sql/query.go index aab8abbcf..438ed9a13 100644 --- a/internal/eventstore/repository/sql/query.go +++ b/internal/eventstore/repository/sql/query.go @@ -239,7 +239,14 @@ func prepareConditions(criteria querier, query *repository.SearchQuery, useV1 bo clauses += "(" + strings.Join(subClauses, " OR ") + ")" } - additionalClauses, additionalArgs := prepareQuery(criteria, useV1, query.Position, query.Owner, query.Sequence, query.CreatedAt, query.Creator) + additionalClauses, additionalArgs := prepareQuery(criteria, useV1, + query.Position, + query.Owner, + query.Sequence, + query.CreatedAfter, + query.CreatedBefore, + query.Creator, + ) if additionalClauses != "" { if clauses != "" { clauses += " AND " diff --git a/internal/eventstore/search_query.go b/internal/eventstore/search_query.go index 2b102db9f..3f0212eb2 100644 --- a/internal/eventstore/search_query.go +++ b/internal/eventstore/search_query.go @@ -25,6 +25,7 @@ type SearchQueryBuilder struct { positionAfter float64 awaitOpenTransactions bool creationDateAfter time.Time + creationDateBefore time.Time eventSequenceGreater uint64 } @@ -84,6 +85,10 @@ func (q SearchQueryBuilder) GetCreationDateAfter() time.Time { return q.creationDateAfter } +func (q SearchQueryBuilder) GetCreationDateBefore() time.Time { + return q.creationDateBefore +} + // ensureInstanceID makes sure that the instance id is always set func (b *SearchQueryBuilder) ensureInstanceID(ctx context.Context) { if b.instanceID == nil && authz.GetInstance(ctx).InstanceID() != "" { @@ -256,6 +261,15 @@ func (builder *SearchQueryBuilder) CreationDateAfter(creationDate time.Time) *Se return builder } +// CreationDateBefore filters for events which happened before the specified time +func (builder *SearchQueryBuilder) CreationDateBefore(creationDate time.Time) *SearchQueryBuilder { + if creationDate.IsZero() || creationDate.Unix() == 0 { + return builder + } + builder.creationDateBefore = creationDate + return builder +} + // AddQuery creates a new sub query. // All fields in the sub query are AND-connected in the storage request. // Multiple sub queries are OR-connected in the storage request. diff --git a/internal/query/event.go b/internal/query/event.go index c387c045a..c44187d9a 100644 --- a/internal/query/event.go +++ b/internal/query/event.go @@ -66,7 +66,13 @@ func filterAuditLogRetention(ctx context.Context, auditLogRetention time.Duratio if callTime.IsZero() { callTime = time.Now() } - return builder.CreationDateAfter(callTime.Add(-auditLogRetention)) + oldestAllowed := callTime.Add(-auditLogRetention) + // The audit log retention time should overwrite the creation date after query only if it is older + // For example API calls should still be able to restrict the creation date after to a more recent date + if builder.GetCreationDateAfter().Before(oldestAllowed) { + return builder.CreationDateAfter(oldestAllowed) + } + return builder } func (q *Queries) SearchEventTypes(ctx context.Context) []string { diff --git a/proto/zitadel/admin.proto b/proto/zitadel/admin.proto index 1a67f03a4..fec52b103 100644 --- a/proto/zitadel/admin.proto +++ b/proto/zitadel/admin.proto @@ -7894,7 +7894,7 @@ message ListEventsRequest { google.protobuf.Timestamp creation_date = 9 [ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { example: "\"2019-04-01T08:45:00.000000Z\""; - description: "If asc is false creation_date is used as less than filter If asc is true creation_date is used as greater than filter. If creation_date is not set the field is ignored."; + description: "If asc is false, the events returned are older than creation_date. If asc is true, the events returned are younger than creation_date. If creation_date is not set the field is ignored."; } ]; }