satellite: add request id to requests
This change adds request IDs to requests, logs them as part of audit logs and sends to the client on error. This is to improve debugging of customer issues. Issue: https://github.com/storj/storj/issues/5898 Change-Id: I801514b547d28d810552d91aa7c8502051e552bf
This commit is contained in:
parent
e8fcdc10a4
commit
4ee647a951
@ -4,24 +4,34 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"storj.io/common/http/requestid"
|
||||
)
|
||||
|
||||
// ServeJSONError writes a JSON error to the response output stream.
|
||||
func ServeJSONError(log *zap.Logger, w http.ResponseWriter, status int, err error) {
|
||||
ServeCustomJSONError(log, w, status, err, err.Error())
|
||||
func ServeJSONError(ctx context.Context, log *zap.Logger, w http.ResponseWriter, status int, err error) {
|
||||
ServeCustomJSONError(ctx, log, w, status, err, err.Error())
|
||||
}
|
||||
|
||||
// ServeCustomJSONError writes a JSON error with a custom message to the response output stream.
|
||||
func ServeCustomJSONError(log *zap.Logger, w http.ResponseWriter, status int, err error, msg string) {
|
||||
func ServeCustomJSONError(ctx context.Context, log *zap.Logger, w http.ResponseWriter, status int, err error, msg string) {
|
||||
fields := []zap.Field{
|
||||
zap.Int("code", status),
|
||||
zap.String("message", msg),
|
||||
zap.Error(err),
|
||||
}
|
||||
|
||||
if requestID := requestid.FromContext(ctx); requestID != "" {
|
||||
fields = append(fields, zap.String("requestID", requestID))
|
||||
msg += fmt.Sprintf(" (request id: %s)", requestID)
|
||||
}
|
||||
|
||||
switch status {
|
||||
case http.StatusNoContent:
|
||||
return
|
||||
|
@ -87,12 +87,12 @@ func (rl *RateLimiter) Limit(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
key, err := rl.keyFunc(r)
|
||||
if err != nil {
|
||||
ServeCustomJSONError(rl.log, w, http.StatusInternalServerError, err, internalServerErrMsg)
|
||||
ServeCustomJSONError(r.Context(), rl.log, w, http.StatusInternalServerError, err, internalServerErrMsg)
|
||||
return
|
||||
}
|
||||
limit := rl.getUserLimit(key)
|
||||
if !limit.Allow() {
|
||||
ServeJSONError(rl.log, w, http.StatusTooManyRequests, errs.New(rateLimitErrMsg))
|
||||
ServeJSONError(r.Context(), rl.log, w, http.StatusTooManyRequests, errs.New(rateLimitErrMsg))
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
|
@ -41,13 +41,13 @@ func (a *ABTesting) GetABValues(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
user, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
web.ServeJSONError(a.log, w, http.StatusUnauthorized, err)
|
||||
web.ServeJSONError(ctx, a.log, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
values, err := a.service.GetABValues(ctx, *user)
|
||||
if err != nil {
|
||||
web.ServeJSONError(a.log, w, http.StatusInternalServerError, err)
|
||||
web.ServeJSONError(ctx, a.log, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@ -66,13 +66,13 @@ func (a *ABTesting) SendHit(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
action := mux.Vars(r)["action"]
|
||||
if action == "" {
|
||||
web.ServeJSONError(a.log, w, http.StatusBadRequest, errs.New("parameter 'action' can't be empty"))
|
||||
web.ServeJSONError(ctx, a.log, w, http.StatusBadRequest, errs.New("parameter 'action' can't be empty"))
|
||||
return
|
||||
}
|
||||
|
||||
user, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
web.ServeJSONError(a.log, w, http.StatusUnauthorized, err)
|
||||
web.ServeJSONError(ctx, a.log, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
package consoleapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
@ -54,17 +55,17 @@ func (a *Analytics) EventTriggered(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
a.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
var et eventTriggeredBody
|
||||
err = json.Unmarshal(body, &et)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
a.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
user, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
a.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -86,17 +87,17 @@ func (a *Analytics) PageEventTriggered(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
a.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
var pv pageVisitBody
|
||||
err = json.Unmarshal(body, &pv)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
a.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
user, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
a.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -106,6 +107,6 @@ func (a *Analytics) PageEventTriggered(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// serveJSONError writes JSON error to response output stream.
|
||||
func (a *Analytics) serveJSONError(w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(a.log, w, status, err)
|
||||
func (a *Analytics) serveJSONError(ctx context.Context, w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(ctx, a.log, w, status, err)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
package consoleapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
@ -42,24 +43,24 @@ func (keys *APIKeys) GetAllAPIKeyNames(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
projectIDString := r.URL.Query().Get("projectID")
|
||||
if projectIDString == "" {
|
||||
keys.serveJSONError(w, http.StatusBadRequest, errs.New("Project ID was not provided."))
|
||||
keys.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("Project ID was not provided."))
|
||||
return
|
||||
}
|
||||
|
||||
projectID, err := uuid.FromString(projectIDString)
|
||||
if err != nil {
|
||||
keys.serveJSONError(w, http.StatusBadRequest, err)
|
||||
keys.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
apiKeyNames, err := keys.service.GetAllAPIKeyNamesByProjectID(ctx, projectID)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
keys.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
keys.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
keys.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
keys.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -81,7 +82,7 @@ func (keys *APIKeys) DeleteByNameAndProjectID(w http.ResponseWriter, r *http.Req
|
||||
publicIDString := r.URL.Query().Get("publicID")
|
||||
|
||||
if name == "" {
|
||||
keys.serveJSONError(w, http.StatusBadRequest, err)
|
||||
keys.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -89,38 +90,38 @@ func (keys *APIKeys) DeleteByNameAndProjectID(w http.ResponseWriter, r *http.Req
|
||||
if projectIDString != "" {
|
||||
projectID, err = uuid.FromString(projectIDString)
|
||||
if err != nil {
|
||||
keys.serveJSONError(w, http.StatusBadRequest, err)
|
||||
keys.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
} else if publicIDString != "" {
|
||||
projectID, err = uuid.FromString(publicIDString)
|
||||
if err != nil {
|
||||
keys.serveJSONError(w, http.StatusBadRequest, err)
|
||||
keys.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
keys.serveJSONError(w, http.StatusBadRequest, errs.New("Project ID was not provided."))
|
||||
keys.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("Project ID was not provided."))
|
||||
return
|
||||
}
|
||||
|
||||
err = keys.service.DeleteAPIKeyByNameAndProjectID(ctx, name, projectID)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
keys.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
keys.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
if console.ErrNoAPIKey.Has(err) {
|
||||
keys.serveJSONError(w, http.StatusNoContent, err)
|
||||
keys.serveJSONError(ctx, w, http.StatusNoContent, err)
|
||||
return
|
||||
}
|
||||
|
||||
keys.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
keys.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// serveJSONError writes JSON error to response output stream.
|
||||
func (keys *APIKeys) serveJSONError(w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(keys.log, w, status, err)
|
||||
func (keys *APIKeys) serveJSONError(ctx context.Context, w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(ctx, keys.log, w, status, err)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
package consoleapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
@ -82,24 +83,24 @@ func (a *Auth) Token(w http.ResponseWriter, r *http.Request) {
|
||||
tokenRequest := console.AuthUser{}
|
||||
err = json.NewDecoder(r.Body).Decode(&tokenRequest)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
tokenRequest.UserAgent = r.UserAgent()
|
||||
tokenRequest.IP, err = web.GetRequestIP(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
tokenInfo, err := a.service.Token(ctx, tokenRequest)
|
||||
if err != nil {
|
||||
if console.ErrMFAMissing.Has(err) {
|
||||
web.ServeCustomJSONError(a.log, w, http.StatusOK, err, a.getUserErrorMessage(err))
|
||||
web.ServeCustomJSONError(ctx, a.log, w, http.StatusOK, err, a.getUserErrorMessage(err))
|
||||
} else {
|
||||
a.log.Info("Error authenticating token request", zap.String("email", tokenRequest.Email), zap.Error(ErrAuthAPI.Wrap(err)))
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -126,7 +127,7 @@ func (a *Auth) TokenByAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
authToken := r.Header.Get("Authorization")
|
||||
if !(strings.HasPrefix(authToken, "Bearer ")) {
|
||||
a.log.Info("authorization key format is incorrect. Should be 'Bearer <key>'")
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -135,14 +136,14 @@ func (a *Auth) TokenByAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
userAgent := r.UserAgent()
|
||||
ip, err := web.GetRequestIP(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
tokenInfo, err := a.service.TokenByAPIKey(ctx, userAgent, ip, apiKey)
|
||||
if err != nil {
|
||||
a.log.Info("Error authenticating token request", zap.Error(ErrAuthAPI.Wrap(err)))
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -184,13 +185,13 @@ func (a *Auth) Logout(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
sessionID, err := a.getSessionID(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.service.DeleteSession(ctx, sessionID)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -225,7 +226,7 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(®isterData)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -234,23 +235,23 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
isValidEmail := utils.ValidateEmail(registerData.Email)
|
||||
if !isValidEmail {
|
||||
a.serveJSONError(w, console.ErrValidation.Wrap(errs.New("Invalid email.")))
|
||||
a.serveJSONError(ctx, w, console.ErrValidation.Wrap(errs.New("Invalid email.")))
|
||||
return
|
||||
}
|
||||
|
||||
if len([]rune(registerData.Partner)) > 100 {
|
||||
a.serveJSONError(w, console.ErrValidation.Wrap(errs.New("Partner must be less than or equal to 100 characters")))
|
||||
a.serveJSONError(ctx, w, console.ErrValidation.Wrap(errs.New("Partner must be less than or equal to 100 characters")))
|
||||
return
|
||||
}
|
||||
|
||||
if len([]rune(registerData.SignupPromoCode)) > 100 {
|
||||
a.serveJSONError(w, console.ErrValidation.Wrap(errs.New("Promo code must be less than or equal to 100 characters")))
|
||||
a.serveJSONError(ctx, w, console.ErrValidation.Wrap(errs.New("Promo code must be less than or equal to 100 characters")))
|
||||
return
|
||||
}
|
||||
|
||||
verified, unverified, err := a.service.GetUserByEmailWithUnverified(ctx, registerData.Email)
|
||||
if err != nil && !console.ErrEmailNotFound.Has(err) {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -279,7 +280,7 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
secret, err := console.RegistrationSecretFromBase64(registerData.SecretInput)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -289,7 +290,7 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
ip, err := web.GetRequestIP(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -312,7 +313,7 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
secret,
|
||||
)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -351,7 +352,7 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
token, err := a.service.GenerateActivationToken(ctx, user.ID, user.Email)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -390,13 +391,13 @@ func (a *Auth) GetFreezeStatus(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
userID, err := a.service.GetUserID(ctx)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
freeze, warning, err := a.accountFreezeService.GetAll(ctx, userID)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -424,12 +425,12 @@ func (a *Auth) UpdateAccount(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&updatedInfo)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = a.service.UpdateAccount(ctx, updatedInfo.FullName, updatedInfo.ShortName); err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -462,7 +463,7 @@ func (a *Auth) GetAccount(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
consoleUser, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -501,7 +502,7 @@ func (a *Auth) DeleteAccount(w http.ResponseWriter, r *http.Request) {
|
||||
defer mon.Task()(&ctx)(&errNotImplemented)
|
||||
|
||||
// We do not want to allow account deletion via API currently.
|
||||
a.serveJSONError(w, errNotImplemented)
|
||||
a.serveJSONError(ctx, w, errNotImplemented)
|
||||
}
|
||||
|
||||
// ChangeEmail auth user, changes users email for a new one.
|
||||
@ -516,13 +517,13 @@ func (a *Auth) ChangeEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&emailChange)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.service.ChangeEmail(ctx, emailChange.NewEmail)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -540,13 +541,13 @@ func (a *Auth) ChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&passwordChange)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.service.ChangePassword(ctx, passwordChange.CurrentPassword, passwordChange.NewPassword)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -564,23 +565,23 @@ func (a *Auth) ForgotPassword(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&forgotPassword)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
ip, err := web.GetRequestIP(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
valid, err := a.service.VerifyForgotPasswordCaptcha(ctx, forgotPassword.CaptchaResponse, ip)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
if !valid {
|
||||
a.serveJSONError(w, console.ErrCaptcha.New("captcha validation unsuccessful"))
|
||||
a.serveJSONError(ctx, w, console.ErrCaptcha.New("captcha validation unsuccessful"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -612,7 +613,7 @@ func (a *Auth) ForgotPassword(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
recoveryToken, err := a.service.GeneratePasswordRecoveryToken(ctx, user.ID)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -663,7 +664,7 @@ func (a *Auth) ResendEmail(w http.ResponseWriter, r *http.Request) {
|
||||
if verified != nil {
|
||||
recoveryToken, err := a.service.GeneratePasswordRecoveryToken(ctx, verified.ID)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -692,7 +693,7 @@ func (a *Auth) ResendEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
token, err := a.service.GenerateActivationToken(ctx, user.ID, user.Email)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -723,31 +724,31 @@ func (a *Auth) EnableUserMFA(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
err = json.NewDecoder(r.Body).Decode(&data)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.service.EnableUserMFA(ctx, data.Passcode, time.Now())
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
sessionID, err := a.getSessionID(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
consoleUser, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.service.DeleteAllSessionsByUserIDExcept(ctx, consoleUser.ID, sessionID)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -764,31 +765,31 @@ func (a *Auth) DisableUserMFA(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
err = json.NewDecoder(r.Body).Decode(&data)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.service.DisableUserMFA(ctx, data.Passcode, time.Now(), data.RecoveryCode)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
sessionID, err := a.getSessionID(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
consoleUser, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.service.DeleteAllSessionsByUserIDExcept(ctx, consoleUser.ID, sessionID)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -801,7 +802,7 @@ func (a *Auth) GenerateMFASecretKey(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
key, err := a.service.ResetMFASecretKey(ctx)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -821,7 +822,7 @@ func (a *Auth) GenerateMFARecoveryCodes(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
codes, err := a.service.ResetMFARecoveryCodes(ctx)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -848,7 +849,7 @@ func (a *Auth) ResetPassword(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&resetPassword)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
}
|
||||
|
||||
err = a.service.ResetPassword(ctx, resetPassword.RecoveryToken, resetPassword.NewPassword, resetPassword.MFAPasscode, resetPassword.MFARecoveryCode, time.Now())
|
||||
@ -886,7 +887,7 @@ func (a *Auth) ResetPassword(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
} else {
|
||||
a.cookieAuth.RemoveTokenCookie(w)
|
||||
}
|
||||
@ -900,19 +901,19 @@ func (a *Auth) RefreshSession(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
tokenInfo, err := a.cookieAuth.GetToken(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := uuid.FromBytes(tokenInfo.Token.Payload)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
tokenInfo.ExpiresAt, err = a.service.RefreshSession(ctx, id)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -933,7 +934,7 @@ func (a *Auth) GetUserSettings(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
settings, err := a.service.GetUserSettings(ctx)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -958,7 +959,7 @@ func (a *Auth) SetOnboardingStatus(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&updateInfo)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -968,7 +969,7 @@ func (a *Auth) SetOnboardingStatus(w http.ResponseWriter, r *http.Request) {
|
||||
OnboardingStep: updateInfo.OnboardingStep,
|
||||
})
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -989,7 +990,7 @@ func (a *Auth) SetUserSettings(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&updateInfo)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -1010,7 +1011,7 @@ func (a *Auth) SetUserSettings(w http.ResponseWriter, r *http.Request) {
|
||||
SessionDuration: newDuration,
|
||||
})
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -1022,9 +1023,9 @@ func (a *Auth) SetUserSettings(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// serveJSONError writes JSON error to response output stream.
|
||||
func (a *Auth) serveJSONError(w http.ResponseWriter, err error) {
|
||||
func (a *Auth) serveJSONError(ctx context.Context, w http.ResponseWriter, err error) {
|
||||
status := a.getStatusCode(err)
|
||||
web.ServeCustomJSONError(a.log, w, status, err, a.getUserErrorMessage(err))
|
||||
web.ServeCustomJSONError(ctx, a.log, w, status, err, a.getUserErrorMessage(err))
|
||||
}
|
||||
|
||||
// getStatusCode returns http.StatusCode depends on console error class.
|
||||
|
@ -4,6 +4,7 @@
|
||||
package consoleapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
@ -49,28 +50,28 @@ func (b *Buckets) AllBucketNames(w http.ResponseWriter, r *http.Request) {
|
||||
if projectIDString != "" {
|
||||
projectID, err = uuid.FromString(projectIDString)
|
||||
if err != nil {
|
||||
b.serveJSONError(w, http.StatusBadRequest, err)
|
||||
b.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
} else if publicIDString != "" {
|
||||
projectID, err = uuid.FromString(publicIDString)
|
||||
if err != nil {
|
||||
b.serveJSONError(w, http.StatusBadRequest, err)
|
||||
b.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
b.serveJSONError(w, http.StatusBadRequest, errs.New("Project ID was not provided."))
|
||||
b.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("Project ID was not provided."))
|
||||
return
|
||||
}
|
||||
|
||||
bucketNames, err := b.service.GetAllBucketNames(ctx, projectID)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
b.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
b.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
b.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
b.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -81,6 +82,6 @@ func (b *Buckets) AllBucketNames(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// serveJSONError writes JSON error to response output stream.
|
||||
func (b *Buckets) serveJSONError(w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(b.log, w, status, err)
|
||||
func (b *Buckets) serveJSONError(ctx context.Context, w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(ctx, b.log, w, status, err)
|
||||
}
|
||||
|
@ -58,11 +58,11 @@ func (p *Payments) SetupAccount(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -83,11 +83,11 @@ func (p *Payments) AccountBalance(w http.ResponseWriter, r *http.Request) {
|
||||
balance, err := p.service.Payments().AccountBalance(ctx)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -112,12 +112,12 @@ func (p *Payments) ProjectsCharges(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
sinceStamp, err := strconv.ParseInt(r.URL.Query().Get("from"), 10, 64)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
beforeStamp, err := strconv.ParseInt(r.URL.Query().Get("to"), 10, 64)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -127,11 +127,11 @@ func (p *Payments) ProjectsCharges(w http.ResponseWriter, r *http.Request) {
|
||||
charges, err := p.service.Payments().ProjectsCharges(ctx, since, before)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ func (p *Payments) AddCreditCard(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
bodyBytes, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -206,17 +206,17 @@ func (p *Payments) AddCreditCard(w http.ResponseWriter, r *http.Request) {
|
||||
_, err = p.service.Payments().AddCreditCard(ctx, token)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = p.triggerAttemptPaymentIfFrozenOrWarned(ctx)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -232,11 +232,11 @@ func (p *Payments) ListCreditCards(w http.ResponseWriter, r *http.Request) {
|
||||
cards, err := p.service.Payments().ListCreditCards(ctx)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -259,24 +259,24 @@ func (p *Payments) MakeCreditCardDefault(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
cardID, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = p.service.Payments().MakeCreditCardDefault(ctx, string(cardID))
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = p.triggerAttemptPaymentIfFrozenOrWarned(ctx)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -291,18 +291,18 @@ func (p *Payments) RemoveCreditCard(w http.ResponseWriter, r *http.Request) {
|
||||
cardID := vars["cardId"]
|
||||
|
||||
if cardID == "" {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = p.service.Payments().RemoveCreditCard(ctx, cardID)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -318,11 +318,11 @@ func (p *Payments) BillingHistory(w http.ResponseWriter, r *http.Request) {
|
||||
billingHistory, err := p.service.Payments().BillingHistory(ctx)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -345,7 +345,7 @@ func (p *Payments) ApplyCouponCode(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
bodyBytes, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
couponCode := string(bodyBytes)
|
||||
@ -358,7 +358,7 @@ func (p *Payments) ApplyCouponCode(w http.ResponseWriter, r *http.Request) {
|
||||
} else if payments.ErrCouponConflict.Has(err) {
|
||||
status = http.StatusConflict
|
||||
}
|
||||
p.serveJSONError(w, status, err)
|
||||
p.serveJSONError(ctx, w, status, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -378,11 +378,11 @@ func (p *Payments) GetCoupon(w http.ResponseWriter, r *http.Request) {
|
||||
coupon, err := p.service.Payments().GetCoupon(ctx)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -402,15 +402,15 @@ func (p *Payments) GetWallet(w http.ResponseWriter, r *http.Request) {
|
||||
walletInfo, err := p.service.Payments().GetWallet(ctx)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
if errs.Is(err, billing.ErrNoWallet) {
|
||||
p.serveJSONError(w, http.StatusNotFound, err)
|
||||
p.serveJSONError(ctx, w, http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -430,11 +430,11 @@ func (p *Payments) ClaimWallet(w http.ResponseWriter, r *http.Request) {
|
||||
walletInfo, err := p.service.Payments().ClaimWallet(ctx)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -454,11 +454,11 @@ func (p *Payments) WalletPayments(w http.ResponseWriter, r *http.Request) {
|
||||
walletPayments, err := p.service.Payments().WalletPayments(ctx)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -477,7 +477,7 @@ func (p *Payments) GetProjectUsagePriceModel(w http.ResponseWriter, r *http.Requ
|
||||
|
||||
user, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -496,7 +496,7 @@ func (p *Payments) PurchasePackage(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
bodyBytes, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -504,13 +504,13 @@ func (p *Payments) PurchasePackage(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
u, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
pkg, err := p.packagePlans.Get(u.UserAgent)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusNotFound, err)
|
||||
p.serveJSONError(ctx, w, http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -518,9 +518,9 @@ func (p *Payments) PurchasePackage(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
switch {
|
||||
case console.ErrUnauthorized.Has(err):
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
default:
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -529,19 +529,19 @@ func (p *Payments) PurchasePackage(w http.ResponseWriter, r *http.Request) {
|
||||
err = p.service.Payments().UpdatePackage(ctx, description, time.Now())
|
||||
if err != nil {
|
||||
if !console.ErrAlreadyHasPackage.Has(err) {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = p.service.Payments().Purchase(ctx, pkg.Price, description, card.ID)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = p.service.Payments().ApplyCredit(ctx, pkg.Credit, description); err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -554,7 +554,7 @@ func (p *Payments) PackageAvailable(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
u, err := console.GetUser(ctx)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -567,6 +567,6 @@ func (p *Payments) PackageAvailable(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// serveJSONError writes JSON error to response output stream.
|
||||
func (p *Payments) serveJSONError(w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(p.log, w, status, err)
|
||||
func (p *Payments) serveJSONError(ctx context.Context, w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(ctx, p.log, w, status, err)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
package consoleapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
@ -43,18 +44,18 @@ func (p *Projects) GetSalt(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
idParam, ok := mux.Vars(r)["id"]
|
||||
if !ok {
|
||||
p.serveJSONError(w, http.StatusBadRequest, errs.New("missing id route param"))
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("missing id route param"))
|
||||
return
|
||||
}
|
||||
|
||||
id, err := uuid.FromString(idParam)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
}
|
||||
|
||||
salt, err := p.service.GetSalt(ctx, id)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -62,7 +63,7 @@ func (p *Projects) GetSalt(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewEncoder(w).Encode(b64SaltString)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,12 +75,12 @@ func (p *Projects) InviteUsers(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
idParam, ok := mux.Vars(r)["id"]
|
||||
if !ok {
|
||||
p.serveJSONError(w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
return
|
||||
}
|
||||
id, err := uuid.FromString(idParam)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
}
|
||||
|
||||
var data struct {
|
||||
@ -88,7 +89,7 @@ func (p *Projects) InviteUsers(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&data)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -98,7 +99,7 @@ func (p *Projects) InviteUsers(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
_, err = p.service.InviteProjectMembers(ctx, id, data.Emails)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,28 +110,28 @@ func (p *Projects) GetInviteLink(w http.ResponseWriter, r *http.Request) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
idParam, ok := mux.Vars(r)["id"]
|
||||
if !ok {
|
||||
p.serveJSONError(w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
return
|
||||
}
|
||||
id, err := uuid.FromString(idParam)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
}
|
||||
|
||||
email := r.URL.Query().Get("email")
|
||||
if email == "" {
|
||||
p.serveJSONError(w, http.StatusBadRequest, errs.New("missing email query param"))
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("missing email query param"))
|
||||
return
|
||||
}
|
||||
|
||||
link, err := p.service.GetInviteLink(ctx, id, email)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).Encode(link)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +145,7 @@ func (p *Projects) GetUserInvitations(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
invites, err := p.service.GetUserProjectInvitations(ctx)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -161,7 +162,7 @@ func (p *Projects) GetUserInvitations(w http.ResponseWriter, r *http.Request) {
|
||||
for _, invite := range invites {
|
||||
proj, err := p.service.GetProjectNoAuth(ctx, invite.ProjectID)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -175,7 +176,7 @@ func (p *Projects) GetUserInvitations(w http.ResponseWriter, r *http.Request) {
|
||||
if invite.InviterID != nil {
|
||||
inviter, err := p.service.GetUser(ctx, *invite.InviterID)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
respInvite.InviterEmail = inviter.Email
|
||||
@ -186,7 +187,7 @@ func (p *Projects) GetUserInvitations(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewEncoder(w).Encode(response)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,13 +201,13 @@ func (p *Projects) RespondToInvitation(w http.ResponseWriter, r *http.Request) {
|
||||
var idParam string
|
||||
|
||||
if idParam, ok = mux.Vars(r)["id"]; !ok {
|
||||
p.serveJSONError(w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
return
|
||||
}
|
||||
|
||||
id, err := uuid.FromString(idParam)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
}
|
||||
|
||||
var payload struct {
|
||||
@ -215,7 +216,7 @@ func (p *Projects) RespondToInvitation(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&payload)
|
||||
if err != nil {
|
||||
p.serveJSONError(w, http.StatusBadRequest, err)
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -230,11 +231,11 @@ func (p *Projects) RespondToInvitation(w http.ResponseWriter, r *http.Request) {
|
||||
case console.ErrValidation.Has(err):
|
||||
status = http.StatusBadRequest
|
||||
}
|
||||
p.serveJSONError(w, status, err)
|
||||
p.serveJSONError(ctx, w, status, err)
|
||||
}
|
||||
}
|
||||
|
||||
// serveJSONError writes JSON error to response output stream.
|
||||
func (p *Projects) serveJSONError(w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(p.log, w, status, err)
|
||||
func (p *Projects) serveJSONError(ctx context.Context, w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(ctx, p.log, w, status, err)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
package consoleapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@ -50,13 +51,13 @@ func (ul *UsageLimits) ProjectUsageLimits(w http.ResponseWriter, r *http.Request
|
||||
var idParam string
|
||||
|
||||
if idParam, ok = mux.Vars(r)["id"]; !ok {
|
||||
ul.serveJSONError(w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
ul.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
return
|
||||
}
|
||||
|
||||
projectID, err := uuid.FromString(idParam)
|
||||
if err != nil {
|
||||
ul.serveJSONError(w, http.StatusBadRequest, errs.New("invalid project id: %v", err))
|
||||
ul.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("invalid project id: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
@ -64,13 +65,13 @@ func (ul *UsageLimits) ProjectUsageLimits(w http.ResponseWriter, r *http.Request
|
||||
if err != nil {
|
||||
switch {
|
||||
case console.ErrUnauthorized.Has(err):
|
||||
ul.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
ul.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
case accounting.ErrInvalidArgument.Has(err):
|
||||
ul.serveJSONError(w, http.StatusBadRequest, err)
|
||||
ul.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
default:
|
||||
ul.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
ul.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -90,11 +91,11 @@ func (ul *UsageLimits) TotalUsageLimits(w http.ResponseWriter, r *http.Request)
|
||||
usageLimits, err := ul.service.GetTotalUsageLimits(ctx)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
ul.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
ul.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
ul.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
ul.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -114,23 +115,23 @@ func (ul *UsageLimits) DailyUsage(w http.ResponseWriter, r *http.Request) {
|
||||
var idParam string
|
||||
|
||||
if idParam, ok = mux.Vars(r)["id"]; !ok {
|
||||
ul.serveJSONError(w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
ul.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
return
|
||||
}
|
||||
projectID, err := uuid.FromString(idParam)
|
||||
if err != nil {
|
||||
ul.serveJSONError(w, http.StatusBadRequest, errs.New("invalid project id: %v", err))
|
||||
ul.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("invalid project id: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
sinceStamp, err := strconv.ParseInt(r.URL.Query().Get("from"), 10, 64)
|
||||
if err != nil {
|
||||
ul.serveJSONError(w, http.StatusBadRequest, err)
|
||||
ul.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
beforeStamp, err := strconv.ParseInt(r.URL.Query().Get("to"), 10, 64)
|
||||
if err != nil {
|
||||
ul.serveJSONError(w, http.StatusBadRequest, err)
|
||||
ul.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -140,11 +141,11 @@ func (ul *UsageLimits) DailyUsage(w http.ResponseWriter, r *http.Request) {
|
||||
dailyUsage, err := ul.service.GetDailyProjectUsage(ctx, projectID, since, before)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
ul.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
ul.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
ul.serveJSONError(w, http.StatusInternalServerError, err)
|
||||
ul.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -155,6 +156,6 @@ func (ul *UsageLimits) DailyUsage(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// serveJSONError writes JSON error to response output stream.
|
||||
func (ul *UsageLimits) serveJSONError(w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(ul.log, w, status, err)
|
||||
func (ul *UsageLimits) serveJSONError(ctx context.Context, w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(ctx, ul.log, w, status, err)
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"storj.io/common/errs2"
|
||||
"storj.io/common/http/requestid"
|
||||
"storj.io/common/memory"
|
||||
"storj.io/common/storj"
|
||||
"storj.io/storj/private/web"
|
||||
@ -250,6 +251,8 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc
|
||||
// the earliest in the HTTP chain.
|
||||
router.Use(newTraceRequestMiddleware(logger, router))
|
||||
|
||||
router.Use(requestid.AddToContext)
|
||||
|
||||
// limit body size
|
||||
router.Use(newBodyLimiterMiddleware(logger.Named("body-limiter-middleware"), config.BodySizeLimit))
|
||||
|
||||
@ -645,7 +648,7 @@ func (server *Server) withAuth(handler http.Handler) http.Handler {
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
web.ServeJSONError(server.log, w, http.StatusUnauthorized, console.ErrUnauthorized.Wrap(err))
|
||||
web.ServeJSONError(ctx, server.log, w, http.StatusUnauthorized, console.ErrUnauthorized.Wrap(err))
|
||||
server.cookieAuth.RemoveTokenCookie(w)
|
||||
}
|
||||
}()
|
||||
@ -924,6 +927,10 @@ func (server *Server) graphqlHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
jsonError.Error = err.Error()
|
||||
|
||||
if requestID := requestid.FromContext(ctx); requestID != "" {
|
||||
jsonError.Error += fmt.Sprintf(" (request id: %s)", requestID)
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(jsonError); err != nil {
|
||||
server.log.Error("error graphql error", zap.Error(err))
|
||||
}
|
||||
@ -988,6 +995,10 @@ func (server *Server) graphqlHandler(w http.ResponseWriter, r *http.Request) {
|
||||
jsonError.Errors = append(jsonError.Errors, err.Message)
|
||||
}
|
||||
|
||||
if requestID := requestid.FromContext(ctx); requestID != "" {
|
||||
jsonError.Errors = append(jsonError.Errors, fmt.Sprintf("request id: %s", requestID))
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(jsonError); err != nil {
|
||||
server.log.Error("error graphql error", zap.Error(err))
|
||||
}
|
||||
@ -1219,7 +1230,7 @@ func newBodyLimiterMiddleware(log *zap.Logger, limit memory.Size) mux.Middleware
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.ContentLength > limit.Int64() {
|
||||
web.ServeJSONError(log, w, http.StatusRequestEntityTooLarge, errs.New("Request body is too large"))
|
||||
web.ServeJSONError(r.Context(), log, w, http.StatusRequestEntityTooLarge, errs.New("Request body is too large"))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"storj.io/common/currency"
|
||||
"storj.io/common/http/requestid"
|
||||
"storj.io/common/macaroon"
|
||||
"storj.io/common/memory"
|
||||
"storj.io/common/uuid"
|
||||
@ -302,6 +303,10 @@ func (s *Service) auditLog(ctx context.Context, operation string, userID *uuid.U
|
||||
if email != "" {
|
||||
fields = append(fields, zap.String("email", email))
|
||||
}
|
||||
if requestID := requestid.FromContext(ctx); requestID != "" {
|
||||
fields = append(fields, zap.String("requestID", requestID))
|
||||
}
|
||||
|
||||
fields = append(fields, fields...)
|
||||
s.auditLogger.Info("console activity", fields...)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user