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
This commit is contained in:
Wilfred Asomani 2023-03-10 11:19:07 +00:00 committed by Storj Robot
parent c4f8695e8a
commit 0177ef79da
8 changed files with 59 additions and 13 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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