Skip to content

Commit

Permalink
NOISSUE - Enforce error wrapping (#240)
Browse files Browse the repository at this point in the history
add error handling for external packages mainly magistrala SDK

Signed-off-by: Rodney Osodo <[email protected]>
  • Loading branch information
rodneyosodo authored Mar 15, 2024
1 parent f1788ba commit 38b1017
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 180 deletions.
9 changes: 9 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ linters-settings:
unused:
field-writes-are-uses: false
generated-is-used: false
wrapcheck:
ignoreSigRegexps:
- "github.com/absmach/magistrala-ui/ui.Service"
- "encoding/json.*"
- "net/http.Request"
- "golang.org/x/sync/errgroup.Group"
- "net/http.ResponseWriter"
- "database/sql"

linters:
disable-all: true
Expand Down Expand Up @@ -78,3 +86,4 @@ linters:
- unconvert
- unparam
- usestdlibvars
- wrapcheck
21 changes: 11 additions & 10 deletions ui/api/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/absmach/magistrala-ui/ui"
"github.com/absmach/magistrala/pkg/errors"
"github.com/go-kit/kit/endpoint"
"github.com/golang-jwt/jwt"
"github.com/gorilla/securecookie"
Expand Down Expand Up @@ -311,16 +312,16 @@ func secureTokenEndpoint(svc ui.Service, s *securecookie.SecureCookie, prefix st
sessionDetails.Token = req.AccessToken
session, err := json.Marshal(sessionDetails)
if err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONMarshal, err)
}
secureSessionDetails, err := s.Encode(sessionDetailsKey, string(session))
if err != nil {
return nil, err
return nil, errors.Wrap(errCookieEncrypt, err)
}

secureRefreshToken, err := s.Encode(refreshTokenKey, req.RefreshToken)
if err != nil {
return nil, err
return nil, errors.Wrap(errCookieEncrypt, err)
}

refreshExp, err := extractTokenExpiry(req.RefreshToken)
Expand Down Expand Up @@ -384,16 +385,16 @@ func refreshTokenEndpoint(svc ui.Service, s *securecookie.SecureCookie, prefix s
req.Session.Token = token.AccessToken
session, err := json.Marshal(req.Session)
if err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONMarshal, err)
}
secureSessionDetails, err := s.Encode(sessionDetailsKey, string(session))
if err != nil {
return nil, err
return nil, errors.Wrap(errCookieEncrypt, err)
}

secureRefreshToken, err := s.Encode(refreshTokenKey, token.RefreshToken)
if err != nil {
return nil, err
return nil, errors.Wrap(errCookieEncrypt, err)
}
refreshExp, err := extractTokenExpiry(token.RefreshToken)
if err != nil {
Expand Down Expand Up @@ -1637,16 +1638,16 @@ func domainLoginEndpoint(svc ui.Service, s *securecookie.SecureCookie, prefix st
sessionDetails.Token = token.AccessToken
session, err := json.Marshal(sessionDetails)
if err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONMarshal, err)
}
secureSessionDetails, err := s.Encode(sessionDetailsKey, string(session))
if err != nil {
return nil, err
return nil, errors.Wrap(errCookieEncrypt, err)
}

secureRefreshToken, err := s.Encode(refreshTokenKey, token.RefreshToken)
if err != nil {
return nil, err
return nil, errors.Wrap(errCookieEncrypt, err)
}

