From b90424655d210b11a8ba878f3ca4f16ae03ccfdd Mon Sep 17 00:00:00 2001 From: Gianmaria Del Monte <39946305+gmgigi96@users.noreply.github.com> Date: Thu, 11 May 2023 15:11:04 +0200 Subject: [PATCH] Implement historical way of constructing OCM WebDAV URL (#3868) * adapt webdav ocm endpoint according to historical way of contructing webdav url * add discovery endpoint in the ocm client * Make root OCM URLs configurable in /ocm-provider * add changelog * fix path for old ocm webdav * Added reverse proxy for /ocm-provider * Revert "Added reverse proxy for /ocm-provider" This reverts commit 1ecb6e4e48910209b790ed5138fce8d007dea788. * Moved ocm-provider to a new http service * Updated examples * Linting * Simplified ocmprovider and documented config * Further simplification + relaunching the CI * Regenerated docs * Expose OCM as disabled if no endpoint is configured for it * Update internal/http/services/owncloud/ocdav/propfind.go Co-authored-by: Giuseppe Lo Presti * Update internal/http/services/owncloud/ocdav/dav.go Co-authored-by: Giuseppe Lo Presti * Update internal/http/services/owncloud/ocdav/dav.go Co-authored-by: Giuseppe Lo Presti * Update internal/http/services/owncloud/ocdav/ocdav.go Co-authored-by: Giuseppe Lo Presti * Update internal/http/services/owncloud/ocdav/propfind.go Co-authored-by: Giuseppe Lo Presti * fix support legacy ocm access --------- Co-authored-by: Giuseppe Lo Presti --- .../expose-historical-ocm-webdav.md | 8 + .../http/services/ocmprovider/_index.md | 66 ++++++++ .../http/services/owncloud/ocdav/_index.md | 2 +- .../packages/auth/manager/oidc/_index.md | 16 +- .../config/packages/cbox/group/rest/_index.md | 18 +- examples/meshdirectory/meshdirectory.toml | 1 + examples/nextcloud-integration/revad.toml | 6 +- examples/oc-phoenix/ocmd.toml | 4 +- examples/ocmd/server-1/ocmd-server-1.toml | 3 + examples/ocmd/server-2/ocmd-server-2.toml | 3 +- examples/oidc-mapping-tpc/server-1.toml | 1 + examples/oidc-mapping-tpc/server-2.toml | 1 + .../notifications.toml | 0 examples/standalone/standalone.toml | 1 + examples/storage-references/gateway.toml | 1 + examples/two-server-setup/gateway-1.toml | 1 + examples/two-server-setup/gateway-2.toml | 1 + internal/http/services/loader/loader.go | 1 + internal/http/services/ocmd/discovery.go | 81 --------- internal/http/services/ocmd/ocm.go | 17 +- .../http/services/ocmprovider/ocmprovider.go | 156 ++++++++++++++++++ internal/http/services/owncloud/ocdav/dav.go | 16 +- .../http/services/owncloud/ocdav/ocdav.go | 1 + .../http/services/owncloud/ocdav/propfind.go | 12 ++ pkg/ocm/client/client.go | 47 ++++++ 25 files changed, 344 insertions(+), 120 deletions(-) create mode 100644 changelog/unreleased/expose-historical-ocm-webdav.md create mode 100644 docs/content/en/docs/config/http/services/ocmprovider/_index.md rename examples/{serverless-example => serverless}/notifications.toml (100%) delete mode 100644 internal/http/services/ocmd/discovery.go create mode 100644 internal/http/services/ocmprovider/ocmprovider.go diff --git a/changelog/unreleased/expose-historical-ocm-webdav.md b/changelog/unreleased/expose-historical-ocm-webdav.md new file mode 100644 index 00000000000..55b47ce051f --- /dev/null +++ b/changelog/unreleased/expose-historical-ocm-webdav.md @@ -0,0 +1,8 @@ +Enhancement: Implement historical way of constructing OCM WebDAV URL + +Expose the expected WebDAV endpoint for OCM by OC10 and Nextcloud as described +in https://github.com/cs3org/OCM-API/issues/70#issuecomment-1538551138 to allow +reva providers to participate to mesh. + +https://github.com/cs3org/reva/pull/3868 +https://github.com/cs3org/reva/issues/3855 \ No newline at end of file diff --git a/docs/content/en/docs/config/http/services/ocmprovider/_index.md b/docs/content/en/docs/config/http/services/ocmprovider/_index.md new file mode 100644 index 00000000000..20e5938918a --- /dev/null +++ b/docs/content/en/docs/config/http/services/ocmprovider/_index.md @@ -0,0 +1,66 @@ +--- +title: "ocmprovider" +linkTitle: "ocmprovider" +weight: 10 +description: > + Configuration for the ocmprovider service +--- + +# _struct: config_ + +{{% dir name="ocm_prefix" type="string" default="ocm" %}} +The prefix URL where the OCM API is served. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L37) +{{< highlight toml >}} +[http.services.ocmprovider] +ocm_prefix = "ocm" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="endpoint" type="string" default="http://localhost" %}} +This host's URL. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L38) +{{< highlight toml >}} +[http.services.ocmprovider] +endpoint = "http://localhost" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="provider" type="string" default="reva" %}} +A friendly name that defines this service. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L39) +{{< highlight toml >}} +[http.services.ocmprovider] +provider = "reva" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="webdav_root" type="string" default="/remote.php/dav/ocm" %}} +The root URL of the WebDAV endpoint to serve OCM shares. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L40) +{{< highlight toml >}} +[http.services.ocmprovider] +webdav_root = "/remote.php/dav/ocm" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="webapp_root" type="string" default="/external/sciencemesh" %}} +The root URL to serve Web apps via OCM. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L41) +{{< highlight toml >}} +[http.services.ocmprovider] +webapp_root = "/external/sciencemesh" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="enable_webapp" type="bool" default=false %}} +Whether web apps are enabled in OCM shares. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L42) +{{< highlight toml >}} +[http.services.ocmprovider] +enable_webapp = false +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="enable_datatx" type="bool" default=false %}} +Whether data transfers are enabled in OCM shares. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L43) +{{< highlight toml >}} +[http.services.ocmprovider] +enable_datatx = false +{{< /highlight >}} +{{% /dir %}} + diff --git a/docs/content/en/docs/config/http/services/owncloud/ocdav/_index.md b/docs/content/en/docs/config/http/services/owncloud/ocdav/_index.md index 887d0acc24b..edeb84444cc 100644 --- a/docs/content/en/docs/config/http/services/owncloud/ocdav/_index.md +++ b/docs/content/en/docs/config/http/services/owncloud/ocdav/_index.md @@ -9,7 +9,7 @@ description: > # _struct: Config_ {{% dir name="insecure" type="bool" default=false %}} -Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/owncloud/ocdav/ocdav.go#L102) +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/owncloud/ocdav/ocdav.go#L103) {{< highlight toml >}} [http.services.owncloud.ocdav] insecure = false diff --git a/docs/content/en/docs/config/packages/auth/manager/oidc/_index.md b/docs/content/en/docs/config/packages/auth/manager/oidc/_index.md index 758a8a14af4..96d81c6d93a 100644 --- a/docs/content/en/docs/config/packages/auth/manager/oidc/_index.md +++ b/docs/content/en/docs/config/packages/auth/manager/oidc/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="insecure" type="bool" default=false %}} -Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L61) +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L63) {{< highlight toml >}} [auth.manager.oidc] insecure = false @@ -17,7 +17,7 @@ insecure = false {{% /dir %}} {{% dir name="issuer" type="string" default="" %}} -The issuer of the OIDC token. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L62) +The issuer of the OIDC token. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L64) {{< highlight toml >}} [auth.manager.oidc] issuer = "" @@ -25,7 +25,7 @@ issuer = "" {{% /dir %}} {{% dir name="id_claim" type="string" default="sub" %}} -The claim containing the ID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L63) +The claim containing the ID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L65) {{< highlight toml >}} [auth.manager.oidc] id_claim = "sub" @@ -33,7 +33,7 @@ id_claim = "sub" {{% /dir %}} {{% dir name="uid_claim" type="string" default="" %}} -The claim containing the UID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L64) +The claim containing the UID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L66) {{< highlight toml >}} [auth.manager.oidc] uid_claim = "" @@ -41,7 +41,7 @@ uid_claim = "" {{% /dir %}} {{% dir name="gid_claim" type="string" default="" %}} -The claim containing the GID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L65) +The claim containing the GID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L67) {{< highlight toml >}} [auth.manager.oidc] gid_claim = "" @@ -49,7 +49,7 @@ gid_claim = "" {{% /dir %}} {{% dir name="gatewaysvc" type="string" default="" %}} -The endpoint at which the GRPC gateway is exposed. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L66) +The endpoint at which the GRPC gateway is exposed. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L68) {{< highlight toml >}} [auth.manager.oidc] gatewaysvc = "" @@ -57,7 +57,7 @@ gatewaysvc = "" {{% /dir %}} {{% dir name="users_mapping" type="string" default="" %}} - The optional OIDC users mapping file path [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L67) + The optional OIDC users mapping file path [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L69) {{< highlight toml >}} [auth.manager.oidc] users_mapping = "" @@ -65,7 +65,7 @@ users_mapping = "" {{% /dir %}} {{% dir name="group_claim" type="string" default="" %}} - The group claim to be looked up to map the user (default to 'groups'). [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L68) + The group claim to be looked up to map the user (default to 'groups'). [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L70) {{< highlight toml >}} [auth.manager.oidc] group_claim = "" diff --git a/docs/content/en/docs/config/packages/cbox/group/rest/_index.md b/docs/content/en/docs/config/packages/cbox/group/rest/_index.md index 4f7bf6bd9a1..36888b42b10 100644 --- a/docs/content/en/docs/config/packages/cbox/group/rest/_index.md +++ b/docs/content/en/docs/config/packages/cbox/group/rest/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="redis_address" type="string" default="localhost:6379" %}} -The address at which the redis server is running [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L54) +The address at which the redis server is running [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L56) {{< highlight toml >}} [cbox.group.rest] redis_address = "localhost:6379" @@ -17,7 +17,7 @@ redis_address = "localhost:6379" {{% /dir %}} {{% dir name="group_members_cache_expiration" type="int" default=5 %}} -The time in minutes for which the members of a group would be cached [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L60) +The time in minutes for which the members of a group would be cached [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L62) {{< highlight toml >}} [cbox.group.rest] group_members_cache_expiration = 5 @@ -25,7 +25,7 @@ group_members_cache_expiration = 5 {{% /dir %}} {{% dir name="id_provider" type="string" default="http://cernbox.cern.ch" %}} -The OIDC Provider [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L62) +The OIDC Provider [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L64) {{< highlight toml >}} [cbox.group.rest] id_provider = "http://cernbox.cern.ch" @@ -33,7 +33,7 @@ id_provider = "http://cernbox.cern.ch" {{% /dir %}} {{% dir name="api_base_url" type="string" default="https://authorization-service-api-dev.web.cern.ch" %}} -Base API Endpoint [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L64) +Base API Endpoint [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L66) {{< highlight toml >}} [cbox.group.rest] api_base_url = "https://authorization-service-api-dev.web.cern.ch" @@ -41,7 +41,7 @@ api_base_url = "https://authorization-service-api-dev.web.cern.ch" {{% /dir %}} {{% dir name="client_id" type="string" default="-" %}} -Client ID needed to authenticate [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L66) +Client ID needed to authenticate [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L68) {{< highlight toml >}} [cbox.group.rest] client_id = "-" @@ -49,7 +49,7 @@ client_id = "-" {{% /dir %}} {{% dir name="client_secret" type="string" default="-" %}} -Client Secret [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L68) +Client Secret [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L70) {{< highlight toml >}} [cbox.group.rest] client_secret = "-" @@ -57,7 +57,7 @@ client_secret = "-" {{% /dir %}} {{% dir name="oidc_token_endpoint" type="string" default="https://keycloak-dev.cern.ch/auth/realms/cern/api-access/token" %}} -Endpoint to generate token to access the API [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L71) +Endpoint to generate token to access the API [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L73) {{< highlight toml >}} [cbox.group.rest] oidc_token_endpoint = "https://keycloak-dev.cern.ch/auth/realms/cern/api-access/token" @@ -65,7 +65,7 @@ oidc_token_endpoint = "https://keycloak-dev.cern.ch/auth/realms/cern/api-access/ {{% /dir %}} {{% dir name="target_api" type="string" default="authorization-service-api" %}} -The target application for which token needs to be generated [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L73) +The target application for which token needs to be generated [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L75) {{< highlight toml >}} [cbox.group.rest] target_api = "authorization-service-api" @@ -73,7 +73,7 @@ target_api = "authorization-service-api" {{% /dir %}} {{% dir name="group_fetch_interval" type="int" default=3600 %}} -The time in seconds between bulk fetch of groups [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L75) +The time in seconds between bulk fetch of groups [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L77) {{< highlight toml >}} [cbox.group.rest] group_fetch_interval = 3600 diff --git a/examples/meshdirectory/meshdirectory.toml b/examples/meshdirectory/meshdirectory.toml index c525e9ad0cc..97110444162 100644 --- a/examples/meshdirectory/meshdirectory.toml +++ b/examples/meshdirectory/meshdirectory.toml @@ -24,6 +24,7 @@ file = "/var/tmp/reva/shares_server_1.json" [http.services.dataprovider] [http.services.prometheus] [http.services.ocmd] +[http.services.ocmprovider] [http.services.ocdav] [http.services.ocs] diff --git a/examples/nextcloud-integration/revad.toml b/examples/nextcloud-integration/revad.toml index f44a43f4fae..b37faacdc8f 100644 --- a/examples/nextcloud-integration/revad.toml +++ b/examples/nextcloud-integration/revad.toml @@ -112,7 +112,7 @@ driver = "nextcloud" endpoint = "http://localhost/apps/sciencemesh/" [http] -enabled_services = ["ocmd"] +enabled_services = ["ocmd", "ocmprovider"] enabled_middlewares = ["providerauthorizer", "cors"] address = "0.0.0.0:19001" @@ -126,9 +126,11 @@ driver = "nextcloud" user_layout = "{{.Username}}" [http.services.ocmd] -prefix = "ocm" + +[http.services.ocmprovider] provider = "Reva-Nextcloud" endpoint = "http://localhost" +webdav_root = "/remote.php/dav/ocm" enable_webapp = true enable_datatx = true diff --git a/examples/oc-phoenix/ocmd.toml b/examples/oc-phoenix/ocmd.toml index 1814c6157fb..0864d48b545 100644 --- a/examples/oc-phoenix/ocmd.toml +++ b/examples/oc-phoenix/ocmd.toml @@ -28,12 +28,14 @@ driver = "json" providers = "providers.demo.json" [http] -enabled_services = ["ocmd"] +enabled_services = ["ocmd", "ocmprovider"] enabled_middlewares = ["providerauthorizer", "cors"] address = "0.0.0.0:13001" [http.services.ocmd] prefix = "ocm" + +[http.services.ocmprovider] endpoint = "http://localhost:13001" [http.middlewares.providerauthorizer] diff --git a/examples/ocmd/server-1/ocmd-server-1.toml b/examples/ocmd/server-1/ocmd-server-1.toml index 7f826f3da8d..5ecf5857454 100644 --- a/examples/ocmd/server-1/ocmd-server-1.toml +++ b/examples/ocmd/server-1/ocmd-server-1.toml @@ -122,6 +122,9 @@ user_layout = "{{.Username}}" [http.services.ocmd] prefix = "ocm" + +[http.services.ocmprovider] +ocm_prefix = "ocm" provider = "reva@cern" endpoint = "http://localhost:19001" enable_webapp = true diff --git a/examples/ocmd/server-2/ocmd-server-2.toml b/examples/ocmd/server-2/ocmd-server-2.toml index 745c46eefad..8ac94f9ba9b 100644 --- a/examples/ocmd/server-2/ocmd-server-2.toml +++ b/examples/ocmd/server-2/ocmd-server-2.toml @@ -112,7 +112,8 @@ driver = "localhome" user_layout = "{{.Username}}" [http.services.ocmd] -prefix = "ocm" + +[http.services.ocmprovider] provider = "reva@cesnet" endpoint = "http://localhost:17001" enable_webapp = true diff --git a/examples/oidc-mapping-tpc/server-1.toml b/examples/oidc-mapping-tpc/server-1.toml index c212892e59c..61248b2a13f 100644 --- a/examples/oidc-mapping-tpc/server-1.toml +++ b/examples/oidc-mapping-tpc/server-1.toml @@ -62,6 +62,7 @@ driver = "localhome" [http.services.datagateway] [http.services.prometheus] [http.services.ocmd] +[http.services.ocmprovider] [http.services.ocs] [http.services.ocdav] enable_http_tpc = true diff --git a/examples/oidc-mapping-tpc/server-2.toml b/examples/oidc-mapping-tpc/server-2.toml index 259c4b77d89..02eaee63bc3 100644 --- a/examples/oidc-mapping-tpc/server-2.toml +++ b/examples/oidc-mapping-tpc/server-2.toml @@ -62,6 +62,7 @@ driver = "localhome" [http.services.datagateway] [http.services.prometheus] [http.services.ocmd] +[http.services.ocmprovider] [http.services.ocs] [http.services.ocdav] enable_http_tpc = true diff --git a/examples/serverless-example/notifications.toml b/examples/serverless/notifications.toml similarity index 100% rename from examples/serverless-example/notifications.toml rename to examples/serverless/notifications.toml diff --git a/examples/standalone/standalone.toml b/examples/standalone/standalone.toml index fe293dbb01f..0b54edd8419 100644 --- a/examples/standalone/standalone.toml +++ b/examples/standalone/standalone.toml @@ -17,5 +17,6 @@ [http.services.dataprovider] [http.services.prometheus] [http.services.ocmd] +[http.services.ocmprovider] [http.services.ocdav] [http.services.ocs] diff --git a/examples/storage-references/gateway.toml b/examples/storage-references/gateway.toml index a8e90d88662..8b887d1d3db 100644 --- a/examples/storage-references/gateway.toml +++ b/examples/storage-references/gateway.toml @@ -44,6 +44,7 @@ mime_types = [ [http.services.datagateway] [http.services.prometheus] [http.services.ocmd] +[http.services.ocmprovider] [http.services.ocdav] [http.services.ocs] [http.services.appprovider] diff --git a/examples/two-server-setup/gateway-1.toml b/examples/two-server-setup/gateway-1.toml index 912b24d043c..4a6990a42a3 100644 --- a/examples/two-server-setup/gateway-1.toml +++ b/examples/two-server-setup/gateway-1.toml @@ -54,6 +54,7 @@ address = "0.0.0.0:19001" [http.services.datagateway] [http.services.prometheus] [http.services.ocmd] +[http.services.ocmprovider] provider = "Reva-Server-1" endpoint = "http://localhost:19001" enable_webapp = true diff --git a/examples/two-server-setup/gateway-2.toml b/examples/two-server-setup/gateway-2.toml index 04186a7e5bd..808ec4c9ed4 100644 --- a/examples/two-server-setup/gateway-2.toml +++ b/examples/two-server-setup/gateway-2.toml @@ -69,6 +69,7 @@ address = "0.0.0.0:29001" [http.services.datagateway] [http.services.prometheus] [http.services.ocmd] +[http.services.ocmprovider] provider = "Reva-Server-2" endpoint = "http://localhost:29001" enable_webapp = true diff --git a/internal/http/services/loader/loader.go b/internal/http/services/loader/loader.go index 87a96be029a..693264c1577 100644 --- a/internal/http/services/loader/loader.go +++ b/internal/http/services/loader/loader.go @@ -30,6 +30,7 @@ import ( _ "github.com/cs3org/reva/internal/http/services/meshdirectory" _ "github.com/cs3org/reva/internal/http/services/metrics" _ "github.com/cs3org/reva/internal/http/services/ocmd" + _ "github.com/cs3org/reva/internal/http/services/ocmprovider" _ "github.com/cs3org/reva/internal/http/services/owncloud/ocdav" _ "github.com/cs3org/reva/internal/http/services/owncloud/ocs" _ "github.com/cs3org/reva/internal/http/services/preferences" diff --git a/internal/http/services/ocmd/discovery.go b/internal/http/services/ocmd/discovery.go deleted file mode 100644 index 891f914cf93..00000000000 --- a/internal/http/services/ocmd/discovery.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2018-2023 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// In applying this license, CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -package ocmd - -import ( - "encoding/json" - "fmt" - "net/http" - - "github.com/cs3org/reva/pkg/appctx" -) - -type discoveryData struct { - Enabled bool `json:"enabled" xml:"enabled"` - APIVersion string `json:"apiVersion" xml:"apiVersion"` - Endpoint string `json:"endPoint" xml:"endPoint"` - Provider string `json:"provider" xml:"provider"` - ResourceTypes []resourceTypes `json:"resourceTypes" xml:"resourceTypes"` - Capabilities []string `json:"capabilities" xml:"capabilities"` -} - -type resourceTypes struct { - Name string `json:"name"` - ShareTypes []string `json:"shareTypes"` - Protocols map[string]string `json:"protocols"` -} - -type discoHandler struct { - d discoveryData -} - -func (h *discoHandler) init(c *config) { - h.d.Enabled = true - h.d.APIVersion = "1.1.0" - h.d.Endpoint = fmt.Sprintf("%s/%s", c.Endpoint, c.Prefix) - h.d.Provider = c.Provider - rtProtos := map[string]string{} - // webdav is always enabled - rtProtos["webdav"] = fmt.Sprintf("%s/remote.php/dav/%s", c.Endpoint, c.Prefix) - if c.EnableWebApp { - rtProtos["webapp"] = fmt.Sprintf("%s/external/sciencemesh", c.Endpoint) - } - if c.EnableDataTx { - rtProtos["datatx"] = fmt.Sprintf("%s/remote.php/dav/%s", c.Endpoint, c.Prefix) - } - h.d.ResourceTypes = []resourceTypes{{ - Name: "file", // so far we only support `file` - ShareTypes: []string{"user"}, // so far we only support `user` - Protocols: rtProtos, // expose the protocols as per configuration - }} - // for now we hardcode the capabilities, as this is currently only advisory - h.d.Capabilities = []string{"/invite-accepted"} -} - -// Send sends the discovery info to the caller. -func (h *discoHandler) Send(w http.ResponseWriter, r *http.Request) { - log := appctx.GetLogger(r.Context()) - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - indentedConf, _ := json.MarshalIndent(h.d, "", " ") - if _, err := w.Write(indentedConf); err != nil { - log.Err(err).Msg("Error writing to ResponseWriter") - } -} diff --git a/internal/http/services/ocmd/ocm.go b/internal/http/services/ocmd/ocm.go index f91f29c4ae9..ab178796f63 100644 --- a/internal/http/services/ocmd/ocm.go +++ b/internal/http/services/ocmd/ocm.go @@ -36,25 +36,14 @@ func init() { type config struct { Prefix string `mapstructure:"prefix"` GatewaySvc string `mapstructure:"gatewaysvc"` - Endpoint string `mapstructure:"endpoint"` - Provider string `mapstructure:"provider"` - EnableWebApp bool `mapstructure:"enable_webapp"` - EnableDataTx bool `mapstructure:"enable_datatx"` ExposeRecipientDisplayName bool `mapstructure:"expose_recipient_display_name"` } func (c *config) init() { c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) - if c.Prefix == "" { c.Prefix = "ocm" } - if c.Endpoint == "" { - c.Endpoint = "http://localhost" - } - if c.Provider == "" { - c.Provider = "reva" - } } type svc struct { @@ -85,12 +74,10 @@ func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) } func (s *svc) routerInit() error { - discoHandler := new(discoHandler) sharesHandler := new(sharesHandler) notificationsHandler := new(notificationsHandler) invitesHandler := new(invitesHandler) - discoHandler.init(s.Conf) if err := sharesHandler.init(s.Conf); err != nil { return err } @@ -99,11 +86,9 @@ func (s *svc) routerInit() error { return err } - s.router.Get("/ocm-provider", discoHandler.Send) s.router.Post("/shares", sharesHandler.CreateShare) s.router.Post("/notifications", notificationsHandler.SendNotification) s.router.Post("/invite-accepted", invitesHandler.AcceptInvite) - return nil } @@ -123,7 +108,7 @@ func (s *svc) Unprotected() []string { func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log := appctx.GetLogger(r.Context()) - log.Debug().Str("path", r.URL.Path).Msg("ocs routing") + log.Debug().Str("path", r.URL.Path).Msg("ocm routing") // unset raw path, otherwise chi uses it to route and then fails to match percent encoded path segments r.URL.RawPath = "" diff --git a/internal/http/services/ocmprovider/ocmprovider.go b/internal/http/services/ocmprovider/ocmprovider.go new file mode 100644 index 00000000000..a88f9e52a01 --- /dev/null +++ b/internal/http/services/ocmprovider/ocmprovider.go @@ -0,0 +1,156 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package ocmprovider + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/mitchellh/mapstructure" + "github.com/rs/zerolog" +) + +func init() { + global.Register("ocmprovider", New) +} + +type config struct { + OCMPrefix string `mapstructure:"ocm_prefix" docs:"ocm;The prefix URL where the OCM API is served."` + Endpoint string `mapstructure:"endpoint" docs:"This host's URL. If it's not configured, it is assumed OCM is not available."` + Provider string `mapstructure:"provider" docs:"reva;A friendly name that defines this service."` + WebdavRoot string `mapstructure:"webdav_root" docs:"/remote.php/dav/ocm;The root URL of the WebDAV endpoint to serve OCM shares."` + WebappRoot string `mapstructure:"webapp_root" docs:"/external/sciencemesh;The root URL to serve Web apps via OCM."` + EnableWebapp bool `mapstructure:"enable_webapp" docs:"false;Whether web apps are enabled in OCM shares."` + EnableDatatx bool `mapstructure:"enable_datatx" docs:"false;Whether data transfers are enabled in OCM shares."` +} + +type discoveryData struct { + Enabled bool `json:"enabled" xml:"enabled"` + APIVersion string `json:"apiVersion" xml:"apiVersion"` + Endpoint string `json:"endPoint" xml:"endPoint"` + Provider string `json:"provider" xml:"provider"` + ResourceTypes []resourceTypes `json:"resourceTypes" xml:"resourceTypes"` + Capabilities []string `json:"capabilities" xml:"capabilities"` +} + +type resourceTypes struct { + Name string `json:"name"` + ShareTypes []string `json:"shareTypes"` + Protocols map[string]string `json:"protocols"` +} + +type svc struct { + data *discoveryData +} + +func (c *config) init() { + if c.OCMPrefix == "" { + c.OCMPrefix = "ocm" + } + if c.Provider == "" { + c.Provider = "reva" + } + if c.WebdavRoot == "" { + c.WebdavRoot = "/remote.php/dav/ocm" + } + if c.WebappRoot == "" { + c.WebappRoot = "/external/sciencemesh" + } +} + +func (c *config) prepare() *discoveryData { + // generates the (static) data structure to be exposed by /ocm-provider + d := &discoveryData{} + if c.Endpoint == "" { + d.Enabled = false + d.Endpoint = "" + d.APIVersion = "1.1.0" + d.Provider = c.Provider + d.ResourceTypes = []resourceTypes{{ + Name: "file", + ShareTypes: []string{}, + Protocols: map[string]string{}, + }} + d.Capabilities = []string{} + return d + } + d.Enabled = true + d.APIVersion = "1.1.0" + d.Endpoint = fmt.Sprintf("%s/%s", c.Endpoint, c.OCMPrefix) + d.Provider = c.Provider + rtProtos := map[string]string{} + // webdav is always enabled + rtProtos["webdav"] = fmt.Sprintf("%s%s", c.Endpoint, c.WebdavRoot) + if c.EnableWebapp { + rtProtos["webapp"] = fmt.Sprintf("%s%s", c.Endpoint, c.WebappRoot) + } + if c.EnableDatatx { + rtProtos["datatx"] = fmt.Sprintf("%s%s", c.Endpoint, c.WebdavRoot) + } + d.ResourceTypes = []resourceTypes{{ + Name: "file", // so far we only support `file` + ShareTypes: []string{"user"}, // so far we only support `user` + Protocols: rtProtos, // expose the protocols as per configuration + }} + // for now we hardcode the capabilities, as this is currently only advisory + d.Capabilities = []string{"/invite-accepted"} + return d +} + +// New returns a new ocmprovider object, that implements +// the OCM discovery endpoint specified in +// https://cs3org.github.io/OCM-API/docs.html?repo=OCM-API&user=cs3org#/paths/~1ocm-provider/get +func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) { + conf := &config{} + if err := mapstructure.Decode(m, conf); err != nil { + return nil, err + } + + conf.init() + return &svc{data: conf.prepare()}, nil +} + +// Close performs cleanup. +func (s *svc) Close() error { + return nil +} + +func (s *svc) Prefix() string { + // this is hardcoded as per OCM specifications + return "/ocm-provider" +} + +func (s *svc) Unprotected() []string { + return []string{"/"} +} + +func (s *svc) Handler() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log := appctx.GetLogger(r.Context()) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + indented, _ := json.MarshalIndent(s.data, "", " ") + if _, err := w.Write(indented); err != nil { + log.Err(err).Msg("Error writing to ResponseWriter") + } + }) +} diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go index 54589c322c2..ca42666023b 100644 --- a/internal/http/services/owncloud/ocdav/dav.go +++ b/internal/http/services/owncloud/ocdav/dav.go @@ -21,6 +21,7 @@ package ocdav import ( "context" "net/http" + "net/url" "path" "strings" @@ -187,7 +188,20 @@ func (h *DavHandler) Handler(s *svc) http.Handler { return } - token, _ := router.ShiftPath(r.URL.Path) + // OC10 and Nextcloud (OCM 1.0) are using basic auth for carrying the + // shared token. + var token string + username, _, ok := r.BasicAuth() + if ok { + // OCM 1.0 + token = username + r.URL.Path, _ = url.JoinPath("/", token, r.URL.Path) + ctx = context.WithValue(ctx, ctxOCM10, true) + } else { + token, _ = router.ShiftPath(r.URL.Path) + ctx = context.WithValue(ctx, ctxOCM10, false) + } + authRes, err := handleOCMAuth(ctx, c, token) switch { case err != nil: diff --git a/internal/http/services/owncloud/ocdav/ocdav.go b/internal/http/services/owncloud/ocdav/ocdav.go index ad608ad67b1..4c029c65602 100644 --- a/internal/http/services/owncloud/ocdav/ocdav.go +++ b/internal/http/services/owncloud/ocdav/ocdav.go @@ -50,6 +50,7 @@ type ctxKey int const ( ctxKeyBaseURI ctxKey = iota + ctxOCM10 ) var ( diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index 3fbd197be64..fda9e06e179 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -43,6 +43,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/publicshare" + "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/share" rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" @@ -501,6 +502,16 @@ func (s *svc) newPropRaw(key, val string) *propertyXML { } } +func supportLegacyOCMAccess(ctx context.Context, md *provider.ResourceInfo) { + ocm10, _ := ctx.Value(ctxOCM10).(bool) + if ocm10 { + // the path is something like //... + // we need to strip the token part as this + // is passed as username in the basic auth + _, md.Path = router.ShiftPath(md.Path) + } +} + // mdToPropResponse converts the CS3 metadata into a webdav PropResponse // ns is the CS3 namespace that needs to be removed from the CS3 path before // prefixing it with the baseURI. @@ -510,6 +521,7 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide baseURI := ctx.Value(ctxKeyBaseURI).(string) + supportLegacyOCMAccess(ctx, md) ref := path.Join(baseURI, md.Path) if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { ref += "/" diff --git a/pkg/ocm/client/client.go b/pkg/ocm/client/client.go index 4f291bd6d69..651129bf5b2 100644 --- a/pkg/ocm/client/client.go +++ b/pkg/ocm/client/client.go @@ -231,3 +231,50 @@ func (c *OCMClient) parseNewShareResponse(r *http.Response) (*NewShareResponse, } return nil, errtypes.InternalError(string(body)) } + +// Capabilities contains a set of properties exposed by +// a remote cloud storage. +type Capabilities struct { + Enabled bool `json:"enabled"` + APIVersion string `json:"apiVersion"` + EndPoint string `json:"endPoint"` + Provider string `json:"provider"` + ResourceTypes []struct { + Name string `json:"name"` + ShareTypes []string `json:"shareTypes"` + Protocols struct { + Webdav *string `json:"webdav"` + Webapp *string `json:"webapp"` + Datatx *string `json:"datatx"` + } `json:"protocols"` + } `json:"resourceTypes"` + Capabilities []string `json:"capabilities"` +} + +// Discovery returns a number of properties used to discover the capabilities offered by a remote cloud storage. +// https://cs3org.github.io/OCM-API/docs.html?branch=develop&repo=OCM-API&user=cs3org#/paths/~1ocm-provider/get +func (c *OCMClient) Discovery(ctx context.Context, endpoint string) (*Capabilities, error) { + url, err := url.JoinPath(endpoint, "shares") + if err != nil { + return nil, err + } + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return nil, errors.Wrap(err, "error creating request") + } + req.Header.Set("Content-Type", "application/json") + + resp, err := c.client.Do(req) + if err != nil { + return nil, errors.Wrap(err, "error doing request") + } + defer resp.Body.Close() + + var cap Capabilities + if err := json.NewDecoder(resp.Body).Decode(&c); err != nil { + return nil, err + } + + return &cap, nil +}