safing-portmaster/spn/access/account/view.go

123 lines
3.7 KiB
Go

package account
import (
"fmt"
"strings"
"time"
)
// View holds metadata that assists in displaying account information.
type View struct {
Message string
ShowAccountData bool
ShowAccountButton bool
ShowLoginButton bool
ShowRefreshButton bool
ShowLogoutButton bool
}
// UpdateView updates the view and handles plan/package fallbacks.
func (u *User) UpdateView(requestStatusCode int) {
v := &View{}
// Clean up naming and fallbacks when finished.
defer func() {
// Display "Free" package if no plan is set or if it expired.
switch {
case u.CurrentPlan == nil,
u.Subscription == nil,
u.Subscription.EndsAt == nil:
// Reset to free plan.
u.CurrentPlan = &Plan{
Name: "Free",
}
u.Subscription = nil
case u.Subscription.NextBillingDate != nil:
// Subscription is on auto-renew.
// Wait for update from server.
case time.Since(*u.Subscription.EndsAt) > 0:
// Reset to free plan.
u.CurrentPlan = &Plan{
Name: "Free",
}
u.Subscription = nil
}
// Prepend "Portmaster " to plan name.
// TODO: Remove when Plan/Package naming has been updated.
if u.CurrentPlan != nil && !strings.HasPrefix(u.CurrentPlan.Name, "Portmaster ") {
u.CurrentPlan.Name = "Portmaster " + u.CurrentPlan.Name
}
// Apply new view to user.
u.View = v
}()
// Set view data based on return code.
switch requestStatusCode {
case StatusInvalidAuth, StatusInvalidDevice, StatusDeviceInactive:
// Account deleted or Device inactive or deleted.
// When using token based auth, there is no difference between these cases.
v.Message = "This device may have been deactivated or removed from your account. Please log in again."
v.ShowAccountData = true
v.ShowAccountButton = true
v.ShowLoginButton = true
v.ShowLogoutButton = true
return
case StatusUnknownError:
v.Message = "There is an unknown error in the communication with the account server. The shown information may not be accurate. "
case StatusConnectionError:
v.Message = "Portmaster could not connect to the account server. The shown information may not be accurate. "
}
// Set view data based on profile data.
switch {
case u.State == UserStateLoggedOut:
// User logged out.
v.ShowAccountButton = true
v.ShowLoginButton = true
return
case u.State == UserStateSuspended:
// Account is suspended.
v.Message += fmt.Sprintf("Your account (%s) was suspended. Please contact support for details.", u.Username)
v.ShowAccountButton = true
v.ShowRefreshButton = true
v.ShowLogoutButton = true
return
case u.Subscription == nil || u.Subscription.EndsAt == nil:
// Account has never had a subscription.
v.Message += "Get more features. Upgrade today."
case u.Subscription.NextBillingDate != nil:
switch {
case time.Since(*u.Subscription.NextBillingDate) > 0:
v.Message += "Your auto-renewal seems to be delayed. Please refresh and check the status of your payment. Payment information may be delayed."
case time.Until(*u.Subscription.NextBillingDate) < 24*time.Hour:
v.Message += "Your subscription will auto-renew soon. Please note that payment information may be delayed."
}
case time.Since(*u.Subscription.EndsAt) > 0:
// Subscription expired.
if u.CurrentPlan != nil {
v.Message += fmt.Sprintf("Your package %s has ended. Extend it on the Account Page.", u.CurrentPlan.Name)
} else {
v.Message += "Your package has ended. Extend it on the Account Page."
}
case time.Until(*u.Subscription.EndsAt) < 7*24*time.Hour:
// Add generic ending soon message if the package ends in less than 7 days.
v.Message += "Your package ends soon. Extend it on the Account Page."
}
// Defaults for generally good accounts.
v.ShowAccountData = true
v.ShowAccountButton = true
v.ShowRefreshButton = true
v.ShowLogoutButton = true
}