diff --git a/changelog/unreleased/delete-spaces.md b/changelog/unreleased/delete-spaces.md new file mode 100644 index 00000000000..c3d9109a861 --- /dev/null +++ b/changelog/unreleased/delete-spaces.md @@ -0,0 +1,5 @@ +Enhancement: Add graph endpoint to delete and purge spaces + +Added a new graph endpoint to delete and purge spaces. + +https://github.com/owncloud/ocis/pull/2979 diff --git a/go.mod b/go.mod index 3367895a3d1..2c2a1c2b4fc 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/blevesearch/bleve/v2 v2.3.0 github.com/coreos/go-oidc/v3 v3.1.0 github.com/cs3org/go-cs3apis v0.0.0-20211214102047-7ce3134d7bf8 - github.com/cs3org/reva v1.16.1-0.20220112085026-07451f6cd806 + github.com/cs3org/reva v1.16.1-0.20220118104140-9dd1f7562012 github.com/disintegration/imaging v1.6.2 github.com/glauth/glauth/v2 v2.0.0-20211021011345-ef3151c28733 github.com/go-chi/chi/v5 v5.0.7 diff --git a/go.sum b/go.sum index 13b0d7800ed..ee053b6fd7e 100644 --- a/go.sum +++ b/go.sum @@ -324,8 +324,8 @@ github.com/crewjam/saml v0.4.5/go.mod h1:qCJQpUtZte9R1ZjUBcW8qtCNlinbO363ooNl02S github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= github.com/cs3org/go-cs3apis v0.0.0-20211214102047-7ce3134d7bf8 h1:PqOprF37OvwCbAN5W23znknGk6N/LMayqLAeP904FHE= github.com/cs3org/go-cs3apis v0.0.0-20211214102047-7ce3134d7bf8/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva v1.16.1-0.20220112085026-07451f6cd806 h1:kwGCQOlC/x0sz4KZ28n7GgZ+aBlmqbKn8CmbkNK6WU4= -github.com/cs3org/reva v1.16.1-0.20220112085026-07451f6cd806/go.mod h1:HisUI5sBYaR3kqqtP+O8MzY7XRjqpV8IgxzK4aK0BtI= +github.com/cs3org/reva v1.16.1-0.20220118104140-9dd1f7562012 h1:cLXBV71Nnug7RMma8BDo9VcGQRUmKYH5JQiu3PaXJNk= +github.com/cs3org/reva v1.16.1-0.20220118104140-9dd1f7562012/go.mod h1:86uvpL6IYmqoyAWT0DDCooo9Bh4tp5A33SLOLapc7V0= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= @@ -638,7 +638,6 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= -github.com/gomodule/redigo v1.8.6/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gomodule/redigo v1.8.8 h1:f6cXq6RRfiyrOJEV7p3JhLDlmawGBVBBP1MggY8Mo4E= github.com/gomodule/redigo v1.8.8/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -935,7 +934,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= diff --git a/graph/pkg/service/v0/drives.go b/graph/pkg/service/v0/drives.go index 2757c8cd982..6fc482e3e0e 100644 --- a/graph/pkg/service/v0/drives.go +++ b/graph/pkg/service/v0/drives.go @@ -735,3 +735,61 @@ func generateCs3Filters(request *godata.GoDataRequest) ([]*storageprovider.ListS } return filters, nil } + +func (g Graph) DeleteDrive(w http.ResponseWriter, r *http.Request) { + driveID, err := url.PathUnescape(chi.URLParam(r, "driveID")) + if err != nil { + errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping drive id failed") + return + } + + if driveID == "" { + errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "missing drive id") + return + } + + client, err := g.GetClient() + if err != nil { + g.logger.Error().Err(err).Msg("error creating grpc client") + return + } + + root := &storageprovider.ResourceId{} + + identifierParts := strings.Split(driveID, "!") + switch len(identifierParts) { + case 1: + root.StorageId, root.OpaqueId = identifierParts[0], identifierParts[0] + case 2: + root.StorageId, root.OpaqueId = identifierParts[0], identifierParts[1] + default: + errorcode.GeneralException.Render(w, r, http.StatusBadRequest, fmt.Sprintf("invalid resource id: %v", driveID)) + w.WriteHeader(http.StatusInternalServerError) + return + } + + purge := parsePurgeHeader(r.Header) + + var opaque *types.Opaque + if purge { + opaque = &types.Opaque{ + Map: map[string]*types.OpaqueEntry{ + "purge": {}, + }, + } + } + + dRes, err := client.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{ + Opaque: opaque, + Id: &storageprovider.StorageSpaceId{ + OpaqueId: root.StorageId, + }, + }) + if err != nil || dRes.Status.Code != cs3rpc.Code_CODE_OK { + g.logger.Error().Err(err).Msg("error deleting storage space") + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusNoContent) +} diff --git a/graph/pkg/service/v0/service.go b/graph/pkg/service/v0/service.go index 529fec816b3..a0f057d4fd9 100644 --- a/graph/pkg/service/v0/service.go +++ b/graph/pkg/service/v0/service.go @@ -3,6 +3,7 @@ package svc import ( "crypto/tls" "net/http" + "strconv" "github.com/ReneKroon/ttlcache/v2" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -15,6 +16,11 @@ import ( opkgm "github.com/owncloud/ocis/ocis-pkg/middleware" ) +const ( + // HeaderPurge defines the header name for the purge header. + HeaderPurge = "Purge" +) + // Service defines the extension handlers. type Service interface { ServeHTTP(http.ResponseWriter, *http.Request) @@ -117,7 +123,11 @@ func NewService(opts ...Option) Service { r.Post("/", svc.CreateDrive) r.Route("/{driveID}", func(r chi.Router) { r.Patch("/", svc.UpdateDrive) +<<<<<<< HEAD r.Get("/", svc.GetSingleDrive) +======= + r.Delete("/", svc.DeleteDrive) +>>>>>>> 0ec198086 (implement graph endpoint to delete spaces) }) }) }) @@ -126,3 +136,16 @@ func NewService(opts ...Option) Service { return svc } + +// parseHeaderPurge parses the 'Purge' header. +// Expected values are 'T' or 'F' case insensitive. +// If the header is not set or if any other values +// are present in the header false is returned. +func parsePurgeHeader(h http.Header) bool { + val := h.Get(HeaderPurge) + + if b, err := strconv.ParseBool(val); err == nil { + return b + } + return false +} diff --git a/graph/pkg/service/v0/service_test.go b/graph/pkg/service/v0/service_test.go new file mode 100644 index 00000000000..8467b706db6 --- /dev/null +++ b/graph/pkg/service/v0/service_test.go @@ -0,0 +1,30 @@ +package svc + +import ( + "net/http" + "testing" +) + +func TestParsePurgeHeader(t *testing.T) { + tests := map[string]bool{ + "": false, + "f": false, + "F": false, + "anything": false, + "t": true, + "T": true, + } + + for input, expected := range tests { + h := make(http.Header) + h.Add(HeaderPurge, input) + + if expected != parsePurgeHeader(h) { + t.Errorf("parsePurgeHeader with input %s got %t expected %t", input, !expected, expected) + } + } + + if h := make(http.Header); parsePurgeHeader(h) { + t.Error("parsePurgeHeader without Purge header set got true expected false") + } +} diff --git a/proxy/pkg/middleware/create_home.go b/proxy/pkg/middleware/create_home.go index 9de555653fe..f85d2c8aa00 100644 --- a/proxy/pkg/middleware/create_home.go +++ b/proxy/pkg/middleware/create_home.go @@ -51,7 +51,9 @@ func (m createHome) ServeHTTP(w http.ResponseWriter, req *http.Request) { m.logger.Err(err).Msg("error calling CreateHome") } else if createHomeRes.Status.Code != rpc.Code_CODE_OK { err := status.NewErrorFromCode(createHomeRes.Status.Code, "gateway") - m.logger.Err(err).Msg("error when calling Createhome") + if createHomeRes.Status.Code != rpc.Code_CODE_ALREADY_EXISTS { + m.logger.Err(err).Msg("error when calling Createhome") + } } m.next.ServeHTTP(w, req)