-
Notifications
You must be signed in to change notification settings - Fork 3
/
user.go
113 lines (97 loc) · 4.3 KB
/
user.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright 2021 Monoskope Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package overviews
import (
"context"
"fmt"
esApi "github.com/finleap-connect/monoskope/pkg/api/eventsourcing"
"github.com/finleap-connect/monoskope/pkg/audit/formatters"
"github.com/finleap-connect/monoskope/pkg/domain/projections"
"github.com/finleap-connect/monoskope/pkg/domain/projectors"
esErrors "github.com/finleap-connect/monoskope/pkg/eventsourcing/errors"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/wrapperspb"
"strings"
"time"
)
// userOverviewFormatter OverviewFormatter implementation for the user-aggregate
type userOverviewFormatter struct {
*formatters.FormatterBase
}
// NewUserOverviewFormatter creates a new overview formatter for the user-aggregate
func NewUserOverviewFormatter(esClient esApi.EventStoreClient) *userOverviewFormatter {
return &userOverviewFormatter{FormatterBase: &formatters.FormatterBase{EsClient: esClient}}
}
// GetFormattedDetails returns the user overview details in a human-readable format.
// The given timestamp is used to create the snapshots of the needed aggregates
func (f *userOverviewFormatter) GetFormattedDetails(ctx context.Context, user *projections.User, timestamp time.Time) (string, error) {
var details string
eventFilter := &esApi.EventFilter{MaxTimestamp: timestamppb.New(timestamp)}
eventFilter.AggregateId = wrapperspb.String(user.CreatedById)
creatorSnapshot, err := f.CreateSnapshot(ctx, projectors.NewUserProjector(), eventFilter)
if err != nil {
return "", err
}
creator, ok := creatorSnapshot.(*projections.User)
if !ok {
return "", esErrors.ErrInvalidProjectionType
}
details += fmt.Sprintf("“%s“ was created by “%s“ at “%s“", user.Email, creator.Email, user.Created.AsTime().Format(time.RFC822))
if len(user.DeletedById) == 0 {
return details, nil
}
eventFilter.AggregateId = wrapperspb.String(user.DeletedById)
deleterSnapshot, err := f.CreateSnapshot(ctx, projectors.NewUserProjector(), eventFilter)
if err != nil {
return "", err
}
deleter, ok := deleterSnapshot.(*projections.User)
if !ok {
return "", esErrors.ErrInvalidProjectionType
}
details += fmt.Sprintf(" and was deleted by “%s“ at “%s“", deleter.Email, user.Deleted.AsTime().Format(time.RFC822))
return details, nil
}
// GetRolesDetails returns the roles details in general and the tenants and clusters details to which the roles apply.
// The given timestamp is used to create the snapshots of the needed aggregates
func (f *userOverviewFormatter) GetRolesDetails(ctx context.Context, user *projections.User, timestamp time.Time) (string, string, string, error) {
var rolesDetails, tenantsDetails, clustersDetails string
eventFilter := &esApi.EventFilter{MaxTimestamp: timestamppb.New(timestamp)}
for _, role := range user.Roles {
roleDetails := fmt.Sprintf("- %s %s\n", role.Scope, role.Role)
if !strings.Contains(rolesDetails, roleDetails) { // avoid having the same role multiple times
rolesDetails += roleDetails
}
if len(role.Resource) == 0 {
continue
}
eventFilter.AggregateId = wrapperspb.String(role.Resource)
tenantSnapshot, err := f.CreateSnapshot(ctx, projectors.NewTenantProjector(), eventFilter)
if err == nil {
tenant, ok := tenantSnapshot.(*projections.Tenant)
if ok {
tenantsDetails += fmt.Sprintf("- %s (%s)\n", tenant.Name, role.Role)
continue // it's either a tenant or cluster
}
}
clusterSnapshot, err := f.CreateSnapshot(ctx, projectors.NewClusterProjector(), eventFilter)
if err == nil {
cluster, ok := clusterSnapshot.(*projections.Cluster)
if ok {
clustersDetails += fmt.Sprintf("- %s (%s)\n", cluster.DisplayName, role.Role)
}
}
}
return strings.TrimSpace(rolesDetails), strings.TrimSpace(tenantsDetails), strings.TrimSpace(clustersDetails), nil
}