Skip to content

Commit 573537f

Browse files
committed
Add the favorite flag to REPORT results
1 parent 0ca2d65 commit 573537f

2 files changed

Lines changed: 46 additions & 19 deletions

File tree

services/webdav/pkg/service/v0/search.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import (
88
"net/http"
99
"net/url"
1010
"path"
11+
"slices"
1112
"strconv"
1213
"strings"
1314

15+
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
1416
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
1517
merrors "go-micro.dev/v4/errors"
1618
"go-micro.dev/v4/metadata"
@@ -37,6 +39,22 @@ const (
3739
// Search is the endpoint for retrieving search results for REPORT requests
3840
func (g Webdav) Search(w http.ResponseWriter, r *http.Request) {
3941
logger := g.log.SubloggerWithRequestID(r.Context())
42+
t := r.Header.Get(revactx.TokenHeader)
43+
44+
gatewayClient, err := g.gatewaySelector.Next()
45+
if err != nil {
46+
logger.Error().Err(err).Msg("could not get reva gatewayClient")
47+
renderError(w, r, errInternalError("could not get reva gatewayClient"))
48+
return
49+
}
50+
51+
user, err := whoami(gatewayClient, r.Context(), t)
52+
if err != nil {
53+
logger.Error().Err(err).Msg("could not get user")
54+
renderError(w, r, errInternalError("could not get user"))
55+
return
56+
}
57+
4058
rep, err := readReport(r.Body)
4159
if err != nil {
4260
renderError(w, r, errBadRequest(err.Error()))
@@ -50,7 +68,6 @@ func (g Webdav) Search(w http.ResponseWriter, r *http.Request) {
5068
return
5169
}
5270

53-
t := r.Header.Get(revactx.TokenHeader)
5471
ctx := revactx.ContextSetToken(r.Context(), t)
5572
ctx = metadata.Set(ctx, revactx.TokenHeader, t)
5673

@@ -88,13 +105,12 @@ func (g Webdav) Search(w http.ResponseWriter, r *http.Request) {
88105
logger.Error().Err(err).Msg("could not get search results")
89106
return
90107
}
91-
92-
g.sendSearchResponse(rsp, w, r)
108+
g.sendSearchResponse(rsp, w, r, user)
93109
}
94110

95-
func (g Webdav) sendSearchResponse(rsp *searchsvc.SearchResponse, w http.ResponseWriter, r *http.Request) {
111+
func (g Webdav) sendSearchResponse(rsp *searchsvc.SearchResponse, w http.ResponseWriter, r *http.Request, user *userv1beta1.User) {
96112
logger := g.log.SubloggerWithRequestID(r.Context())
97-
responsesXML, err := multistatusResponse(r.Context(), g.config.OpenCloudPublicURL, rsp.Matches)
113+
responsesXML, err := multistatusResponse(r.Context(), g.config.OpenCloudPublicURL, rsp.Matches, user)
98114
if err != nil {
99115
logger.Error().Err(err).Msg("error formatting propfind")
100116
w.WriteHeader(http.StatusInternalServerError)
@@ -112,10 +128,10 @@ func (g Webdav) sendSearchResponse(rsp *searchsvc.SearchResponse, w http.Respons
112128
}
113129

114130
// multistatusResponse converts a list of matches into a multistatus response string
115-
func multistatusResponse(ctx context.Context, publicURL string, matches []*searchmsg.Match) ([]byte, error) {
131+
func multistatusResponse(ctx context.Context, publicURL string, matches []*searchmsg.Match, user *userv1beta1.User) ([]byte, error) {
116132
responses := make([]*propfind.ResponseXML, 0, len(matches))
117133
for i := range matches {
118-
res, err := matchToPropResponse(ctx, publicURL, matches[i])
134+
res, err := matchToPropResponse(ctx, publicURL, matches[i], user)
119135
if err != nil {
120136
return nil, err
121137
}
@@ -131,7 +147,7 @@ func multistatusResponse(ctx context.Context, publicURL string, matches []*searc
131147
return msg, nil
132148
}
133149

134-
func matchToPropResponse(ctx context.Context, publicURL string, match *searchmsg.Match) (*propfind.ResponseXML, error) {
150+
func matchToPropResponse(ctx context.Context, publicURL string, match *searchmsg.Match, user *userv1beta1.User) (*propfind.ResponseXML, error) {
135151
// unfortunately, search uses own versions of ResourceId and Ref. So we need to assert them here
136152
var (
137153
ref string
@@ -234,6 +250,11 @@ func matchToPropResponse(ctx context.Context, publicURL string, match *searchmsg
234250
propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:privatelink", privateURL.String()))
235251
}
236252

253+
// enrich results with favorite flag for the user performing the search
254+
if slices.Contains(match.Entity.Favorites, user.Id.OpaqueId) {
255+
propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:favorite", "1"))
256+
}
257+
237258
if len(propstatOK.Prop) > 0 {
238259
response.Propstat = append(response.Propstat, propstatOK)
239260
}

services/webdav/pkg/service/v0/service.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package svc
33
import (
44
"context"
55
"encoding/xml"
6+
"fmt"
67
"io"
78
"math/rand/v2"
89
"net/http"
@@ -277,6 +278,20 @@ func (g Webdav) SpacesThumbnail(w http.ResponseWriter, r *http.Request) {
277278
g.sendThumbnailResponse(rsp, w, r)
278279
}
279280

281+
func whoami(gatewayClient gatewayv1beta1.GatewayAPIClient, ctx context.Context, token string) (*userv1beta1.User, error) {
282+
// look up user from token via WhoAmI
283+
userRes, err := gatewayClient.WhoAmI(ctx, &gatewayv1beta1.WhoAmIRequest{
284+
Token: token,
285+
})
286+
if err != nil {
287+
return nil, err
288+
}
289+
if userRes.Status.Code != rpcv1beta1.Code_CODE_OK {
290+
return nil, fmt.Errorf("could not get user: %s", userRes.GetStatus().GetMessage())
291+
}
292+
return userRes.GetUser(), nil
293+
}
294+
280295
// Thumbnail implements the Service interface.
281296
func (g Webdav) Thumbnail(w http.ResponseWriter, r *http.Request) {
282297
logger := g.log.SubloggerWithRequestID(r.Context())
@@ -298,21 +313,12 @@ func (g Webdav) Thumbnail(w http.ResponseWriter, r *http.Request) {
298313

299314
var user *userv1beta1.User
300315
if tr.Identifier == "" {
301-
// look up user from token via WhoAmI
302-
userRes, err := gatewayClient.WhoAmI(r.Context(), &gatewayv1beta1.WhoAmIRequest{
303-
Token: t,
304-
})
316+
user, err = whoami(gatewayClient, r.Context(), t)
305317
if err != nil {
306-
logger.Error().Err(err).Msg("could not get user: transport error")
318+
logger.Error().Err(err).Msg("could not get user")
307319
renderError(w, r, errInternalError("could not get user"))
308320
return
309321
}
310-
if userRes.Status.Code != rpcv1beta1.Code_CODE_OK {
311-
logger.Debug().Str("grpcmessage", userRes.GetStatus().GetMessage()).Msg("could not get user")
312-
renderError(w, r, errInternalError("could not get user"))
313-
return
314-
}
315-
user = userRes.GetUser()
316322
} else {
317323
// look up user from URL via GetUserByClaim
318324
ctx := grpcmetadata.AppendToOutgoingContext(r.Context(), revactx.TokenHeader, t)

0 commit comments

Comments
 (0)