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:
Silvan 2023-03-17 10:14:06 +01:00 committed by GitHub
parent 09abf06d4d
commit a3b36a0138
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 261 additions and 215 deletions

View File

@ -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"

View File

@ -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 {

View File

@ -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
}

View File

@ -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,
}
}

View File

@ -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
}

View File

@ -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,
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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}
}