mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 04:57:33 +00:00
refactor(changes): use queries.SearchEvents
(#5388)
* refactor(changes): use `queries.SearchEvents` --------- Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
@@ -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
|
||||
}
|
@@ -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}
|
||||
}
|
||||
|
Reference in New Issue
Block a user