-
Notifications
You must be signed in to change notification settings - Fork 387
/
observerupgradeuser.go
123 lines (104 loc) · 3.57 KB
/
observerupgradeuser.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
114
115
116
117
118
119
120
121
122
123
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
package console
import (
"context"
"time"
"storj.io/common/memory"
"storj.io/storj/satellite/analytics"
"storj.io/storj/satellite/payments/billing"
)
var _ billing.Observer = (*UpgradeUserObserver)(nil)
// UpgradeUserObserver used to upgrade user if their balance is more than $10 after confirmed token transaction.
type UpgradeUserObserver struct {
consoleDB DB
transactionsDB billing.TransactionsDB
usageLimitsConfig UsageLimitsConfig
userBalanceForUpgrade int64
freezeService *AccountFreezeService
analyticsService *analytics.Service
nowFn func() time.Time
}
// NewUpgradeUserObserver creates new observer instance.
func NewUpgradeUserObserver(consoleDB DB, transactionsDB billing.TransactionsDB, usageLimitsConfig UsageLimitsConfig, userBalanceForUpgrade int64, freezeService *AccountFreezeService, analyticsService *analytics.Service) *UpgradeUserObserver {
return &UpgradeUserObserver{
consoleDB: consoleDB,
transactionsDB: transactionsDB,
usageLimitsConfig: usageLimitsConfig,
userBalanceForUpgrade: userBalanceForUpgrade,
freezeService: freezeService,
analyticsService: analyticsService,
nowFn: time.Now,
}
}
// Process puts user into the paid tier and converts projects to upgraded limits.
func (o *UpgradeUserObserver) Process(ctx context.Context, transaction billing.Transaction) (err error) {
defer mon.Task()(&ctx)(&err)
freezes, err := o.freezeService.GetAll(ctx, transaction.UserID)
if err != nil {
return err
}
if freezes.LegalFreeze != nil || freezes.ViolationFreeze != nil {
// user can not exit these freezes by paying with tokens
return nil
}
user, err := o.consoleDB.Users().Get(ctx, transaction.UserID)
if err != nil {
return err
}
if user.PaidTier {
return nil
}
balance, err := o.transactionsDB.GetBalance(ctx, user.ID)
if err != nil {
return err
}
// check if user's balance is less than needed amount for upgrade.
if balance.BaseUnits() < o.userBalanceForUpgrade {
return nil
}
if freezes.TrialExpirationFreeze != nil {
err = o.freezeService.TrialExpirationUnfreezeUser(ctx, user.ID)
if err != nil {
return err
}
}
now := o.nowFn()
err = o.consoleDB.Users().UpdatePaidTier(ctx, user.ID, true,
o.usageLimitsConfig.Bandwidth.Paid,
o.usageLimitsConfig.Storage.Paid,
o.usageLimitsConfig.Segment.Paid,
o.usageLimitsConfig.Project.Paid,
&now,
)
if err != nil {
return err
}
o.analyticsService.TrackUserUpgraded(user.ID, user.Email, user.TrialExpiration)
projects, err := o.consoleDB.Projects().GetOwn(ctx, user.ID)
if err != nil {
return err
}
for _, project := range projects {
if project.StorageLimit == nil || *project.StorageLimit < o.usageLimitsConfig.Storage.Paid {
project.StorageLimit = new(memory.Size)
*project.StorageLimit = o.usageLimitsConfig.Storage.Paid
}
if project.BandwidthLimit == nil || *project.BandwidthLimit < o.usageLimitsConfig.Bandwidth.Paid {
project.BandwidthLimit = new(memory.Size)
*project.BandwidthLimit = o.usageLimitsConfig.Bandwidth.Paid
}
if project.SegmentLimit == nil || *project.SegmentLimit < o.usageLimitsConfig.Segment.Paid {
*project.SegmentLimit = o.usageLimitsConfig.Segment.Paid
}
err = o.consoleDB.Projects().Update(ctx, &project)
if err != nil {
return err
}
}
return nil
}
// TestSetNow allows tests to have the observer act as if the current time is whatever they want.
func (o *UpgradeUserObserver) TestSetNow(nowFn func() time.Time) {
o.nowFn = nowFn
}