Repository: owncloud/ocis
Pull request #3229 (2022-02-23 17:50:03)

allow requesting capabilities from password protected links
## Description
Requesting capabilities from password protected links wasn't possible.

## Related Issue
- requirement for https://github.com/owncloud/web/pull/6471
- requested by: https://github.com/owncloud/web/issues/5863

## Motivation and Context
allow public links with password protection to request capabilities.

## How Has This Been Tested?
- tests added
- 
## Types of changes
- [X] Bug fix (non-breaking change which fixes an issue)


Patch:
diff --git a/changelog/unreleased/fix-capabilities-for-public-links.md b/changelog/unreleased/fix-capabilities-for-public-links.md
new file mode 100644
index 00000000000..c1546a4376a
--- /dev/null
+++ b/changelog/unreleased/fix-capabilities-for-public-links.md
@@ -0,0 +1,7 @@
+Bugfix: Capabilities for password protected public links
+
+Allow password protected public links to request capabilities.
+
+https://github.com/owncloud/ocis/pull/3229
+https://github.com/owncloud/web/pull/6471
+https://github.com/owncloud/web/issues/5863
diff --git a/proxy/pkg/middleware/basic_auth.go b/proxy/pkg/middleware/basic_auth.go
index 6b26dbd0ce7..64e467497ef 100644
--- a/proxy/pkg/middleware/basic_auth.go
+++ b/proxy/pkg/middleware/basic_auth.go
@@ -11,8 +11,6 @@ import (
 	"github.com/owncloud/ocis/proxy/pkg/webdav"
 )
 
-const publicFilesEndpoint = "/remote.php/dav/public-files/"
-
 // BasicAuth provides a middleware to check if BasicAuth is provided
 func BasicAuth(optionSetters ...Option) func(next http.Handler) http.Handler {
 	options := newOptions(optionSetters...)
@@ -111,7 +109,25 @@ type basicAuth struct {
 
 func (m basicAuth) isPublicLink(req *http.Request) bool {
 	login, _, ok := req.BasicAuth()
-	return ok && login == "public" && strings.HasPrefix(req.URL.Path, publicFilesEndpoint)
+
+	if !ok || login != "public" {
+		return false
+	}
+
+	publicPaths := []string{
+		"/remote.php/dav/public-files/",
+		"/ocs/v1.php/cloud/capabilities",
+	}
+	isPublic := false
+
+	for _, p := range publicPaths {
+		if strings.HasPrefix(req.URL.Path, p) {
+			isPublic = true
+			break
+		}
+	}
+
+	return isPublic
 }
 
 // The token auth endpoint uses basic auth for clients, see https://openid.net/specs/openid-connect-basic-1_0.html#TokenRequest


Test patch:
diff --git a/proxy/pkg/middleware/basic_auth_test.go b/proxy/pkg/middleware/basic_auth_test.go
index fbdfab057f6..46c7f48285e 100644
--- a/proxy/pkg/middleware/basic_auth_test.go
+++ b/proxy/pkg/middleware/basic_auth_test.go
@@ -1,3 +1,40 @@
 package middleware
 
+import (
+	"net/http/httptest"
+	"testing"
+)
+
 /**/
+
+func TestBasicAuth__isPublicLink(t *testing.T) {
+	tests := []struct {
+		url      string
+		username string
+		expected bool
+	}{
+		{url: "/remote.php/dav/public-files/", username: "", expected: false},
+		{url: "/remote.php/dav/public-files/", username: "abc", expected: false},
+		{url: "/remote.php/dav/public-files/", username: "private", expected: false},
+		{url: "/remote.php/dav/public-files/", username: "public", expected: true},
+		{url: "/ocs/v1.php/cloud/capabilities", username: "", expected: false},
+		{url: "/ocs/v1.php/cloud/capabilities", username: "abc", expected: false},
+		{url: "/ocs/v1.php/cloud/capabilities", username: "private", expected: false},
+		{url: "/ocs/v1.php/cloud/capabilities", username: "public", expected: true},
+		{url: "/ocs/v1.php/cloud/users/admin", username: "public", expected: false},
+	}
+	ba := basicAuth{}
+
+	for _, tt := range tests {
+		req := httptest.NewRequest("", tt.url, nil)
+
+		if tt.username != "" {
+			req.SetBasicAuth(tt.username, "")
+		}
+
+		result := ba.isPublicLink(req)
+		if result != tt.expected {
+			t.Errorf("with %s expected %t got %t", tt.url, tt.expected, result)
+		}
+	}
+}