diff options
Diffstat (limited to 'api')
-rw-r--r-- | api/api.go | 43 | ||||
-rw-r--r-- | api/const.go | 74 | ||||
-rw-r--r-- | api/const_string.go | 14 | ||||
-rw-r--r-- | api/logger.go | 12 | ||||
-rw-r--r-- | api/market_config.go | 19 | ||||
-rw-r--r-- | api/routes.go | 2 |
6 files changed, 96 insertions, 68 deletions
@@ -5,6 +5,7 @@ import ( | |||
5 | "unicode" | 5 | "unicode" |
6 | 6 | ||
7 | "github.com/gin-gonic/gin" | 7 | "github.com/gin-gonic/gin" |
8 | "github.com/jloup/utils" | ||
8 | ) | 9 | ) |
9 | 10 | ||
10 | var CONFIG Config | 11 | var CONFIG Config |
@@ -43,11 +44,30 @@ func SetMailConfig(config MailConfig) { | |||
43 | } | 44 | } |
44 | 45 | ||
45 | type Error struct { | 46 | type Error struct { |
46 | Code ErrorCode | 47 | Code utils.Flag |
47 | UserMessage string | 48 | UserMessage string |
48 | err error | 49 | err error |
49 | } | 50 | } |
50 | 51 | ||
52 | func (e Error) FlagString() string { | ||
53 | return e.Code.String() | ||
54 | } | ||
55 | |||
56 | func (e Error) Flag() utils.Flag { | ||
57 | return e.Code | ||
58 | } | ||
59 | |||
60 | func (e Error) Msg() string { | ||
61 | return e.UserMessage | ||
62 | } | ||
63 | |||
64 | func (e Error) ErrorWithCode(f utils.Flag) utils.ErrorFlagged { | ||
65 | if utils.Intersect(e.Code, f) { | ||
66 | return e | ||
67 | } | ||
68 | |||
69 | return nil | ||
70 | } | ||
51 | func (e Error) Err() error { | 71 | func (e Error) Err() error { |
52 | if e.err != nil { | 72 | if e.err != nil { |
53 | return e | 73 | return e |
@@ -64,7 +84,7 @@ func (e Error) Error() string { | |||
64 | return "" | 84 | return "" |
65 | } | 85 | } |
66 | 86 | ||
67 | func ErrorIs(err error, code ErrorCode) bool { | 87 | func ErrorIs(err error, code utils.Flag) bool { |
68 | if err == nil { | 88 | if err == nil { |
69 | return false | 89 | return false |
70 | } | 90 | } |
@@ -72,7 +92,7 @@ func ErrorIs(err error, code ErrorCode) bool { | |||
72 | if apiError, ok := err.(*Error); !ok { | 92 | if apiError, ok := err.(*Error); !ok { |
73 | return false | 93 | return false |
74 | } else { | 94 | } else { |
75 | return apiError.Code == code | 95 | return utils.Intersect(apiError.Code, code) && apiError.Code.String() == code.String() |
76 | } | 96 | } |
77 | } | 97 | } |
78 | 98 | ||
@@ -99,8 +119,8 @@ func ToSnake(in string) string { | |||
99 | } | 119 | } |
100 | 120 | ||
101 | type Response struct { | 121 | type Response struct { |
102 | StatusCode Status `json:"-"` | 122 | StatusCode Status `json:"-"` |
103 | ErrorCode ErrorCode `json:"-"` | 123 | ErrorCode utils.Flag `json:"-"` |
104 | 124 | ||
105 | Status string `json:"status"` | 125 | Status string `json:"status"` |
106 | Code string `json:"code,omitempty"` | 126 | Code string `json:"code,omitempty"` |
@@ -110,15 +130,12 @@ type Response struct { | |||
110 | 130 | ||
111 | func (r Response) populateStatus() Response { | 131 | func (r Response) populateStatus() Response { |
112 | r.Status = ToSnake(r.StatusCode.String()) | 132 | r.Status = ToSnake(r.StatusCode.String()) |
113 | 133 | r.Code = ToSnake(r.ErrorCode.String()) | |
114 | if r.ErrorCode != 0 { | ||
115 | r.Code = ToSnake(r.ErrorCode.String()) | ||
116 | } | ||
117 | 134 | ||
118 | return r | 135 | return r |
119 | } | 136 | } |
120 | 137 | ||
121 | func ErrorResponse(code ErrorCode, message string) Response { | 138 | func ErrorResponse(code utils.Flag, message string) Response { |
122 | return Response{ | 139 | return Response{ |
123 | StatusCode: NOK, | 140 | StatusCode: NOK, |
124 | ErrorCode: code, | 141 | ErrorCode: code, |
@@ -150,7 +167,7 @@ func M(handler Middleware) gin.HandlerFunc { | |||
150 | err := handler(c) | 167 | err := handler(c) |
151 | 168 | ||
152 | if err != nil { | 169 | if err != nil { |
153 | WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) | 170 | WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c) |
154 | c.Error(err) | 171 | c.Error(err) |
155 | c.Abort() | 172 | c.Abort() |
156 | } else { | 173 | } else { |
@@ -166,13 +183,13 @@ type Query interface { | |||
166 | 183 | ||
167 | func RunQuery(query Query, c *gin.Context) { | 184 | func RunQuery(query Query, c *gin.Context) { |
168 | if err := query.ValidateParams(); err != nil { | 185 | if err := query.ValidateParams(); err != nil { |
169 | WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) | 186 | WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c) |
170 | c.Error(err) | 187 | c.Error(err) |
171 | return | 188 | return |
172 | } | 189 | } |
173 | 190 | ||
174 | if out, err := query.Run(); err != nil { | 191 | if out, err := query.Run(); err != nil { |
175 | WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) | 192 | WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c) |
176 | c.Error(err) | 193 | c.Error(err) |
177 | } else { | 194 | } else { |
178 | WriteJsonResponse(SuccessResponse(out), c) | 195 | WriteJsonResponse(SuccessResponse(out), c) |
diff --git a/api/const.go b/api/const.go index 2ad4d61..4f608d5 100644 --- a/api/const.go +++ b/api/const.go | |||
@@ -1,58 +1,66 @@ | |||
1 | package api | 1 | package api |
2 | 2 | ||
3 | import "net/http" | 3 | import ( |
4 | "net/http" | ||
4 | 5 | ||
5 | //go:generate stringer -type=Status,ErrorCode -output const_string.go | 6 | "github.com/jloup/utils" |
7 | ) | ||
8 | |||
9 | //go:generate stringer -type=Status -output const_string.go | ||
6 | type Status uint32 | 10 | type Status uint32 |
7 | type ErrorCode uint32 | ||
8 | 11 | ||
9 | const EXTERNAL_SERVICE_TIMEOUT_SECONDS = 20 | 12 | const EXTERNAL_SERVICE_TIMEOUT_SECONDS = 20 |
10 | 13 | ||
11 | const ( | 14 | const ( |
12 | OK Status = iota | 15 | OK Status = iota |
13 | NOK | 16 | NOK |
17 | ) | ||
14 | 18 | ||
15 | BadRequest ErrorCode = iota + 1 | 19 | var ( |
16 | EmailExists | 20 | errorFlagCounter utils.Counter = 0 |
17 | ExternalServiceTimeout | 21 | BadRequest utils.Flag = utils.InitFlag(&errorFlagCounter, "BadRequest") |
18 | InternalError | 22 | EmailExists utils.Flag = utils.InitFlag(&errorFlagCounter, "EmailExists") |
19 | InvalidCredentials | 23 | ExternalServiceTimeout utils.Flag = utils.InitFlag(&errorFlagCounter, "ExternalServiceTimeout") |
20 | InvalidEmail | 24 | InternalError utils.Flag = utils.InitFlag(&errorFlagCounter, "InternalError") |
21 | InvalidMarketCredentials | 25 | InvalidCredentials utils.Flag = utils.InitFlag(&errorFlagCounter, "InvalidCredentials") |
22 | MarketCredentialsNotConfigured | 26 | InvalidEmail utils.Flag = utils.InitFlag(&errorFlagCounter, "InvalidEmail") |
23 | IPRestrictedApiKey | 27 | InvalidMarketCredentials utils.Flag = utils.InitFlag(&errorFlagCounter, "InvalidMarketCredentials") |
24 | InvalidOtp | 28 | MarketCredentialsNotConfigured utils.Flag = utils.InitFlag(&errorFlagCounter, "MarketCredentialsNotConfigured") |
25 | InvalidPassword | 29 | IPRestrictedApiKey utils.Flag = utils.InitFlag(&errorFlagCounter, "IPRestrictedApiKey") |
26 | NeedOtpValidation | 30 | InvalidOtp utils.Flag = utils.InitFlag(&errorFlagCounter, "InvalidOtp") |
27 | NotAuthorized | 31 | InvalidPassword utils.Flag = utils.InitFlag(&errorFlagCounter, "InvalidPassword") |
28 | NotFound | 32 | NeedOtpValidation utils.Flag = utils.InitFlag(&errorFlagCounter, "NeedOtpValidation") |
29 | OtpAlreadySetup | 33 | NotAuthorized utils.Flag = utils.InitFlag(&errorFlagCounter, "NotAuthorized") |
30 | OtpNotSetup | 34 | NotFound utils.Flag = utils.InitFlag(&errorFlagCounter, "NotFound") |
31 | UserNotConfirmed | 35 | OtpAlreadySetup utils.Flag = utils.InitFlag(&errorFlagCounter, "OtpAlreadySetup") |
36 | OtpNotSetup utils.Flag = utils.InitFlag(&errorFlagCounter, "OtpNotSetup") | ||
37 | UserNotConfirmed utils.Flag = utils.InitFlag(&errorFlagCounter, "UserNotConfirmed") | ||
38 | |||
39 | StatusBadRequest utils.Flag = utils.Join("BadRequest", BadRequest, InvalidPassword, InvalidEmail, InvalidMarketCredentials, IPRestrictedApiKey, MarketCredentialsNotConfigured) | ||
40 | StatusUnauthorized utils.Flag = utils.Join("Unauthorized", InvalidCredentials, InvalidOtp) | ||
41 | StatusForbidden utils.Flag = utils.Join("Forbidden", UserNotConfirmed, NotAuthorized, OtpAlreadySetup, OtpNotSetup, NeedOtpValidation) | ||
42 | StatusConflicts utils.Flag = utils.Join("Conflicts", EmailExists) | ||
43 | StatusNotFound utils.Flag = utils.Join("NotFound", NotFound) | ||
44 | StatusGatewayTimeout utils.Flag = utils.Join("GatewayTimeout", ExternalServiceTimeout) | ||
32 | ) | 45 | ) |
33 | 46 | ||
34 | func StatusToHttpCode(status Status, code ErrorCode) int { | 47 | func StatusToHttpCode(status Status, code utils.Flag) int { |
35 | if status == OK { | 48 | if status == OK { |
36 | return http.StatusOK | 49 | return http.StatusOK |
37 | } | 50 | } |
38 | 51 | ||
39 | switch code { | 52 | switch { |
40 | case BadRequest, InvalidPassword, InvalidEmail, InvalidMarketCredentials, IPRestrictedApiKey, MarketCredentialsNotConfigured: | 53 | case utils.Intersect(code, StatusBadRequest): |
41 | return http.StatusBadRequest | 54 | return http.StatusBadRequest |
42 | 55 | case utils.Intersect(code, StatusUnauthorized): | |
43 | case InvalidCredentials, InvalidOtp: | ||
44 | return http.StatusUnauthorized | 56 | return http.StatusUnauthorized |
45 | 57 | case utils.Intersect(code, StatusForbidden): | |
46 | case UserNotConfirmed, NotAuthorized, OtpAlreadySetup, OtpNotSetup, NeedOtpValidation: | ||
47 | return http.StatusForbidden | 58 | return http.StatusForbidden |
48 | 59 | case utils.Intersect(code, StatusConflicts): | |
49 | case EmailExists: | ||
50 | return http.StatusConflict | 60 | return http.StatusConflict |
51 | 61 | case utils.Intersect(code, StatusNotFound): | |
52 | case NotFound: | ||
53 | return http.StatusNotFound | 62 | return http.StatusNotFound |
54 | 63 | case utils.Intersect(code, StatusGatewayTimeout): | |
55 | case ExternalServiceTimeout: | ||
56 | return http.StatusGatewayTimeout | 64 | return http.StatusGatewayTimeout |
57 | } | 65 | } |
58 | 66 | ||
diff --git a/api/const_string.go b/api/const_string.go index 5af7574..c22d1ae 100644 --- a/api/const_string.go +++ b/api/const_string.go | |||
@@ -1,4 +1,4 @@ | |||
1 | // Code generated by "stringer -type=Status,ErrorCode -output const_string.go"; DO NOT EDIT. | 1 | // Code generated by "stringer -type=Status -output const_string.go"; DO NOT EDIT. |
2 | 2 | ||
3 | package api | 3 | package api |
4 | 4 | ||
@@ -14,15 +14,3 @@ func (i Status) String() string { | |||
14 | } | 14 | } |
15 | return _Status_name[_Status_index[i]:_Status_index[i+1]] | 15 | return _Status_name[_Status_index[i]:_Status_index[i+1]] |
16 | } | 16 | } |
17 | |||
18 | const _ErrorCode_name = "BadRequestEmailExistsExternalServiceTimeoutInternalErrorInvalidCredentialsInvalidEmailInvalidMarketCredentialsMarketCredentialsNotConfiguredIPRestrictedApiKeyInvalidOtpInvalidPasswordNeedOtpValidationNotAuthorizedNotFoundOtpAlreadySetupOtpNotSetupUserNotConfirmed" | ||
19 | |||
20 | var _ErrorCode_index = [...]uint16{0, 10, 21, 43, 56, 74, 86, 110, 140, 158, 168, 183, 200, 213, 221, 236, 247, 263} | ||
21 | |||
22 | func (i ErrorCode) String() string { | ||
23 | i -= 3 | ||
24 | if i >= ErrorCode(len(_ErrorCode_index)-1) { | ||
25 | return "ErrorCode(" + strconv.FormatInt(int64(i+3), 10) + ")" | ||
26 | } | ||
27 | return _ErrorCode_name[_ErrorCode_index[i]:_ErrorCode_index[i+1]] | ||
28 | } | ||
diff --git a/api/logger.go b/api/logger.go index a24e08a..5f49d29 100644 --- a/api/logger.go +++ b/api/logger.go | |||
@@ -2,7 +2,6 @@ package api | |||
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "fmt" | 4 | "fmt" |
5 | "strings" | ||
6 | "time" | 5 | "time" |
7 | 6 | ||
8 | "github.com/Sirupsen/logrus" | 7 | "github.com/Sirupsen/logrus" |
@@ -51,11 +50,14 @@ func Logger() gin.HandlerFunc { | |||
51 | level = logrus.ErrorLevel | 50 | level = logrus.ErrorLevel |
52 | } | 51 | } |
53 | 52 | ||
54 | comment := c.Errors.ByType(gin.ErrorTypePrivate).String() | 53 | errors := c.Errors.ByType(gin.ErrorTypePrivate) |
55 | if comment != "" { | 54 | |
56 | msgLog = fmt.Sprintf("%s: %s", msgLog, strings.TrimSpace(comment)) | 55 | for _, err := range errors { |
56 | l.Logf(level, "%s: %s", msgLog, err.Err) | ||
57 | } | 57 | } |
58 | 58 | ||
59 | l.Logf(level, msgLog) | 59 | if errors == nil { |
60 | l.Logf(level, msgLog) | ||
61 | } | ||
60 | } | 62 | } |
61 | } | 63 | } |
diff --git a/api/market_config.go b/api/market_config.go index e02c3ba..c7e2e15 100644 --- a/api/market_config.go +++ b/api/market_config.go | |||
@@ -5,9 +5,9 @@ import ( | |||
5 | "strings" | 5 | "strings" |
6 | "time" | 6 | "time" |
7 | 7 | ||
8 | "github.com/jloup/utils" | ||
9 | "git.immae.eu/Cryptoportfolio/Front.git/db" | 8 | "git.immae.eu/Cryptoportfolio/Front.git/db" |
10 | "git.immae.eu/Cryptoportfolio/Front.git/markets" | 9 | "git.immae.eu/Cryptoportfolio/Front.git/markets" |
10 | "github.com/jloup/utils" | ||
11 | ) | 11 | ) |
12 | 12 | ||
13 | type MarketConfigQuery struct { | 13 | type MarketConfigQuery struct { |
@@ -97,10 +97,23 @@ func (q TestMarketCredentialsQuery) Run() (interface{}, *Error) { | |||
97 | return nil | 97 | return nil |
98 | }) | 98 | }) |
99 | 99 | ||
100 | if resultErr != nil { | 100 | var newStatus db.MarketConfigStatus = config.Status |
101 | |||
102 | if ErrorIs(resultErr, InvalidMarketCredentials) || ErrorIs(resultErr, IPRestrictedApiKey) || ErrorIs(resultErr, MarketCredentialsNotConfigured) { | ||
103 | newStatus = db.MarketConfigInvalidCredentials | ||
104 | } else if resultErr != nil { | ||
105 | return nil, NewInternalError(resultErr) | ||
106 | } else if resultErr != nil { | ||
101 | return nil, NewInternalError(resultErr) | 107 | return nil, NewInternalError(resultErr) |
102 | } | 108 | } |
103 | 109 | ||
110 | if newStatus != config.Status { | ||
111 | config, err = db.SetMarketConfigStatus(*config, newStatus) | ||
112 | if err != nil { | ||
113 | return nil, NewInternalError(err) | ||
114 | } | ||
115 | } | ||
116 | |||
104 | return nil, nil | 117 | return nil, nil |
105 | } | 118 | } |
106 | 119 | ||
@@ -158,7 +171,7 @@ func (q UpdateMarketConfigQuery) Run() (interface{}, *Error) { | |||
158 | 171 | ||
159 | var newStatus db.MarketConfigStatus = db.MarketConfigEnabled | 172 | var newStatus db.MarketConfigStatus = db.MarketConfigEnabled |
160 | 173 | ||
161 | if ErrorIs(resultErr, InvalidMarketCredentials) || ErrorIs(resultErr, IPRestrictedApiKey) { | 174 | if ErrorIs(resultErr, InvalidMarketCredentials) || ErrorIs(resultErr, IPRestrictedApiKey) || ErrorIs(resultErr, MarketCredentialsNotConfigured) { |
162 | newStatus = db.MarketConfigInvalidCredentials | 175 | newStatus = db.MarketConfigInvalidCredentials |
163 | } else if resultErr != nil { | 176 | } else if resultErr != nil { |
164 | return nil, NewInternalError(resultErr) | 177 | return nil, NewInternalError(resultErr) |
diff --git a/api/routes.go b/api/routes.go index a102419..671d22e 100644 --- a/api/routes.go +++ b/api/routes.go | |||
@@ -99,7 +99,7 @@ func OtpEnrollment(c *gin.Context) { | |||
99 | 99 | ||
100 | qrPng, secret, err := query.Run() | 100 | qrPng, secret, err := query.Run() |
101 | if err != nil { | 101 | if err != nil { |
102 | WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) | 102 | WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c) |
103 | c.Error(err) | 103 | c.Error(err) |
104 | return | 104 | return |
105 | } | 105 | } |