diff --git a/services/collaboration/README.md b/services/collaboration/README.md index 3983ac45e1..4a446fec2e 100644 --- a/services/collaboration/README.md +++ b/services/collaboration/README.md @@ -52,6 +52,11 @@ There are a few variables that you need to set: * `COLLABORATION_WOPI_ENABLE_MOBILE`:\ Enables the mobile web view of the office web frontend. Only applies to EuroOffice. `ce` offers the mobile view for reading only, `de` and `ee` also for editing, so set `COLLABORATION_APP_PRODUCT_EDITION` accordingly. +* `COLLABORATION_WOPI_DISABLED_EXTENSIONS`:\ + A comma separated list of file extensions the app must not offer, even though the document server announces them.\ + The webUI offers no editor of this app for them and opening such a file with it fails.\ + For example: `COLLABORATION_WOPI_DISABLED_EXTENSIONS=docx,xlsx,pptx`. + The application can be customized further by changing the `COLLABORATION_APP_*` options to better describe the application. ## Storing diff --git a/services/collaboration/pkg/config/wopi.go b/services/collaboration/pkg/config/wopi.go index b8ca0f09ee..572f993c5d 100644 --- a/services/collaboration/pkg/config/wopi.go +++ b/services/collaboration/pkg/config/wopi.go @@ -10,4 +10,6 @@ type Wopi struct { ShortTokens bool `yaml:"short_tokens" env:"COLLABORATION_WOPI_SHORTTOKENS" desc:"Use short access tokens for WOPI access. This is useful for office packages, like Microsoft Office Online, which have URL length restrictions. If enabled, a persistent store must be configured." introductionVersion:"1.0.0"` EnableMobile bool `yaml:"enable_mobile" env:"COLLABORATION_WOPI_ENABLE_MOBILE" desc:"Enable the mobile web view of the office web frontend. This feature applies to EuroOffice, where the product edition decides whether it covers editing as well." introductionVersion:"%%NEXT%%"` + + DisabledExtensions []string `yaml:"disabled_extensions" env:"COLLABORATION_WOPI_DISABLED_EXTENSIONS" desc:"A comma separated list of file extensions the office web frontend must not offer, for example 'docx,xlsx'. Extensions are matched case-insensitively, with or without the leading dot." introductionVersion:"%%NEXT%%"` } diff --git a/services/collaboration/pkg/helpers/discovery.go b/services/collaboration/pkg/helpers/discovery.go index a2c1834a49..cc417382fa 100644 --- a/services/collaboration/pkg/helpers/discovery.go +++ b/services/collaboration/pkg/helpers/discovery.go @@ -110,7 +110,7 @@ func GetAppURLs(cfg *config.Config, logger log.Logger) (map[string]map[string]st var appURLs map[string]map[string]string - appURLs, err = parseWopiDiscovery(httpResp.Body) + appURLs, err = parseWopiDiscovery(httpResp.Body, cfg.Wopi.DisabledExtensions) if err != nil { logger.Error(). Err(err). @@ -123,10 +123,16 @@ func GetAppURLs(cfg *config.Config, logger log.Logger) (map[string]map[string]st return appURLs, nil } -// parseWopiDiscovery parses the response of the "/hosting/discovery" endpoint -func parseWopiDiscovery(body io.Reader) (map[string]map[string]string, error) { +// parseWopiDiscovery parses the response of the "/hosting/discovery" endpoint. +// Extensions listed in disabledExtensions are left out. +func parseWopiDiscovery(body io.Reader, disabledExtensions []string) (map[string]map[string]string, error) { appURLs := make(map[string]map[string]string) + disabled := make(map[string]struct{}, len(disabledExtensions)) + for _, ext := range disabledExtensions { + disabled[strings.ToLower(strings.TrimPrefix(strings.TrimSpace(ext), "."))] = struct{}{} + } + doc := etree.NewDocument() if _, err := doc.ReadFrom(body); err != nil { return nil, err @@ -147,6 +153,10 @@ func parseWopiDiscovery(body io.Reader) (map[string]map[string]string, error) { continue } + if _, ok := disabled[strings.ToLower(ext)]; ok { + continue + } + u, err := url.Parse(urlString) if err != nil { continue diff --git a/services/collaboration/pkg/helpers/discovery_test.go b/services/collaboration/pkg/helpers/discovery_test.go index 8416e032e1..7fa5065b84 100644 --- a/services/collaboration/pkg/helpers/discovery_test.go +++ b/services/collaboration/pkg/helpers/discovery_test.go @@ -366,6 +366,32 @@ var _ = Describe("Discovery", func() { Expect(appUrls).To(Equal(expectedAppUrls)) }) + It("Skips the disabled extensions", func() { + cfg := &config.Config{ + App: config.App{ + Addr: srv.URL + "/good", + Insecure: true, + }, + Wopi: config.Wopi{ + // written the way an admin might, the match ignores dot and case + DisabledExtensions: []string{"docx", ".DJVU", " xls ", "odt"}, + }, + } + logger := log.NopLogger() + + appUrls, err := helpers.GetAppURLs(cfg, logger) + + expectedAppUrls := map[string]map[string]string{ + "view": { + ".pdf": "https://cloud.opencloud.test/hosting/wopi/word/view", + ".xlsb": "https://cloud.opencloud.test/hosting/wopi/cell/view", + }, + } + + Expect(err).To(Succeed()) + Expect(appUrls).To(Equal(expectedAppUrls)) + }) + It("Wrong discovery URL", func() { cfg := &config.Config{ App: config.App{