implement delete, better return codes, correct result payload

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
Jörn Friedrich Dreyer
2020-07-29 11:19:29 +02:00
parent 8a2cbd98a7
commit cdde45290a
3 changed files with 76 additions and 14 deletions

View File

@@ -9,9 +9,15 @@ type Meta struct {
ItemsPerPage string `json:"itemsperpage,omitempty" xml:"itemsperpage,omitempty"`
}
// MetaOK is the default ok response
// MetaOK is the default ok response with code 100
var MetaOK = Meta{Status: "ok", StatusCode: 100, Message: "OK"}
// MetaFailure is a failure response with code 101
var MetaFailure = Meta{Status: "", StatusCode: 101, Message: "Failure"}
// MetaInvalidInput is an error response with code 102
var MetaInvalidInput = Meta{Status: "", StatusCode: 102, Message: "Invalid Input"}
// MetaBadRequest is used for unknown errors
var MetaBadRequest = Meta{Status: "error", StatusCode: 400, Message: "Bad Request"}

View File

@@ -3,7 +3,7 @@ package data
// User holds the payload for a GetUser response
type User struct {
// TODO needs better naming, clarify if we need a userid, a username or both
UserID string `json:"userid" xml:"userid"`
UserID string `json:"id" xml:"id"`
Username string `json:"username" xml:"username"`
DisplayName string `json:"displayname" xml:"displayname"`
Email string `json:"email" xml:"email"`

View File

@@ -33,15 +33,27 @@ func (o Ocs) GetUser(w http.ResponseWriter, r *http.Request) {
userid = u.Id.OpaqueId
}
accSvc := accounts.NewAccountsService("com.owncloud.api.accounts", grpc.NewClient())
accSvc := o.getAccountService()
account, err := accSvc.GetAccount(r.Context(), &accounts.GetAccountRequest{
Id: userid,
})
if err != nil {
render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, err.Error()))
merr := merrors.FromError(err)
if merr.Code == http.StatusNotFound {
render.Render(w, r, response.ErrRender(data.MetaNotFound.StatusCode, "The requested user could not be found"))
} else {
render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, err.Error()))
}
o.logger.Error().Err(err).Str("userid", userid).Msg("could not get user")
return
}
// remove password from log if it is set
if account.PasswordProfile != nil {
account.PasswordProfile.Password = ""
}
o.logger.Debug().Interface("account", account).Msg("got user")
render.Render(w, r, response.DataRender(&data.User{
UserID: account.Id, // TODO userid vs username! implications for clients if we return the userid here? -> implement graph ASAP?
Username: account.PreferredName,
@@ -60,7 +72,7 @@ func (o Ocs) AddUser(w http.ResponseWriter, r *http.Request) {
displayname := r.PostFormValue("displayname")
email := r.PostFormValue("email")
accSvc := accounts.NewAccountsService("com.owncloud.api.accounts", grpc.NewClient())
accSvc := o.getAccountService()
account, err := accSvc.CreateAccount(r.Context(), &accounts.CreateAccountRequest{
Account: &accounts.Account{
DisplayName: displayname,
@@ -75,11 +87,22 @@ func (o Ocs) AddUser(w http.ResponseWriter, r *http.Request) {
},
})
if err != nil {
render.Render(w, r, response.DataRender(data.MetaServerError))
merr := merrors.FromError(err)
if merr.Code == http.StatusBadRequest {
render.Render(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, merr.Detail))
} else {
render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, err.Error()))
}
o.logger.Error().Err(err).Str("userid", userid).Msg("could not add user")
// TODO check error if account already existed
return
}
o.logger.Debug().Interface("account", account).Msg("add user: account info")
// remove password from log if it is set
if account.PasswordProfile != nil {
account.PasswordProfile.Password = ""
}
o.logger.Debug().Interface("account", account).Msg("added user")
render.Render(w, r, response.DataRender(&data.User{
UserID: account.Id,
@@ -118,26 +141,55 @@ func (o Ocs) EditUser(w http.ResponseWriter, r *http.Request) {
req.Account.DisplayName = value
req.UpdateMask = &fieldmaskpb.FieldMask{Paths: []string{"DisplayName"}}
default:
render.Render(w, r, response.DataRender(data.MetaServerError))
// https://github.com/owncloud/core/blob/24b7fa1d2604a208582055309a5638dbd9bda1d1/apps/provisioning_api/lib/Users.php#L321
render.Render(w, r, response.ErrRender(103, "unknown key '"+key+"'"))
return
}
accSvc := accounts.NewAccountsService("com.owncloud.api.accounts", grpc.NewClient())
accSvc := o.getAccountService()
account, err := accSvc.UpdateAccount(r.Context(), &req)
if err != nil {
// TODO to be compliant with the spec, check whether the user exists or not
// https://doc.owncloud.com/server/admin_manual/configuration/user/user_provisioning_api.html#edit-user
render.Render(w, r, response.DataRender(data.MetaServerError))
merr := merrors.FromError(err)
switch merr.Code {
case http.StatusNotFound:
render.Render(w, r, response.ErrRender(data.MetaNotFound.StatusCode, "The requested user could not be found"))
case http.StatusBadRequest:
render.Render(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, merr.Detail))
default:
render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, err.Error()))
}
o.logger.Error().Err(err).Str("userid", req.Account.Id).Msg("could not edit user")
return
}
o.logger.Debug().Interface("account", account).Msg("update user: account info")
// remove password from log if it is set
if account.PasswordProfile != nil {
account.PasswordProfile.Password = ""
}
o.logger.Debug().Interface("account", account).Msg("updated user")
render.Render(w, r, response.DataRender(struct{}{}))
}
// DeleteUser deletes a user
func (o Ocs) DeleteUser(w http.ResponseWriter, r *http.Request) {
req := accounts.DeleteAccountRequest{
Id: chi.URLParam(r, "userid"),
}
accSvc := o.getAccountService()
_, err := accSvc.DeleteAccount(r.Context(), &req)
if err != nil {
merr := merrors.FromError(err)
if merr.Code == http.StatusNotFound {
render.Render(w, r, response.ErrRender(data.MetaNotFound.StatusCode, "The requested user could not be found"))
} else {
render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, err.Error()))
}
o.logger.Error().Err(err).Str("userid", req.Id).Msg("could not delete user")
return
}
o.logger.Debug().Str("userid", req.Id).Msg("deleted user")
render.Render(w, r, response.DataRender(struct{}{}))
return
}
// GetSigningKey returns the signing key for the current user. It will create it on the fly if it does not exist
@@ -215,3 +267,7 @@ func (o Ocs) ListUsers(w http.ResponseWriter, r *http.Request) {
render.Render(w, r, response.ErrRender(data.MetaUnknownError.StatusCode, "please check the syntax. API specifications are here: http://www.freedesktop.org/wiki/Specifications/open-collaboration-services"))
}
func (o Ocs) getAccountService() accounts.AccountsService {
return accounts.NewAccountsService("com.owncloud.api.accounts", grpc.NewClient())
}