From 506a92d2c1263f9aa57d79a9714e8bf8459a8420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Jerman?= Date: Wed, 2 Mar 2022 13:48:05 +0100 Subject: [PATCH] Expand report output to show user fields as Compose does --- system/service/report.go | 83 ++++++++++++++++++++++++++++++++++++++- system/service/service.go | 5 ++- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/system/service/report.go b/system/service/report.go index c810b8c45..0ef049b99 100644 --- a/system/service/report.go +++ b/system/service/report.go @@ -6,6 +6,8 @@ import ( "strconv" "github.com/cortezaproject/corteza-server/pkg/actionlog" + "github.com/cortezaproject/corteza-server/pkg/expr" + "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/cortezaproject/corteza-server/pkg/label" rep "github.com/cortezaproject/corteza-server/pkg/report" "github.com/cortezaproject/corteza-server/store" @@ -19,6 +21,8 @@ type ( eventbus eventDispatcher actionlog actionlog.Recorder store store.Storer + + users UserService } reportAccessController interface { @@ -37,7 +41,14 @@ var ( // Report is a default report service initializer func Report(s store.Storer, ac reportAccessController, al actionlog.Recorder, eb eventDispatcher) *report { - return &report{store: s, ac: ac, actionlog: al, eventbus: eb} + return &report{ + store: s, + ac: ac, + actionlog: al, + eventbus: eb, + + users: DefaultUser, + } } func (svc *report) RegisterReporter(key string, r rep.DatasourceProvider) { @@ -421,6 +432,9 @@ func (svc *report) Run(ctx context.Context, reportID uint64, dd rep.FrameDefinit if err != nil { return err } + + ff, err = svc.enhance(ctx, ff) + out = append(out, ff...) } @@ -432,6 +446,73 @@ func (svc *report) Run(ctx context.Context, reportID uint64, dd rep.FrameDefinit return out, svc.recordAction(ctx, aaProps, ReportActionRun, err) } +// enhance is a temporary function that enriches the output to satisfy some current requirements. +// @todo extend core implementation to support such operatons +// +// - userID is replaced by the user name || username || email || handle || userID +func (svc *report) enhance(ctx context.Context, ff []*rep.Frame) (_ []*rep.Frame, err error) { + // Preload sys users + uIndex := make(map[uint64]*types.User) + uu, uf, err := svc.users.Find(ctx, types.UserFilter{Paging: filter.Paging{Limit: 1024}}) + if err != nil { + return + } + hasMore := uf.NextPage != nil + for i := range uu { + uIndex[uu[i].ID] = uu[i] + } + + for _, f := range ff { + userCols := make([]int, 0, len(f.Columns)) + for i, c := range f.Columns { + if c.Kind != "User" { + continue + } + userCols = append(userCols, i) + } + + for _, r := range f.Rows { + for _, ci := range userCols { + col := r[ci] + switch col.Type() { + case "ID": + uID := col.Get().(uint64) + user, ok := uIndex[uID] + if !ok && hasMore { + user, err = svc.users.FindByID(ctx, uID) + if err != nil && err != store.ErrNotFound { + return + } + } + + if user == nil { + continue + } else if _, ok := uIndex[uID]; !ok { + uIndex[uID] = user + } + + if usr, ok := uIndex[uID]; ok { + label := strconv.FormatUint(uID, 10) + if usr.Name != "" { + label = usr.Name + } else if usr.Username != "" { + label = usr.Username + } else if usr.Email != "" { + label = usr.Email + } else if usr.Handle != "" { + label = usr.Handle + } + + r[ci], _ = expr.NewString(label) + } + } + } + } + } + + return ff, err +} + func (svc *report) setIDs(r *types.Report) *types.Report { // scenarios for _, s := range r.Scenarios { diff --git a/system/service/service.go b/system/service/service.go index 41634feb2..4a966ab1c 100644 --- a/system/service/service.go +++ b/system/service/service.go @@ -3,9 +3,10 @@ package service import ( "context" "errors" - "github.com/cortezaproject/corteza-server/pkg/discovery" "time" + "github.com/cortezaproject/corteza-server/pkg/discovery" + automationService "github.com/cortezaproject/corteza-server/automation/service" "github.com/cortezaproject/corteza-server/pkg/actionlog" "github.com/cortezaproject/corteza-server/pkg/eventbus" @@ -183,11 +184,11 @@ func Initialize(ctx context.Context, log *zap.Logger, s store.Storer, ws websock DefaultRenderer = Renderer(c.Template) DefaultResourceTranslation = ResourceTranslation() - DefaultReport = Report(DefaultStore, DefaultAccessControl, DefaultActionlog, eventbus.Service()) DefaultAuthNotification = AuthNotification(CurrentSettings, DefaultRenderer, c.Auth) DefaultAuth = Auth(AuthOptions{LimitUsers: c.Limit.SystemUsers}) DefaultAuthClient = AuthClient(DefaultStore, DefaultAccessControl, DefaultActionlog, eventbus.Service(), c.Auth) DefaultUser = User(UserOptions{LimitUsers: c.Limit.SystemUsers}) + DefaultReport = Report(DefaultStore, DefaultAccessControl, DefaultActionlog, eventbus.Service()) DefaultRole = Role() DefaultApplication = Application(DefaultStore, DefaultAccessControl, DefaultActionlog, eventbus.Service()) DefaultReminder = Reminder(ctx, DefaultLogger.Named("reminder"), ws)