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:
Wilfred Asomani 2023-06-28 13:06:32 +00:00
parent e8fcdc10a4
commit 4ee647a951
12 changed files with 214 additions and 182 deletions

View File

@ -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

View File

@ -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)

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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(&registerData)
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.

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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...)
}