satellite/{payment,console} rename freeze events and add violation event

This change introduces a new freeze event, ViolationFreeze, for ToS
violations and also prepends other events with Billing to clarify what
they signify.

Issue: https://github.com/storj/storj-private/issues/386

Change-Id: Ieef2abbbb03d06377dc7a73ba5ef0742ada75e8e
This commit is contained in:
Wilfred Asomani 2023-09-28 11:12:09 +00:00 committed by Storj Robot
parent 4dbf26e153
commit 33fe731620
11 changed files with 82 additions and 76 deletions

View File

@ -597,7 +597,7 @@ func (server *Server) freezeUser(w http.ResponseWriter, r *http.Request) {
return
}
err = server.freezeAccounts.FreezeUser(ctx, u.ID)
err = server.freezeAccounts.BillingFreezeUser(ctx, u.ID)
if err != nil {
sendJSONError(w, "failed to freeze user",
err.Error(), http.StatusInternalServerError)
@ -626,7 +626,7 @@ func (server *Server) unfreezeUser(w http.ResponseWriter, r *http.Request) {
return
}
if err = server.freezeAccounts.UnfreezeUser(ctx, u.ID); err != nil {
if err = server.freezeAccounts.BillingUnfreezeUser(ctx, u.ID); err != nil {
sendJSONError(w, "failed to unfreeze user",
err.Error(), http.StatusInternalServerError)
return
@ -655,7 +655,7 @@ func (server *Server) unWarnUser(w http.ResponseWriter, r *http.Request) {
return
}
if err = server.freezeAccounts.UnWarnUser(ctx, u.ID); err != nil {
if err = server.freezeAccounts.BillingUnWarnUser(ctx, u.ID); err != nil {
sendJSONError(w, "failed to unwarn user",
err.Error(), http.StatusInternalServerError)
return

View File

@ -444,7 +444,7 @@ func TestWarnUnwarnUser(t *testing.T) {
user, err := planet.Satellites[0].DB.Console().Users().Get(ctx, planet.Uplinks[0].Projects[0].Owner.ID)
require.NoError(t, err)
err = planet.Satellites[0].Admin.FreezeAccounts.Service.WarnUser(ctx, user.ID)
err = planet.Satellites[0].Admin.FreezeAccounts.Service.BillingWarnUser(ctx, user.ID)
require.NoError(t, err)
freeze, warning, err := planet.Satellites[0].DB.Console().AccountFreezeEvents().GetAll(ctx, user.ID)

View File

@ -71,19 +71,24 @@ type FreezeEventsPage struct {
type AccountFreezeEventType int
const (
// Freeze signifies that the user has been frozen.
Freeze AccountFreezeEventType = 0
// Warning signifies that the user has been warned that they may be frozen soon.
Warning AccountFreezeEventType = 1
// BillingFreeze signifies that the user has been frozen due to nonpayment of invoices.
BillingFreeze AccountFreezeEventType = 0
// BillingWarning signifies that the user has been warned that they may be frozen soon
// due to nonpayment of invoices.
BillingWarning AccountFreezeEventType = 1
// ViolationFreeze signifies that the user has been frozen due to ToS violation.
ViolationFreeze AccountFreezeEventType = 2
)
// String returns a string representation of this event.
func (et AccountFreezeEventType) String() string {
switch et {
case Freeze:
return "Freeze"
case Warning:
return "Warning"
case BillingFreeze:
return "Billing Freeze"
case BillingWarning:
return "Billing Warning"
case ViolationFreeze:
return "Violation Freeze"
default:
return ""
}
@ -107,11 +112,12 @@ func NewAccountFreezeService(freezeEventsDB AccountFreezeEvents, usersDB Users,
}
}
// IsUserFrozen returns whether the user specified by the given ID is frozen.
func (s *AccountFreezeService) IsUserFrozen(ctx context.Context, userID uuid.UUID) (_ bool, err error) {
// IsUserBillingFrozen returns whether the user specified by the given ID is frozen
// due to nonpayment of invoices.
func (s *AccountFreezeService) IsUserBillingFrozen(ctx context.Context, userID uuid.UUID) (_ bool, err error) {
defer mon.Task()(&ctx)(&err)
_, err = s.freezeEventsDB.Get(ctx, userID, Freeze)
_, err = s.freezeEventsDB.Get(ctx, userID, BillingFreeze)
switch {
case errors.Is(err, sql.ErrNoRows):
return false, nil
@ -122,8 +128,8 @@ func (s *AccountFreezeService) IsUserFrozen(ctx context.Context, userID uuid.UUI
}
}
// FreezeUser freezes the user specified by the given ID.
func (s *AccountFreezeService) FreezeUser(ctx context.Context, userID uuid.UUID) (err error) {
// BillingFreezeUser freezes the user specified by the given ID due to nonpayment of invoices.
func (s *AccountFreezeService) BillingFreezeUser(ctx context.Context, userID uuid.UUID) (err error) {
defer mon.Task()(&ctx)(&err)
user, err := s.usersDB.Get(ctx, userID)
@ -136,7 +142,7 @@ func (s *AccountFreezeService) FreezeUser(ctx context.Context, userID uuid.UUID)
return ErrAccountFreeze.Wrap(err)
}
if warning != nil {
err = s.freezeEventsDB.DeleteByUserIDAndEvent(ctx, userID, Warning)
err = s.freezeEventsDB.DeleteByUserIDAndEvent(ctx, userID, BillingWarning)
if err != nil {
return ErrAccountFreeze.Wrap(err)
}
@ -144,7 +150,7 @@ func (s *AccountFreezeService) FreezeUser(ctx context.Context, userID uuid.UUID)
if freeze == nil {
freeze = &AccountFreezeEvent{
UserID: userID,
Type: Freeze,
Type: BillingFreeze,
Limits: &AccountFreezeEventLimits{
User: UsageLimits{
Storage: user.ProjectStorageLimit,
@ -208,8 +214,8 @@ func (s *AccountFreezeService) FreezeUser(ctx context.Context, userID uuid.UUID)
return nil
}
// UnfreezeUser reverses the freeze placed on the user specified by the given ID.
func (s *AccountFreezeService) UnfreezeUser(ctx context.Context, userID uuid.UUID) (err error) {
// BillingUnfreezeUser reverses the billing freeze placed on the user specified by the given ID.
func (s *AccountFreezeService) BillingUnfreezeUser(ctx context.Context, userID uuid.UUID) (err error) {
defer mon.Task()(&ctx)(&err)
user, err := s.usersDB.Get(ctx, userID)
@ -217,9 +223,9 @@ func (s *AccountFreezeService) UnfreezeUser(ctx context.Context, userID uuid.UUI
return ErrAccountFreeze.Wrap(err)
}
event, err := s.freezeEventsDB.Get(ctx, userID, Freeze)
event, err := s.freezeEventsDB.Get(ctx, userID, BillingFreeze)
if errors.Is(err, sql.ErrNoRows) {
return ErrAccountFreeze.New("user is not frozen")
return ErrAccountFreeze.New("user is not frozen due to nonpayment of invoices")
}
if event.Limits == nil {
@ -247,8 +253,8 @@ func (s *AccountFreezeService) UnfreezeUser(ctx context.Context, userID uuid.UUI
return nil
}
// WarnUser adds a warning event to the freeze events table.
func (s *AccountFreezeService) WarnUser(ctx context.Context, userID uuid.UUID) (err error) {
// BillingWarnUser adds a billing warning event to the freeze events table.
func (s *AccountFreezeService) BillingWarnUser(ctx context.Context, userID uuid.UUID) (err error) {
defer mon.Task()(&ctx)(&err)
user, err := s.usersDB.Get(ctx, userID)
@ -258,7 +264,7 @@ func (s *AccountFreezeService) WarnUser(ctx context.Context, userID uuid.UUID) (
_, err = s.freezeEventsDB.Upsert(ctx, &AccountFreezeEvent{
UserID: userID,
Type: Warning,
Type: BillingWarning,
})
if err != nil {
return ErrAccountFreeze.Wrap(err)
@ -268,8 +274,8 @@ func (s *AccountFreezeService) WarnUser(ctx context.Context, userID uuid.UUID) (
return nil
}
// UnWarnUser reverses the warning placed on the user specified by the given ID.
func (s *AccountFreezeService) UnWarnUser(ctx context.Context, userID uuid.UUID) (err error) {
// BillingUnWarnUser reverses the warning placed on the user specified by the given ID.
func (s *AccountFreezeService) BillingUnWarnUser(ctx context.Context, userID uuid.UUID) (err error) {
defer mon.Task()(&ctx)(&err)
user, err := s.usersDB.Get(ctx, userID)
@ -277,12 +283,12 @@ func (s *AccountFreezeService) UnWarnUser(ctx context.Context, userID uuid.UUID)
return ErrAccountFreeze.Wrap(err)
}
_, err = s.freezeEventsDB.Get(ctx, userID, Warning)
_, err = s.freezeEventsDB.Get(ctx, userID, BillingWarning)
if errors.Is(err, sql.ErrNoRows) {
return ErrAccountFreeze.New("user is not warned")
}
err = ErrAccountFreeze.Wrap(s.freezeEventsDB.DeleteByUserIDAndEvent(ctx, userID, Warning))
err = ErrAccountFreeze.Wrap(s.freezeEventsDB.DeleteByUserIDAndEvent(ctx, userID, BillingWarning))
if err != nil {
return err
}

View File

@ -60,11 +60,11 @@ func TestAccountFreeze(t *testing.T) {
require.NoError(t, err)
require.NoError(t, projectsDB.UpdateUsageLimits(ctx, proj.ID, projLimits))
frozen, err := service.IsUserFrozen(ctx, user.ID)
frozen, err := service.IsUserBillingFrozen(ctx, user.ID)
require.NoError(t, err)
require.False(t, frozen)
require.NoError(t, service.FreezeUser(ctx, user.ID))
require.NoError(t, service.BillingFreezeUser(ctx, user.ID))
user, err = usersDB.Get(ctx, user.ID)
require.NoError(t, err)
@ -74,7 +74,7 @@ func TestAccountFreeze(t *testing.T) {
require.NoError(t, err)
require.Zero(t, getProjectLimits(proj))
frozen, err = service.IsUserFrozen(ctx, user.ID)
frozen, err = service.IsUserBillingFrozen(ctx, user.ID)
require.NoError(t, err)
require.True(t, frozen)
})
@ -102,8 +102,8 @@ func TestAccountUnfreeze(t *testing.T) {
require.NoError(t, err)
require.NoError(t, projectsDB.UpdateUsageLimits(ctx, proj.ID, projLimits))
require.NoError(t, service.FreezeUser(ctx, user.ID))
require.NoError(t, service.UnfreezeUser(ctx, user.ID))
require.NoError(t, service.BillingFreezeUser(ctx, user.ID))
require.NoError(t, service.BillingUnfreezeUser(ctx, user.ID))
user, err = usersDB.Get(ctx, user.ID)
require.NoError(t, err)
@ -113,13 +113,13 @@ func TestAccountUnfreeze(t *testing.T) {
require.NoError(t, err)
require.Equal(t, projLimits, getProjectLimits(proj))
frozen, err := service.IsUserFrozen(ctx, user.ID)
frozen, err := service.IsUserBillingFrozen(ctx, user.ID)
require.NoError(t, err)
require.False(t, frozen)
})
}
func TestRemoveAccountWarning(t *testing.T) {
func TestRemoveAccountBillingWarning(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
@ -134,21 +134,21 @@ func TestRemoveAccountWarning(t *testing.T) {
}, 2)
require.NoError(t, err)
require.NoError(t, service.WarnUser(ctx, user.ID))
require.NoError(t, service.UnWarnUser(ctx, user.ID))
require.NoError(t, service.BillingWarnUser(ctx, user.ID))
require.NoError(t, service.BillingUnWarnUser(ctx, user.ID))
freeze, warning, err := service.GetAll(ctx, user.ID)
require.NoError(t, err)
require.Nil(t, warning)
require.Nil(t, freeze)
require.NoError(t, service.WarnUser(ctx, user.ID))
require.NoError(t, service.FreezeUser(ctx, user.ID))
require.NoError(t, service.BillingWarnUser(ctx, user.ID))
require.NoError(t, service.BillingFreezeUser(ctx, user.ID))
freeze, warning, err = service.GetAll(ctx, user.ID)
require.NoError(t, err)
require.NotNil(t, freeze)
// freezing should remove prior warning events.
// billing-freezing should remove prior warning events.
require.Nil(t, warning)
})
}
@ -178,14 +178,14 @@ func TestAccountFreezeAlreadyFrozen(t *testing.T) {
// Freezing a frozen user should freeze any projects that were unable to be frozen prior.
// The limits stored for projects frozen by the prior freeze should not be modified.
t.Run("Project limits", func(t *testing.T) {
require.NoError(t, service.FreezeUser(ctx, user.ID))
require.NoError(t, service.BillingFreezeUser(ctx, user.ID))
proj2Limits := randUsageLimits()
proj2, err := sat.AddProject(ctx, user.ID, "project2")
require.NoError(t, err)
require.NoError(t, projectsDB.UpdateUsageLimits(ctx, proj2.ID, proj2Limits))
require.NoError(t, service.FreezeUser(ctx, user.ID))
require.NoError(t, service.BillingFreezeUser(ctx, user.ID))
user, err := usersDB.Get(ctx, user.ID)
require.NoError(t, err)
@ -195,7 +195,7 @@ func TestAccountFreezeAlreadyFrozen(t *testing.T) {
require.NoError(t, err)
require.Zero(t, getProjectLimits(proj2))
require.NoError(t, service.UnfreezeUser(ctx, user.ID))
require.NoError(t, service.BillingUnfreezeUser(ctx, user.ID))
user, err = usersDB.Get(ctx, user.ID)
require.NoError(t, err)
@ -215,15 +215,15 @@ func TestAccountFreezeAlreadyFrozen(t *testing.T) {
user, err := usersDB.Get(ctx, user.ID)
require.NoError(t, err)
require.NoError(t, service.FreezeUser(ctx, user.ID))
require.NoError(t, service.BillingFreezeUser(ctx, user.ID))
require.NoError(t, usersDB.UpdateUserProjectLimits(ctx, user.ID, userLimits))
require.NoError(t, service.FreezeUser(ctx, user.ID))
require.NoError(t, service.BillingFreezeUser(ctx, user.ID))
user, err = usersDB.Get(ctx, user.ID)
require.NoError(t, err)
require.Zero(t, getUserLimits(user))
require.NoError(t, service.UnfreezeUser(ctx, user.ID))
require.NoError(t, service.BillingUnfreezeUser(ctx, user.ID))
user, err = usersDB.Get(ctx, user.ID)
require.NoError(t, err)
@ -232,14 +232,14 @@ func TestAccountFreezeAlreadyFrozen(t *testing.T) {
// Freezing a frozen user should not modify user limits stored by the prior freeze.
t.Run("Frozen user limits", func(t *testing.T) {
require.NoError(t, service.FreezeUser(ctx, user.ID))
require.NoError(t, service.FreezeUser(ctx, user.ID))
require.NoError(t, service.BillingFreezeUser(ctx, user.ID))
require.NoError(t, service.BillingFreezeUser(ctx, user.ID))
user, err = usersDB.Get(ctx, user.ID)
require.NoError(t, err)
require.Zero(t, getUserLimits(user))
require.NoError(t, service.UnfreezeUser(ctx, user.ID))
require.NoError(t, service.BillingUnfreezeUser(ctx, user.ID))
user, err = usersDB.Get(ctx, user.ID)
require.NoError(t, err)
require.Equal(t, userLimits, getUserLimits(user))
@ -282,10 +282,10 @@ func TestFreezeEffects(t *testing.T) {
require.Equal(testT, expectedData, data)
}
t.Run("Freeze effect on project owner", func(t *testing.T) {
t.Run("BillingFreeze effect on project owner", func(t *testing.T) {
shouldUploadAndDownload(t)
err = freezeService.WarnUser(ctx, user1.ID)
err = freezeService.BillingWarnUser(ctx, user1.ID)
require.NoError(t, err)
// Should be able to download because account is not frozen.
@ -293,7 +293,7 @@ func TestFreezeEffects(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expectedData, data)
err = freezeService.FreezeUser(ctx, user1.ID)
err = freezeService.BillingFreezeUser(ctx, user1.ID)
require.NoError(t, err)
// Should not be able to upload because account is frozen.

View File

@ -176,12 +176,12 @@ func (p *Payments) triggerAttemptPayment(ctx context.Context) (err error) {
}
if freeze != nil {
err = p.accountFreezeService.UnfreezeUser(ctx, userID)
err = p.accountFreezeService.BillingUnfreezeUser(ctx, userID)
if err != nil {
return err
}
} else if warning != nil {
err = p.accountFreezeService.UnWarnUser(ctx, userID)
err = p.accountFreezeService.BillingUnWarnUser(ctx, userID)
if err != nil {
return err
}

View File

@ -67,12 +67,12 @@ func (o *InvoiceTokenPaymentObserver) Process(ctx context.Context, transaction b
}
if freeze != nil {
err = o.freezeService.UnfreezeUser(ctx, user.ID)
err = o.freezeService.BillingUnfreezeUser(ctx, user.ID)
if err != nil {
return err
}
} else if warning != nil {
err = o.freezeService.UnWarnUser(ctx, user.ID)
err = o.freezeService.BillingUnWarnUser(ctx, user.ID)
if err != nil {
return err
}

View File

@ -188,13 +188,13 @@ func (chore *Chore) attemptFreezeWarn(ctx context.Context) {
debugLog("Ignoring invoice; Payment attempt successful")
if warning != nil {
err = chore.freezeService.UnWarnUser(ctx, userID)
err = chore.freezeService.BillingUnWarnUser(ctx, userID)
if err != nil {
errorLog("Could not remove warning event", err)
}
}
if freeze != nil {
err = chore.freezeService.UnfreezeUser(ctx, userID)
err = chore.freezeService.BillingUnfreezeUser(ctx, userID)
if err != nil {
errorLog("Could not remove freeze event", err)
}
@ -221,7 +221,7 @@ func (chore *Chore) attemptFreezeWarn(ctx context.Context) {
debugLog("Ignoring invoice; payment already made")
continue
}
err = chore.freezeService.WarnUser(ctx, userID)
err = chore.freezeService.BillingWarnUser(ctx, userID)
if err != nil {
errorLog("Could not add warning event", err)
continue
@ -242,7 +242,7 @@ func (chore *Chore) attemptFreezeWarn(ctx context.Context) {
debugLog("Ignoring invoice; payment already made")
continue
}
err = chore.freezeService.FreezeUser(ctx, userID)
err = chore.freezeService.BillingFreezeUser(ctx, userID)
if err != nil {
errorLog("Could not freeze account", err)
continue
@ -310,14 +310,14 @@ func (chore *Chore) attemptUnfreezeUnwarn(ctx context.Context) {
continue
}
if event.Type == console.Freeze {
err = chore.freezeService.UnfreezeUser(ctx, event.UserID)
if event.Type == console.BillingFreeze {
err = chore.freezeService.BillingUnfreezeUser(ctx, event.UserID)
if err != nil {
errorLog("Could not unfreeze user", err)
}
unfrozenCount++
} else {
err = chore.freezeService.UnWarnUser(ctx, event.UserID)
err = chore.freezeService.BillingUnWarnUser(ctx, event.UserID)
if err != nil {
errorLog("Could not unwarn user", err)
}

View File

@ -113,7 +113,7 @@ func TestAutoFreezeChore(t *testing.T) {
require.Nil(t, warning)
})
t.Run("Freeze event for failed invoice (failed later payment attempt)", func(t *testing.T) {
t.Run("BillingFreeze event for failed invoice (failed later payment attempt)", func(t *testing.T) {
// AnalyticsMock tests that events are sent once.
service.TestChangeFreezeTracker(newFreezeTrackerMock(t))
// reset chore clock
@ -181,7 +181,7 @@ func TestAutoFreezeChore(t *testing.T) {
require.Equal(t, stripe.InvoiceStatusPaid, inv.Status)
// unfreeze user so they're not frozen in the next test.
err = service.UnfreezeUser(ctx, user.ID)
err = service.BillingUnfreezeUser(ctx, user.ID)
require.NoError(t, err)
})
@ -283,9 +283,9 @@ func TestAutoFreezeChore(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 1, len(failed))
err = service.FreezeUser(ctx, user.ID)
err = service.BillingFreezeUser(ctx, user.ID)
require.NoError(t, err)
err = service.FreezeUser(ctx, user2.ID)
err = service.BillingFreezeUser(ctx, user2.ID)
require.NoError(t, err)
chore.Loop.TriggerWait()
@ -301,7 +301,7 @@ func TestAutoFreezeChore(t *testing.T) {
require.NotNil(t, freeze)
// warn user though they have no failed invoices
err = service.WarnUser(ctx, user.ID)
err = service.BillingWarnUser(ctx, user.ID)
require.NoError(t, err)
chore.Loop.TriggerWait()
@ -320,7 +320,7 @@ func TestAutoFreezeChore(t *testing.T) {
require.Equal(t, stripe.InvoiceStatusPaid, inv.Status)
// unfreeze user so they're not frozen in the next test.
err = service.UnfreezeUser(ctx, user2.ID)
err = service.BillingUnfreezeUser(ctx, user2.ID)
require.NoError(t, err)
})
})

View File

@ -331,7 +331,7 @@ func TestChore_PayInvoiceObserver(t *testing.T) {
require.Equal(t, inv.ID, invoices[0].ID)
require.Equal(t, string(inv.Status), invoices[0].Status)
err = freezeService.FreezeUser(ctx, userID)
err = freezeService.BillingFreezeUser(ctx, userID)
require.NoError(t, err)
chore.TransactionCycle.TriggerWait()
@ -349,7 +349,7 @@ func TestChore_PayInvoiceObserver(t *testing.T) {
require.Equal(t, string(stripe.InvoiceStatusOpen), invoices[0].Status)
// user remains frozen since payment is not complete.
frozen, err := freezeService.IsUserFrozen(ctx, userID)
frozen, err := freezeService.IsUserBillingFrozen(ctx, userID)
require.NoError(t, err)
require.True(t, frozen)
@ -363,7 +363,7 @@ func TestChore_PayInvoiceObserver(t *testing.T) {
require.Equal(t, string(stripe.InvoiceStatusPaid), invoices[0].Status)
// user is not frozen since payment is complete.
frozen, err = freezeService.IsUserFrozen(ctx, userID)
frozen, err = freezeService.IsUserBillingFrozen(ctx, userID)
require.NoError(t, err)
require.False(t, frozen)
})

View File

@ -133,7 +133,7 @@ func (events *accountFreezeEvents) GetAll(ctx context.Context, userID uuid.UUID)
}
for _, event := range dbxEvents {
if console.AccountFreezeEventType(event.Event) == console.Freeze {
if console.AccountFreezeEventType(event.Event) == console.BillingFreeze {
freeze, err = fromDBXAccountFreezeEvent(event)
if err != nil {
return nil, nil, err

View File

@ -27,7 +27,7 @@ func TestAccountFreezeEvents(t *testing.T) {
event := &console.AccountFreezeEvent{
UserID: testrand.UUID(),
Type: console.Freeze,
Type: console.BillingFreeze,
Limits: &console.AccountFreezeEventLimits{
User: randUsageLimits(),
Projects: map[uuid.UUID]console.UsageLimits{