diff --git a/docs/full-configuration.md b/docs/full-configuration.md index 93f34bfa..881e786d 100644 --- a/docs/full-configuration.md +++ b/docs/full-configuration.md @@ -321,9 +321,6 @@ The configuration file contains the following sections: - `client_ip_header_depth`, integer. Some client IP headers such as `X-Forwarded-For` can contain multiple IP address, this setting define the position to trust starting from the right. For example if we have: `10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1` and the depth is `0`, SFTPGo will use `13.0.0.1` as client IP, if depth is `1`, `12.0.0.1` will be used and so on. Default: `0`. - `hide_login_url`, integer. If both web admin and web client are enabled each login page will show a link to the other one. This setting allows to hide this link. 0 means that the login links are displayed on both admin and client login page. This is the default. 1 means that the login link to the web client login page is hidden on admin login page. 2 means that the login link to the web admin login page is hidden on client login page. The flags can be combined, for example 3 will disable both login links. - `render_openapi`, boolean. Set to `false` to disable serving of the OpenAPI schema and renderer. Default `true`. - - `web_client_integrations`, list of struct. The SFTPGo web client allows to send the files with the specified extensions to the configured URL using the [postMessage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage). This way you can integrate your own file viewer or editor. Take a look at the commentented example [here](../examples/webclient-integrations/test.html) to understand how to use this feature. Each struct has the following fields: - - `file_extensions`, list of strings. File extensions must be specified with the leading dot, for example `.pdf`. - - `url`, string. URL to open for the configured file extensions. The url will open in a new tab. - `oidc`, struct. Defines the OpenID connect configuration. OpenID integration allows you to map your identity provider users to SFTPGo users and so you can login to SFTPGo Web Client and Web Admin user interfaces using your identity provider. The following fields are supported: - `config_url`, string. Identifier for the service. If defined, SFTPGo will add `/.well-known/openid-configuration` to this url and attempt to retrieve the provider configuration on startup. SFTPGo will refuse to start if it fails to connect to the specified URL. Default: blank. - `client_id`, string. Defines the application's ID. Default: blank. diff --git a/examples/webclient-integrations/test.html b/examples/webclient-integrations/test.html deleted file mode 100644 index 15148f67..00000000 --- a/examples/webclient-integrations/test.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - SFTPGo WebClient - External integration test - - - - -
- -
- -

- Logs -

