Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions services/collaboration/pkg/connector/fileconnector.go
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,7 @@
//
// If the operation is successful, a "FileInfo" instance will be returned,
// otherwise the "FileInfo" will be empty and an error will be returned.
func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse, error) {

Check failure on line 1140 in services/collaboration/pkg/connector/fileconnector.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 35 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=opencloud-eu_opencloud&issues=AZ1JapVxPAYx8a-QPY4M&open=AZ1JapVxPAYx8a-QPY4M&pullRequest=2560
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return nil, err
Expand Down Expand Up @@ -1302,6 +1302,17 @@
}
}

if !isPublicShare && !isAnonymousUser {
infoMap[fileinfo.KeyUserExtraInfo] = &fileinfo.UserExtraInfo{
Avatar: (&url.URL{
Scheme: ocURL.Scheme,
Host: ocURL.Host,
Path: path.Join(ocURL.Path, "graph/v1.0/users", user.GetId().GetOpaqueId(), "photo/$value"),
}).String(),
Mail: user.GetMail(),
}
}

// if the file content is empty and a template reference is set, add the template source URL
if wopiContext.TemplateReference != nil && statRes.GetInfo().GetSize() == 0 {
if tu, err := f.createDownloadURL(wopiContext, collaborationURL); err == nil {
Expand Down
4 changes: 4 additions & 0 deletions services/collaboration/pkg/connector/fileconnector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1994,6 +1994,10 @@ var _ = Describe("FileConnector", func() {
PostMessageOrigin: "https://cloud.opencloud.test",
EnableInsertRemoteImage: true,
IsAdminUser: true,
UserExtraInfo: &fileinfo.UserExtraInfo{
Avatar: "https://cloud.opencloud.test/graph/v1.0/users/aabbcc/photo/$value",
Mail: "shaft@example.com",
},
}

response, err := fc.CheckFileInfo(ctx)
Expand Down
14 changes: 12 additions & 2 deletions services/collaboration/pkg/connector/fileinfo/collabora.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package fileinfo

// UserExtraInfo contains additional user info shared across collaborative
// editing views, such as the user's avatar image and email.
// https://sdk.collaboraonline.com/docs/advanced_integration.html#userextrainfo
type UserExtraInfo struct {
Avatar string `json:"avatar,omitempty"`
Mail string `json:"mail,omitempty"`
}

// Collabora fileInfo properties
//
// Collabora WOPI check file info specification:
Expand Down Expand Up @@ -62,7 +70,8 @@
IsAnonymousUser bool `json:"IsAnonymousUser,omitempty"`

// JSON object that contains additional info about the user, namely the avatar image.
//UserExtraInfo -> requires definition, currently not used
// Shared among all views in collaborative editing sessions.
UserExtraInfo *UserExtraInfo `json:"UserExtraInfo,omitempty"`
// JSON object that contains additional info about the user, but unlike the UserExtraInfo it is not shared among the views in collaborative editing sessions.
//UserPrivateInfo -> requires definition, currently not used

Expand All @@ -87,7 +96,7 @@
// SetProperties will set the file properties for the Collabora implementation.
func (cinfo *Collabora) SetProperties(props map[string]interface{}) {
for key, value := range props {
switch key {

Check warning on line 99 in services/collaboration/pkg/connector/fileinfo/collabora.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reduce the number of switch branches from 31 to at most 30.

See more on https://sonarcloud.io/project/issues?id=opencloud-eu_opencloud&issues=AZ1JapTpPAYx8a-QPY4L&open=AZ1JapTpPAYx8a-QPY4L&pullRequest=2560
case KeyBaseFileName:
cinfo.BaseFileName = value.(string)
case KeyDisablePrint:
Expand Down Expand Up @@ -131,7 +140,8 @@
cinfo.SaveAsPostmessage = value.(bool)
case KeyEnableOwnerTermination:
cinfo.EnableOwnerTermination = value.(bool)
//UserExtraInfo -> requires definition, currently not used
case KeyUserExtraInfo:
cinfo.UserExtraInfo = value.(*UserExtraInfo)
//UserPrivateInfo -> requires definition, currently not used
case KeyWatermarkText:
cinfo.WatermarkText = value.(string)
Expand Down
2 changes: 1 addition & 1 deletion services/collaboration/pkg/connector/fileinfo/fileinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const (
KeyDownloadAsPostMessage = "DownloadAsPostMessage"
KeySaveAsPostmessage = "SaveAsPostmessage"
KeyEnableOwnerTermination = "EnableOwnerTermination"
//KeyUserExtraInfo -> requires definition, currently not used
KeyUserExtraInfo = "UserExtraInfo"
//KeyUserPrivateInfo -> requires definition, currently not used
KeyWatermarkText = "WatermarkText"

Expand Down
15 changes: 15 additions & 0 deletions services/graph/pkg/middleware/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import (
"net/http"
"strings"

gmmetadata "go-micro.dev/v4/metadata"
"google.golang.org/grpc/metadata"
Expand All @@ -28,7 +29,7 @@

// Auth provides a middleware to authenticate requests using the x-access-token header value
// and write it to the context. If there is no x-access-token the middleware prevents access and renders a json document.
func Auth(opts ...account.Option) func(http.Handler) http.Handler {

Check failure on line 32 in services/graph/pkg/middleware/auth.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 24 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=opencloud-eu_opencloud&issues=AZ1JapZtPAYx8a-QPY4N&open=AZ1JapZtPAYx8a-QPY4N&pullRequest=2560
// Note: This largely duplicates what pkg/middleware/account.go already does (apart from a slightly different error
// handling). Ideally we should merge both middlewares.
opt := authOptions(opts...)
Expand All @@ -41,6 +42,11 @@
}
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if isPublicProfilePhotoRequest(r) {
next.ServeHTTP(w, r)
return
}

ctx := r.Context()
t := r.Header.Get(revactx.TokenHeader)
if t == "" {
Expand Down Expand Up @@ -93,3 +99,12 @@
})
}
}

// isPublicProfilePhotoRequest returns true for unauthenticated GET requests
// to user profile photo endpoints. These serve avatar images used by
// integrations like Collabora Online during collaborative editing.
func isPublicProfilePhotoRequest(r *http.Request) bool {
return r.Method == http.MethodGet &&
strings.Contains(r.URL.Path, "/users/") &&
strings.HasSuffix(r.URL.Path, "/photo/$value")
}
7 changes: 7 additions & 0 deletions services/proxy/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,13 @@ func DefaultPolicies() []config.Policy {
Endpoint: "/graph/v1.0/invitations",
Service: "eu.opencloud.web.invitations",
},
{
Type: config.RegexRoute,
Method: "GET",
Endpoint: `/graph/v1\.0/users/[^/]+/photo/\$value`,
Service: "eu.opencloud.web.graph",
Unprotected: true,
},
{
Endpoint: "/graph/",
Service: "eu.opencloud.web.graph",
Expand Down