- |
+ |
{{ 'IAM.EVENTS.SEQUENCE' | translate }}
|
@@ -81,10 +81,12 @@
- | {{ 'IAM.EVENTS.CREATIONDATE' | translate }} |
+
+ {{ 'IAM.EVENTS.CREATIONDATE' | translate }}
+ |
- {{ event?.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}
+ {{ event?.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm:ss' }}
|
diff --git a/console/src/app/pages/events/events.component.ts b/console/src/app/pages/events/events.component.ts
index 41f520a7a..c6dd22fc8 100644
--- a/console/src/app/pages/events/events.component.ts
+++ b/console/src/app/pages/events/events.component.ts
@@ -176,13 +176,13 @@ export class EventsComponent implements OnDestroy {
req.setEditorUserId(filterRequest.getEditorUserId());
req.setResourceOwner(filterRequest.getResourceOwner());
req.setSequence(filterRequest.getSequence());
- req.setCreationDate(filterRequest.getCreationDate());
+ req.setRange(filterRequest.getRange());
+ req.setFrom(filterRequest.getFrom());
const isAsc: boolean = filterRequest.getAsc();
req.setAsc(isAsc);
if (this.sortAsc !== isAsc) {
- this.sort.sort({ id: 'sequence', start: isAsc ? 'asc' : 'desc', disableClear: true });
+ this.sort.sort({ id: 'creationDate', start: isAsc ? 'asc' : 'desc', disableClear: true });
}
-
this.loadEvents(req, true);
}
diff --git a/console/src/assets/i18n/bg.json b/console/src/assets/i18n/bg.json
index e3a1e7876..349a8496a 100644
--- a/console/src/assets/i18n/bg.json
+++ b/console/src/assets/i18n/bg.json
@@ -865,14 +865,16 @@
},
"SEQUENCE": {
"LABEL": "Последователност",
- "CHECKBOX": "Филтриране по последователност",
- "SORT": "Сортиране",
- "ASC": "Възходящ",
- "DESC": "Спускане"
+ "CHECKBOX": "Филтриране по последователност"
},
+ "SORT": "Сортиране",
+ "ASC": "Възходящ",
+ "DESC": "Спускане",
"CREATIONDATE": {
- "LABEL": "Дата на създаване",
- "CHECKBOX": "Филтриране по дата на създаване"
+ "RADIO_FROM": "От",
+ "RADIO_RANGE": "Обхват",
+ "LABEL_SINCE": "От",
+ "LABEL_UNTIL": "До"
},
"OTHER": "друго",
"OTHERS": "други"
diff --git a/console/src/assets/i18n/cs.json b/console/src/assets/i18n/cs.json
index ead54bb53..2da0d463e 100644
--- a/console/src/assets/i18n/cs.json
+++ b/console/src/assets/i18n/cs.json
@@ -872,14 +872,16 @@
},
"SEQUENCE": {
"LABEL": "Sekvence",
- "CHECKBOX": "Filtrovat podle Sekvence",
- "SORT": "Třídění",
- "ASC": "Vzestupně",
- "DESC": "Sestupně"
+ "CHECKBOX": "Filtrovat podle Sekvence"
},
+ "SORT": "Třídění",
+ "ASC": "Vzestupně",
+ "DESC": "Sestupně",
"CREATIONDATE": {
- "LABEL": "Datum vytvoření",
- "CHECKBOX": "Filtrovat podle Datumu vytvoření"
+ "RADIO_FROM": "Od",
+ "RADIO_RANGE": "Rozsah",
+ "LABEL_SINCE": "Od",
+ "LABEL_UNTIL": "Do"
},
"OTHER": "jiný",
"OTHERS": "jiné"
diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json
index 1afe195e0..c2c28c751 100644
--- a/console/src/assets/i18n/de.json
+++ b/console/src/assets/i18n/de.json
@@ -871,14 +871,16 @@
},
"SEQUENCE": {
"LABEL": "Sequenz",
- "CHECKBOX": "Nach Sequenz filtern",
- "SORT": "Sortierung",
- "ASC": "aufsteigend",
- "DESC": "absteigend"
+ "CHECKBOX": "Nach Sequenz filtern"
},
+ "SORT": "Sortierung",
+ "ASC": "Aufsteigend",
+ "DESC": "Absteigend",
"CREATIONDATE": {
- "LABEL": "Erstelldatum",
- "CHECKBOX": "Nach Erstelldatum filtern"
+ "RADIO_FROM": "Von",
+ "RADIO_RANGE": "Zeitraum",
+ "LABEL_SINCE": "Seit",
+ "LABEL_UNTIL": "Bis"
},
"OTHER": "weiterer",
"OTHERS": "weitere"
diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json
index 5b96e6e8d..38066e722 100644
--- a/console/src/assets/i18n/en.json
+++ b/console/src/assets/i18n/en.json
@@ -872,14 +872,16 @@
},
"SEQUENCE": {
"LABEL": "Sequence",
- "CHECKBOX": "Filter by Sequence",
- "SORT": "Sorting",
- "ASC": "Ascending",
- "DESC": "Descending"
+ "CHECKBOX": "Filter by Sequence"
},
+ "SORT": "Sort",
+ "ASC": "Ascending",
+ "DESC": "Descending",
"CREATIONDATE": {
- "LABEL": "Creation Date",
- "CHECKBOX": "Filter by Creation Date"
+ "RADIO_FROM": "From",
+ "RADIO_RANGE": "Range",
+ "LABEL_SINCE": "Since",
+ "LABEL_UNTIL": "Until"
},
"OTHER": "other",
"OTHERS": "others"
diff --git a/console/src/assets/i18n/es.json b/console/src/assets/i18n/es.json
index 7be679000..c2444c228 100644
--- a/console/src/assets/i18n/es.json
+++ b/console/src/assets/i18n/es.json
@@ -872,14 +872,16 @@
},
"SEQUENCE": {
"LABEL": "Secuencia",
- "CHECKBOX": "Filtrar por secuencia",
- "SORT": "Ordenado",
- "ASC": "Ascendente",
- "DESC": "Descendente"
+ "CHECKBOX": "Filtrar por secuencia"
},
+ "SORT": "Ordenado",
+ "ASC": "Ascendente",
+ "DESC": "Descendente",
"CREATIONDATE": {
- "LABEL": "Fecha de creación",
- "CHECKBOX": "Filtrar por fecha de creación"
+ "RADIO_FROM": "Desde",
+ "RADIO_RANGE": "Rango",
+ "LABEL_SINCE": "Desde",
+ "LABEL_UNTIL": "Hasta"
},
"OTHER": "otro",
"OTHERS": "otros"
diff --git a/console/src/assets/i18n/fr.json b/console/src/assets/i18n/fr.json
index 3659d9000..bcb2a9d50 100644
--- a/console/src/assets/i18n/fr.json
+++ b/console/src/assets/i18n/fr.json
@@ -871,14 +871,16 @@
},
"SEQUENCE": {
"LABEL": "séquence",
- "CHECKBOX": "Filtrer par séquence",
- "SORT": "Triage",
- "ASC": "Ascendant",
- "DESC": "Descendant"
+ "CHECKBOX": "Filtrer par séquence"
},
+ "SORT": "Triage",
+ "ASC": "Ascendant",
+ "DESC": "Descendant",
"CREATIONDATE": {
- "LABEL": "Date de création",
- "CHECKBOX": "Filtrer par date de création"
+ "RADIO_FROM": "De",
+ "RADIO_RANGE": "Gamme",
+ "LABEL_SINCE": "Depuis",
+ "LABEL_UNTIL": "Jusqu'à"
},
"OTHER": "autre",
"OTHERS": "autres"
diff --git a/console/src/assets/i18n/it.json b/console/src/assets/i18n/it.json
index 97c890eed..e3feb17fd 100644
--- a/console/src/assets/i18n/it.json
+++ b/console/src/assets/i18n/it.json
@@ -870,14 +870,16 @@
},
"SEQUENCE": {
"LABEL": "Sequence",
- "CHECKBOX": "Filter per sequenza",
- "SORT": "",
- "ASC": "Ascending",
- "DESC": "Descending"
+ "CHECKBOX": "Filter per sequenza"
},
+ "SORT": "Ordina per",
+ "ASC": "Ascendente",
+ "DESC": "Discendente",
"CREATIONDATE": {
- "LABEL": "Creation Date",
- "CHECKBOX": "Filter by Creation Date"
+ "RADIO_FROM": "Da",
+ "RADIO_RANGE": "Intervallo",
+ "LABEL_SINCE": "Da",
+ "LABEL_UNTIL": "A"
},
"OTHER": "altro",
"OTHERS": "altri"
diff --git a/console/src/assets/i18n/ja.json b/console/src/assets/i18n/ja.json
index 0977ea2be..036eef223 100644
--- a/console/src/assets/i18n/ja.json
+++ b/console/src/assets/i18n/ja.json
@@ -872,14 +872,16 @@
},
"SEQUENCE": {
"LABEL": "シーケンス",
- "CHECKBOX": "シーケンスで絞り込み",
- "SORT": "ソート",
- "ASC": "昇順",
- "DESC": "降順"
+ "CHECKBOX": "シーケンスで絞り込み"
},
+ "SORT": "ソート",
+ "ASC": "昇順",
+ "DESC": "降順",
"CREATIONDATE": {
- "LABEL": "作成日",
- "CHECKBOX": "作成日で絞り込み"
+ "RADIO_FROM": "から",
+ "RADIO_RANGE": "範囲",
+ "LABEL_SINCE": "以降",
+ "LABEL_UNTIL": "まで"
},
"OTHER": "その他",
"OTHERS": "その他"
diff --git a/console/src/assets/i18n/mk.json b/console/src/assets/i18n/mk.json
index 34810be3c..54d1053ae 100644
--- a/console/src/assets/i18n/mk.json
+++ b/console/src/assets/i18n/mk.json
@@ -872,14 +872,16 @@
},
"SEQUENCE": {
"LABEL": "Секвенца",
- "CHECKBOX": "Филтер според секвенцата",
- "SORT": "Сортирање",
- "ASC": "Растечки",
- "DESC": "Опаѓачки"
+ "CHECKBOX": "Филтер според секвенцата"
},
+ "SORT": "Сортирање",
+ "ASC": "Растечки",
+ "DESC": "Опаѓачки",
"CREATIONDATE": {
- "LABEL": "Датум на креирање",
- "CHECKBOX": "Филтер според датумот на креирање"
+ "RADIO_FROM": "Од",
+ "RADIO_RANGE": "Ранг",
+ "LABEL_SINCE": "Од",
+ "LABEL_UNTIL": "До"
},
"OTHER": "друго",
"OTHERS": "други"
diff --git a/console/src/assets/i18n/nl.json b/console/src/assets/i18n/nl.json
index cb8c5dc55..9a1614799 100644
--- a/console/src/assets/i18n/nl.json
+++ b/console/src/assets/i18n/nl.json
@@ -872,14 +872,16 @@
},
"SEQUENCE": {
"LABEL": "Reeks",
- "CHECKBOX": "Filter op Reeks",
- "SORT": "Sortering",
- "ASC": "Oplopend",
- "DESC": "Aflopend"
+ "CHECKBOX": "Filter op Reeks"
},
+ "SORT": "Sortering",
+ "ASC": "Oplopend",
+ "DESC": "Aflopend",
"CREATIONDATE": {
- "LABEL": "Aanmaakdatum",
- "CHECKBOX": "Filter op Aanmaakdatum"
+ "RADIO_FROM": "Van",
+ "RADIO_RANGE": "Reeks",
+ "LABEL_SINCE": "Sinds",
+ "LABEL_UNTIL": "Tot"
},
"OTHER": "ander",
"OTHERS": "anderen"
diff --git a/console/src/assets/i18n/pl.json b/console/src/assets/i18n/pl.json
index aa48a434a..4c5c20068 100644
--- a/console/src/assets/i18n/pl.json
+++ b/console/src/assets/i18n/pl.json
@@ -871,14 +871,16 @@
},
"SEQUENCE": {
"LABEL": "Sekwencja",
- "CHECKBOX": "Filtruj według sekwencji",
- "SORT": "Sortowanie",
- "ASC": "Rosnące",
- "DESC": "Malejące"
+ "CHECKBOX": "Filtruj według sekwencji"
},
+ "SORT": "Sortowanie",
+ "ASC": "Rosnące",
+ "DESC": "Malejące",
"CREATIONDATE": {
- "LABEL": "Data utworzenia",
- "CHECKBOX": "Filtruj według daty utworzenia"
+ "RADIO_FROM": "Od",
+ "RADIO_RANGE": "Zakres",
+ "LABEL_SINCE": "Od",
+ "LABEL_UNTIL": "Do"
},
"OTHER": "inne",
"OTHERS": "inni"
diff --git a/console/src/assets/i18n/pt.json b/console/src/assets/i18n/pt.json
index 69984728b..6535c5b95 100644
--- a/console/src/assets/i18n/pt.json
+++ b/console/src/assets/i18n/pt.json
@@ -872,14 +872,16 @@
},
"SEQUENCE": {
"LABEL": "Sequência",
- "CHECKBOX": "Filtrar por Sequência",
- "SORT": "Ordenação",
- "ASC": "Crescente",
- "DESC": "Decrescente"
+ "CHECKBOX": "Filtrar por Sequência"
},
+ "SORT": "Ordenação",
+ "ASC": "Crescente",
+ "DESC": "Decrescente",
"CREATIONDATE": {
- "LABEL": "Data de Criação",
- "CHECKBOX": "Filtrar por Data de Criação"
+ "RADIO_FROM": "Desde",
+ "RADIO_RANGE": "Intervalo",
+ "LABEL_SINCE": "Desde",
+ "LABEL_UNTIL": "Até"
},
"OTHER": "outro",
"OTHERS": "outros"
diff --git a/console/src/assets/i18n/ru.json b/console/src/assets/i18n/ru.json
index 02c023f5b..f147f8fb3 100644
--- a/console/src/assets/i18n/ru.json
+++ b/console/src/assets/i18n/ru.json
@@ -868,14 +868,16 @@
},
"SEQUENCE": {
"LABEL": "Последовательность",
- "CHECKBOX": "Фильтровать по последовательности",
- "SORT": "Сортировка",
- "ASC": "Восходящий",
- "DESC": "По убыванию"
+ "CHECKBOX": "Фильтровать по последовательности"
},
+ "SORT": "Сортировка",
+ "ASC": "Восходящий",
+ "DESC": "По убыванию",
"CREATIONDATE": {
- "LABEL": "Дата создания",
- "CHECKBOX": "Фильтровать по дате создания"
+ "RADIO_FROM": "От",
+ "RADIO_RANGE": "Диапазон",
+ "LABEL_SINCE": "С",
+ "LABEL_UNTIL": "К"
},
"OTHER": "другой",
"OTHERS": "другие"
diff --git a/console/src/assets/i18n/zh.json b/console/src/assets/i18n/zh.json
index d1eb3551d..e6cb353a8 100644
--- a/console/src/assets/i18n/zh.json
+++ b/console/src/assets/i18n/zh.json
@@ -871,14 +871,16 @@
},
"SEQUENCE": {
"LABEL": "序列",
- "CHECKBOX": "按顺序过滤",
- "SORT": "分拣",
- "ASC": "上升中",
- "DESC": "下降"
+ "CHECKBOX": "按顺序过滤"
},
+ "SORT": "分拣",
+ "ASC": "上升中",
+ "DESC": "下降",
"CREATIONDATE": {
- "LABEL": "创建日期",
- "CHECKBOX": "按创建日期过滤"
+ "RADIO_FROM": "从",
+ "RADIO_RANGE": "范围",
+ "LABEL_SINCE": "自从",
+ "LABEL_UNTIL": "直到"
},
"OTHER": "其他",
"OTHERS": "其他"
diff --git a/e2e/cypress/e2e/events/events.cy.ts b/e2e/cypress/e2e/events/events.cy.ts
index 65362b612..facd298b1 100644
--- a/e2e/cypress/e2e/events/events.cy.ts
+++ b/e2e/cypress/e2e/events/events.cy.ts
@@ -9,9 +9,8 @@ describe('events', () => {
cy.get('[data-e2e="event-type-cell"]').should('have.length', 20);
cy.get('[data-e2e="open-filter-button"]').click();
cy.get('[data-e2e="event-type-filter-checkbox"]').click();
- cy.get('#mat-select-value-1').click();
- cy.contains('mat-option', eventTypeEnglish).click();
- cy.get('body').click();
+ cy.contains('mat-select', 'Descending').click();
+ cy.contains('mat-option', 'Ascending').click();
cy.get('[data-e2e="filter-finish-button"]').click();
cy.contains('[data-e2e="event-type-cell"]', eventTypeEnglish).should('have.length.at.least', 1);
});
diff --git a/internal/api/grpc/admin/event.go b/internal/api/grpc/admin/event.go
index 72adfa015..576fce8af 100644
--- a/internal/api/grpc/admin/event.go
+++ b/internal/api/grpc/admin/event.go
@@ -2,6 +2,7 @@ package admin
import (
"context"
+ "time"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/eventstore"
@@ -36,6 +37,25 @@ func (s *Server) ListAggregateTypes(ctx context.Context, in *admin_pb.ListAggreg
}
func eventRequestToFilter(ctx context.Context, req *admin_pb.ListEventsRequest) (*eventstore.SearchQueryBuilder, error) {
+ var fromTime, sinceTime, untilTime time.Time
+ // We ignore the deprecation warning here because we still need to support the deprecated field.
+ //nolint:staticcheck
+ if creationDatePb := req.GetCreationDate(); creationDatePb != nil {
+ fromTime = creationDatePb.AsTime()
+ }
+ if fromTimePb := req.GetFrom(); fromTimePb != nil {
+ fromTime = fromTimePb.AsTime()
+ }
+ if timeRange := req.GetRange(); timeRange != nil {
+ // If range is set, we ignore the from and the deprecated creation_date fields
+ fromTime = time.Time{}
+ if timeSincePb := timeRange.GetSince(); timeSincePb != nil {
+ sinceTime = timeSincePb.AsTime()
+ }
+ if timeUntilPb := timeRange.GetUntil(); timeUntilPb != nil {
+ untilTime = timeUntilPb.AsTime()
+ }
+ }
eventTypes := make([]eventstore.EventType, len(req.EventTypes))
for i, eventType := range req.EventTypes {
eventTypes[i] = eventstore.EventType(eventType)
@@ -60,7 +80,9 @@ func eventRequestToFilter(ctx context.Context, req *admin_pb.ListEventsRequest)
AwaitOpenTransactions().
ResourceOwner(req.ResourceOwner).
EditorUser(req.EditorUserId).
- SequenceGreater(req.Sequence)
+ SequenceGreater(req.Sequence).
+ CreationDateAfter(sinceTime).
+ CreationDateBefore(untilTime)
if len(aggregateIDs) > 0 || len(aggregateTypes) > 0 || len(eventTypes) > 0 {
builder.AddQuery().
@@ -72,10 +94,9 @@ func eventRequestToFilter(ctx context.Context, req *admin_pb.ListEventsRequest)
if req.GetAsc() {
builder.OrderAsc()
- builder.CreationDateAfter(req.CreationDate.AsTime())
+ builder.CreationDateAfter(fromTime)
} else {
- builder.CreationDateBefore(req.CreationDate.AsTime())
+ builder.CreationDateBefore(fromTime)
}
-
return builder, nil
}
diff --git a/internal/api/grpc/system/limits_integration_test.go b/internal/api/grpc/system/limits_integration_test.go
index 2557d72c2..96ceafcdc 100644
--- a/internal/api/grpc/system/limits_integration_test.go
+++ b/internal/api/grpc/system/limits_integration_test.go
@@ -4,6 +4,7 @@ package system_test
import (
"context"
+ "google.golang.org/protobuf/types/known/timestamppb"
"math/rand"
"sync"
"testing"
@@ -23,6 +24,7 @@ func TestServer_Limits_AuditLogRetention(t *testing.T) {
_, instanceID, iamOwnerCtx := Tester.UseIsolatedInstance(t, CTX, SystemCTX)
userID, projectID, appID, projectGrantID := seedObjects(iamOwnerCtx, t)
beforeTime := time.Now()
+ farPast := timestamppb.New(beforeTime.Add(-10 * time.Hour).UTC())
zeroCounts := &eventCounts{}
seededCount := requireEventually(t, iamOwnerCtx, userID, projectID, appID, projectGrantID, func(c assert.TestingT, counts *eventCounts) {
counts.assertAll(t, c, "seeded events are > 0", assert.Greater, zeroCounts)
@@ -36,10 +38,22 @@ func TestServer_Limits_AuditLogRetention(t *testing.T) {
AuditLogRetention: durationpb.New(time.Now().Sub(beforeTime)),
})
require.NoError(t, err)
+ var limitedCounts *eventCounts
requireEventually(t, iamOwnerCtx, userID, projectID, appID, projectGrantID, func(c assert.TestingT, counts *eventCounts) {
counts.assertAll(t, c, "limited events < added events", assert.Less, addedCount)
counts.assertAll(t, c, "limited events > 0", assert.Greater, zeroCounts)
+ limitedCounts = counts
}, "wait for limited event assertions to pass")
+ listedEvents, err := Tester.Client.Admin.ListEvents(iamOwnerCtx, &admin.ListEventsRequest{CreationDateFilter: &admin.ListEventsRequest_From{
+ From: farPast,
+ }})
+ require.NoError(t, err)
+ assert.LessOrEqual(t, len(listedEvents.GetEvents()), limitedCounts.all, "ListEvents with from query older than retention doesn't return more events")
+ listedEvents, err = Tester.Client.Admin.ListEvents(iamOwnerCtx, &admin.ListEventsRequest{CreationDateFilter: &admin.ListEventsRequest_Range{Range: &admin.ListEventsRequestCreationDateRange{
+ Since: farPast,
+ }}})
+ require.NoError(t, err)
+ assert.LessOrEqual(t, len(listedEvents.GetEvents()), limitedCounts.all, "ListEvents with since query older than retention doesn't return more events")
_, err = Tester.Client.System.ResetLimits(SystemCTX, &system.ResetLimitsRequest{
InstanceId: instanceID,
})
diff --git a/proto/zitadel/admin.proto b/proto/zitadel/admin.proto
index dc0dc962e..e85ccea8a 100644
--- a/proto/zitadel/admin.proto
+++ b/proto/zitadel/admin.proto
@@ -7972,11 +7972,35 @@ message ListEventsRequest {
}
];
google.protobuf.Timestamp creation_date = 9 [
+ deprecated = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2019-04-01T08:45:00.000000Z\"";
- 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.";
+ description: "Use from instead.";
}
];
+ message creation_date_range {
+ google.protobuf.Timestamp since = 1 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ example: "\"2019-04-01T08:45:00.000000Z\"";
+ description: "The events returned are younger than the UTC since date";
+ }
+ ];
+ google.protobuf.Timestamp until = 2 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ example: "\"2019-04-01T08:45:00.000000Z\"";
+ description: "The events returned are older than the UTC until date.";
+ }
+ ];
+ }
+ oneof creation_date_filter {
+ creation_date_range range = 10;
+ google.protobuf.Timestamp from = 11 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ example: "\"2019-04-01T08:45:00.000000Z\"";
+ description: "If asc is false, the events returned are older than the UTC from date. If asc is true, the events returned are younger than from.";
+ }
+ ];
+ }
}
message ListEventsResponse {
|