refreshExp, err := extractTokenExpiry(token.RefreshToken)
Expand Down Expand Up @@ -2144,7 +2145,7 @@ func deleteDashboardEndpoint(svc ui.Service) endpoint.Endpoint {
func extractTokenExpiry(token string) (time.Time, error) {
jwtToken, _, err := new(jwt.Parser).ParseUnverified(token, jwt.MapClaims{})
if err != nil {
return time.Time{}, err
return time.Time{}, errors.Wrap(errParseToken, err)
}
var expTime time.Time
if claims, ok := jwtToken.Claims.(jwt.MapClaims); ok {
Expand Down
3 changes: 3 additions & 0 deletions ui/api/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@ var (
errMissingRefreshToken = errors.New("missing refresh token")
errMissingRef = errors.New("missing ref")
errInvalidQueryParams = errors.New("invalid query parameters")
errInvalidFormValue = errors.New("invalid form values")
errFileFormat = errors.New("invalid file format")
errInvalidFile = errors.New("unsupported file type")
errMissingDomainID = errors.New("missing domain id")
errMissingRole = errors.New("missing role")
errMissingValue = errors.New("missing value")
errCookieDecryption = errors.New("failed to decrypt the cookie")
errCookieEncrypt = errors.New("failed to encrypt the cookie")
errMissingFrom = errors.New("missing from time value")
errMissingTo = errors.New("missing to time value")
errInvalidAggregation = errors.New("invalid aggregation value")
errInvalidInterval = errors.New("invalid interval value")
errParseToken = errors.New("failed to parse token")
)
48 changes: 28 additions & 20 deletions ui/api/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -1093,16 +1093,16 @@ func decodeRefreshTokenRequest(s *securecookie.SecureCookie) kithttp.DecodeReque

var session string
if err := s.Decode(sessionDetailsKey, sessionCookie, &session); err != nil {
return nil, err
return nil, errors.Wrap(errCookieDecryption, err)
}
var sessionDetails ui.Session
if err := json.Unmarshal([]byte(session), &sessionDetails); err != nil {
return ui.Session{}, err
return ui.Session{}, errors.Wrap(ui.ErrJSONUnmarshal, err)
}

var refreshToken string
if err := s.Decode(refreshTokenKey, refreshTokenCookie, &refreshToken); err != nil {
return ui.Session{}, err
return ui.Session{}, errors.Wrap(errCookieDecryption, err)
}
sessionDetails.Token = refreshToken

Expand Down Expand Up @@ -1151,11 +1151,11 @@ func decodeUserCreation(_ context.Context, r *http.Request) (interface{}, error)
}
var meta map[string]interface{}
if err := json.Unmarshal([]byte(r.PostFormValue("metadata")), &meta); err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONUnmarshal, err)
}
var tags []string
if err := json.Unmarshal([]byte(r.PostFormValue("tags")), &tags); err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONUnmarshal, err)
}
credentials := sdk.Credentials{
Identity: r.PostFormValue("identity"),
Expand Down Expand Up @@ -1393,11 +1393,11 @@ func decodeThingCreation(_ context.Context, r *http.Request) (interface{}, error
}
var meta map[string]interface{}
if err := json.Unmarshal([]byte(r.PostFormValue("metadata")), &meta); err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONUnmarshal, err)
}
var tags []string
if err := json.Unmarshal([]byte(r.PostFormValue("tags")), &tags); err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONUnmarshal, err)
}

return createThingReq{
Expand Down Expand Up @@ -1555,7 +1555,7 @@ func decodeChannelCreation(_ context.Context, r *http.Request) (interface{}, err
}
var meta map[string]interface{}
if err := json.Unmarshal([]byte(r.PostFormValue("metadata")), &meta); err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONUnmarshal, err)
}

ch := sdk.Channel{
Expand Down Expand Up @@ -1730,7 +1730,7 @@ func decodeGroupCreation(_ context.Context, r *http.Request) (interface{}, error
}
var meta map[string]interface{}
if err := json.Unmarshal([]byte(r.PostFormValue("metadata")), &meta); err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONUnmarshal, err)
}

