Skip to content

Commit

Permalink
Merge pull request #15 from owncloud/feature/use-proper-error-object
Browse files Browse the repository at this point in the history
Introduce ErrorCode enum for error handling
  • Loading branch information
DeepDiver1975 authored Dec 9, 2019
2 parents eed8205 + 7c538b2 commit b8e4604
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 13 deletions.
75 changes: 75 additions & 0 deletions pkg/service/v0/errorcode/errorcode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package errorcode

import (
"net/http"

"github.com/go-chi/render"
msgraph "github.com/yaegashi/msgraph.go/v1.0"
)

// ErrorCode defines code as used in MS Graph - see https://docs.microsoft.com/en-us/graph/errors?context=graph%2Fapi%2F1.0&view=graph-rest-1.0
type ErrorCode int

const (
// AccessDenied defines the error if the caller doesn't have permission to perform the action.
AccessDenied ErrorCode = iota
// ActivityLimitReached defines the error if the app or user has been throttled.
ActivityLimitReached
// GeneralException defines the error if an unspecified error has occurred.
GeneralException
// InvalidRange defines the error if the specified byte range is invalid or unavailable.
InvalidRange
// InvalidRequest defines the error if the request is malformed or incorrect.
InvalidRequest
// ItemNotFound defines the error if the resource could not be found.
ItemNotFound
// MalwareDetected defines the error if malware was detected in the requested resource.
MalwareDetected
// NameAlreadyExists defines the error if the specified item name already exists.
NameAlreadyExists
// NotAllowed defines the error if the action is not allowed by the system.
NotAllowed
// NotSupported defines the error if the request is not supported by the system.
NotSupported
// ResourceModified defines the error if the resource being updated has changed since the caller last read it, usually an eTag mismatch.
ResourceModified
// ResyncRequired defines the error if the delta token is no longer valid, and the app must reset the sync state.
ResyncRequired
// ServiceNotAvailable defines the error if the service is not available. Try the request again after a delay. There may be a Retry-After header.
ServiceNotAvailable
// QuotaLimitReached the user has reached their quota limit.
QuotaLimitReached
// Unauthenticated the caller is not authenticated.
Unauthenticated
)

var errorCodes = [...]string{
"accessDenied",
"activityLimitReached",
"generalException",
"invalidRange",
"invalidRequest",
"itemNotFound",
"malwareDetected",
"nameAlreadyExists",
"notAllowed",
"notSupported",
"resourceModified",
"resyncRequired",
"serviceNotAvailable",
"quotaLimitReached",
"unauthenticated",
}

// Render writes an Graph ErrorObject to the response writer
func (e ErrorCode) Render(w http.ResponseWriter, r *http.Request, status int) {
resp := &msgraph.ErrorObject{
Code: e.String(),
}
render.Status(r, status)
render.JSON(w, r, resp)
}

func (e ErrorCode) String() string {
return errorCodes[e]
}
27 changes: 14 additions & 13 deletions pkg/service/v0/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"fmt"
"net/http"

"github.com/owncloud/ocis-graph/pkg/service/v0/errorcode"

"github.com/go-chi/chi"
"github.com/go-chi/render"
"github.com/owncloud/ocis-graph/pkg/config"
Expand Down Expand Up @@ -35,17 +37,15 @@ func (g Graph) UserCtx(next http.Handler) http.Handler {
var user *ldap.Entry
var err error

if userID := chi.URLParam(r, "userID"); userID != "" {
user, err = g.ldapGetUser(userID)
} else {
// TODO: we should not give this error out to users
// http.Error(w, err.Error(), http.StatusInternalServerError)
render.Status(r, http.StatusNotFound)
userID := chi.URLParam(r, "userID")
if userID == "" {
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest)
return
}
user, err = g.ldapGetUser(userID)
if err != nil {
g.logger.Info().Msgf("error reading user: %s", err.Error())
render.Status(r, http.StatusNotFound)
g.logger.Info().Err(err).Msgf("Failed to read user %s", userID)
errorcode.ItemNotFound.Render(w, r, http.StatusNotFound)
return
}

Expand All @@ -64,7 +64,8 @@ func (g Graph) GetMe(w http.ResponseWriter, r *http.Request) {
resp, err := json.Marshal(me)

if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
g.logger.Error().Err(err).Msgf("Failed to marshal object %s", me)
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
return
}

Expand All @@ -76,16 +77,16 @@ func (g Graph) GetMe(w http.ResponseWriter, r *http.Request) {
func (g Graph) GetUsers(w http.ResponseWriter, r *http.Request) {
con, err := g.initLdap()
if err != nil {
// TODO: we should not give this error out to users
http.Error(w, err.Error(), http.StatusInternalServerError)
g.logger.Error().Err(err).Msg("Failed to initialize ldap")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
return
}

result, err := g.ldapSearch(con, "(objectclass=*)")

if err != nil {
// TODO: we should not give this error out to users
http.Error(w, err.Error(), http.StatusInternalServerError)
g.logger.Error().Err(err).Msg("Failed search ldap with filter: '(objectclass=*)'")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
return
}

Expand Down

0 comments on commit b8e4604

Please sign in to comment.