Merge pull request #15 from owncloud/feature/use-proper-error-object

Introduce ErrorCode enum for error handling
This commit is contained in:
Thomas Müller
2019-12-09 22:00:17 +01:00
committed by GitHub
2 changed files with 89 additions and 13 deletions

View File

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

View File

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