return createGroupReq{
Expand Down Expand Up @@ -1833,7 +1833,7 @@ func decodeGroupStatusUpdate(_ context.Context, r *http.Request) (interface{}, e
func decodePublishRequest(_ context.Context, r *http.Request) (interface{}, error) {
floatValue, err := strconv.ParseFloat(r.PostFormValue("value"), 64)
if err != nil {
return nil, err
return nil, errors.Wrap(errInvalidFormValue, err)
}

return publishReq{
Expand Down Expand Up @@ -2032,7 +2032,7 @@ func decodeUpdateBootstrapState(_ context.Context, r *http.Request) (interface{}
}
state, err := strconv.Atoi(r.FormValue("state"))
if err != nil {
return nil, err
return nil, errors.Wrap(errInvalidFormValue, err)
}

return updateBootstrapStateReq{
Expand Down Expand Up @@ -2191,7 +2191,7 @@ func decodeDomainLoginRequest(s *securecookie.SecureCookie) kithttp.DecodeReques
}
var refreshToken string
if err := s.Decode(refreshTokenKey, refreshTokenCookie, &refreshToken); err != nil {
return ui.Session{}, err
return ui.Session{}, errors.Wrap(errCookieDecryption, err)
}

session, err := sessionFromHeader(r)
Expand Down Expand Up @@ -2507,7 +2507,7 @@ func readBoolQuery(r *http.Request, key string, def bool) (bool, error) {
func tokenFromCookie(r *http.Request, cookie string) (string, error) {
c, err := r.Cookie(cookie)
if err != nil {
return "", errors.Wrap(err, errInvalidCredentials)
return "", errors.Wrap(errInvalidCredentials, err)
}

return c.Value, nil
Expand All @@ -2517,7 +2517,7 @@ func sessionFromHeader(r *http.Request) (ui.Session, error) {
session := r.Header.Get(sessionDetailsKey)
var sessionDetails ui.Session
if err := json.Unmarshal([]byte(session), &sessionDetails); err != nil {
return ui.Session{}, err
return ui.Session{}, errors.Wrap(ui.ErrJSONUnmarshal, err)
}

return sessionDetails, nil
Expand Down Expand Up @@ -2609,8 +2609,7 @@ func DecryptCookieMiddleware(s *securecookie.SecureCookie, prefix string) func(h
return
}
if err = s.Decode(sessionDetailsKey, sessionCookie, &decryptedSessionCookie); err != nil {
err = errors.Wrap(err, errCookieDecryption)
http.Redirect(w, r, fmt.Sprintf("%s/%s?error=%s", prefix, errorAPIEndpoint, url.QueryEscape(err.Error())), http.StatusSeeOther)
http.Redirect(w, r, fmt.Sprintf("%s/%s?error=%s", prefix, errorAPIEndpoint, url.QueryEscape(errors.Wrap(errCookieDecryption, err).Error())), http.StatusSeeOther)
return
}

Expand All @@ -2624,7 +2623,7 @@ func DecryptCookieMiddleware(s *securecookie.SecureCookie, prefix string) func(h
func handleStaticFiles(m *chi.Mux) error {
entries, err := ui.StaticFS.ReadDir(ui.StaticDir)
if err != nil {
return err
return errors.Wrap(ui.ErrReadDir, err)
}
for _, entry := range entries {
if entry.IsDir() {
Expand All @@ -2649,7 +2648,7 @@ func parseMetadata(r *http.Request) (map[string]interface{}, error) {
metadata := make(map[string]interface{})
if len(metadataStr) > 0 {
if err := json.Unmarshal([]byte(metadataStr), &metadata); err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONUnmarshal, err)
}
}

Expand All @@ -2662,7 +2661,7 @@ func parseTags(r *http.Request) ([]string, error) {
tags := make([]string, 0)
if len(tagsStr) > 0 {
if err := json.Unmarshal([]byte(tagsStr), &tags); err != nil {
return nil, err
return nil, errors.Wrap(ui.ErrJSONUnmarshal, err)
}
}

Expand Down Expand Up @@ -2717,6 +2716,7 @@ func encodeError(prefix string) kithttp.ErrorEncoder {
switch {
case errors.Contains(err, errInvalidCredentials),
errors.Contains(err, errAuthentication),
errors.Contains(err, errParseToken),
errors.Contains(err, ui.ErrTokenRefresh):
w.Header().Set("Location", fmt.Sprintf("%s/login", prefix))
w.WriteHeader(http.StatusSeeOther)
Expand All @@ -2728,7 +2728,10 @@ func encodeError(prefix string) kithttp.ErrorEncoder {
case errors.Contains(err, errInvalidFile):
w.Header().Set("X-Error-Message", err.Error())
w.WriteHeader(http.StatusUnsupportedMediaType)
case errors.Contains(err, errFileFormat):
case errors.Contains(err, errFileFormat),
errors.Contains(err, errCookieEncrypt),
errors.Contains(err, errInvalidQueryParams),
errors.Contains(err, errInvalidFormValue):
w.Header().Set("X-Error-Message", err.Error())
w.WriteHeader(http.StatusBadRequest)
case errors.Contains(err, ui.ErrFailedCreate),
Expand All @@ -2747,13 +2750,18 @@ func encodeError(prefix string) kithttp.ErrorEncoder {
errors.Contains(err, ui.ErrFailedResetRequest),
errors.Contains(err, ui.ErrFailedPublish),
errors.Contains(err, ui.ErrExecTemplate),
errors.Contains(err, ui.ErrParseTemplate),
errors.Contains(err, ui.ErrReadDir),
errors.Contains(err, ui.ErrFailedDelete),
errors.Contains(err, ui.ErrFailedShare),
errors.Contains(err, ui.ErrFailedUnshare),
errors.Contains(err, ui.ErrFailedDashboardSave),
errors.Contains(err, ui.ErrFailedDashboardDelete),
errors.Contains(err, ui.ErrFailedDashboardUpdate),
errors.Contains(err, ui.ErrJSONMarshal),
errors.Contains(err, ui.ErrJSONUnmarshal),
errors.Contains(err, ui.ErrFailedSend),
errors.Contains(err, ui.ErrFailedAccept),
errors.Contains(err, ui.ErrFailedDashboardRetrieve):
w.Header().Set("Location", fmt.Sprintf("%s/%s?error=%s", prefix, errorAPIEndpoint, url.QueryEscape(displayError.Error())))
w.WriteHeader(http.StatusSeeOther)
Expand Down
Loading

0 comments on commit 38b1017

Please sign in to comment.