forked from cozy/cozy-stack
/
warnings.go
142 lines (131 loc) · 3.98 KB
/
warnings.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package instance
import (
"net/http"
"strconv"
"strings"
"time"
"github.com/cozy/cozy-stack/pkg/jsonapi"
)
// BlockingReason structs holds a reason why an instance had been blocked
type BlockingReason struct {
Code string
Message string
}
var (
// BlockedLoginFailed is used when a security issue has been detected on the instance
BlockedLoginFailed = BlockingReason{Code: "LOGIN_FAILED", Message: "Instance Blocked Login"}
// BlockedPaymentFailed is used when a payment is missing for the instance
BlockedPaymentFailed = BlockingReason{Code: "PAYMENT_FAILED", Message: "Instance Blocked Payment"}
// BlockedImporting is used when importing the data from another instance
BlockedImporting = BlockingReason{Code: "IMPORTING", Message: "Instance Blocked Importing"}
// BlockedMoving is used when moving data from another instance
BlockedMoving = BlockingReason{Code: "IMPORTING", Message: "Instance Blocked Moving"}
// BlockedUnknown is used when an instance is blocked but the reason is unknown
BlockedUnknown = BlockingReason{Code: "UNKNOWN", Message: "Instance Blocked Unknown"}
)
// Warnings returns a list of possible warnings associated with the instance.
func (i *Instance) Warnings() (warnings []*jsonapi.Error) {
if err := i.MovedError(); err != nil {
warnings = append(warnings, err)
}
notSigned, deadline := i.CheckTOSNotSignedAndDeadline()
if notSigned && deadline >= TOSWarning {
tosLink, _ := i.ManagerURL(ManagerTOSURL)
warnings = append(warnings, &jsonapi.Error{
Status: http.StatusPaymentRequired,
Title: "TOS Updated",
Code: "tos-updated",
Detail: i.Translate("Terms of services have been updated"),
Links: &jsonapi.LinksList{Self: tosLink},
})
}
return
}
// TOSDeadline represent the state for reaching the TOS deadline.
type TOSDeadline int
const (
// TOSNone when no deadline is reached.
TOSNone TOSDeadline = iota
// TOSWarning when the warning deadline is reached, 2 weeks before the actual
// activation of the CGU.
TOSWarning
// TOSBlocked when the deadline is reached and the access should be blocked.
TOSBlocked
)
// CheckInstanceBlocked returns whether or not the instance is currently in a
// blocked state: meaning it should be accessible.
func (i *Instance) CheckInstanceBlocked() bool {
return i.Blocked
}
// CheckTOSNotSigned checks whether or not the current Term of Services have
// been signed by the user.
func (i *Instance) CheckTOSNotSigned(args ...string) (notSigned bool) {
notSigned, _ = i.CheckTOSNotSignedAndDeadline(args...)
return
}
// CheckTOSNotSignedAndDeadline checks whether or not the current Term of
// Services have been signed by the user and returns the deadline state to
// perform this signature.
func (i *Instance) CheckTOSNotSignedAndDeadline(args ...string) (notSigned bool, deadline TOSDeadline) {
tosLatest := i.TOSLatest
if len(args) > 0 {
tosLatest = args[0]
}
latest, latestDate, ok := ParseTOSVersion(tosLatest)
if !ok || latestDate.IsZero() {
return
}
defer func() {
if notSigned {
now := time.Now()
if now.After(latestDate) {
deadline = TOSBlocked
} else if now.After(latestDate.Add(-30 * 24 * time.Hour)) {
deadline = TOSWarning
} else {
deadline = TOSNone
}
}
}()
signed, _, ok := ParseTOSVersion(i.TOSSigned)
if !ok {
notSigned = true
} else {
notSigned = signed < latest
}
return
}
// ParseTOSVersion returns the "major" and the date encoded in a version string
// with the following format:
// parseTOSVersion(A.B.C-YYYYMMDD) -> (A, YYYY, true)
func ParseTOSVersion(v string) (major int, date time.Time, ok bool) {
if v == "" {
return
}
if len(v) == 8 {
var err error
major = 1
date, err = time.Parse("20060102", v)
ok = err == nil
return
}
if v[0] == 'v' {
v = v[1:]
}
a := strings.SplitN(v, ".", 3)
if len(a) != 3 {
return
}
major, err := strconv.Atoi(a[0])
if err != nil {
return
}
suffix := strings.SplitN(a[2], "-", 2)
if len(suffix) < 2 {
ok = true
return
}
date, err = time.Parse("20060102", suffix[1])
ok = err == nil
return
}