-
Notifications
You must be signed in to change notification settings - Fork 158
/
errors.go
128 lines (115 loc) · 3.33 KB
/
errors.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
package heroku
import (
"errors"
"fmt"
"net/http"
"github.com/jinzhu/gorm"
"github.com/remind101/empire"
"github.com/remind101/empire/pkg/heroku"
)
// Named matching heroku's error codes. See
// https://devcenter.heroku.com/articles/platform-api-reference#error-responses
var (
ErrBadRequest = &ErrorResource{
Status: http.StatusBadRequest,
ID: "bad_request",
Message: "Request invalid, validate usage and try again",
}
ErrUnauthorized = &ErrorResource{
Status: http.StatusUnauthorized,
ID: "unauthorized",
Message: "Request not authenticated, API token is missing, invalid or expired",
}
ErrForbidden = &ErrorResource{
Status: http.StatusForbidden,
ID: "forbidden",
Message: "Request not authorized, provided credentials do not provide access to specified resource",
}
ErrNotFound = &ErrorResource{
Status: http.StatusNotFound,
ID: "not_found",
Message: "Request failed, the specified resource does not exist",
}
ErrTwoFactor = &ErrorResource{
Status: http.StatusUnauthorized,
ID: "two_factor",
Message: "Two factor code is required.",
}
ErrSSLRemoved = &ErrorResource{
Status: http.StatusNotFound,
ID: "not_found",
Message: "Support for uploading SSL certificates through Empire has been removed and replaced with certificate attachments.",
URL: "http://empire.readthedocs.org/en/latest/ssl_certs/",
}
ErrMessageRequired = &ErrorResource{
Status: http.StatusBadRequest,
ID: "message_required",
Message: fmt.Sprintf("Header '%s' is required", heroku.CommitMessageHeader),
}
)
// ErrorResource represents the error response format that we return.
type ErrorResource struct {
Status int `json:"-"`
ID string `json:"id"`
Message string `json:"message"`
URL string `json:"url"`
}
func newError(err error) *ErrorResource {
if err == gorm.RecordNotFound {
return ErrNotFound
}
switch err := err.(type) {
case *ErrorResource:
return err
case *empire.MessageRequiredError:
return ErrMessageRequired
case *empire.ValidationError:
return ErrBadRequest
default:
return &ErrorResource{
Message: err.Error(),
}
}
}
// Error implements error interface.
func (e *ErrorResource) Error() string {
return e.Message
}
func errNotImplemented(message string) *ErrorResource {
return &ErrorResource{
Status: http.StatusNotImplemented,
ID: "not_implemented",
Message: message,
}
}
// Returns an appropriate ErrorResource when a request is unauthorized.
func Unauthorized(reason error) *ErrorResource {
if reason == nil {
return ErrUnauthorized
}
return &ErrorResource{
Status: http.StatusUnauthorized,
ID: "unauthorized",
Message: reason.Error(),
}
}
// SAMLUnauthorized can be used in place of Unauthorized to return a link to
// login via SAML.
func SAMLUnauthorized(loginURL string) func(error) *ErrorResource {
return func(reason error) *ErrorResource {
if reason == nil {
reason = errors.New("Request not authenticated, API token is missing, invalid or expired")
}
return &ErrorResource{
Status: http.StatusUnauthorized,
ID: "saml_unauthorized",
Message: fmt.Sprintf("%s. Login at %s", reason, loginURL),
}
}
}
// errHandler returns a handler that responds with the given error.
func errHandler(err error) handlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
return err
}
}