From 0177ef79da881d907a09dafc8d10fe579115e1d6 Mon Sep 17 00:00:00 2001 From: Wilfred Asomani Date: Fri, 10 Mar 2023 11:19:07 +0000 Subject: [PATCH] satellite/{console,analytics,accountfreeze}: send unfreeze event This change sends an event to segment for when a user is unfrozen. It also moves freeze and warning event triggers from the autofreeze chore to the account freeze service. Change-Id: I5c0522b921b7baf52d6db5eb7ef841c08644a461 --- satellite/admin.go | 8 ++++- satellite/analytics/service.go | 17 +++++++++++ satellite/api.go | 2 +- satellite/console/accountfreezes.go | 30 +++++++++++++++++-- satellite/console/accountfreezes_test.go | 6 ++-- satellite/core.go | 5 ++-- satellite/payments/accountfreeze/chore.go | 2 -- .../payments/accountfreeze/chore_test.go | 2 +- 8 files changed, 59 insertions(+), 13 deletions(-) diff --git a/satellite/admin.go b/satellite/admin.go index fa096420d..c7e31a169 100644 --- a/satellite/admin.go +++ b/satellite/admin.go @@ -21,6 +21,7 @@ import ( "storj.io/storj/private/lifecycle" "storj.io/storj/private/version/checker" "storj.io/storj/satellite/admin" + "storj.io/storj/satellite/analytics" "storj.io/storj/satellite/buckets" "storj.io/storj/satellite/console" "storj.io/storj/satellite/console/restkeys" @@ -183,7 +184,12 @@ func NewAdmin(log *zap.Logger, full *identity.FullIdentity, db DB, metabaseDB *m peer.Payments.Stripe = stripeClient peer.Payments.Accounts = peer.Payments.Service.Accounts() - peer.FreezeAccounts.Service = console.NewAccountFreezeService(db.Console().AccountFreezeEvents(), db.Console().Users(), db.Console().Projects()) + peer.FreezeAccounts.Service = console.NewAccountFreezeService( + db.Console().AccountFreezeEvents(), + db.Console().Users(), + db.Console().Projects(), + analytics.NewService(peer.Log.Named("analytics:service"), config.Analytics, config.Console.SatelliteName), + ) } { // setup admin endpoint diff --git a/satellite/analytics/service.go b/satellite/analytics/service.go index 58379c725..87f86b9c1 100644 --- a/satellite/analytics/service.go +++ b/satellite/analytics/service.go @@ -80,6 +80,7 @@ const ( eventProjectStorageLimitUpdated = "Project Storage Limit Updated" eventProjectBandwidthLimitUpdated = "Project Bandwidth Limit Updated" eventAccountFrozen = "Account Frozen" + eventAccountUnfrozen = "Account Unfrozen" eventAccountFreezeWarning = "Account Freeze Warning" eventUnpaidLargeInvoice = "Large Invoice Unpaid" ) @@ -322,6 +323,22 @@ func (service *Service) TrackAccountFrozen(userID uuid.UUID, email string) { }) } +// TrackAccountUnfrozen sends an account unfrozen event to Segment. +func (service *Service) TrackAccountUnfrozen(userID uuid.UUID, email string) { + if !service.config.Enabled { + return + } + + props := segment.NewProperties() + props.Set("email", email) + + service.enqueueMessage(segment.Track{ + UserId: userID.String(), + Event: service.satelliteName + " " + eventAccountUnfrozen, + Properties: props, + }) +} + // TrackAccountFreezeWarning sends an account freeze warning event to Segment. func (service *Service) TrackAccountFreezeWarning(userID uuid.UUID, email string) { if !service.config.Enabled { diff --git a/satellite/api.go b/satellite/api.go index 0d19f8b83..f4341321e 100644 --- a/satellite/api.go +++ b/satellite/api.go @@ -622,7 +622,7 @@ func NewAPI(log *zap.Logger, full *identity.FullIdentity, db DB, return nil, errs.Combine(err, peer.Close()) } - accountFreezeService := console.NewAccountFreezeService(db.Console().AccountFreezeEvents(), db.Console().Users(), db.Console().Projects()) + accountFreezeService := console.NewAccountFreezeService(db.Console().AccountFreezeEvents(), db.Console().Users(), db.Console().Projects(), peer.Analytics.Service) peer.Console.Endpoint = consoleweb.NewServer( peer.Log.Named("console:endpoint"), diff --git a/satellite/console/accountfreezes.go b/satellite/console/accountfreezes.go index 7ce31fa8e..a082fda64 100644 --- a/satellite/console/accountfreezes.go +++ b/satellite/console/accountfreezes.go @@ -12,6 +12,7 @@ import ( "github.com/zeebo/errs" "storj.io/common/uuid" + "storj.io/storj/satellite/analytics" ) // ErrAccountFreeze is the class for errors that occur during operation of the account freeze service. @@ -60,14 +61,16 @@ type AccountFreezeService struct { freezeEventsDB AccountFreezeEvents usersDB Users projectsDB Projects + analytics *analytics.Service } // NewAccountFreezeService creates a new account freeze service. -func NewAccountFreezeService(freezeEventsDB AccountFreezeEvents, usersDB Users, projectsDB Projects) *AccountFreezeService { +func NewAccountFreezeService(freezeEventsDB AccountFreezeEvents, usersDB Users, projectsDB Projects, analytics *analytics.Service) *AccountFreezeService { return &AccountFreezeService{ freezeEventsDB: freezeEventsDB, usersDB: usersDB, projectsDB: projectsDB, + analytics: analytics, } } @@ -161,6 +164,7 @@ func (s *AccountFreezeService) FreezeUser(ctx context.Context, userID uuid.UUID) } } + s.analytics.TrackAccountFrozen(userID, user.Email) return nil } @@ -168,6 +172,11 @@ func (s *AccountFreezeService) FreezeUser(ctx context.Context, userID uuid.UUID) func (s *AccountFreezeService) UnfreezeUser(ctx context.Context, userID uuid.UUID) (err error) { defer mon.Task()(&ctx)(&err) + user, err := s.usersDB.Get(ctx, userID) + if err != nil { + return ErrAccountFreeze.Wrap(err) + } + event, err := s.freezeEventsDB.Get(ctx, userID, Freeze) if errors.Is(err, sql.ErrNoRows) { return ErrAccountFreeze.New("user is not frozen") @@ -189,19 +198,34 @@ func (s *AccountFreezeService) UnfreezeUser(ctx context.Context, userID uuid.UUI return ErrAccountFreeze.Wrap(err) } - return ErrAccountFreeze.Wrap(s.freezeEventsDB.DeleteAllByUserID(ctx, userID)) + err = ErrAccountFreeze.Wrap(s.freezeEventsDB.DeleteAllByUserID(ctx, userID)) + if err != nil { + return err + } + + s.analytics.TrackAccountUnfrozen(userID, user.Email) + return nil } // WarnUser adds a warning event to the freeze events table. func (s *AccountFreezeService) WarnUser(ctx context.Context, userID uuid.UUID) (err error) { defer mon.Task()(&ctx)(&err) + user, err := s.usersDB.Get(ctx, userID) + if err != nil { + return ErrAccountFreeze.Wrap(err) + } + _, err = s.freezeEventsDB.Upsert(ctx, &AccountFreezeEvent{ UserID: userID, Type: Warning, }) + if err != nil { + return ErrAccountFreeze.Wrap(err) + } - return ErrAccountFreeze.Wrap(err) + s.analytics.TrackAccountFreezeWarning(userID, user.Email) + return nil } // GetAll returns all events for a user. diff --git a/satellite/console/accountfreezes_test.go b/satellite/console/accountfreezes_test.go index eedb56d7f..9628f8bac 100644 --- a/satellite/console/accountfreezes_test.go +++ b/satellite/console/accountfreezes_test.go @@ -41,7 +41,7 @@ func TestAccountFreeze(t *testing.T) { sat := planet.Satellites[0] usersDB := sat.DB.Console().Users() projectsDB := sat.DB.Console().Projects() - service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB) + service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB, sat.API.Analytics.Service) userLimits := randUsageLimits() user, err := sat.AddUser(ctx, console.CreateUser{ @@ -83,7 +83,7 @@ func TestAccountUnfreeze(t *testing.T) { sat := planet.Satellites[0] usersDB := sat.DB.Console().Users() projectsDB := sat.DB.Console().Projects() - service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB) + service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB, sat.API.Analytics.Service) userLimits := randUsageLimits() user, err := sat.AddUser(ctx, console.CreateUser{ @@ -122,7 +122,7 @@ func TestAccountFreezeAlreadyFrozen(t *testing.T) { sat := planet.Satellites[0] usersDB := sat.DB.Console().Users() projectsDB := sat.DB.Console().Projects() - service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB) + service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB, sat.API.Analytics.Service) userLimits := randUsageLimits() user, err := sat.AddUser(ctx, console.CreateUser{ diff --git a/satellite/core.go b/satellite/core.go index 9c80d0332..1a7857c91 100644 --- a/satellite/core.go +++ b/satellite/core.go @@ -592,13 +592,14 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, { // setup account freeze if config.AccountFreeze.Enabled { + analyticService := analytics.NewService(peer.Log.Named("analytics:service"), config.Analytics, config.Console.SatelliteName) peer.Payments.AccountFreeze = accountfreeze.NewChore( peer.Log.Named("payments.accountfreeze:chore"), peer.DB.StripeCoinPayments(), peer.Payments.Accounts, peer.DB.Console().Users(), - console.NewAccountFreezeService(db.Console().AccountFreezeEvents(), db.Console().Users(), db.Console().Projects()), - analytics.NewService(peer.Log.Named("analytics:service"), config.Analytics, config.Console.SatelliteName), + console.NewAccountFreezeService(db.Console().AccountFreezeEvents(), db.Console().Users(), db.Console().Projects(), analyticService), + analyticService, config.AccountFreeze, ) diff --git a/satellite/payments/accountfreeze/chore.go b/satellite/payments/accountfreeze/chore.go index c1f301d10..b6196a432 100644 --- a/satellite/payments/accountfreeze/chore.go +++ b/satellite/payments/accountfreeze/chore.go @@ -105,7 +105,6 @@ func (chore *Chore) Run(ctx context.Context) (err error) { chore.log.Error("Could not add warning event", zap.String("invoice", invoice.ID), zap.Error(Error.Wrap(err))) continue } - chore.analytics.TrackAccountFreezeWarning(userID, user.Email) continue } @@ -115,7 +114,6 @@ func (chore *Chore) Run(ctx context.Context) (err error) { chore.log.Error("Could not freeze account", zap.String("invoice", invoice.ID), zap.Error(Error.Wrap(err))) continue } - chore.analytics.TrackAccountFrozen(userID, user.Email) } } diff --git a/satellite/payments/accountfreeze/chore_test.go b/satellite/payments/accountfreeze/chore_test.go index 0c75b8485..d96e13d13 100644 --- a/satellite/payments/accountfreeze/chore_test.go +++ b/satellite/payments/accountfreeze/chore_test.go @@ -33,7 +33,7 @@ func TestAutoFreezeChore(t *testing.T) { customerDB := sat.Core.DB.StripeCoinPayments().Customers() usersDB := sat.DB.Console().Users() projectsDB := sat.DB.Console().Projects() - service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB) + service := console.NewAccountFreezeService(sat.DB.Console().AccountFreezeEvents(), usersDB, projectsDB, sat.API.Analytics.Service) chore := sat.Core.Payments.AccountFreeze user, err := sat.AddUser(ctx, console.CreateUser{