From ee8195cd5f7301a85e47b3ae1d9ba3791a81e82a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Wed, 29 Jul 2020 12:14:44 +0200 Subject: [PATCH] initial user and group listing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- pkg/service/v0/data/group.go | 6 ++++ pkg/service/v0/data/user.go | 5 +++ pkg/service/v0/groups.go | 66 ++++++++++++++++++++++++++++++++++++ pkg/service/v0/service.go | 24 ++++++++++++- pkg/service/v0/users.go | 27 +++++++++++++-- 5 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 pkg/service/v0/data/group.go create mode 100644 pkg/service/v0/groups.go diff --git a/pkg/service/v0/data/group.go b/pkg/service/v0/data/group.go new file mode 100644 index 0000000000..1eab5d8bd3 --- /dev/null +++ b/pkg/service/v0/data/group.go @@ -0,0 +1,6 @@ +package data + +// Groups holds group ids for the groups listing +type Groups struct { + Groups []string `json:"groups" xml:"groups>element"` +} diff --git a/pkg/service/v0/data/user.go b/pkg/service/v0/data/user.go index c72f94690b..b882d779ed 100644 --- a/pkg/service/v0/data/user.go +++ b/pkg/service/v0/data/user.go @@ -10,6 +10,11 @@ type User struct { Enabled bool `json:"enabled" xml:"enabled"` } +// Users holds user ids for the user listing +type Users struct { + Users []string `json:"users" xml:"users>element"` +} + // SigningKey holds the Payload for a GetSigningKey response type SigningKey struct { User string `json:"user" xml:"user"` diff --git a/pkg/service/v0/groups.go b/pkg/service/v0/groups.go new file mode 100644 index 0000000000..65df8d2c3a --- /dev/null +++ b/pkg/service/v0/groups.go @@ -0,0 +1,66 @@ +package svc + +import ( + "fmt" + "net/http" + + "github.com/go-chi/render" + + accounts "github.com/owncloud/ocis-accounts/pkg/proto/v0" + "github.com/owncloud/ocis-ocs/pkg/service/v0/data" + "github.com/owncloud/ocis-ocs/pkg/service/v0/response" +) + +// ListUserGroups lists a users groups +func (o Ocs) ListUserGroups(w http.ResponseWriter, r *http.Request) { + render.Render(w, r, response.ErrRender(data.MetaUnknownError.StatusCode, "not implemented")) +} + +// AddToGroup adds a user to a group +func (o Ocs) AddToGroup(w http.ResponseWriter, r *http.Request) { + render.Render(w, r, response.ErrRender(data.MetaUnknownError.StatusCode, "not implemented")) +} + +// RemoveFromGroup removes a user from a group +func (o Ocs) RemoveFromGroup(w http.ResponseWriter, r *http.Request) { + render.Render(w, r, response.ErrRender(data.MetaUnknownError.StatusCode, "not implemented")) +} + +// ListGroups lists all groups +func (o Ocs) ListGroups(w http.ResponseWriter, r *http.Request) { + search := r.URL.Query().Get("search") + query := "" + if search != "" { + query = fmt.Sprintf("id eq '%s' or on_premises_sam_account_name eq '%s'", escapeValue(search), escapeValue(search)) + } + accSvc := o.getGroupsService() + res, err := accSvc.ListGroups(r.Context(), &accounts.ListGroupsRequest{ + Query: query, + }) + if err != nil { + o.logger.Err(err).Msg("could not list users") + render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, "could not list users")) + return + } + groups := []string{} + for i := range res.Groups { + groups = append(groups, res.Groups[i].Id) + } + + render.Render(w, r, response.DataRender(&data.Groups{Groups: groups})) +} + +// AddGroup adds a group +func (o Ocs) AddGroup(w http.ResponseWriter, r *http.Request) { + render.Render(w, r, response.ErrRender(data.MetaUnknownError.StatusCode, "not implemented")) +} + +// DeleteGroup deletes a group +func (o Ocs) DeleteGroup(w http.ResponseWriter, r *http.Request) { + render.Render(w, r, response.ErrRender(data.MetaUnknownError.StatusCode, "not implemented")) +} + +// GetGroupMembers lists all members of a group +func (o Ocs) GetGroupMembers(w http.ResponseWriter, r *http.Request) { + render.Render(w, r, response.ErrRender(data.MetaUnknownError.StatusCode, "not implemented")) +} diff --git a/pkg/service/v0/service.go b/pkg/service/v0/service.go index 0c92f86912..8bc38b0389 100644 --- a/pkg/service/v0/service.go +++ b/pkg/service/v0/service.go @@ -6,7 +6,9 @@ import ( "github.com/go-chi/chi" "github.com/go-chi/chi/middleware" "github.com/go-chi/render" + "github.com/micro/go-micro/v2/client/grpc" + accounts "github.com/owncloud/ocis-accounts/pkg/proto/v0" "github.com/owncloud/ocis-ocs/pkg/config" ocsm "github.com/owncloud/ocis-ocs/pkg/middleware" "github.com/owncloud/ocis-ocs/pkg/service/v0/data" @@ -57,6 +59,18 @@ func NewService(opts ...Option) Service { r.Get("/{userid}", svc.GetUser) r.Put("/{userid}", svc.EditUser) r.Delete("/{userid}", svc.DeleteUser) + + r.Route("/{userid}/groups", func(r chi.Router) { + r.Get("/", svc.ListUserGroups) + r.Post("/", svc.AddToGroup) + r.Delete("/", svc.RemoveFromGroup) + }) + }) + r.Route("/groups", func(r chi.Router) { + r.Get("/", svc.ListGroups) + r.Post("/", svc.AddGroup) + r.Delete("/{groupid}", svc.DeleteGroup) + r.Get("/{groupid}", svc.GetGroupMembers) }) }) r.Route("/config", func(r chi.Router) { @@ -82,5 +96,13 @@ func (o Ocs) ServeHTTP(w http.ResponseWriter, r *http.Request) { // NotFound uses ErrRender to always return a proper OCS payload func (o Ocs) NotFound(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")) + render.Render(w, r, response.ErrRender(data.MetaNotFound.StatusCode, "not found")) +} + +func (o Ocs) getAccountService() accounts.AccountsService { + return accounts.NewAccountsService("com.owncloud.api.accounts", grpc.NewClient()) +} + +func (o Ocs) getGroupsService() accounts.GroupsService { + return accounts.NewGroupsService("com.owncloud.api.accounts", grpc.NewClient()) } diff --git a/pkg/service/v0/users.go b/pkg/service/v0/users.go index 29bccdb58c..208673d356 100644 --- a/pkg/service/v0/users.go +++ b/pkg/service/v0/users.go @@ -3,7 +3,9 @@ package svc import ( "crypto/rand" "encoding/hex" + "fmt" "net/http" + "strings" "github.com/cs3org/reva/pkg/user" "github.com/go-chi/chi" @@ -264,10 +266,29 @@ func (o Ocs) GetSigningKey(w http.ResponseWriter, r *http.Request) { // ListUsers lists the users func (o Ocs) ListUsers(w http.ResponseWriter, r *http.Request) { + search := r.URL.Query().Get("search") + query := "" + if search != "" { + query = fmt.Sprintf("id eq '%s' or on_premises_sam_account_name eq '%s'", escapeValue(search), escapeValue(search)) + } + accSvc := o.getAccountService() + res, err := accSvc.ListAccounts(r.Context(), &accounts.ListAccountsRequest{ + Query: query, + }) + if err != nil { + o.logger.Err(err).Msg("could not list users") + render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, "could not list users")) + return + } + users := []string{} + for i := range res.Accounts { + users = append(users, res.Accounts[i].Id) + } - 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")) + render.Render(w, r, response.DataRender(&data.Users{Users: users})) } -func (o Ocs) getAccountService() accounts.AccountsService { - return accounts.NewAccountsService("com.owncloud.api.accounts", grpc.NewClient()) +// escapeValue escapes all special characters in the value +func escapeValue(value string) string { + return strings.ReplaceAll(value, "'", "''") }