From eb3ace862973fc6605572fb916cbd30f887df549 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Tue, 25 Jan 2022 13:06:41 +0100 Subject: [PATCH] Implement deleting a Group This implements DELETE request on the graph/v1.0/groups/{groupid} endpoint. Allowing to remove an entire group. --- graph/pkg/identity/backend.go | 4 +++- graph/pkg/identity/cs3.go | 5 +++++ graph/pkg/identity/ldap.go | 16 ++++++++++++++++ graph/pkg/service/v0/groups.go | 29 +++++++++++++++++++++++++++++ graph/pkg/service/v0/instrument.go | 5 +++++ graph/pkg/service/v0/logging.go | 5 +++++ graph/pkg/service/v0/service.go | 2 ++ graph/pkg/service/v0/tracing.go | 5 +++++ 8 files changed, 70 insertions(+), 1 deletion(-) diff --git a/graph/pkg/identity/backend.go b/graph/pkg/identity/backend.go index f9cda702f7..24e84f3265 100644 --- a/graph/pkg/identity/backend.go +++ b/graph/pkg/identity/backend.go @@ -21,8 +21,10 @@ type Backend interface { GetUser(ctx context.Context, nameOrID string) (*libregraph.User, error) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregraph.User, error) - // Create Group creates the supplied group in the identity backend. + // CreateGroup creates the supplied group in the identity backend. CreateGroup(ctx context.Context, group libregraph.Group) (*libregraph.Group, error) + // DeleteGroup deletes a given group, identified by id + DeleteGroup(ctx context.Context, id string) error GetGroup(ctx context.Context, nameOrID string) (*libregraph.Group, error) GetGroups(ctx context.Context, queryParam url.Values) ([]*libregraph.Group, error) GetGroupMembers(ctx context.Context, id string) ([]*libregraph.User, error) diff --git a/graph/pkg/identity/cs3.go b/graph/pkg/identity/cs3.go index 682ec5ae0f..fea10be536 100644 --- a/graph/pkg/identity/cs3.go +++ b/graph/pkg/identity/cs3.go @@ -174,6 +174,11 @@ func (i *CS3) GetGroup(ctx context.Context, groupID string) (*libregraph.Group, return createGroupModelFromCS3(res.Group), nil } +// DeleteGroup implements the Backend Interface. It's currently not supported for the CS3 backend +func (i *CS3) DeleteGroup(ctx context.Context, id string) error { + return errorcode.New(errorcode.NotSupported, "not implemented") +} + // GetGroupMembers implements the Backend Interface. It's currently not supported for the CS3 backend func (i *CS3) GetGroupMembers(ctx context.Context, groupID string) ([]*libregraph.User, error) { return nil, errorcode.New(errorcode.NotSupported, "not implemented") diff --git a/graph/pkg/identity/ldap.go b/graph/pkg/identity/ldap.go index e902a49c0c..1f032eebae 100644 --- a/graph/pkg/identity/ldap.go +++ b/graph/pkg/identity/ldap.go @@ -552,6 +552,22 @@ func (i *LDAP) CreateGroup(ctx context.Context, group libregraph.Group) (*libreg return i.createGroupModelFromLDAP(e), nil } +// DeleteGroup implements the Backend Interface. +func (i *LDAP) DeleteGroup(ctx context.Context, id string) error { + if !i.writeEnabled { + return errorcode.New(errorcode.NotAllowed, "server is configured read-only") + } + e, err := i.getLDAPGroupByID(id, false) + if err != nil { + return err + } + dr := ldap.DelRequest{DN: e.DN} + if err = i.conn.Del(&dr); err != nil { + return err + } + return nil +} + // AddMemberToGroup implements the Backend Interface for the LDAP backend. // Currently it is limited to adding Users as Group members. Adding other groups // as members is not yet implemented diff --git a/graph/pkg/service/v0/groups.go b/graph/pkg/service/v0/groups.go index 4cbdfd1e95..379a1b7f06 100644 --- a/graph/pkg/service/v0/groups.go +++ b/graph/pkg/service/v0/groups.go @@ -88,6 +88,35 @@ func (g Graph) GetGroup(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, group) } +// DeleteGroup implements the Service interface. +func (g Graph) DeleteGroup(w http.ResponseWriter, r *http.Request) { + groupID := chi.URLParam(r, "groupID") + groupID, err := url.PathUnescape(groupID) + if err != nil { + errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping group id failed") + return + } + + if groupID == "" { + errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "missing group id") + return + } + + err = g.identityBackend.DeleteGroup(r.Context(), groupID) + + if err != nil { + var errcode errorcode.Error + if errors.As(err, &errcode) { + errcode.Render(w, r) + } else { + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) + } + return + } + render.Status(r, http.StatusNoContent) + render.NoContent(w, r) +} + func (g Graph) GetGroupMembers(w http.ResponseWriter, r *http.Request) { groupID := chi.URLParam(r, "groupID") groupID, err := url.PathUnescape(groupID) diff --git a/graph/pkg/service/v0/instrument.go b/graph/pkg/service/v0/instrument.go index d4742d69ae..c3b36388ec 100644 --- a/graph/pkg/service/v0/instrument.go +++ b/graph/pkg/service/v0/instrument.go @@ -69,6 +69,11 @@ func (i instrument) PostGroup(w http.ResponseWriter, r *http.Request) { i.next.PostGroup(w, r) } +// DeleteGroup implements the Service interface. +func (i instrument) DeleteGroup(w http.ResponseWriter, r *http.Request) { + i.next.DeleteGroup(w, r) +} + // GetGroupMembers implements the Service interface. func (i instrument) GetGroupMembers(w http.ResponseWriter, r *http.Request) { i.next.GetGroupMembers(w, r) diff --git a/graph/pkg/service/v0/logging.go b/graph/pkg/service/v0/logging.go index 436b7d11a8..43116b9f6e 100644 --- a/graph/pkg/service/v0/logging.go +++ b/graph/pkg/service/v0/logging.go @@ -69,6 +69,11 @@ func (l logging) PostGroup(w http.ResponseWriter, r *http.Request) { l.next.PostGroup(w, r) } +// DeleteGroup implements the Service interface. +func (l logging) DeleteGroup(w http.ResponseWriter, r *http.Request) { + l.next.DeleteGroup(w, r) +} + // GetGroupMembers implements the Service interface. func (l logging) GetGroupMembers(w http.ResponseWriter, r *http.Request) { l.next.GetGroupMembers(w, r) diff --git a/graph/pkg/service/v0/service.go b/graph/pkg/service/v0/service.go index e2d4374d59..44b82f90f6 100644 --- a/graph/pkg/service/v0/service.go +++ b/graph/pkg/service/v0/service.go @@ -34,6 +34,7 @@ type Service interface { GetGroups(http.ResponseWriter, *http.Request) GetGroup(http.ResponseWriter, *http.Request) PostGroup(http.ResponseWriter, *http.Request) + DeleteGroup(http.ResponseWriter, *http.Request) GetGroupMembers(http.ResponseWriter, *http.Request) PostGroupMember(http.ResponseWriter, *http.Request) @@ -118,6 +119,7 @@ func NewService(opts ...Option) Service { r.Post("/", svc.PostGroup) r.Route("/{groupID}", func(r chi.Router) { r.Get("/", svc.GetGroup) + r.Delete("/", svc.DeleteGroup) r.Route("/members", func(r chi.Router) { r.Get("/", svc.GetGroupMembers) r.Post("/$ref", svc.PostGroupMember) diff --git a/graph/pkg/service/v0/tracing.go b/graph/pkg/service/v0/tracing.go index 4507459f73..4ab90e5038 100644 --- a/graph/pkg/service/v0/tracing.go +++ b/graph/pkg/service/v0/tracing.go @@ -65,6 +65,11 @@ func (t tracing) PostGroup(w http.ResponseWriter, r *http.Request) { t.next.PostGroup(w, r) } +// DeleteGroup implements the Service interface. +func (t tracing) DeleteGroup(w http.ResponseWriter, r *http.Request) { + t.next.DeleteGroup(w, r) +} + // GetGroupMembers implements the Service interface. func (t tracing) GetGroupMembers(w http.ResponseWriter, r *http.Request) { t.next.GetGroupMembers(w, r)