diff --git a/go.mod b/go.mod index ce607cd718..872ef722e8 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/rs/zerolog v1.19.0 // indirect github.com/spf13/viper v1.7.0 go.opencensus.io v0.22.4 + google.golang.org/protobuf v1.25.0 gopkg.in/square/go-jose.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.2.8 // indirect ) diff --git a/pkg/service/v0/service.go b/pkg/service/v0/service.go index 68df0a0501..0c92f86912 100644 --- a/pkg/service/v0/service.go +++ b/pkg/service/v0/service.go @@ -53,7 +53,10 @@ func NewService(opts ...Option) Service { }) r.Route("/users", func(r chi.Router) { r.Get("/", svc.ListUsers) + r.Post("/", svc.AddUser) r.Get("/{userid}", svc.GetUser) + r.Put("/{userid}", svc.EditUser) + r.Delete("/{userid}", svc.DeleteUser) }) }) r.Route("/config", func(r chi.Router) { diff --git a/pkg/service/v0/users.go b/pkg/service/v0/users.go index db742dcaa6..a722f2aeec 100644 --- a/pkg/service/v0/users.go +++ b/pkg/service/v0/users.go @@ -4,10 +4,12 @@ import ( "crypto/rand" "encoding/hex" "net/http" + "strconv" "github.com/cs3org/reva/pkg/user" "github.com/go-chi/chi" "github.com/go-chi/render" + "google.golang.org/protobuf/types/known/fieldmaskpb" "github.com/micro/go-micro/v2/client/grpc" merrors "github.com/micro/go-micro/v2/errors" @@ -19,7 +21,7 @@ import ( // GetUser returns the currently logged in user func (o Ocs) GetUser(w http.ResponseWriter, r *http.Request) { - + // TODO this endpoint needs authentication userid := chi.URLParam(r, "userid") if userid == "" { @@ -50,6 +52,96 @@ func (o Ocs) GetUser(w http.ResponseWriter, r *http.Request) { })) } +// AddUser creates a new user account +func (o Ocs) AddUser(w http.ResponseWriter, r *http.Request) { + // TODO this endpoint needs authentication + userid := r.PostFormValue("userid") + password := r.PostFormValue("password") + username := r.PostFormValue("username") + displayname := r.PostFormValue("displayname") + email := r.PostFormValue("email") + enabled, err := strconv.ParseBool(r.PostFormValue("enabled")) + if err != nil { + render.Render(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, err.Error())) + return + } + + accSvc := accounts.NewAccountsService("com.owncloud.api.accounts", grpc.NewClient()) + account, err := accSvc.CreateAccount(r.Context(), &accounts.CreateAccountRequest{ + Account: &accounts.Account{ + DisplayName: displayname, + PreferredName: username, + OnPremisesSamAccountName: username, + PasswordProfile: &accounts.PasswordProfile{ + Password: password, + }, + Id: userid, + Mail: email, + AccountEnabled: enabled, + }, + }) + + o.logger.Debug().Interface("account", account).Msg("add user: account info") + + render.Render(w, r, response.DataRender(&data.User{ + UserID: account.Id, + Username: account.PreferredName, + DisplayName: account.DisplayName, + Email: account.Mail, + Enabled: account.AccountEnabled, + })) +} + +// EditUser creates a new user account +func (o Ocs) EditUser(w http.ResponseWriter, r *http.Request) { + // TODO this endpoint needs authentication + req := accounts.UpdateAccountRequest{ + Account: &accounts.Account{ + Id: chi.URLParam(r, "userid"), + }, + } + key := r.PostFormValue("key") + value := r.PostFormValue("value") + + switch key { + case "email": + req.Account.Mail = value + req.UpdateMask = &fieldmaskpb.FieldMask{Paths: []string{"Mail"}} + case "username": + req.Account.PreferredName = value + req.Account.OnPremisesSamAccountName = value + req.UpdateMask = &fieldmaskpb.FieldMask{Paths: []string{"PreferredName", "OnPremisesSamAccountName"}} + case "password": + req.Account.PasswordProfile = &accounts.PasswordProfile{ + Password: value, + } + req.UpdateMask = &fieldmaskpb.FieldMask{Paths: []string{"PasswordProfile.Password"}} + case "displayname", "display": + req.Account.DisplayName = value + req.UpdateMask = &fieldmaskpb.FieldMask{Paths: []string{"DisplayName"}} + default: + render.Render(w, r, response.DataRender(data.MetaServerError)) + return + } + + accSvc := accounts.NewAccountsService("com.owncloud.api.accounts", grpc.NewClient()) + 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)) + return + } + + o.logger.Debug().Interface("account", account).Msg("update user: account info") + render.Render(w, r, response.DataRender(struct{}{})) +} + +// DeleteUser deletes a user +func (o Ocs) DeleteUser(w http.ResponseWriter, r *http.Request) { + +} + // GetSigningKey returns the signing key for the current user. It will create it on the fly if it does not exist // The signing key is part of the user settings and is used by the proxy to authenticate requests // Currently, the username is used as the OC-Credential