diff --git a/changelog/unreleased/ocm-compat.md b/changelog/unreleased/ocm-compat.md new file mode 100644 index 0000000000..4198ad3563 --- /dev/null +++ b/changelog/unreleased/ocm-compat.md @@ -0,0 +1,7 @@ +Bugfix: OCM-related compatibility fixes + +Following analysis of OC and NC code to access a remote share, +we must expose paths and not full URIs on the /ocm-provider endpoint. +Also we fix a lookup issue with apps over OCM and update examples. + +https://github.com/cs3org/reva/pull/3962 diff --git a/examples/meshdirectory/meshdirectory.toml b/examples/meshdirectory/meshdirectory.toml index 9711044416..1bea8c36e0 100644 --- a/examples/meshdirectory/meshdirectory.toml +++ b/examples/meshdirectory/meshdirectory.toml @@ -65,4 +65,4 @@ timeout = 10 refresh = 900 [http.services.meshdirectory] -mesh_directory_url = 'http://localhost:19001/meshdir/' \ No newline at end of file +mesh_directory_url = 'http://localhost:19001/meshdir/' diff --git a/examples/nextcloud-integration/revad.toml b/examples/nextcloud-integration/revad.toml index b37faacdc8..97288f5cf8 100644 --- a/examples/nextcloud-integration/revad.toml +++ b/examples/nextcloud-integration/revad.toml @@ -7,7 +7,7 @@ address = "0.0.0.0:19000" [grpc.services.gateway] authregistrysvc = "localhost:19000" appprovidersvc = "localhost:19000" -appregistry = "localhost:19000" +appregistrysvc = "localhost:19000" storageregistrysvc = "localhost:19000" preferencessvc = "localhost:19000" userprovidersvc = "localhost:19000" @@ -21,6 +21,29 @@ commit_share_to_storage_grant = false datagateway = "http://localhost:19001/data" transfer_expires = 6 # give it a moment +[grpc.services.appregistry] +driver = "static" + +[grpc.services.appregistry.drivers.static] +mime_types = [ + {"mime_type" = "text/plain", "extension" = "txt", "name" = "Text file", "description" = "Text file", "allow_creation" = true}, + {"mime_type" = "text/markdown", "extension" = "md", "name" = "Markdown file", "description" = "Markdown file", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.text", "extension" = "odt", "name" = "OpenDocument", "description" = "OpenDocument text document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.spreadsheet", "extension" = "ods", "name" = "OpenSpreadsheet", "description" = "OpenDocument spreadsheet document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.presentation", "extension" = "odp", "name" = "OpenPresentation", "description" = "OpenDocument presentation document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.jupyter", "extension" = "ipynb", "name" = "Jupyter Notebook", "description" = "Jupyter Notebook"} +] + +[grpc.services.appprovider] +driver = "wopi" +app_provider_url = "localhost:19000" + +[grpc.services.appprovider.drivers.wopi] +iop_secret = "shared-secret-with-wopiserver" +wopi_url = "http://0.0.0.0:8880/" +app_name = "Collabora" +app_url = "https://your-collabora-server.org:9980" + [grpc.services.authregistry] driver = "static" @@ -65,27 +88,6 @@ providers = "/etc/revad/providers.json" [grpc.services.publicshareprovider] driver = "memory" -[grpc.services.appprovider] -driver = "wopi" -custom_mime_types_json = "custom-mime-types-demo.json" - -[grpc.services.appprovider.drivers.wopi] -iop_secret = "hello" -wopi_url = "http://0.0.0.0:8880/" -app_name = "Collabora" -app_url = "https://your-collabora-server.org:9980" - -[grpc.services.appregistry] -driver = "static" - -[grpc.services.appregistry.static.rules] -"text/plain" = "localhost:19000" -"text/markdown" = "localhost:19000" -"application/compressed-markdown" = "localhost:19000" -"application/vnd.oasis.opendocument.text" = "localhost:19000" -"application/vnd.oasis.opendocument.spreadsheet" = "localhost:19000" -"application/vnd.oasis.opendocument.presentation" = "localhost:19000" - [grpc.services.storageprovider] driver = "nextcloud" mount_path = "/home" @@ -100,7 +102,6 @@ custom_mime_types_json = "custom-mime-types-demo.json" endpoint = "http://localhost/apps/sciencemesh/" user_layout = "{{.Username}}" - [grpc.services.authprovider] auth_manager = "nextcloud" [grpc.services.authprovider.drivers.nextcloud] @@ -112,10 +113,10 @@ driver = "nextcloud" endpoint = "http://localhost/apps/sciencemesh/" [http] -enabled_services = ["ocmd", "ocmprovider"] -enabled_middlewares = ["providerauthorizer", "cors"] address = "0.0.0.0:19001" +[http.services.appprovider] + [http.services.dataprovider] driver = "nextcloud" @@ -134,6 +135,11 @@ webdav_root = "/remote.php/dav/ocm" enable_webapp = true enable_datatx = true +[http.services.sciencemesh] +mesh_directory_url = 'https://sciencemesh.cesnet.cz/iop/meshdir' +provider_domain = 'your-domain.org' +ocm_mount_point = '/sciencemesh' + [http.middlewares.providerauthorizer] driver = "json" diff --git a/examples/oc-phoenix/ocmd.toml b/examples/oc-phoenix/ocmd.toml index 0864d48b54..bd53def4ae 100644 --- a/examples/oc-phoenix/ocmd.toml +++ b/examples/oc-phoenix/ocmd.toml @@ -35,13 +35,10 @@ address = "0.0.0.0:13001" [http.services.ocmd] prefix = "ocm" -[http.services.ocmprovider] -endpoint = "http://localhost:13001" - [http.middlewares.providerauthorizer] driver = "json" [http.middlewares.providerauthorizer.drivers.json] providers = "providers.demo.json" -[http.middlewares.cors] \ No newline at end of file +[http.middlewares.cors] diff --git a/examples/ocmd/server-1/ocmd-server-1.toml b/examples/ocmd/server-1/ocmd-server-1.toml index 5ecf585745..0d9adbf513 100644 --- a/examples/ocmd/server-1/ocmd-server-1.toml +++ b/examples/ocmd/server-1/ocmd-server-1.toml @@ -6,8 +6,7 @@ address = "0.0.0.0:19000" [grpc.services.gateway] authregistrysvc = "localhost:19000" -appprovidersvc = "localhost:19000" -appregistry = "localhost:19000" +appregistrysvc = "localhost:19000" storageregistrysvc = "localhost:19000" preferencessvc = "localhost:19000" userprovidersvc = "localhost:19000" @@ -22,6 +21,29 @@ transfer_expires = 6 # give it a moment commit_share_to_storage_grant = true commit_share_to_storage_ref = true +[grpc.services.appregistry] +driver = "static" + +[grpc.services.appregistry.drivers.static] +mime_types = [ + {"mime_type" = "text/plain", "extension" = "txt", "name" = "Text file", "description" = "Text file", "allow_creation" = true}, + {"mime_type" = "text/markdown", "extension" = "md", "name" = "Markdown file", "description" = "Markdown file", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.text", "extension" = "odt", "name" = "OpenDocument", "description" = "OpenDocument text document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.spreadsheet", "extension" = "ods", "name" = "OpenSpreadsheet", "description" = "OpenDocument spreadsheet document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.presentation", "extension" = "odp", "name" = "OpenPresentation", "description" = "OpenDocument presentation document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.jupyter", "extension" = "ipynb", "name" = "Jupyter Notebook", "description" = "Jupyter Notebook"} +] + +[grpc.services.appprovider] +driver = "wopi" +appregistrysvc = "localhost:19000" + +[grpc.services.appprovider.drivers.wopi] +iop_secret = "shared-secret-with-wopiserver" +wopi_url = "http://0.0.0.0:8880/" +app_name = "Collabora" +app_url = "https://your-collabora-server.org:9980" + [grpc.services.authregistry] driver = "static" @@ -111,6 +133,8 @@ users = "users.demo.json" [http] address = "0.0.0.0:19001" +[http.services.appprovider] + [http.services.dataprovider] driver = "localhome" @@ -141,6 +165,13 @@ prefix = "ocs" [http.services.ocdav] -[http.services.appprovider] +[http.services.sciencemesh] +mesh_directory_url = 'https://sciencemesh.cesnet.cz/iop/meshdir' +provider_domain = 'your-domain-1.org' +ocm_mount_point = '/sciencemesh' [http.middlewares.cors] + +[http.middlewares.auth] +credential_chain = ["publicshares", "ocmshares", "basic", "bearer"] + diff --git a/examples/ocmd/server-2/ocmd-server-2.toml b/examples/ocmd/server-2/ocmd-server-2.toml index 8ac94f9ba9..755d00116e 100644 --- a/examples/ocmd/server-2/ocmd-server-2.toml +++ b/examples/ocmd/server-2/ocmd-server-2.toml @@ -6,6 +6,7 @@ address = "0.0.0.0:17000" [grpc.services.gateway] authregistrysvc = "localhost:17000" +appregistrysvc = "localhost:17000" storageregistrysvc = "localhost:17000" preferencessvc = "localhost:17000" userprovidersvc = "localhost:17000" @@ -20,6 +21,29 @@ transfer_expires = 6 # give it a moment commit_share_to_storage_grant = true commit_share_to_storage_ref = true +[grpc.services.appregistry] +driver = "static" + +[grpc.services.appregistry.drivers.static] +mime_types = [ + {"mime_type" = "text/plain", "extension" = "txt", "name" = "Text file", "description" = "Text file", "allow_creation" = true}, + {"mime_type" = "text/markdown", "extension" = "md", "name" = "Markdown file", "description" = "Markdown file", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.text", "extension" = "odt", "name" = "OpenDocument", "description" = "OpenDocument text document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.spreadsheet", "extension" = "ods", "name" = "OpenSpreadsheet", "description" = "OpenDocument spreadsheet document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.presentation", "extension" = "odp", "name" = "OpenPresentation", "description" = "OpenDocument presentation document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.jupyter", "extension" = "ipynb", "name" = "Jupyter Notebook", "description" = "Jupyter Notebook"} +] + +[grpc.services.appprovider] +driver = "wopi" +app_provider_url = "localhost:17000" + +[grpc.services.appprovider.drivers.wopi] +iop_secret = "shared-secret-with-wopiserver" +wopi_url = "http://0.0.0.0:8880/" +app_name = "Collabora" +app_url = "https://your-collabora-server.org:9980" + [grpc.services.authregistry] driver = "static" @@ -102,6 +126,8 @@ users = "users.demo.json" [http] address = "0.0.0.0:17001" +[http.services.appprovider] + [http.services.dataprovider] driver = "localhome" @@ -130,4 +156,13 @@ prefix = "ocs" [http.services.ocdav] +[http.services.sciencemesh] +mesh_directory_url = 'https://sciencemesh.cesnet.cz/iop/meshdir' +provider_domain = 'your-domain.org' +ocm_mount_point = '/sciencemesh' + [http.middlewares.cors] + +[http.middlewares.auth] +credential_chain = ["publicshares", "ocmshares", "basic", "bearer"] + diff --git a/examples/oidc-mapping-tpc/server-1.toml b/examples/oidc-mapping-tpc/server-1.toml index 61248b2a13..c212892e59 100644 --- a/examples/oidc-mapping-tpc/server-1.toml +++ b/examples/oidc-mapping-tpc/server-1.toml @@ -62,7 +62,6 @@ 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 02eaee63bc..259c4b77d8 100644 --- a/examples/oidc-mapping-tpc/server-2.toml +++ b/examples/oidc-mapping-tpc/server-2.toml @@ -62,7 +62,6 @@ 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/storage-references/gateway.toml b/examples/storage-references/gateway.toml index 3070078503..0cbed478ae 100644 --- a/examples/storage-references/gateway.toml +++ b/examples/storage-references/gateway.toml @@ -31,6 +31,8 @@ appauth = "localhost:15000" [grpc.services.ocmproviderauthorizer] [grpc.services.appregistry] +driver = "static" + [grpc.services.appregistry.drivers.static] mime_types = [ {"mime_type" = "text/plain", "extension" = "txt", "name" = "Text file", "description" = "Text file", "allow_creation" = true}, @@ -41,13 +43,23 @@ mime_types = [ {"mime_type" = "application/vnd.jupyter", "extension" = "ipynb", "name" = "Jupyter Notebook", "description" = "Jupyter Notebook"} ] +[grpc.services.appprovider] +driver = "wopi" +appregistrysvc = "localhost:19000" +custom_mime_types_json = "/etc/revad/custom-mime-types-demo.json" + +[grpc.services.appprovider.drivers.wopi] +iop_secret = "shared-secret-with-wopiserver" +wopi_url = "http://0.0.0.0:8880/" +app_name = "Collabora" +app_url = "https://your-collabora-server.org:9980" + [http.services.datagateway] [http.services.prometheus] [http.services.ocmd] [http.services.ocmprovider] [http.services.ocdav] [http.services.ocs] -[http.services.appprovider] [http.services.sciencemesh] mesh_directory_url = 'https://sciencemesh.cesnet.cz/iop/meshdir' @@ -60,4 +72,3 @@ disable_auth = true sender_mail = "sciencemesh@your-domain.org" smtp_server = "your-smtp-server.your-domain.org" smtp_port = 25 - diff --git a/examples/two-server-setup/gateway-1.toml b/examples/two-server-setup/gateway-1.toml index 4a6990a42a..6421454da3 100644 --- a/examples/two-server-setup/gateway-1.toml +++ b/examples/two-server-setup/gateway-1.toml @@ -1,11 +1,51 @@ +[shared] +gatewaysvc = "localhost:19000" +datagateway = "http://localhost:19001/datagateway" + [grpc] address = "0.0.0.0:19000" # services to enable [grpc.services.gateway] +authregistrysvc = "localhost:19000" +appregistrysvc = "localhost:19000" +storageregistrysvc = "localhost:19000" +preferencessvc = "localhost:19000" +userprovidersvc = "localhost:19000" +groupprovidersvc = "localhost:19000" +usershareprovidersvc = "localhost:19000" +publicshareprovidersvc = "localhost:19000" +ocmcoresvc = "localhost:19000" +ocmshareprovidersvc = "localhost:19000" +ocminvitemanagersvc = "localhost:19000" +ocmproviderauthorizersvc = "localhost:19000" +datagateway = "http://localhost:19001/data" commit_share_to_storage_grant = true commit_share_to_storage_ref = true +[grpc.services.appregistry] +driver = "static" + +[grpc.services.appregistry.drivers.static] +mime_types = [ + {"mime_type" = "text/plain", "extension" = "txt", "name" = "Text file", "description" = "Text file", "allow_creation" = true}, + {"mime_type" = "text/markdown", "extension" = "md", "name" = "Markdown file", "description" = "Markdown file", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.text", "extension" = "odt", "name" = "OpenDocument", "description" = "OpenDocument text document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.spreadsheet", "extension" = "ods", "name" = "OpenSpreadsheet", "description" = "OpenDocument spreadsheet document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.presentation", "extension" = "odp", "name" = "OpenPresentation", "description" = "OpenDocument presentation document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.jupyter", "extension" = "ipynb", "name" = "Jupyter Notebook", "description" = "Jupyter Notebook"} +] + +[grpc.services.appprovider] +driver = "wopi" +app_provider_url = "localhost:19000" + +[grpc.services.appprovider.drivers.wopi] +iop_secret = "shared-secret-with-wopiserver" +wopi_url = "http://0.0.0.0:8880/" +app_name = "Collabora" +app_url = "https://your-collabora-server.org:9980" + [grpc.services.storageregistry] [grpc.services.storageregistry.drivers.static] home_provider = "/home" @@ -51,6 +91,7 @@ providers = "providers.demo.json" [http] address = "0.0.0.0:19001" +[http.services.appprovider] [http.services.datagateway] [http.services.prometheus] [http.services.ocmd] @@ -62,6 +103,10 @@ enable_datatx = true [http.services.ocdav] [http.services.ocs] +[http.services.sciencemesh] +mesh_directory_url = 'https://sciencemesh.cesnet.cz/iop/meshdir' +provider_domain = 'your-domain.org' +ocm_mount_point = '/sciencemesh' [http.middlewares.providerauthorizer.drivers.json] providers = "providers.demo.json" diff --git a/examples/two-server-setup/gateway-2.toml b/examples/two-server-setup/gateway-2.toml index 808ec4c9ed..65aa63a30f 100644 --- a/examples/two-server-setup/gateway-2.toml +++ b/examples/two-server-setup/gateway-2.toml @@ -8,6 +8,7 @@ address = "0.0.0.0:29000" # services to enable [grpc.services.gateway] authregistrysvc = "localhost:29000" +appregistrysvc = "localhost:29000" storageregistrysvc = "localhost:29000" preferencessvc = "localhost:29000" userprovidersvc = "localhost:29000" @@ -18,9 +19,33 @@ ocmcoresvc = "localhost:29000" ocmshareprovidersvc = "localhost:29000" ocminvitemanagersvc = "localhost:29000" ocmproviderauthorizersvc = "localhost:29000" +datagateway = "http://localhost:29001/data" commit_share_to_storage_grant = true commit_share_to_storage_ref = true +[grpc.services.appregistry] +driver = "static" + +[grpc.services.appregistry.drivers.static] +mime_types = [ + {"mime_type" = "text/plain", "extension" = "txt", "name" = "Text file", "description" = "Text file", "allow_creation" = true}, + {"mime_type" = "text/markdown", "extension" = "md", "name" = "Markdown file", "description" = "Markdown file", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.text", "extension" = "odt", "name" = "OpenDocument", "description" = "OpenDocument text document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.spreadsheet", "extension" = "ods", "name" = "OpenSpreadsheet", "description" = "OpenDocument spreadsheet document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.oasis.opendocument.presentation", "extension" = "odp", "name" = "OpenPresentation", "description" = "OpenDocument presentation document", "default_app" = "Collabora", "allow_creation" = true}, + {"mime_type" = "application/vnd.jupyter", "extension" = "ipynb", "name" = "Jupyter Notebook", "description" = "Jupyter Notebook"} +] + +[grpc.services.appprovider] +driver = "wopi" +appregistrysvc = "localhost:29000" + +[grpc.services.appprovider.drivers.wopi] +iop_secret = "shared-secret-with-wopiserver" +wopi_url = "http://0.0.0.0:8880/" +app_name = "Collabora" +app_url = "https://your-collabora-server.org:9980" + [grpc.services.storageregistry] [grpc.services.storageregistry.drivers.static] home_provider = "/home" @@ -66,6 +91,7 @@ providers = "providers.demo.json" [http] address = "0.0.0.0:29001" +[http.services.appprovider] [http.services.datagateway] [http.services.prometheus] [http.services.ocmd] @@ -78,5 +104,10 @@ enable_datatx = true [http.services.ocdav] [http.services.ocs] +[http.services.sciencemesh] +mesh_directory_url = 'https://sciencemesh.cesnet.cz/iop/meshdir' +provider_domain = 'your-domain.org' +ocm_mount_point = '/sciencemesh' + [http.middlewares.providerauthorizer.drivers.json] providers = "providers.demo.json" diff --git a/internal/http/services/ocmd/notifications.go b/internal/http/services/ocmd/notifications.go new file mode 100644 index 0000000000..7f2249f074 --- /dev/null +++ b/internal/http/services/ocmd/notifications.go @@ -0,0 +1,106 @@ +// 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 ( + "io" + "mime" + "net/http" + + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + + "github.com/cs3org/reva/internal/http/services/reqres" + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/rgrpc/todo/pool" +) + +// var validate = validator.New() + +type notifHandler struct { + gatewayClient gateway.GatewayAPIClient +} + +func (h *notifHandler) init(c *config) error { + var err error + h.gatewayClient, err = pool.GetGatewayServiceClient(pool.Endpoint(c.GatewaySvc)) + if err != nil { + return err + } + return nil +} + +// type notificationRequest struct { +// NotificationType string `json:"notificationType" validate:"required"` +// ResourceType string `json:"resourceType" validate:"required"` +// ProviderId string `json:"providerId" validate:"required"` +// Notification ... `json:"notification"` +//} + +// Example of payload from Nextcloud: +// { +// "notificationType": , +// "resourceType" : "file", +// "providerId" : , +// "notification" : { +// "sharedSecret" : , +// "message" : "human-readable message", +// "shareWith" : , +// "senderId" : , +// "shareType" : +// } +// } + +// Notifications dispatches any notifications received from remote OCM sites +// according to the specifications at: +// https://cs3org.github.io/OCM-API/docs.html?branch=v1.1.0&repo=OCM-API&user=cs3org#/paths/~1notifications/post +func (h *notifHandler) Notifications(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + log := appctx.GetLogger(ctx) + req, err := getNotification(r) + if err != nil { + reqres.WriteError(w, r, reqres.APIErrorInvalidParameter, err.Error(), nil) + return + } + + // TODO(lopresti) this is all to be implemented. For now we just log what we got + log.Debug().Msgf("Received OCM notification: %+v", req) + + // this is to please Nextcloud + w.WriteHeader(http.StatusCreated) +} + +func getNotification(r *http.Request) (string, error) { // (*notificationRequest, error) + // var req notificationRequest + contentType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) + if err == nil && contentType == "application/json" { + bytes, _ := io.ReadAll(r.Body) + return string(bytes), nil + // if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + // return nil, err + //} + // } else { + // return nil, errors.New("body request not recognised") + } + return "", nil + // validate the request + // if err := validate.Struct(req); err != nil { + // return nil, err + //} + // return &req, nil +} diff --git a/internal/http/services/ocmd/ocm.go b/internal/http/services/ocmd/ocm.go index fa92fb4121..8cbb4821a0 100644 --- a/internal/http/services/ocmd/ocm.go +++ b/internal/http/services/ocmd/ocm.go @@ -76,6 +76,7 @@ func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) func (s *svc) routerInit() error { sharesHandler := new(sharesHandler) invitesHandler := new(invitesHandler) + notifHandler := new(notifHandler) if err := sharesHandler.init(s.Conf); err != nil { return err @@ -83,9 +84,13 @@ func (s *svc) routerInit() error { if err := invitesHandler.init(s.Conf); err != nil { return err } + if err := notifHandler.init(s.Conf); err != nil { + return err + } s.router.Post("/shares", sharesHandler.CreateShare) s.router.Post("/invite-accepted", invitesHandler.AcceptInvite) + s.router.Post("/notifications", notifHandler.Notifications) return nil } @@ -99,7 +104,7 @@ func (s *svc) Prefix() string { } func (s *svc) Unprotected() []string { - return []string{"/invite-accepted", "/shares", "/ocm-provider", "/notifications"} + return []string{"/invite-accepted", "/shares", "/notifications"} } func (s *svc) Handler() http.Handler { diff --git a/internal/http/services/ocmprovider/ocmprovider.go b/internal/http/services/ocmprovider/ocmprovider.go index a88f9e52a0..8ed83cf116 100644 --- a/internal/http/services/ocmprovider/ocmprovider.go +++ b/internal/http/services/ocmprovider/ocmprovider.go @@ -70,10 +70,16 @@ func (c *config) init() { c.Provider = "reva" } if c.WebdavRoot == "" { - c.WebdavRoot = "/remote.php/dav/ocm" + c.WebdavRoot = "/remote.php/dav/ocm/" + } + if c.WebdavRoot[len(c.WebdavRoot)-1:] != "/" { + c.WebdavRoot += "/" } if c.WebappRoot == "" { - c.WebappRoot = "/external/sciencemesh" + c.WebappRoot = "/external/sciencemesh/" + } + if c.WebappRoot[len(c.WebappRoot)-1:] != "/" { + c.WebappRoot += "/" } } @@ -99,12 +105,12 @@ func (c *config) prepare() *discoveryData { d.Provider = c.Provider rtProtos := map[string]string{} // webdav is always enabled - rtProtos["webdav"] = fmt.Sprintf("%s%s", c.Endpoint, c.WebdavRoot) + rtProtos["webdav"] = c.WebdavRoot if c.EnableWebapp { - rtProtos["webapp"] = fmt.Sprintf("%s%s", c.Endpoint, c.WebappRoot) + rtProtos["webapp"] = c.WebappRoot } if c.EnableDatatx { - rtProtos["datatx"] = fmt.Sprintf("%s%s", c.Endpoint, c.WebdavRoot) + rtProtos["datatx"] = c.WebdavRoot } d.ResourceTypes = []resourceTypes{{ Name: "file", // so far we only support `file` @@ -148,6 +154,12 @@ func (s *svc) Handler() http.Handler { log := appctx.GetLogger(r.Context()) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) + if r.UserAgent() == "Nextcloud Server Crawler" { + // TODO(lopresti) remove this hack once Nextcloud is able to talk OCM! + s.data.APIVersion = "1.0-proposal1" + } else { + s.data.APIVersion = "1.1.0" + } indented, _ := json.MarshalIndent(s.data, "", " ") if _, err := w.Write(indented); err != nil { log.Err(err).Msg("Error writing to ResponseWriter") diff --git a/pkg/app/provider/wopi/wopi.go b/pkg/app/provider/wopi/wopi.go index 640e0319f2..b3bfd46415 100644 --- a/pkg/app/provider/wopi/wopi.go +++ b/pkg/app/provider/wopi/wopi.go @@ -51,6 +51,7 @@ import ( "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" + gomime "github.com/glpatcern/go-mime" "github.com/golang-jwt/jwt" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" @@ -192,7 +193,7 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc ut = anonymous rPath, pathErr = getPathForExternalLink(ctx, scopes, resource, publicLinkURLPrefix) if pathErr != nil { - log.Warn().Err(pathErr).Msg("wopi: failed to extract relative path from public link scope") + log.Warn().Interface("resId", resource.Id).Interface("path", resource.Path).Err(pathErr).Msg("wopi: failed to extract relative path from public link scope") } case ocmrole: // OCM users have no username: use displayname@Idp @@ -201,7 +202,21 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc // and resolve the folder rPath, pathErr = getPathForExternalLink(ctx, scopes, resource, ocmLinkURLPrefix) if pathErr != nil { - log.Warn().Err(pathErr).Msg("wopi: failed to extract relative path from ocm link scope") + log.Warn().Interface("resId", resource.Id).Interface("path", resource.Path).Err(pathErr).Msg("wopi: failed to extract relative path from ocm link scope") + } + if ext == "" { + // this is a single-file share, and we have to re-resolve the extension from the mime type + exts := gomime.ExtensionsByType(resource.MimeType) + for _, e := range exts { + if len(e) < len(ext) || len(ext) == 0 { + ext = e // heuristically we know we want the shortest file extension + } + } + ext = "." + ext + log.Debug().Interface("mime", resource.MimeType).Interface("ext", ext).Msg("wopi: resolved extension for single-file OCM share") + } + if ext == "" { + return nil, errors.New("wopi: failed to resolve extension from OCM file's mime type %s" + resource.MimeType) } default: // in all other cases use the resource's path @@ -246,7 +261,7 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc q.Add("appurl", viewAppURL) } if q.Get("appurl") == "" && q.Get("appviewurl") == "" { - return nil, errors.New("wopi: neither edit nor view app url found") + return nil, errors.New("wopi: neither edit nor view app url found for type " + ext) } if p.conf.AppIntURL != "" { q.Add("appinturl", p.conf.AppIntURL) @@ -532,17 +547,17 @@ func getPathForExternalLink(ctx context.Context, scopes map[string]*authpb.Scope return "", err } - if statRes.Info.Path == resource.Path { + if statRes.Info.Path == resource.Path || utils.ResourceIDEqual(statRes.Info.Id, resource.Id) { // this is a direct link to the resource return pathPrefix + token, nil } - // otherwise we are in a subfolder of the public link + // otherwise we are in a subfolder of the link relPath, err := filepath.Rel(statRes.Info.Path, resource.Path) if err != nil { return "", err } if strings.HasPrefix(relPath, "../") { - return "", errors.New("Scope path does not contain target resource") + return "", errors.New("Scope path does not contain target resource path " + statRes.Info.Path) } return path.Join(pathPrefix+token, path.Dir(relPath)), nil }