From 05a60fd3a57a8c431e8e84343c628c73ef7fba2c Mon Sep 17 00:00:00 2001 From: Christian Richter Date: Tue, 23 Aug 2022 18:00:32 +0200 Subject: [PATCH 1/3] add home space deletion on user delete Signed-off-by: Christian Richter --- services/graph/pkg/service/v0/users.go | 29 +++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/services/graph/pkg/service/v0/users.go b/services/graph/pkg/service/v0/users.go index d96007597ab..363dc2d8134 100644 --- a/services/graph/pkg/service/v0/users.go +++ b/services/graph/pkg/service/v0/users.go @@ -238,6 +238,34 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) { return } + currentUser := ctxpkg.ContextMustGetUser(r.Context()) + + opaque := utils.AppendPlainToOpaque(nil, "unrestricted", "T") + f := listStorageSpacesUserFilter(userID) + lspr, err := g.gatewayClient.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{ + Opaque: opaque, + Filters: []*storageprovider.ListStorageSpacesRequest_Filter{f}, + }) + if err != nil { + errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "could not read spaces") + } + for _, sp := range lspr.GetStorageSpaces() { + if sp.SpaceType == "personal" { + if sp.Owner.Id.OpaqueId == userID { + _, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{ + Opaque: opaque, + Id: &storageprovider.StorageSpaceId{ + OpaqueId: sp.Id.OpaqueId, + }, + }) + if err != nil { + errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "could not delete homespace") + } + break + } + } + } + err = g.identityBackend.DeleteUser(r.Context(), userID) if err != nil { @@ -249,7 +277,6 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) { } } - currentUser := ctxpkg.ContextMustGetUser(r.Context()) g.publishEvent(events.UserDeleted{Executant: currentUser.Id, UserID: userID}) render.Status(r, http.StatusNoContent) From 6a9d4efef6e3d3157e08911fcd44edafc0fecd72 Mon Sep 17 00:00:00 2001 From: Christian Richter Date: Fri, 26 Aug 2022 15:01:26 +0200 Subject: [PATCH 2/3] add delete home space permission to admin role Signed-off-by: Christian Richter --- services/graph/pkg/service/v0/users.go | 3 +++ .../settings/pkg/store/defaults/defaults.go | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/services/graph/pkg/service/v0/users.go b/services/graph/pkg/service/v0/users.go index 363dc2d8134..3d5532a598d 100644 --- a/services/graph/pkg/service/v0/users.go +++ b/services/graph/pkg/service/v0/users.go @@ -252,6 +252,9 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) { for _, sp := range lspr.GetStorageSpaces() { if sp.SpaceType == "personal" { if sp.Owner.Id.OpaqueId == userID { + // TODO: check if request contains a homespace and if, check if requesting user has the privilege to + // delete it and make sure it is not deleting its own homespace + // needs modification of the cs3api _, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{ Opaque: opaque, Id: &storageprovider.StorageSpaceId{ diff --git a/services/settings/pkg/store/defaults/defaults.go b/services/settings/pkg/store/defaults/defaults.go index 37c1b07a207..e9a0d7de125 100644 --- a/services/settings/pkg/store/defaults/defaults.go +++ b/services/settings/pkg/store/defaults/defaults.go @@ -43,6 +43,11 @@ const ( // CreateSpacePermissionName is the hardcoded setting name for the create space permission CreateSpacePermissionName string = "create-space" + // DeleteHomeSpacesPermissionID is the hardcoded setting UUID for the delete home space permission + DeleteHomeSpacesPermissionID string = "5de9fe0a-4bc5-4a47-b758-28f370caf169" + // DeleteHomeSpacesPermissionName is the hardcoded setting name for the delete home space permission + DeleteHomeSpacesPermissionName string = "delete-all-home-spaces" + settingUUIDProfileLanguage = "aa8cfbe5-95d4-4f7e-a032-c3c01f5f062f" // AccountManagementPermissionID is the hardcoded setting UUID for the account management permission @@ -205,6 +210,21 @@ func generateBundleAdminRole() *settingsmsg.Bundle { }, }, }, + { + Id: DeleteHomeSpacesPermissionID, + Name: DeleteHomeSpacesPermissionName, + DisplayName: "Delete All Home Spaces", + Description: "This permission allows to delete home spaces.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_DELETE, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, }, } } From e36cd4fa7f14f3d36c4f67753e2bf0975cec9940 Mon Sep 17 00:00:00 2001 From: David Christofas Date: Fri, 2 Sep 2022 11:35:38 +0200 Subject: [PATCH 3/3] add returns after rendering errors and simplify loop condition --- services/graph/pkg/service/v0/users.go | 47 +++++++++++++++++--------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/services/graph/pkg/service/v0/users.go b/services/graph/pkg/service/v0/users.go index 3d5532a598d..26dd4bde31d 100644 --- a/services/graph/pkg/service/v0/users.go +++ b/services/graph/pkg/service/v0/users.go @@ -159,6 +159,7 @@ func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) { userID, err := url.PathUnescape(userID) if err != nil { errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping user id failed") + return } if userID == "" { @@ -175,11 +176,20 @@ func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) { } else { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) } + return } sel := strings.Split(r.URL.Query().Get("$select"), ",") exp := strings.Split(r.URL.Query().Get("$expand"), ",") if slices.Contains(sel, "drive") || slices.Contains(sel, "drives") || slices.Contains(exp, "drive") || slices.Contains(exp, "drives") { wdu, err := url.Parse(g.config.Spaces.WebDavBase + g.config.Spaces.WebDavPath) + if err != nil { + g.logger.Err(err). + Str("webdav_base", g.config.Spaces.WebDavBase). + Str("webdav_path", g.config.Spaces.WebDavPath). + Msg("error parsing webdav URL") + render.Status(r, http.StatusInternalServerError) + return + } f := listStorageSpacesUserFilter(user.GetId()) // use the unrestricted flag to get all possible spaces // users with the canListAllSpaces permission should see all spaces @@ -231,6 +241,7 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) { userID, err := url.PathUnescape(userID) if err != nil { errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping user id failed") + return } if userID == "" { @@ -248,25 +259,26 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) { }) if err != nil { errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "could not read spaces") + return } for _, sp := range lspr.GetStorageSpaces() { - if sp.SpaceType == "personal" { - if sp.Owner.Id.OpaqueId == userID { - // TODO: check if request contains a homespace and if, check if requesting user has the privilege to - // delete it and make sure it is not deleting its own homespace - // needs modification of the cs3api - _, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{ - Opaque: opaque, - Id: &storageprovider.StorageSpaceId{ - OpaqueId: sp.Id.OpaqueId, - }, - }) - if err != nil { - errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "could not delete homespace") - } - break - } + if !(sp.SpaceType == "personal" && sp.Owner.Id.OpaqueId == userID) { + continue + } + // TODO: check if request contains a homespace and if, check if requesting user has the privilege to + // delete it and make sure it is not deleting its own homespace + // needs modification of the cs3api + _, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{ + Opaque: opaque, + Id: &storageprovider.StorageSpaceId{ + OpaqueId: sp.Id.OpaqueId, + }, + }) + if err != nil { + errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "could not delete homespace") + return } + break } err = g.identityBackend.DeleteUser(r.Context(), userID) @@ -277,6 +289,7 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) { errcode.Render(w, r) } else { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) + return } } @@ -293,6 +306,7 @@ func (g Graph) PatchUser(w http.ResponseWriter, r *http.Request) { nameOrID, err := url.PathUnescape(nameOrID) if err != nil { errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping user id failed") + return } if nameOrID == "" { @@ -328,6 +342,7 @@ func (g Graph) PatchUser(w http.ResponseWriter, r *http.Request) { } else { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) } + return } currentUser := ctxpkg.ContextMustGetUser(r.Context())