From 286e54f6cefecf1d3a9f1ebc168b81d1744adfde Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Wed, 19 Jan 2022 10:58:23 +0100 Subject: [PATCH 01/15] Fix docker-compose ocis_keycloak example docker-compose doesn't like bare boolean values in the `environment` section. From the compose-file docs: Any boolean values (true, false, yes, no) need to be enclosed in quotes to ensure they are not converted to True or False by the YML parser. --- deployments/examples/ocis_keycloak/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployments/examples/ocis_keycloak/docker-compose.yml b/deployments/examples/ocis_keycloak/docker-compose.yml index ec11d218f9..72be457ae4 100644 --- a/deployments/examples/ocis_keycloak/docker-compose.yml +++ b/deployments/examples/ocis_keycloak/docker-compose.yml @@ -63,7 +63,7 @@ services: OCIS_URL: https://${OCIS_DOMAIN:-ocis.owncloud.test} OCIS_LOG_LEVEL: ${OCIS_LOG_LEVEL:-error} # make oCIS less verbose PROXY_TLS: "false" # do not use SSL between Traefik and oCIS - ACCOUNTS_DEMO_USERS_AND_GROUPS: false # don't generate demo users + ACCOUNTS_DEMO_USERS_AND_GROUPS: "false" # don't generate demo users # change default secrets IDP_LDAP_BIND_PASSWORD: ${IDP_LDAP_BIND_PASSWORD:-idp} STORAGE_LDAP_BIND_PASSWORD: ${STORAGE_LDAP_BIND_PASSWORD:-reva} From 3e764825c591961f2d43a6164ff4d7c51df8cf7b Mon Sep 17 00:00:00 2001 From: pwengerter Date: Wed, 19 Jan 2022 12:11:43 +0100 Subject: [PATCH 02/15] Pin acceptance test middleware version --- .drone.star | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.star b/.drone.star index 3e13b66bc2..b82577b2b2 100644 --- a/.drone.star +++ b/.drone.star @@ -7,6 +7,7 @@ OC_CI_GOLANG = "owncloudci/golang:1.17" OC_CI_NODEJS = "owncloudci/nodejs:14" OC_CI_PHP = "owncloudci/php:7.4" OC_CI_WAIT_FOR = "owncloudci/wait-for:latest" +OC_TESTING_MIDDLEWARE = "owncloud/owncloud-test-middleware:1.2.0" MINIO_MC = "minio/mc:RELEASE.2021-10-07T04-19-58Z" REDIS = "redis:6-alpine" @@ -1443,8 +1444,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = []): def middlewareService(): return [{ "name": "middleware", - "image": "owncloud/owncloud-test-middleware", - "pull": "always", + "image": OC_TESTING_MIDDLEWARE, "environment": { "BACKEND_HOST": "https://ocis-server:9200", "OCIS_REVA_DATA_ROOT": "/srv/app/tmp/ocis/storage/owncloud/", From 85fd0158ddc0f36f9dfb87cd4d9527898fbf2101 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Tue, 18 Jan 2022 12:01:29 +0100 Subject: [PATCH 03/15] add GetSingleDrive handler --- graph/pkg/service/v0/drives.go | 242 ++++++++++++++++++++++++++++---- graph/pkg/service/v0/service.go | 1 + 2 files changed, 214 insertions(+), 29 deletions(-) diff --git a/graph/pkg/service/v0/drives.go b/graph/pkg/service/v0/drives.go index 0d15adc48d..370da01ae1 100644 --- a/graph/pkg/service/v0/drives.go +++ b/graph/pkg/service/v0/drives.go @@ -7,6 +7,7 @@ import ( "math" "net/http" "net/url" + "path" "path/filepath" "strconv" "strings" @@ -43,46 +44,20 @@ func (g Graph) GetDrives(w http.ResponseWriter, r *http.Request) { errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error()) return } - g.logger.Info().Msg("Calling GetDrives") + g.logger.Info().Interface("query", r.URL.Query()).Msg("Calling GetDrives") ctx := r.Context() - client := g.GetGatewayClient() - - permissions := make(map[string]struct{}, 1) - s := sproto.NewPermissionService("com.owncloud.api.settings", grpc.DefaultClient) - - _, err = s.GetPermissionByID(ctx, &sproto.GetPermissionByIDRequest{ - PermissionId: settingsSvc.ListAllSpacesPermissionID, - }) - - // No error means the user has the permission - if err == nil { - permissions[settingsSvc.ListAllSpacesPermissionName] = struct{}{} - } - value, err := json.Marshal(permissions) - if err != nil { - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) - return - } filters, err := generateCs3Filters(odataReq) if err != nil { g.logger.Err(err).Interface("query", r.URL.Query()).Msg("query error") errorcode.NotSupported.Render(w, r, http.StatusNotImplemented, err.Error()) return } - res, err := client.ListStorageSpaces(ctx, &storageprovider.ListStorageSpacesRequest{ - Opaque: &types.Opaque{Map: map[string]*types.OpaqueEntry{ - "permissions": { - Decoder: "json", - Value: value, - }, - }}, - Filters: filters, - }) + res, err := g.ListStorageSpacesWithFilters(ctx, filters) switch { case err != nil: g.logger.Error().Err(err).Msg("error sending list storage spaces grpc request") - errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return case res.Status.Code != cs3rpc.Code_CODE_OK: if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { @@ -113,6 +88,145 @@ func (g Graph) GetDrives(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, &listResponse{Value: files}) } +// GetSingleDrive does a lookup of a single space by spaceId +func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { + sanitizedPath := strings.TrimPrefix(r.URL.Path, "/graph/v1.0/") + driveId := chi.URLParam(r, "driveID") + if driveId == "" { + err := fmt.Errorf("no valid space id retrieved") + g.logger.Err(err) + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) + return + } + // Add the driveId filter to the request query + spaceFilterValue := fmt.Sprintf("id eq %s", driveId) + query := r.URL.Query() + query.Add("$filter", spaceFilterValue) + // Parse the request with odata parser + odataReq, err := godata.ParseRequest(r.Context(), sanitizedPath, query) + if err != nil { + g.logger.Err(err).Interface("query", r.URL.Query()).Msg("query error") + errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error()) + return + } + + g.logger.Info().Str("driveID", driveId).Msg("Calling GetSingleDrive") + ctx := r.Context() + + filters, err := generateCs3Filters(odataReq) + if err != nil { + g.logger.Err(err).Interface("query", r.URL.Query()).Msg("query error") + errorcode.NotSupported.Render(w, r, http.StatusNotImplemented, err.Error()) + return + } + res, err := g.ListStorageSpacesWithFilters(ctx, filters) + switch { + case err != nil: + g.logger.Error().Err(err).Msg("error sending list storage spaces grpc request") + errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) + return + case res.Status.Code != cs3rpc.Code_CODE_OK: + if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { + g.logger.Error().Str("driveId", driveId).Msg("no space found") + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("no space found with id %s", driveId)) + return + } + g.logger.Error().Err(err).Msg("error sending list storage spaces grpc request") + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) + return + } + + wdu, err := url.Parse(g.config.Spaces.WebDavBase + g.config.Spaces.WebDavPath) + if err != nil { + g.logger.Error().Err(err).Msg("error parsing url") + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) + return + } + spaces, err := g.formatDrives(ctx, wdu, res.StorageSpaces) + if err != nil { + g.logger.Error().Err(err).Msg("error encoding response") + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) + return + } + switch num := len(spaces); { + case num == 0: + g.logger.Error().Str("driveId", driveId).Msg("no space found") + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("no space found with id %s", driveId)) + return + case num == 1: + render.Status(r, http.StatusOK) + render.JSON(w, r, spaces[0]) + default: + g.logger.Error().Int("number", num).Msg("an unexpected number of spaces was found") + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "an unexpected number of spaces was found") + return + } +} + +// GetRootDriveChildren implements the Service interface. +func (g Graph) GetRootDriveChildren(w http.ResponseWriter, r *http.Request) { + g.logger.Info().Msg("Calling GetRootDriveChildren") + ctx := r.Context() + + client, err := g.GetClient() + if err != nil { + g.logger.Error().Err(err).Msg("could not get client") + errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) + return + } + + res, err := client.GetHome(ctx, &storageprovider.GetHomeRequest{}) + switch { + case err != nil: + g.logger.Error().Err(err).Msg("error sending get home grpc request") + errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) + return + case res.Status.Code != cs3rpc.Code_CODE_OK: + if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) + return + } + g.logger.Error().Err(err).Msg("error sending get home grpc request") + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) + return + } + + lRes, err := client.ListContainer(ctx, &storageprovider.ListContainerRequest{ + Ref: &storageprovider.Reference{ + Path: res.Path, + }, + }) + switch { + case err != nil: + g.logger.Error().Err(err).Msg("error sending list container grpc request") + errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) + return + case res.Status.Code != cs3rpc.Code_CODE_OK: + if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) + return + } + if res.Status.Code == cs3rpc.Code_CODE_PERMISSION_DENIED { + // TODO check if we should return 404 to not disclose existing items + errorcode.AccessDenied.Render(w, r, http.StatusForbidden, res.Status.Message) + return + } + g.logger.Error().Err(err).Msg("error sending list container grpc request") + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) + return + } + + files, err := formatDriveItems(lRes.Infos) + if err != nil { + g.logger.Error().Err(err).Msg("error encoding response as json") + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) + return + } + + render.Status(r, http.StatusOK) + render.JSON(w, r, &listResponse{Value: files}) +} + // CreateDrive creates a storage drive (space). func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { us, ok := ctxpkg.ContextGetUser(r.Context()) @@ -331,6 +445,76 @@ func (g Graph) formatDrives(ctx context.Context, baseURL *url.URL, mds []*storag } // TODO this overwrites the quota that might already have been mapped in cs3StorageSpaceToDrive above ... move this into the cs3StorageSpaceToDrive method? res.Quota, err = g.getDriveQuota(ctx, space) +// ListStorageSpacesWithFilters List Storage Spaces using filters +func (g Graph) ListStorageSpacesWithFilters(ctx context.Context, filters []*storageprovider.ListStorageSpacesRequest_Filter) (*storageprovider.ListStorageSpacesResponse, error) { + client, err := g.GetClient() + if err != nil { + g.logger.Err(err).Msg("error getting grpc client") + return nil, err + } + + permissions := make(map[string]struct{}, 1) + s := sproto.NewPermissionService("com.owncloud.api.settings", grpc.DefaultClient) + + _, err = s.GetPermissionByID(ctx, &sproto.GetPermissionByIDRequest{ + PermissionId: settingsSvc.ListAllSpacesPermissionID, + }) + + // No error means the user has the permission + if err == nil { + permissions[settingsSvc.ListAllSpacesPermissionName] = struct{}{} + } + value, err := json.Marshal(permissions) + if err != nil { + return nil, err + } + + res, err := client.ListStorageSpaces(ctx, &storageprovider.ListStorageSpacesRequest{ + Opaque: &types.Opaque{Map: map[string]*types.OpaqueEntry{ + "permissions": { + Decoder: "json", + Value: value, + }, + }}, + Filters: filters, + }) + return res, nil +} + +func cs3TimestampToTime(t *types.Timestamp) time.Time { + return time.Unix(int64(t.Seconds), int64(t.Nanos)) +} + +func cs3ResourceToDriveItem(res *storageprovider.ResourceInfo) (*libregraph.DriveItem, error) { + size := new(int64) + *size = int64(res.Size) // uint64 -> int :boom: + name := path.Base(res.Path) + + driveItem := &libregraph.DriveItem{ + Id: &res.Id.OpaqueId, + Name: &name, + ETag: &res.Etag, + Size: size, + } + if res.Mtime != nil { + lastModified := cs3TimestampToTime(res.Mtime) + driveItem.LastModifiedDateTime = &lastModified + } + if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_FILE { + driveItem.File = &libregraph.OpenGraphFile{ // FIXME We cannot use libregraph.File here because the openapi codegenerator autodetects 'File' as a go type ... + MimeType: &res.MimeType, + } + } + if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER { + driveItem.Folder = &libregraph.Folder{} + } + return driveItem, nil +} + +func formatDriveItems(mds []*storageprovider.ResourceInfo) ([]*libregraph.DriveItem, error) { + responses := make([]*libregraph.DriveItem, 0, len(mds)) + for i := range mds { + res, err := cs3ResourceToDriveItem(mds[i]) if err != nil { return nil, err } diff --git a/graph/pkg/service/v0/service.go b/graph/pkg/service/v0/service.go index 5d62e3cdb7..529fec816b 100644 --- a/graph/pkg/service/v0/service.go +++ b/graph/pkg/service/v0/service.go @@ -117,6 +117,7 @@ func NewService(opts ...Option) Service { r.Post("/", svc.CreateDrive) r.Route("/{driveID}", func(r chi.Router) { r.Patch("/", svc.UpdateDrive) + r.Get("/", svc.GetSingleDrive) }) }) }) From e10b524d7124ce1dab14a1774465bbe4e8729a75 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Tue, 18 Jan 2022 16:42:30 +0100 Subject: [PATCH 04/15] add Tests and Test Steps --- .../features/apiSpaces/listSpaces.feature | 32 ++++++++++ .../features/bootstrap/SpacesContext.php | 60 +++++++++++++++++-- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/tests/acceptance/features/apiSpaces/listSpaces.feature b/tests/acceptance/features/apiSpaces/listSpaces.feature index 175c562cc7..ac3afc65e9 100644 --- a/tests/acceptance/features/apiSpaces/listSpaces.feature +++ b/tests/acceptance/features/apiSpaces/listSpaces.feature @@ -79,3 +79,35 @@ Feature: List and create spaces | name | Project Venus | | quota@@@total | 2000 | | root@@@webDavUrl | %base_url%/dav/spaces/%space_id% | + + Scenario: A user can list his personal space via multiple endpoints + When user "Alice" lists all available spaces via the GraphApi with query "$filter=driveType eq 'personal'" + Then the json responded should contain a space "Alice Hansen" with these key and value pairs: + | key | value | + | driveType | personal | + | name | Alice Hansen | + | root@@@webDavUrl | %base_url%/dav/spaces/%space_id% | + When user "Alice" looks up the single space "Alice Hansen" via the GraphApi by using its id + Then the json responded should contain a space "Alice Hansen" with these key and value pairs: + | key | value | + | driveType | personal | + | name | Alice Hansen | + | root@@@webDavUrl | %base_url%/dav/spaces/%space_id% | + + Scenario: A user can list his created spaces via multiple endpoints + Given the administrator has given "Alice" the role "Admin" using the settings api + When user "Alice" creates a space "Project Venus" of type "project" with quota "2000" using the GraphApi + Then the HTTP status code should be "201" + And the json responded should contain a space "Project Venus" with these key and value pairs: + | key | value | + | driveType | project | + | name | Project Venus | + | quota@@@total | 2000 | + | root@@@webDavUrl | %base_url%/dav/spaces/%space_id% | + When user "Alice" looks up the single space "Project Venus" via the GraphApi by using its id + Then the json responded should contain a space "Project Venus" with these key and value pairs: + | key | value | + | driveType | project | + | name | Project Venus | + | quota@@@total | 2000 | + | root@@@webDavUrl | %base_url%/dav/spaces/%space_id% | diff --git a/tests/acceptance/features/bootstrap/SpacesContext.php b/tests/acceptance/features/bootstrap/SpacesContext.php index c5d5a220ae..b0e03b2ef8 100644 --- a/tests/acceptance/features/bootstrap/SpacesContext.php +++ b/tests/acceptance/features/bootstrap/SpacesContext.php @@ -232,7 +232,7 @@ class SpacesContext implements Context { } /** - * Send Graph List Spaces Request + * Send Graph List My Spaces Request * * @param string $user * @param string $password @@ -245,7 +245,7 @@ class SpacesContext implements Context { * * @throws GuzzleException */ - public function listSpacesRequest( + public function listMySpacesRequest( string $user, string $password, string $urlArguments = '', @@ -258,6 +258,34 @@ class SpacesContext implements Context { return HttpRequestHelper::get($fullUrl, $xRequestId, $user, $password, $headers, $body); } + /** + * Send Graph List Single Space Request + * + * @param string $user + * @param string $password + * @param string $urlArguments + * @param string $xRequestId + * @param array $body + * @param array $headers + * + * @return ResponseInterface + * + * @throws GuzzleException + */ + public function listSingleSpaceRequest( + string $user, + string $password, + string $spaceId, + string $urlArguments = '', + string $xRequestId = '', + array $body = [], + array $headers = [] + ): ResponseInterface { + $fullUrl = $this->baseUrl . "/graph/v1.0/drives/" . $spaceId . "/" . $urlArguments; + + return HttpRequestHelper::get($fullUrl, $xRequestId, $user, $password, $headers, $body); + } + /** * Send Graph Create Space Request * @@ -342,7 +370,7 @@ class SpacesContext implements Context { */ public function theUserListsAllHisAvailableSpacesUsingTheGraphApi(string $user): void { $this->featureContext->setResponse( - $this->listSpacesRequest( + $this->listMySpacesRequest( $user, $this->featureContext->getPasswordForUser($user) ) @@ -362,7 +390,7 @@ class SpacesContext implements Context { */ public function theUserListsAllHisAvailableSpacesUsingTheGraphApiWithFilter(string $user, string $query): void { $this->featureContext->setResponse( - $this->listSpacesRequest( + $this->listMySpacesRequest( $user, $this->featureContext->getPasswordForUser($user), "?". $query @@ -370,6 +398,30 @@ class SpacesContext implements Context { ); } + /** + * @When /^user "([^"]*)" looks up the single space "([^"]*)" via the GraphApi by using its id$/ + * + * @param string $user + * @param string $query + * + * @return void + * + * @throws GuzzleException + */ + public function theUserLooksUpTheSingleSpaceUsingTheGraphApiByUsingItsId(string $user, string $spaceName): void { + $space = $this->getSpaceByName($user, $spaceName); + Assert::assertIsArray($space); + Assert::assertNotEmpty($spaceId = $space["id"]); + Assert::assertNotEmpty($spaceWebDavUrl = $space["root"]["webDavUrl"]); + $this->featureContext->setResponse( + $this->listSingleSpaceRequest( + $user, + $this->featureContext->getPasswordForUser($user), + $spaceId + ) + ); + } + /** * @When /^user "([^"]*)" creates a space "([^"]*)" of type "([^"]*)" with the default quota using the GraphApi$/ * From e0a4280de4c9c1ff196d3b615942169996582ffb Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Tue, 18 Jan 2022 16:45:14 +0100 Subject: [PATCH 05/15] add changelog --- changelog/unreleased/single-space-enpoint.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/unreleased/single-space-enpoint.md diff --git a/changelog/unreleased/single-space-enpoint.md b/changelog/unreleased/single-space-enpoint.md new file mode 100644 index 0000000000..c77e6a461a --- /dev/null +++ b/changelog/unreleased/single-space-enpoint.md @@ -0,0 +1,5 @@ +Enhancement: Add endpoint to retrieve a single space + +We added the endpoint ``/drives/{driveID}`` to get a single space by id from the server. + +https://github.com/owncloud/ocis/pull/2978 From 5b9f31e8704c0489163d613d14aaa098dcfe11a0 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Wed, 19 Jan 2022 11:57:42 +0100 Subject: [PATCH 06/15] Apply suggestions from code review Co-authored-by: Alex Unger <6905948+refs@users.noreply.github.com> --- graph/pkg/service/v0/drives.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graph/pkg/service/v0/drives.go b/graph/pkg/service/v0/drives.go index 370da01ae1..79204b17c3 100644 --- a/graph/pkg/service/v0/drives.go +++ b/graph/pkg/service/v0/drives.go @@ -127,8 +127,8 @@ func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { return case res.Status.Code != cs3rpc.Code_CODE_OK: if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { - g.logger.Error().Str("driveId", driveId).Msg("no space found") - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("no space found with id %s", driveId)) + g.logger.Error().Str("driveId", driveId).Msg(fmt.Sprintf("space with id `%s` not found", driveId)) + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("space with id `%s` not found", driveId)) return } g.logger.Error().Err(err).Msg("error sending list storage spaces grpc request") From 6b8a9f9127172eba6e830f57e529760a11fbe1cd Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Wed, 19 Jan 2022 12:07:02 +0100 Subject: [PATCH 07/15] create filter directly, improve logging --- graph/pkg/service/v0/drives.go | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/graph/pkg/service/v0/drives.go b/graph/pkg/service/v0/drives.go index 79204b17c3..4693a0d37c 100644 --- a/graph/pkg/service/v0/drives.go +++ b/graph/pkg/service/v0/drives.go @@ -90,7 +90,6 @@ func (g Graph) GetDrives(w http.ResponseWriter, r *http.Request) { // GetSingleDrive does a lookup of a single space by spaceId func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { - sanitizedPath := strings.TrimPrefix(r.URL.Path, "/graph/v1.0/") driveId := chi.URLParam(r, "driveID") if driveId == "" { err := fmt.Errorf("no valid space id retrieved") @@ -98,27 +97,20 @@ func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return } - // Add the driveId filter to the request query - spaceFilterValue := fmt.Sprintf("id eq %s", driveId) - query := r.URL.Query() - query.Add("$filter", spaceFilterValue) - // Parse the request with odata parser - odataReq, err := godata.ParseRequest(r.Context(), sanitizedPath, query) - if err != nil { - g.logger.Err(err).Interface("query", r.URL.Query()).Msg("query error") - errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error()) - return - } g.logger.Info().Str("driveID", driveId).Msg("Calling GetSingleDrive") ctx := r.Context() - filters, err := generateCs3Filters(odataReq) - if err != nil { - g.logger.Err(err).Interface("query", r.URL.Query()).Msg("query error") - errorcode.NotSupported.Render(w, r, http.StatusNotImplemented, err.Error()) - return + var filters []*storageprovider.ListStorageSpacesRequest_Filter + filterDriveId := &storageprovider.ListStorageSpacesRequest_Filter{ + Type: storageprovider.ListStorageSpacesRequest_Filter_TYPE_ID, + Term: &storageprovider.ListStorageSpacesRequest_Filter_Id{ + Id: &storageprovider.StorageSpaceId{ + OpaqueId: driveId, + }, + }, } + filters = append(filters, filterDriveId) res, err := g.ListStorageSpacesWithFilters(ctx, filters) switch { case err != nil: @@ -127,6 +119,8 @@ func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { return case res.Status.Code != cs3rpc.Code_CODE_OK: if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { + // the client is doing a lookup for a specific space, therefore we need to return + // not found to the caller g.logger.Error().Str("driveId", driveId).Msg(fmt.Sprintf("space with id `%s` not found", driveId)) errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("space with id `%s` not found", driveId)) return @@ -151,14 +145,14 @@ func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { switch num := len(spaces); { case num == 0: g.logger.Error().Str("driveId", driveId).Msg("no space found") - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("no space found with id %s", driveId)) + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("space with id `%s` not found", driveId)) return case num == 1: render.Status(r, http.StatusOK) render.JSON(w, r, spaces[0]) default: - g.logger.Error().Int("number", num).Msg("an unexpected number of spaces was found") - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "an unexpected number of spaces was found") + g.logger.Error().Int("number", num).Msg("expected to find a single space but found more") + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "expected to find a single space but found more") return } } From 4d4dca512b762b89ba15577763192169793ce582 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Wed, 19 Jan 2022 12:30:23 +0100 Subject: [PATCH 08/15] merge master --- graph/pkg/service/v0/drives.go | 155 ++++++--------------------------- graph/pkg/service/v0/graph.go | 6 ++ 2 files changed, 32 insertions(+), 129 deletions(-) diff --git a/graph/pkg/service/v0/drives.go b/graph/pkg/service/v0/drives.go index 4693a0d37c..94b1f69278 100644 --- a/graph/pkg/service/v0/drives.go +++ b/graph/pkg/service/v0/drives.go @@ -7,7 +7,6 @@ import ( "math" "net/http" "net/url" - "path" "path/filepath" "strconv" "strings" @@ -56,7 +55,7 @@ func (g Graph) GetDrives(w http.ResponseWriter, r *http.Request) { res, err := g.ListStorageSpacesWithFilters(ctx, filters) switch { case err != nil: - g.logger.Error().Err(err).Msg("error sending list storage spaces grpc request") + g.logger.Error().Err(err).Msg(ListStorageSpacesTransportErr) errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return case res.Status.Code != cs3rpc.Code_CODE_OK: @@ -66,7 +65,7 @@ func (g Graph) GetDrives(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, &listResponse{}) return } - g.logger.Error().Err(err).Msg("error sending list storage spaces grpc request") + g.logger.Error().Err(err).Msg(ListStorageSpacesReturnsErr) errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) return } @@ -90,42 +89,42 @@ func (g Graph) GetDrives(w http.ResponseWriter, r *http.Request) { // GetSingleDrive does a lookup of a single space by spaceId func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { - driveId := chi.URLParam(r, "driveID") - if driveId == "" { + driveID := chi.URLParam(r, "driveID") + if driveID == "" { err := fmt.Errorf("no valid space id retrieved") g.logger.Err(err) errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return } - g.logger.Info().Str("driveID", driveId).Msg("Calling GetSingleDrive") + g.logger.Info().Str("driveID", driveID).Msg("Calling GetSingleDrive") ctx := r.Context() var filters []*storageprovider.ListStorageSpacesRequest_Filter - filterDriveId := &storageprovider.ListStorageSpacesRequest_Filter{ + filterDriveID := &storageprovider.ListStorageSpacesRequest_Filter{ Type: storageprovider.ListStorageSpacesRequest_Filter_TYPE_ID, Term: &storageprovider.ListStorageSpacesRequest_Filter_Id{ Id: &storageprovider.StorageSpaceId{ - OpaqueId: driveId, + OpaqueId: driveID, }, }, } - filters = append(filters, filterDriveId) + filters = append(filters, filterDriveID) res, err := g.ListStorageSpacesWithFilters(ctx, filters) switch { case err != nil: - g.logger.Error().Err(err).Msg("error sending list storage spaces grpc request") + g.logger.Error().Err(err).Msg(ListStorageSpacesTransportErr) errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) return case res.Status.Code != cs3rpc.Code_CODE_OK: if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { // the client is doing a lookup for a specific space, therefore we need to return // not found to the caller - g.logger.Error().Str("driveId", driveId).Msg(fmt.Sprintf("space with id `%s` not found", driveId)) - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("space with id `%s` not found", driveId)) + g.logger.Error().Str("driveID", driveID).Msg(fmt.Sprintf(NoSpaceFoundMessage, driveID)) + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf(NoSpaceFoundMessage, driveID)) return } - g.logger.Error().Err(err).Msg("error sending list storage spaces grpc request") + g.logger.Error().Err(err).Msg(ListStorageSpacesReturnsErr) errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) return } @@ -144,8 +143,8 @@ func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { } switch num := len(spaces); { case num == 0: - g.logger.Error().Str("driveId", driveId).Msg("no space found") - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("space with id `%s` not found", driveId)) + g.logger.Error().Str("driveID", driveID).Msg("no space found") + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf(NoSpaceFoundMessage, driveID)) return case num == 1: render.Status(r, http.StatusOK) @@ -157,70 +156,6 @@ func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { } } -// GetRootDriveChildren implements the Service interface. -func (g Graph) GetRootDriveChildren(w http.ResponseWriter, r *http.Request) { - g.logger.Info().Msg("Calling GetRootDriveChildren") - ctx := r.Context() - - client, err := g.GetClient() - if err != nil { - g.logger.Error().Err(err).Msg("could not get client") - errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) - return - } - - res, err := client.GetHome(ctx, &storageprovider.GetHomeRequest{}) - switch { - case err != nil: - g.logger.Error().Err(err).Msg("error sending get home grpc request") - errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) - return - case res.Status.Code != cs3rpc.Code_CODE_OK: - if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) - return - } - g.logger.Error().Err(err).Msg("error sending get home grpc request") - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) - return - } - - lRes, err := client.ListContainer(ctx, &storageprovider.ListContainerRequest{ - Ref: &storageprovider.Reference{ - Path: res.Path, - }, - }) - switch { - case err != nil: - g.logger.Error().Err(err).Msg("error sending list container grpc request") - errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) - return - case res.Status.Code != cs3rpc.Code_CODE_OK: - if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) - return - } - if res.Status.Code == cs3rpc.Code_CODE_PERMISSION_DENIED { - // TODO check if we should return 404 to not disclose existing items - errorcode.AccessDenied.Render(w, r, http.StatusForbidden, res.Status.Message) - return - } - g.logger.Error().Err(err).Msg("error sending list container grpc request") - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) - return - } - - files, err := formatDriveItems(lRes.Infos) - if err != nil { - g.logger.Error().Err(err).Msg("error encoding response as json") - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) - return - } - - render.Status(r, http.StatusOK) - render.JSON(w, r, &listResponse{Value: files}) -} - // CreateDrive creates a storage drive (space). func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { us, ok := ctxpkg.ContextGetUser(r.Context()) @@ -439,18 +374,23 @@ func (g Graph) formatDrives(ctx context.Context, baseURL *url.URL, mds []*storag } // TODO this overwrites the quota that might already have been mapped in cs3StorageSpaceToDrive above ... move this into the cs3StorageSpaceToDrive method? res.Quota, err = g.getDriveQuota(ctx, space) + if err != nil { + return nil, err + } + responses = append(responses, res) + } + + return responses, nil +} + // ListStorageSpacesWithFilters List Storage Spaces using filters func (g Graph) ListStorageSpacesWithFilters(ctx context.Context, filters []*storageprovider.ListStorageSpacesRequest_Filter) (*storageprovider.ListStorageSpacesResponse, error) { - client, err := g.GetClient() - if err != nil { - g.logger.Err(err).Msg("error getting grpc client") - return nil, err - } + client := g.GetGatewayClient() permissions := make(map[string]struct{}, 1) s := sproto.NewPermissionService("com.owncloud.api.settings", grpc.DefaultClient) - _, err = s.GetPermissionByID(ctx, &sproto.GetPermissionByIDRequest{ + _, err := s.GetPermissionByID(ctx, &sproto.GetPermissionByIDRequest{ PermissionId: settingsSvc.ListAllSpacesPermissionID, }) @@ -472,50 +412,7 @@ func (g Graph) ListStorageSpacesWithFilters(ctx context.Context, filters []*stor }}, Filters: filters, }) - return res, nil -} - -func cs3TimestampToTime(t *types.Timestamp) time.Time { - return time.Unix(int64(t.Seconds), int64(t.Nanos)) -} - -func cs3ResourceToDriveItem(res *storageprovider.ResourceInfo) (*libregraph.DriveItem, error) { - size := new(int64) - *size = int64(res.Size) // uint64 -> int :boom: - name := path.Base(res.Path) - - driveItem := &libregraph.DriveItem{ - Id: &res.Id.OpaqueId, - Name: &name, - ETag: &res.Etag, - Size: size, - } - if res.Mtime != nil { - lastModified := cs3TimestampToTime(res.Mtime) - driveItem.LastModifiedDateTime = &lastModified - } - if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_FILE { - driveItem.File = &libregraph.OpenGraphFile{ // FIXME We cannot use libregraph.File here because the openapi codegenerator autodetects 'File' as a go type ... - MimeType: &res.MimeType, - } - } - if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER { - driveItem.Folder = &libregraph.Folder{} - } - return driveItem, nil -} - -func formatDriveItems(mds []*storageprovider.ResourceInfo) ([]*libregraph.DriveItem, error) { - responses := make([]*libregraph.DriveItem, 0, len(mds)) - for i := range mds { - res, err := cs3ResourceToDriveItem(mds[i]) - if err != nil { - return nil, err - } - responses = append(responses, res) - } - - return responses, nil + return res, err } func cs3StorageSpaceToDrive(baseURL *url.URL, space *storageprovider.StorageSpace) (*libregraph.Drive, error) { diff --git a/graph/pkg/service/v0/graph.go b/graph/pkg/service/v0/graph.go index 3523dd8fb5..8117859194 100644 --- a/graph/pkg/service/v0/graph.go +++ b/graph/pkg/service/v0/graph.go @@ -85,3 +85,9 @@ func (g Graph) GetHTTPClient() HTTPClient { type listResponse struct { Value interface{} `json:"value,omitempty"` } + +const ( + NoSpaceFoundMessage = "space with id `%s` not found" + ListStorageSpacesTransportErr = "transport error sending list storage spaces grpc request" + ListStorageSpacesReturnsErr = "list storage spaces grpc request returns an errorcode in the response" +) From 3375207a0c8660d850cfb32477bfd0a93ac6dfa5 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Wed, 19 Jan 2022 13:39:17 +0100 Subject: [PATCH 09/15] make code more efficient --- graph/pkg/service/v0/drives.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/graph/pkg/service/v0/drives.go b/graph/pkg/service/v0/drives.go index 94b1f69278..2757c8cd98 100644 --- a/graph/pkg/service/v0/drives.go +++ b/graph/pkg/service/v0/drives.go @@ -100,16 +100,16 @@ func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { g.logger.Info().Str("driveID", driveID).Msg("Calling GetSingleDrive") ctx := r.Context() - var filters []*storageprovider.ListStorageSpacesRequest_Filter - filterDriveID := &storageprovider.ListStorageSpacesRequest_Filter{ - Type: storageprovider.ListStorageSpacesRequest_Filter_TYPE_ID, - Term: &storageprovider.ListStorageSpacesRequest_Filter_Id{ - Id: &storageprovider.StorageSpaceId{ - OpaqueId: driveID, + filters := []*storageprovider.ListStorageSpacesRequest_Filter{ + { + Type: storageprovider.ListStorageSpacesRequest_Filter_TYPE_ID, + Term: &storageprovider.ListStorageSpacesRequest_Filter_Id{ + Id: &storageprovider.StorageSpaceId{ + OpaqueId: driveID, + }, }, }, } - filters = append(filters, filterDriveID) res, err := g.ListStorageSpacesWithFilters(ctx, filters) switch { case err != nil: From ced35e3a9ef441c7b32fefa324b876d85c1d0caa Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Wed, 19 Jan 2022 13:04:17 +0000 Subject: [PATCH 10/15] Automated changelog update [skip ci] --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b1eec11f2..456ff5b69f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The following sections list the changes for unreleased. * Enhancement - Add spaces capability: [#2931](https://github.com/owncloud/ocis/pull/2931) * Enhancement - Support signature auth in the public share auth middleware: [#2831](https://github.com/owncloud/ocis/pull/2831) * Enhancement - Update REVA to v1.16.1-0.20220112085026-07451f6cd806: [#2953](https://github.com/owncloud/ocis/pull/2953) +* Enhancement - Add endpoint to retrieve a single space: [#2978](https://github.com/owncloud/ocis/pull/2978) * Enhancement - Add filter by driveType and id to /me/drives: [#2946](https://github.com/owncloud/ocis/pull/2946) * Enhancement - Update REVA to xxx: [#2878](https://github.com/owncloud/ocis/pull/2878) * Enhancement - Update ownCloud Web to v4.8.0: [#2895](https://github.com/owncloud/ocis/pull/2895) @@ -107,6 +108,12 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/pull/2953 +* Enhancement - Add endpoint to retrieve a single space: [#2978](https://github.com/owncloud/ocis/pull/2978) + + We added the endpoint ``/drives/{driveID}`` to get a single space by id from the server. + + https://github.com/owncloud/ocis/pull/2978 + * Enhancement - Add filter by driveType and id to /me/drives: [#2946](https://github.com/owncloud/ocis/pull/2946) We added two possible filter terms (driveType, id) to the /me/drives endpoint on the graph api. From 97fac6d33b9605e5346cee57743ddb64073d8ba4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Jan 2022 06:20:24 +0000 Subject: [PATCH 11/15] Bump github.com/prometheus/client_golang from 1.11.0 to 1.12.0 Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.11.0 to 1.12.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.11.0...v1.12.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index f0bb8fd601..4437ba0b1a 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/onsi/gomega v1.17.0 github.com/owncloud/libre-graph-api-go v0.8.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.11.0 + github.com/prometheus/client_golang v1.12.0 github.com/rs/zerolog v1.26.1 github.com/sirupsen/logrus v1.8.1 github.com/spf13/cobra v1.3.0 @@ -229,7 +229,7 @@ require ( golang.org/x/mod v0.5.1 // indirect golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect golang.org/x/tools v0.1.8 // indirect diff --git a/go.sum b/go.sum index e0c02ed2f6..80a75340d8 100644 --- a/go.sum +++ b/go.sum @@ -1117,8 +1117,9 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -1719,8 +1720,9 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201113234701-d7a72108b828/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= From 926efa033db80745ae4de16ea50f5073f48c3242 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Jan 2022 06:20:39 +0000 Subject: [PATCH 12/15] Bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.7.2 to 2.7.3 Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.7.2 to 2.7.3. - [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases) - [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/.goreleaser.yml) - [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.7.2...v2.7.3) --- updated-dependencies: - dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index f0bb8fd601..47a7989d0c 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/google/uuid v1.3.0 github.com/gookit/config/v2 v2.0.27 github.com/gorilla/mux v1.8.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.2 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 github.com/iancoleman/strcase v0.2.0 github.com/justinas/alice v1.2.0 github.com/libregraph/lico v0.53.1 @@ -67,7 +67,7 @@ require ( golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e golang.org/x/image v0.0.0-20211028202545-6944b10bf410 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 - google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa + google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5 google.golang.org/grpc v1.43.0 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 @@ -141,7 +141,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gomodule/redigo v1.8.8 // indirect - github.com/google/go-cmp v0.5.6 // indirect + github.com/google/go-cmp v0.5.7 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gookit/goutil v0.4.0 // indirect github.com/gorilla/schema v1.2.0 // indirect diff --git a/go.sum b/go.sum index e0c02ed2f6..7c1d15eb82 100644 --- a/go.sum +++ b/go.sum @@ -654,8 +654,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -725,8 +726,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.2 h1:I/pwhnUln5wbMnTyRbzswA0/JxpK8sZj0aUfI3TV1So= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.2/go.mod h1:lsuH8kb4GlMdSlI4alNIBBSAt5CHJtg3i+0WuN9J5YM= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 h1:I8MsauTJQXZ8df8qJvEln0kYNc3bSapuaSsEsnFdEFU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3/go.mod h1:lZdb/YAJUSj9OqrCHs2ihjtoO3+xK3G53wTYXFWRGDo= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= @@ -1950,8 +1951,9 @@ google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5 h1:zzNejm+EgrbLfDZ6lu9Uud2IVvHySPl8vQzf04laR5Q= +google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= From 7e4c356f49980a84761bc8fcad8f2ebc99db69eb Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Thu, 20 Jan 2022 08:22:48 +0100 Subject: [PATCH 13/15] this fixes the custom clone step for forks with outdated default branch --- .drone.star | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.drone.star b/.drone.star index b82577b2b2..0d3158102f 100644 --- a/.drone.star +++ b/.drone.star @@ -357,7 +357,12 @@ def uploadScanResults(ctx): "SONAR_PULL_REQUEST_KEY": "%s" % (ctx.build.ref.replace("refs/pull/", "").split("/")[0]), }) - repo_slug = ctx.build.source_repo if ctx.build.source_repo else ctx.repo.slug + fork_handling = [] + if ctx.build.source_repo: + fork_handling = [ + "git remote add fork https://github.com/%s.git" % (ctx.build.source_repo), + "git pull fork", + ] return { "kind": "pipeline", @@ -375,9 +380,13 @@ def uploadScanResults(ctx): "name": "clone", "image": "alpine/git:latest", "commands": [ - "git clone https://github.com/%s.git ." % (repo_slug), - "git checkout $DRONE_COMMIT", - ], + # Always use the owncloud/ocis repository as base to have an up to date default branch. + # This is needed for the skipIfUnchanged step, since it references a commit on master (which could be absent on a fork) + "git clone https://github.com/%s.git ." % (ctx.repo.slug), + ] + fork_handling + + [ + "git checkout $DRONE_COMMIT", + ], }, ] + skipIfUnchanged(ctx, "unit-tests") + [ { From e436d7d26c4060aadb16c10a9295b3aeb6b4a685 Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Thu, 20 Jan 2022 08:48:28 +0100 Subject: [PATCH 14/15] fetch infos from fork instead of just pulling --- .drone.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.star b/.drone.star index 0d3158102f..f0dffdf63f 100644 --- a/.drone.star +++ b/.drone.star @@ -361,7 +361,7 @@ def uploadScanResults(ctx): if ctx.build.source_repo: fork_handling = [ "git remote add fork https://github.com/%s.git" % (ctx.build.source_repo), - "git pull fork", + "git fetch fork", ] return { From 4f294d589cd44ca3c199ac275c3c92167e0b462f Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Thu, 20 Jan 2022 08:55:18 +0100 Subject: [PATCH 15/15] only trigger fork handling if the repo slugs don't match --- .drone.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.star b/.drone.star index f0dffdf63f..25420c3d34 100644 --- a/.drone.star +++ b/.drone.star @@ -358,7 +358,7 @@ def uploadScanResults(ctx): }) fork_handling = [] - if ctx.build.source_repo: + if ctx.build.source_repo != "" and ctx.build.source_repo != ctx.repo.slug: fork_handling = [ "git remote add fork https://github.com/%s.git" % (ctx.build.source_repo), "git fetch fork",