diff --git a/services/graph/pkg/service/v0/users.go b/services/graph/pkg/service/v0/users.go index de77a1bc603..c86e7961d3d 100644 --- a/services/graph/pkg/service/v0/users.go +++ b/services/graph/pkg/service/v0/users.go @@ -174,6 +174,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 == "" { @@ -190,11 +191,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 @@ -246,6 +256,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 == "" { @@ -253,6 +264,38 @@ 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") + return + } + for _, sp := range lspr.GetStorageSpaces() { + 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) if err != nil { @@ -261,10 +304,10 @@ 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 } } - currentUser := ctxpkg.ContextMustGetUser(r.Context()) g.publishEvent(events.UserDeleted{Executant: currentUser.Id, UserID: userID}) render.Status(r, http.StatusNoContent) @@ -278,6 +321,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 == "" { @@ -313,6 +357,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()) 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, + }, + }, + }, }, } }