-
Notifications
You must be signed in to change notification settings - Fork 32
/
apitypes.go
269 lines (225 loc) · 6.96 KB
/
apitypes.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// Package apitypes defines types shared between the daemon and its api client.
package apitypes
import (
"encoding/json"
"strings"
"github.com/manifoldco/torus-cli/base64"
"github.com/manifoldco/torus-cli/envelope"
"github.com/manifoldco/torus-cli/identity"
"github.com/manifoldco/torus-cli/primitive"
)
// ErrorType represents the string error types that the daemon and registry can
// return.
type ErrorType string
// These are the possible error types.
const (
BadRequestError = "bad_request"
UnauthorizedError = "unauthorized"
NotFoundError = "not_found"
InternalServerError = "internal_server"
NotImplementedError = "not_implemented"
)
// Error represents standard formatted API errors from the daemon or registry.
type Error struct {
StatusCode int
Type string `json:"type"`
Err []string `json:"error"`
}
// Error implements the error interface for formatted API errors.
func (e *Error) Error() string {
segments := strings.Split(e.Type, "_")
errType := strings.Join(segments, " ")
return strings.Title(errType) + ": " + strings.Join(e.Err, " ")
}
// FormatError updates an error to contain more context
func FormatError(err error) error {
if err == nil {
return nil
}
if apiErr, ok := err.(*Error); ok {
if apiErr.Type == UnauthorizedError {
for _, m := range apiErr.Err {
if strings.Contains(m, "wrong identity state: unverified") {
return NewUnverifiedError()
}
}
return &Error{
StatusCode: 401,
Type: UnauthorizedError,
Err: []string{"You are unauthorized to perform this action."},
}
}
}
return err
}
// NewUnverifiedError returns a message telling the user to verify their account before continuing
func NewUnverifiedError() *Error {
return &Error{
StatusCode: 401,
Type: UnauthorizedError,
Err: []string{"Your account has not yet been verified.\n\n" +
"Please check your email for your verification code and follow the enclosed instructions.\n" +
"Once you have verified your account you may retry this operation."},
}
}
// IsNotFoundError returns whether or not an error is a 404 result from the api.
func IsNotFoundError(err error) bool {
if err == nil {
return false
}
if apiErr, ok := err.(*Error); ok {
return apiErr.Type == NotFoundError
}
return false
}
// IsUnauthorizedError returns whether or not an error is a 401 result from the api.
func IsUnauthorizedError(err error) bool {
if err == nil {
return false
}
if apiErr, ok := err.(*Error); ok {
return apiErr.Type == UnauthorizedError
}
return false
}
// A session can represent either a machine or a user
const (
MachineSession = "machine"
UserSession = "user"
NotLoggedIn = "no_session"
)
// Self represents the current identity and auth combination for this session
type Self struct {
Type string `json:"type"`
Identity *envelope.Unsigned `json:"identity"`
Auth *envelope.Unsigned `json:"auth"`
}
// Version contains the release version of the daemon.
type Version struct {
Version string `json:"version"`
}
// SessionStatus contains details about the user's daemon session.
type SessionStatus struct {
Token bool `json:"token"`
Passphrase bool `json:"passphrase"`
}
// Login is a wrapper around a login request from the CLI to the Daemon
type Login struct {
Type string `json:"type"`
Credentials json.RawMessage `json:"credentials"`
}
// LoginCredential represents an login credentials for a user or machine
type LoginCredential interface {
Type() string
Valid() bool
Passphrase() []byte
Identifier() string
}
// UserLogin contains the required details for logging in to the api and daemon
// as a user.
type UserLogin struct {
Email string `json:"email"`
Password string `json:"passphrase"`
}
// Type returns the type of login request
func (u *UserLogin) Type() string {
return UserSession
}
// Valid returns whether or not this is a valid login request
func (u *UserLogin) Valid() bool {
return u.Email != "" && u.Password != ""
}
// Passphrase returns the "secret" or "password" component of the request
func (u *UserLogin) Passphrase() []byte {
return []byte(u.Password)
}
// Identifier returns the identifying piece of information of the request
func (u *UserLogin) Identifier() string {
return u.Email
}
// MachineLogin contains the required details for logging into the api and
// daemon as a machine.
type MachineLogin struct {
TokenID *identity.ID `json:"token_id"`
Secret *base64.Value `json:"secret"`
}
// Type returns the type of the login request
func (m *MachineLogin) Type() string {
return MachineSession
}
// Valid returns whether or not this is a valid machine login request
func (m *MachineLogin) Valid() bool {
return m.TokenID != nil && m.Secret != nil && m.Secret.String() != ""
}
// Passphrase returns the "secret" component of the request
func (m *MachineLogin) Passphrase() []byte {
return *m.Secret
}
// Identifier returns the identifying piece of information of the request
func (m *MachineLogin) Identifier() string {
return m.TokenID.String()
}
// Profile contains the fields in the response for the profiles endpoint
type Profile struct {
ID *identity.ID `json:"id"`
Body *struct {
Name string `json:"name"`
Username string `json:"username"`
} `json:"body"`
}
// Signup contains information required for registering an account
type Signup struct {
Name string
Username string
Email string
Passphrase string
InviteCode string
OrgName string
OrgInvite bool
}
// ProfileUpdate contains the fields a user can change on their user object
type ProfileUpdate struct {
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
}
// OrgInvite contains information for sending an Org invite
type OrgInvite struct {
ID string `json:"id"`
Version int `json:"version"`
Body *primitive.OrgInvite `json:"body"`
}
// Team contains information for creating a new Team object
type Team struct {
ID *identity.ID `json:"id"`
Version int `json:"version"`
Body *primitive.Team `json:"body"`
}
// Service contains information for creating a new Service object
type Service struct {
ID *identity.ID `json:"id"`
Version int `json:"version"`
Body *primitive.Service `json:"body"`
}
// Environment contains information for creating a new Env object
type Environment struct {
ID string `json:"id"`
Version int `json:"version"`
Body *primitive.Environment `json:"body"`
}
// InviteAccept contains data required to accept org invite
type InviteAccept struct {
Org string `json:"org"`
Email string `json:"email"`
Code string `json:"code"`
}
// Membership contains data required to be added to a team
type Membership struct {
ID *identity.ID `json:"id"`
Version int `json:"version"`
Body *primitive.Membership `json:"body"`
}
// VerifyEmail contains email verification code
type VerifyEmail struct {
Code string `json:"code"`
}