-
-    
-    
-
diff --git a/go.mod b/go.mod
index 3af84afa..c325de5c 100644
--- a/go.mod
+++ b/go.mod
@@ -56,7 +56,7 @@ require (
 	github.com/sftpgo/sdk v0.1.6-0.20231011150824-e8d35102c725
 	github.com/shirou/gopsutil/v3 v3.23.10
 	github.com/spf13/afero v1.10.0
-	github.com/spf13/cobra v1.7.0
+	github.com/spf13/cobra v1.8.0
 	github.com/spf13/viper v1.17.0
 	github.com/stretchr/testify v1.8.4
 	github.com/studio-b12/gowebdav v0.9.0
diff --git a/go.sum b/go.sum
index ac23d575..1d7f2f82 100644
--- a/go.sum
+++ b/go.sum
@@ -140,7 +140,6 @@ github.com/coreos/go-oidc/v3 v3.7.0 h1:FTdj0uexT4diYIPlF4yoFVI5MRO1r5+SEcIpEw9vC
 github.com/coreos/go-oidc/v3 v3.7.0/go.mod h1:yQzSCqBnK3e6Fs5l+f5i0F8Kwf0zpH9bPEsbY00KanM=
 github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
 github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -460,8 +459,8 @@ github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
 github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
 github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
-github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
diff --git a/internal/config/config.go b/internal/config/config.go
index 1d2aa177..136f9966 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -100,25 +100,24 @@ var (
 		DisableWWWAuthHeader: false,
 	}
 	defaultHTTPDBinding = httpd.Binding{
-		Address:               "",
-		Port:                  8080,
-		EnableWebAdmin:        true,
-		EnableWebClient:       true,
-		EnableRESTAPI:         true,
-		EnabledLoginMethods:   0,
-		EnableHTTPS:           false,
-		CertificateFile:       "",
-		CertificateKeyFile:    "",
-		MinTLSVersion:         12,
-		ClientAuthType:        0,
-		TLSCipherSuites:       nil,
-		Protocols:             nil,
-		ProxyAllowed:          nil,
-		ClientIPProxyHeader:   "",
-		ClientIPHeaderDepth:   0,
-		HideLoginURL:          0,
-		RenderOpenAPI:         true,
-		WebClientIntegrations: nil,
+		Address:             "",
+		Port:                8080,
+		EnableWebAdmin:      true,
+		EnableWebClient:     true,
+		EnableRESTAPI:       true,
+		EnabledLoginMethods: 0,
+		EnableHTTPS:         false,
+		CertificateFile:     "",
+		CertificateKeyFile:  "",
+		MinTLSVersion:       12,
+		ClientAuthType:      0,
+		TLSCipherSuites:     nil,
+		Protocols:           nil,
+		ProxyAllowed:        nil,
+		ClientIPProxyHeader: "",
+		ClientIPHeaderDepth: 0,
+		HideLoginURL:        0,
+		RenderOpenAPI:       true,
 		OIDC: httpd.OIDC{
 			ClientID:                   "",
 			ClientSecret:               "",
@@ -1707,44 +1706,6 @@ func getHTTPDBrandingFromEnv(idx int) (httpd.Branding, bool) {
 	return result, isSet
 }
 
-func getHTTPDWebClientIntegrationsFromEnv(idx int) []httpd.WebClientIntegration {
-	var integrations []httpd.WebClientIntegration
-	if len(globalConf.HTTPDConfig.Bindings) > idx {
-		integrations = globalConf.HTTPDConfig.Bindings[idx].WebClientIntegrations
-	}
-
-	for subIdx := 0; subIdx < 10; subIdx++ {
-		var integration httpd.WebClientIntegration
-		var replace bool
-		if len(globalConf.HTTPDConfig.Bindings) > idx &&
-			len(globalConf.HTTPDConfig.Bindings[idx].WebClientIntegrations) > subIdx {
-			integration = integrations[subIdx]
-			replace = true
-		}
-
-		url, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__WEB_CLIENT_INTEGRATIONS__%v__URL", idx, subIdx))
-		if ok {
-			integration.URL = url
-		}
-
-		extensions, ok := lookupStringListFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__WEB_CLIENT_INTEGRATIONS__%v__FILE_EXTENSIONS",
-			idx, subIdx))
-		if ok {
-			integration.FileExtensions = extensions
-		}
-
-		if integration.URL != "" && len(integration.FileExtensions) > 0 {
-			if replace {
-				integrations[subIdx] = integration
-			} else {
-				integrations = append(integrations, integration)
-			}
-		}
-	}
-
-	return integrations
-}
-
 func getDefaultHTTPBinding(idx int) httpd.Binding {
 	binding := defaultHTTPDBinding
 	if len(globalConf.HTTPDConfig.Bindings) > idx {
@@ -1756,12 +1717,6 @@ func getDefaultHTTPBinding(idx int) httpd.Binding {
 func getHTTPDNestedObjectsFromEnv(idx int, binding *httpd.Binding) bool {
 	isSet := false
 
-	webClientIntegrations := getHTTPDWebClientIntegrationsFromEnv(idx)
-	if len(webClientIntegrations) > 0 {
-		binding.WebClientIntegrations = webClientIntegrations
-		isSet = true
-	}
-
 	oidc, ok := getHTTPDOIDCFromEnv(idx)
 	if ok {
 		binding.OIDC = oidc
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
index 532cf6bd..2e0e740f 100644
--- a/internal/config/config_test.go
+++ b/internal/config/config_test.go
@@ -613,8 +613,6 @@ func TestHTTPDSubObjectsFromEnv(t *testing.T) {
 
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__SECURITY__HTTPS_PROXY_HEADERS__0__KEY", "X-Forwarded-Proto")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__SECURITY__HTTPS_PROXY_HEADERS__0__VALUE", "https")
-	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__WEB_CLIENT_INTEGRATIONS__0__URL", "http://127.0.0.1/")
-	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__WEB_CLIENT_INTEGRATIONS__0__FILE_EXTENSIONS", ".pdf, .txt")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__OIDC__CLIENT_ID", "client_id")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__OIDC__CLIENT_SECRET", "client_secret")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__OIDC__CONFIG_URL", "config_url")
@@ -623,8 +621,6 @@ func TestHTTPDSubObjectsFromEnv(t *testing.T) {
 	cleanup := func() {
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__0__SECURITY__HTTPS_PROXY_HEADERS__0__KEY")
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__0__SECURITY__HTTPS_PROXY_HEADERS__0__VALUE")
-		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__0__WEB_CLIENT_INTEGRATIONS__0__URL")
-		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__0__WEB_CLIENT_INTEGRATIONS__0__FILE_EXTENSIONS")
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__0__OIDC__CLIENT_ID")
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__0__OIDC__CLIENT_SECRET")
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__0__OIDC__CONFIG_URL")
@@ -638,7 +634,6 @@ func TestHTTPDSubObjectsFromEnv(t *testing.T) {
 	httpdConf := config.GetHTTPDConfig()
 	require.Len(t, httpdConf.Bindings, 1)
 	require.Len(t, httpdConf.Bindings[0].Security.HTTPSProxyHeaders, 1)
-	require.Len(t, httpdConf.Bindings[0].WebClientIntegrations, 1)
 	require.Equal(t, "client_id", httpdConf.Bindings[0].OIDC.ClientID)
 	require.Equal(t, "client_secret", httpdConf.Bindings[0].OIDC.ClientSecret)
 	require.Equal(t, "config_url", httpdConf.Bindings[0].OIDC.ConfigURL)
@@ -656,7 +651,6 @@ func TestHTTPDSubObjectsFromEnv(t *testing.T) {
 	assert.NoError(t, err)
 
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__SECURITY__HTTPS_PROXY_HEADERS__0__VALUE", "http")
-	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__WEB_CLIENT_INTEGRATIONS__0__URL", "http://127.0.1.1/")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__OIDC__CLIENT_SECRET", "new_client_secret")
 	err = config.LoadConfig(configDir, confName)
 	assert.NoError(t, err)
@@ -664,8 +658,6 @@ func TestHTTPDSubObjectsFromEnv(t *testing.T) {
 	require.Len(t, httpdConf.Bindings, 1)
 	require.Len(t, httpdConf.Bindings[0].Security.HTTPSProxyHeaders, 1)
 	require.Equal(t, "http", httpdConf.Bindings[0].Security.HTTPSProxyHeaders[0].Value)
-	require.Len(t, httpdConf.Bindings[0].WebClientIntegrations, 1)
-	require.Equal(t, "http://127.0.1.1/", httpdConf.Bindings[0].WebClientIntegrations[0].URL)
 	require.Equal(t, "client_id", httpdConf.Bindings[0].OIDC.ClientID)
 	require.Equal(t, "new_client_secret", httpdConf.Bindings[0].OIDC.ClientSecret)
 	require.Equal(t, "config_url", httpdConf.Bindings[0].OIDC.ConfigURL)
@@ -1216,10 +1208,6 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__CLIENT_IP_PROXY_HEADER", "X-Real-IP")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__CLIENT_IP_HEADER_DEPTH", "2")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__HIDE_LOGIN_URL", "3")
-	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__1__URL", "http://127.0.0.1/")
-	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__1__FILE_EXTENSIONS", ".pdf, .txt")
-	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__2__URL", "http://127.0.1.1/")
-	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__3__FILE_EXTENSIONS", ".jpg, .txt")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CLIENT_ID", "client id")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CLIENT_SECRET", "client secret")
 	os.Setenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CONFIG_URL", "config url")
@@ -1286,10 +1274,6 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__CLIENT_IP_PROXY_HEADER")
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__CLIENT_IP_HEADER_DEPTH")
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__HIDE_LOGIN_URL")
-		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__1__URL")
-		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__1__FILE_EXTENSIONS")
-		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__2__URL")
-		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__3__FILE_EXTENSIONS")
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CLIENT_ID")
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CLIENT_SECRET")
 		os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CONFIG_URL")
@@ -1394,9 +1378,6 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
 	require.Equal(t, "X-Real-IP", bindings[2].ClientIPProxyHeader)
 	require.Equal(t, 2, bindings[2].ClientIPHeaderDepth)
 	require.Equal(t, 3, bindings[2].HideLoginURL)
-	require.Len(t, bindings[2].WebClientIntegrations, 1)
-	require.Equal(t, "http://127.0.0.1/", bindings[2].WebClientIntegrations[0].URL)
-	require.Equal(t, []string{".pdf", ".txt"}, bindings[2].WebClientIntegrations[0].FileExtensions)
 	require.Equal(t, "client id", bindings[2].OIDC.ClientID)
 	require.Equal(t, "client secret", bindings[2].OIDC.ClientSecret)
 	require.Equal(t, "config url", bindings[2].OIDC.ConfigURL)
diff --git a/internal/httpd/httpd.go b/internal/httpd/httpd.go
index 90999254..0703b4bc 100644
--- a/internal/httpd/httpd.go
+++ b/internal/httpd/httpd.go
@@ -524,9 +524,6 @@ type Binding struct {
 	HideLoginURL int `json:"hide_login_url" mapstructure:"hide_login_url"`
 	// Enable the built-in OpenAPI renderer
 	RenderOpenAPI bool `json:"render_openapi" mapstructure:"render_openapi"`
-	// Enabling web client integrations you can render or modify the files with the specified
-	// extensions using an external tool.
-	WebClientIntegrations []WebClientIntegration `json:"web_client_integrations" mapstructure:"web_client_integrations"`
 	// Defining an OIDC configuration the web admin and web client UI will use OpenID to authenticate users.
 	OIDC OIDC `json:"oidc" mapstructure:"oidc"`
 	// Security defines security headers to add to HTTP responses and allows to restrict allowed hosts
@@ -536,16 +533,6 @@ type Binding struct {
 	allowHeadersFrom []func(net.IP) bool
 }
 
-func (b *Binding) checkWebClientIntegrations() {
-	var integrations []WebClientIntegration
-	for _, integration := range b.WebClientIntegrations {
-		if integration.URL != "" && len(integration.FileExtensions) > 0 {
-			integrations = append(integrations, integration)
-		}
-	}
-	b.WebClientIntegrations = integrations
-}
-
 func (b *Binding) checkBranding() {
 	b.Branding.WebAdmin.check()
 	b.Branding.WebClient.check()
@@ -973,7 +960,6 @@ func (c *Conf) Initialize(configDir string, isShared int) error {
 		if err := binding.parseAllowedProxy(); err != nil {
 			return err
 		}
-		binding.checkWebClientIntegrations()
 		binding.checkBranding()
 		binding.Security.updateProxyHeaders()
 
diff --git a/internal/httpd/httpd_test.go b/internal/httpd/httpd_test.go
index f11baf2f..a0e9dde2 100644
--- a/internal/httpd/httpd_test.go
+++ b/internal/httpd/httpd_test.go
@@ -313,8 +313,6 @@ func TestMain(m *testing.M) {
 	os.Setenv("SFTPGO_DATA_PROVIDER__NAMING_RULES", "0")
 	os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
 	os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")
-	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__WEB_CLIENT_INTEGRATIONS__0__URL", "http://127.0.0.1/test.html")
-	os.Setenv("SFTPGO_HTTPD__BINDINGS__0__WEB_CLIENT_INTEGRATIONS__0__FILE_EXTENSIONS", ".pdf,.txt")
 	os.Setenv("SFTPGO_HTTPD__MAX_UPLOAD_FILE_SIZE", "1048576000")
 	err := config.LoadConfig(configDir, "")
 	if err != nil {
diff --git a/internal/httpd/webclient.go b/internal/httpd/webclient.go
index 40ec8536..9703f00c 100644
--- a/internal/httpd/webclient.go
+++ b/internal/httpd/webclient.go
@@ -157,7 +157,6 @@ type filesPage struct {
 	ShareUploadBaseURL string
 	Error              string
 	Paths              []dirMapping
-	HasIntegrations    bool
 	QuotaUsage         *userQuotaUsage
 }
 
@@ -763,7 +762,6 @@ func (s *httpdServer) renderSharedFilesPage(w http.ResponseWriter, r *http.Reque
 		CanDelete:          false,
 		CanDownload:        share.Scope != dataprovider.ShareScopeWrite,
 		CanShare:           false,
-		HasIntegrations:    false,
 		Paths:              getDirMapping(dirName, currentURL),
 		QuotaUsage:         newUserQuotaUsage(&dataprovider.User{}),
 	}
@@ -780,9 +778,7 @@ func (s *httpdServer) renderUploadToSharePage(w http.ResponseWriter, r *http.Req
 	renderClientTemplate(w, templateUploadToShare, data)
 }
 
-func (s *httpdServer) renderFilesPage(w http.ResponseWriter, r *http.Request, dirName, error string, user *dataprovider.User,
-	hasIntegrations bool,
-) {
+func (s *httpdServer) renderFilesPage(w http.ResponseWriter, r *http.Request, dirName, error string, user *dataprovider.User) {
 	data := filesPage{
 		baseClientPage:     s.getBaseClientPageData(pageClientFilesTitle, webClientFilesPath, r),
 		Error:              error,
@@ -799,7 +795,6 @@ func (s *httpdServer) renderFilesPage(w http.ResponseWriter, r *http.Request, di
 		CanDownload:        user.HasPerm(dataprovider.PermDownload, dirName),
 		CanShare:           user.CanManageShares(),
 		ShareUploadBaseURL: "",
-		HasIntegrations:    hasIntegrations,
 		Paths:              getDirMapping(dirName, webClientFilesPath),
 		QuotaUsage:         newUserQuotaUsage(user),
 	}
@@ -1167,17 +1162,6 @@ func (s *httpdServer) handleClientGetDirContents(w http.ResponseWriter, r *http.
 				if info.Size() < httpdMaxEditFileSize {
 					res["edit_url"] = strings.Replace(res["url"].(string), webClientFilesPath, webClientEditFilePath, 1)
 				}
-				if len(s.binding.WebClientIntegrations) > 0 {
-					extension := path.Ext(info.Name())
-					for idx := range s.binding.WebClientIntegrations {
-						if util.Contains(s.binding.WebClientIntegrations[idx].FileExtensions, extension) {
-							res["ext_url"] = s.binding.WebClientIntegrations[idx].URL
-							res["ext_link"] = fmt.Sprintf("%v?path=%v&_=%v", webClientFilePath,
-								url.QueryEscape(path.Join(name, info.Name())), time.Now().UTC().Unix())
-							break
-						}
-					}
-				}
 			}
 		}
 		res["meta"] = fmt.Sprintf("%v_%v", res["type"], info.Name())
@@ -1229,12 +1213,11 @@ func (s *httpdServer) handleClientGetFiles(w http.ResponseWriter, r *http.Reques
 		info, err = connection.Stat(name, 0)
 	}
 	if err != nil {
-		s.renderFilesPage(w, r, path.Dir(name), fmt.Sprintf("unable to stat file %q: %v", name, err),
-			&user, len(s.binding.WebClientIntegrations) > 0)
+		s.renderFilesPage(w, r, path.Dir(name), fmt.Sprintf("unable to stat file %q: %v", name, err), &user)
 		return
 	}
 	if info.IsDir() {
-		s.renderFilesPage(w, r, name, "", &user, len(s.binding.WebClientIntegrations) > 0)
+		s.renderFilesPage(w, r, name, "", &user)
 		return
 	}
 	if status, err := downloadFile(w, r, connection, name, info, false, nil); err != nil && status != 0 {
@@ -1243,7 +1226,7 @@ func (s *httpdServer) handleClientGetFiles(w http.ResponseWriter, r *http.Reques
 				s.renderClientMessagePage(w, r, http.StatusText(status), "", status, err, "")
 				return
 			}
-			s.renderFilesPage(w, r, path.Dir(name), err.Error(), &user, len(s.binding.WebClientIntegrations) > 0)
+			s.renderFilesPage(w, r, path.Dir(name), err.Error(), &user)
 		}
 	}
 }
diff --git a/sftpgo.json b/sftpgo.json
index f2b85039..3e7dadb0 100644
--- a/sftpgo.json
+++ b/sftpgo.json
@@ -274,7 +274,6 @@
         "client_ip_header_depth": 0,
         "hide_login_url": 0,
         "render_openapi": true,
-        "web_client_integrations": [],
         "oidc": {
           "client_id": "",
           "client_secret": "",