mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-05-20 03:48:41 -05:00
Merge pull request #2510 from aduffeck/add-favorite-flag-to-search-results
Add the favorite flag to REPORT results
This commit is contained in:
@@ -8,9 +8,11 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
merrors "go-micro.dev/v4/errors"
|
||||
"go-micro.dev/v4/metadata"
|
||||
@@ -37,6 +39,22 @@ const (
|
||||
// Search is the endpoint for retrieving search results for REPORT requests
|
||||
func (g Webdav) Search(w http.ResponseWriter, r *http.Request) {
|
||||
logger := g.log.SubloggerWithRequestID(r.Context())
|
||||
t := r.Header.Get(revactx.TokenHeader)
|
||||
|
||||
gatewayClient, err := g.gatewaySelector.Next()
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("could not get reva gatewayClient")
|
||||
renderError(w, r, errInternalError("could not get reva gatewayClient"))
|
||||
return
|
||||
}
|
||||
|
||||
user, err := whoami(gatewayClient, r.Context(), t)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("could not get user")
|
||||
renderError(w, r, errInternalError("could not get user"))
|
||||
return
|
||||
}
|
||||
|
||||
rep, err := readReport(r.Body)
|
||||
if err != nil {
|
||||
renderError(w, r, errBadRequest(err.Error()))
|
||||
@@ -50,7 +68,6 @@ func (g Webdav) Search(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
t := r.Header.Get(revactx.TokenHeader)
|
||||
ctx := revactx.ContextSetToken(r.Context(), t)
|
||||
ctx = metadata.Set(ctx, revactx.TokenHeader, t)
|
||||
|
||||
@@ -88,13 +105,12 @@ func (g Webdav) Search(w http.ResponseWriter, r *http.Request) {
|
||||
logger.Error().Err(err).Msg("could not get search results")
|
||||
return
|
||||
}
|
||||
|
||||
g.sendSearchResponse(rsp, w, r)
|
||||
g.sendSearchResponse(rsp, w, r, user)
|
||||
}
|
||||
|
||||
func (g Webdav) sendSearchResponse(rsp *searchsvc.SearchResponse, w http.ResponseWriter, r *http.Request) {
|
||||
func (g Webdav) sendSearchResponse(rsp *searchsvc.SearchResponse, w http.ResponseWriter, r *http.Request, user *userv1beta1.User) {
|
||||
logger := g.log.SubloggerWithRequestID(r.Context())
|
||||
responsesXML, err := multistatusResponse(r.Context(), g.config.OpenCloudPublicURL, rsp.Matches)
|
||||
responsesXML, err := multistatusResponse(r.Context(), g.config.OpenCloudPublicURL, rsp.Matches, user)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("error formatting propfind")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
@@ -112,10 +128,10 @@ func (g Webdav) sendSearchResponse(rsp *searchsvc.SearchResponse, w http.Respons
|
||||
}
|
||||
|
||||
// multistatusResponse converts a list of matches into a multistatus response string
|
||||
func multistatusResponse(ctx context.Context, publicURL string, matches []*searchmsg.Match) ([]byte, error) {
|
||||
func multistatusResponse(ctx context.Context, publicURL string, matches []*searchmsg.Match, user *userv1beta1.User) ([]byte, error) {
|
||||
responses := make([]*propfind.ResponseXML, 0, len(matches))
|
||||
for i := range matches {
|
||||
res, err := matchToPropResponse(ctx, publicURL, matches[i])
|
||||
res, err := matchToPropResponse(ctx, publicURL, matches[i], user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -131,7 +147,7 @@ func multistatusResponse(ctx context.Context, publicURL string, matches []*searc
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func matchToPropResponse(ctx context.Context, publicURL string, match *searchmsg.Match) (*propfind.ResponseXML, error) {
|
||||
func matchToPropResponse(ctx context.Context, publicURL string, match *searchmsg.Match, user *userv1beta1.User) (*propfind.ResponseXML, error) {
|
||||
// unfortunately, search uses own versions of ResourceId and Ref. So we need to assert them here
|
||||
var (
|
||||
ref string
|
||||
@@ -234,6 +250,11 @@ func matchToPropResponse(ctx context.Context, publicURL string, match *searchmsg
|
||||
propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:privatelink", privateURL.String()))
|
||||
}
|
||||
|
||||
// enrich results with favorite flag for the user performing the search
|
||||
if slices.Contains(match.Entity.Favorites, user.Id.OpaqueId) {
|
||||
propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:favorite", "1"))
|
||||
}
|
||||
|
||||
if len(propstatOK.Prop) > 0 {
|
||||
response.Propstat = append(response.Propstat, propstatOK)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package svc
|
||||
import (
|
||||
"context"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand/v2"
|
||||
"net/http"
|
||||
@@ -277,6 +278,20 @@ func (g Webdav) SpacesThumbnail(w http.ResponseWriter, r *http.Request) {
|
||||
g.sendThumbnailResponse(rsp, w, r)
|
||||
}
|
||||
|
||||
func whoami(gatewayClient gatewayv1beta1.GatewayAPIClient, ctx context.Context, token string) (*userv1beta1.User, error) {
|
||||
// look up user from token via WhoAmI
|
||||
userRes, err := gatewayClient.WhoAmI(ctx, &gatewayv1beta1.WhoAmIRequest{
|
||||
Token: token,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userRes.Status.Code != rpcv1beta1.Code_CODE_OK {
|
||||
return nil, fmt.Errorf("could not get user: %s", userRes.GetStatus().GetMessage())
|
||||
}
|
||||
return userRes.GetUser(), nil
|
||||
}
|
||||
|
||||
// Thumbnail implements the Service interface.
|
||||
func (g Webdav) Thumbnail(w http.ResponseWriter, r *http.Request) {
|
||||
logger := g.log.SubloggerWithRequestID(r.Context())
|
||||
@@ -298,21 +313,12 @@ func (g Webdav) Thumbnail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var user *userv1beta1.User
|
||||
if tr.Identifier == "" {
|
||||
// look up user from token via WhoAmI
|
||||
userRes, err := gatewayClient.WhoAmI(r.Context(), &gatewayv1beta1.WhoAmIRequest{
|
||||
Token: t,
|
||||
})
|
||||
user, err = whoami(gatewayClient, r.Context(), t)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("could not get user: transport error")
|
||||
logger.Error().Err(err).Msg("could not get user")
|
||||
renderError(w, r, errInternalError("could not get user"))
|
||||
return
|
||||
}
|
||||
if userRes.Status.Code != rpcv1beta1.Code_CODE_OK {
|
||||
logger.Debug().Str("grpcmessage", userRes.GetStatus().GetMessage()).Msg("could not get user")
|
||||
renderError(w, r, errInternalError("could not get user"))
|
||||
return
|
||||
}
|
||||
user = userRes.GetUser()
|
||||
} else {
|
||||
// look up user from URL via GetUserByClaim
|
||||
ctx := grpcmetadata.AppendToOutgoingContext(r.Context(), revactx.TokenHeader, t)
|
||||
|
||||
Reference in New Issue
Block a user