@@ -0,0 +1,5 @@
|
|||||||
|
Enhancement: Bump Reva
|
||||||
|
|
||||||
|
bumps reva
|
||||||
|
|
||||||
|
https://github.com/owncloud/ocis/pull/6381
|
||||||
@@ -13,7 +13,7 @@ require (
|
|||||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||||
github.com/coreos/go-oidc/v3 v3.6.0
|
github.com/coreos/go-oidc/v3 v3.6.0
|
||||||
github.com/cs3org/go-cs3apis v0.0.0-20230516150832-730ac860c71d
|
github.com/cs3org/go-cs3apis v0.0.0-20230516150832-730ac860c71d
|
||||||
github.com/cs3org/reva/v2 v2.13.4-0.20230523132457-4fb99464ab8d
|
github.com/cs3org/reva/v2 v2.13.4-0.20230525110514-9334e2174492
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
||||||
github.com/egirna/icap-client v0.1.1
|
github.com/egirna/icap-client v0.1.1
|
||||||
|
|||||||
@@ -627,8 +627,8 @@ github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo
|
|||||||
github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4=
|
github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4=
|
||||||
github.com/crewjam/saml v0.4.13 h1:TYHggH/hwP7eArqiXSJUvtOPNzQDyQ7vwmwEqlFWhMc=
|
github.com/crewjam/saml v0.4.13 h1:TYHggH/hwP7eArqiXSJUvtOPNzQDyQ7vwmwEqlFWhMc=
|
||||||
github.com/crewjam/saml v0.4.13/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA=
|
github.com/crewjam/saml v0.4.13/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA=
|
||||||
github.com/cs3org/reva/v2 v2.13.4-0.20230523132457-4fb99464ab8d h1:Wuz6lxPY022NP9052zcDFpnqhLkDtik11fYHX1NLF74=
|
github.com/cs3org/reva/v2 v2.13.4-0.20230525110514-9334e2174492 h1:hWJK5O45XN73GVOvRreymiF0lbrHgMcIP4oFkGfuQcg=
|
||||||
github.com/cs3org/reva/v2 v2.13.4-0.20230523132457-4fb99464ab8d/go.mod h1:jkngU/36YdFNQfFurjgKl8URY2dkhwgJ5gQXt1GUoPw=
|
github.com/cs3org/reva/v2 v2.13.4-0.20230525110514-9334e2174492/go.mod h1:jkngU/36YdFNQfFurjgKl8URY2dkhwgJ5gQXt1GUoPw=
|
||||||
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
|
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
|
||||||
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
|
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
|
||||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||||
|
|||||||
Generated
Vendored
+5
@@ -241,6 +241,11 @@ func (s *svc) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSp
|
|||||||
// TODO check for allowed filters
|
// TODO check for allowed filters
|
||||||
filters["mask"] = mask
|
filters["mask"] = mask
|
||||||
}
|
}
|
||||||
|
path := utils.ReadPlainFromOpaque(req.Opaque, "path")
|
||||||
|
if path != "" {
|
||||||
|
// TODO check for allowed filters
|
||||||
|
filters["path"] = path
|
||||||
|
}
|
||||||
|
|
||||||
for _, f := range req.Filters {
|
for _, f := range req.Filters {
|
||||||
switch f.Type {
|
switch f.Type {
|
||||||
|
|||||||
Generated
Vendored
+88
-32
@@ -53,6 +53,7 @@ import (
|
|||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
"go.opentelemetry.io/otel/codes"
|
"go.opentelemetry.io/otel/codes"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
"google.golang.org/protobuf/types/known/fieldmaskpb"
|
"google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -876,13 +877,67 @@ func ReadPropfind(r io.Reader) (pf XML, status int, err error) {
|
|||||||
|
|
||||||
// MultistatusResponse converts a list of resource infos into a multistatus response string
|
// MultistatusResponse converts a list of resource infos into a multistatus response string
|
||||||
func MultistatusResponse(ctx context.Context, pf *XML, mds []*provider.ResourceInfo, publicURL, ns string, linkshares map[string]struct{}, returnMinimal bool) ([]byte, error) {
|
func MultistatusResponse(ctx context.Context, pf *XML, mds []*provider.ResourceInfo, publicURL, ns string, linkshares map[string]struct{}, returnMinimal bool) ([]byte, error) {
|
||||||
responses := make([]*ResponseXML, 0, len(mds))
|
g, ctx := errgroup.WithContext(ctx)
|
||||||
for i := range mds {
|
|
||||||
res, err := mdToPropResponse(ctx, pf, mds[i], publicURL, ns, linkshares, returnMinimal)
|
type work struct {
|
||||||
if err != nil {
|
position int
|
||||||
return nil, err
|
info *provider.ResourceInfo
|
||||||
|
}
|
||||||
|
type result struct {
|
||||||
|
position int
|
||||||
|
info *ResponseXML
|
||||||
|
}
|
||||||
|
workChan := make(chan work, len(mds))
|
||||||
|
resultChan := make(chan result, len(mds))
|
||||||
|
|
||||||
|
// Distribute work
|
||||||
|
g.Go(func() error {
|
||||||
|
defer close(workChan)
|
||||||
|
for i, md := range mds {
|
||||||
|
select {
|
||||||
|
case workChan <- work{position: i, info: md}:
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
responses = append(responses, res)
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
// Spawn workers that'll concurrently work the queue
|
||||||
|
numWorkers := 50
|
||||||
|
if len(mds) < numWorkers {
|
||||||
|
numWorkers = len(mds)
|
||||||
|
}
|
||||||
|
for i := 0; i < numWorkers; i++ {
|
||||||
|
g.Go(func() error {
|
||||||
|
for work := range workChan {
|
||||||
|
res, err := mdToPropResponse(ctx, pf, work.info, publicURL, ns, linkshares, returnMinimal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case resultChan <- result{position: work.position, info: res}:
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for things to settle down, then close results chan
|
||||||
|
go func() {
|
||||||
|
_ = g.Wait() // error is checked later
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := g.Wait(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
responses := make([]*ResponseXML, len(mds))
|
||||||
|
for res := range resultChan {
|
||||||
|
responses[res.position] = res.info
|
||||||
}
|
}
|
||||||
|
|
||||||
msr := NewMultiStatusResponseXML()
|
msr := NewMultiStatusResponseXML()
|
||||||
@@ -904,11 +959,12 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
sublog := appctx.GetLogger(ctx).With().Interface("md", md).Str("ns", ns).Logger()
|
sublog := appctx.GetLogger(ctx).With().Interface("md", md).Str("ns", ns).Logger()
|
||||||
md.Path = strings.TrimPrefix(md.Path, ns)
|
id := md.Id
|
||||||
|
p := strings.TrimPrefix(md.Path, ns)
|
||||||
|
|
||||||
baseURI := ctx.Value(net.CtxKeyBaseURI).(string)
|
baseURI := ctx.Value(net.CtxKeyBaseURI).(string)
|
||||||
|
|
||||||
ref := path.Join(baseURI, md.Path)
|
ref := path.Join(baseURI, p)
|
||||||
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
|
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
|
||||||
ref += "/"
|
ref += "/"
|
||||||
}
|
}
|
||||||
@@ -952,7 +1008,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
|
|
||||||
role := conversions.RoleFromResourcePermissions(md.PermissionSet, ls != nil)
|
role := conversions.RoleFromResourcePermissions(md.PermissionSet, ls != nil)
|
||||||
|
|
||||||
if md.Space != nil && md.Space.SpaceType != "grant" && utils.ResourceIDEqual(md.Space.Root, md.Id) {
|
if md.Space != nil && md.Space.SpaceType != "grant" && utils.ResourceIDEqual(md.Space.Root, id) {
|
||||||
// a space root is never shared
|
// a space root is never shared
|
||||||
shareTypes = ""
|
shareTypes = ""
|
||||||
}
|
}
|
||||||
@@ -969,8 +1025,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
// replace fileid of /public/{token} mountpoint with grant fileid
|
// replace fileid of /public/{token} mountpoint with grant fileid
|
||||||
if ls != nil && md.Id != nil && md.Id.SpaceId == utils.PublicStorageSpaceID && md.Id.OpaqueId == ls.Token {
|
if ls != nil && id != nil && id.SpaceId == utils.PublicStorageSpaceID && id.OpaqueId == ls.Token {
|
||||||
md.Id = ls.ResourceId
|
id = ls.ResourceId
|
||||||
}
|
}
|
||||||
|
|
||||||
propstatOK := PropstatXML{
|
propstatOK := PropstatXML{
|
||||||
@@ -996,12 +1052,12 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
if pf.Allprop != nil {
|
if pf.Allprop != nil {
|
||||||
// return all known properties
|
// return all known properties
|
||||||
|
|
||||||
if md.Id != nil {
|
if id != nil {
|
||||||
id := storagespace.FormatResourceID(*md.Id)
|
sid := storagespace.FormatResourceID(*id)
|
||||||
appendToOK(
|
appendToOK(
|
||||||
prop.Escaped("oc:id", id),
|
prop.Escaped("oc:id", sid),
|
||||||
prop.Escaped("oc:fileid", id),
|
prop.Escaped("oc:fileid", sid),
|
||||||
prop.Escaped("oc:spaceid", md.Id.SpaceId),
|
prop.Escaped("oc:spaceid", id.SpaceId),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1012,7 +1068,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we need to add the shareid if possible - the only way to extract it here is to parse it from the path
|
// we need to add the shareid if possible - the only way to extract it here is to parse it from the path
|
||||||
if ref, err := storagespace.ParseReference(strings.TrimPrefix(md.Path, "/")); err == nil && ref.GetResourceId().GetSpaceId() == utils.ShareStorageSpaceID {
|
if ref, err := storagespace.ParseReference(strings.TrimPrefix(p, "/")); err == nil && ref.GetResourceId().GetSpaceId() == utils.ShareStorageSpaceID {
|
||||||
appendToOK(prop.Raw("oc:shareid", ref.GetResourceId().GetOpaqueId()))
|
appendToOK(prop.Raw("oc:shareid", ref.GetResourceId().GetOpaqueId()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1119,14 +1175,14 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
// TODO(jfd): maybe phoenix and the other clients can just use this id as an opaque string?
|
// TODO(jfd): maybe phoenix and the other clients can just use this id as an opaque string?
|
||||||
// I tested the desktop client and phoenix to annotate which properties are requestted, see below cases
|
// I tested the desktop client and phoenix to annotate which properties are requestted, see below cases
|
||||||
case "fileid": // phoenix only
|
case "fileid": // phoenix only
|
||||||
if md.Id != nil {
|
if id != nil {
|
||||||
appendToOK(prop.Escaped("oc:fileid", storagespace.FormatResourceID(*md.Id)))
|
appendToOK(prop.Escaped("oc:fileid", storagespace.FormatResourceID(*id)))
|
||||||
} else {
|
} else {
|
||||||
appendToNotFound(prop.NotFound("oc:fileid"))
|
appendToNotFound(prop.NotFound("oc:fileid"))
|
||||||
}
|
}
|
||||||
case "id": // desktop client only
|
case "id": // desktop client only
|
||||||
if md.Id != nil {
|
if id != nil {
|
||||||
appendToOK(prop.Escaped("oc:id", storagespace.FormatResourceID(*md.Id)))
|
appendToOK(prop.Escaped("oc:id", storagespace.FormatResourceID(*id)))
|
||||||
} else {
|
} else {
|
||||||
appendToNotFound(prop.NotFound("oc:id"))
|
appendToNotFound(prop.NotFound("oc:id"))
|
||||||
}
|
}
|
||||||
@@ -1137,8 +1193,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
appendToNotFound(prop.NotFound("oc:file-parent"))
|
appendToNotFound(prop.NotFound("oc:file-parent"))
|
||||||
}
|
}
|
||||||
case "spaceid":
|
case "spaceid":
|
||||||
if md.Id != nil {
|
if id != nil {
|
||||||
appendToOK(prop.Escaped("oc:spaceid", md.Id.SpaceId))
|
appendToOK(prop.Escaped("oc:spaceid", id.SpaceId))
|
||||||
} else {
|
} else {
|
||||||
appendToNotFound(prop.Escaped("oc:spaceid", ""))
|
appendToNotFound(prop.Escaped("oc:spaceid", ""))
|
||||||
}
|
}
|
||||||
@@ -1204,7 +1260,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
// TODO what is the difference to d:quota-used-bytes (which only exists for collections)?
|
// TODO what is the difference to d:quota-used-bytes (which only exists for collections)?
|
||||||
// oc:size is available on files and folders and behaves like d:getcontentlength or d:quota-used-bytes respectively
|
// oc:size is available on files and folders and behaves like d:getcontentlength or d:quota-used-bytes respectively
|
||||||
// The hasPrefix is a workaround to make children of the link root show a size if they have 0 bytes
|
// The hasPrefix is a workaround to make children of the link root show a size if they have 0 bytes
|
||||||
if ls == nil || strings.HasPrefix(md.Path, "/"+ls.Token+"/") {
|
if ls == nil || strings.HasPrefix(p, "/"+ls.Token+"/") {
|
||||||
appendToOK(prop.Escaped("oc:size", size))
|
appendToOK(prop.Escaped("oc:size", size))
|
||||||
} else {
|
} else {
|
||||||
// link share root collection has no size
|
// link share root collection has no size
|
||||||
@@ -1289,8 +1345,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if md.Id != nil {
|
if id != nil {
|
||||||
if _, ok := linkshares[md.Id.OpaqueId]; ok {
|
if _, ok := linkshares[id.OpaqueId]; ok {
|
||||||
types.WriteString("<oc:share-type>3</oc:share-type>")
|
types.WriteString("<oc:share-type>3</oc:share-type>")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1316,12 +1372,12 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
if isPublic && md.Type == provider.ResourceType_RESOURCE_TYPE_FILE {
|
if isPublic && md.Type == provider.ResourceType_RESOURCE_TYPE_FILE {
|
||||||
var path string
|
var path string
|
||||||
if !ls.PasswordProtected {
|
if !ls.PasswordProtected {
|
||||||
path = md.Path
|
path = p
|
||||||
} else {
|
} else {
|
||||||
expiration := time.Unix(int64(ls.Signature.SignatureExpiration.Seconds), int64(ls.Signature.SignatureExpiration.Nanos))
|
expiration := time.Unix(int64(ls.Signature.SignatureExpiration.Seconds), int64(ls.Signature.SignatureExpiration.Nanos))
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
|
|
||||||
sb.WriteString(md.Path)
|
sb.WriteString(p)
|
||||||
sb.WriteString("?signature=")
|
sb.WriteString("?signature=")
|
||||||
sb.WriteString(ls.Signature.Signature)
|
sb.WriteString(ls.Signature.Signature)
|
||||||
sb.WriteString("&expiration=")
|
sb.WriteString("&expiration=")
|
||||||
@@ -1335,8 +1391,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
}
|
}
|
||||||
case "privatelink":
|
case "privatelink":
|
||||||
privateURL, err := url.Parse(publicURL)
|
privateURL, err := url.Parse(publicURL)
|
||||||
if err == nil && md.Id != nil {
|
if err == nil && id != nil {
|
||||||
privateURL.Path = path.Join(privateURL.Path, "f", storagespace.FormatResourceID(*md.Id))
|
privateURL.Path = path.Join(privateURL.Path, "f", storagespace.FormatResourceID(*id))
|
||||||
propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:privatelink", privateURL.String()))
|
propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:privatelink", privateURL.String()))
|
||||||
} else {
|
} else {
|
||||||
propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:privatelink"))
|
propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:privatelink"))
|
||||||
@@ -1344,7 +1400,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
case "signature-auth":
|
case "signature-auth":
|
||||||
if isPublic {
|
if isPublic {
|
||||||
// We only want to add the attribute to the root of the propfind.
|
// We only want to add the attribute to the root of the propfind.
|
||||||
if strings.HasSuffix(md.Path, ls.Token) && ls.Signature != nil {
|
if strings.HasSuffix(p, ls.Token) && ls.Signature != nil {
|
||||||
expiration := time.Unix(int64(ls.Signature.SignatureExpiration.Seconds), int64(ls.Signature.SignatureExpiration.Nanos))
|
expiration := time.Unix(int64(ls.Signature.SignatureExpiration.Seconds), int64(ls.Signature.SignatureExpiration.Nanos))
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
sb.WriteString("<oc:signature>")
|
sb.WriteString("<oc:signature>")
|
||||||
@@ -1366,7 +1422,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
|||||||
case "name":
|
case "name":
|
||||||
appendToOK(prop.Escaped("oc:name", md.Name))
|
appendToOK(prop.Escaped("oc:name", md.Name))
|
||||||
case "shareid":
|
case "shareid":
|
||||||
if ref, err := storagespace.ParseReference(strings.TrimPrefix(md.Path, "/")); err == nil && ref.GetResourceId().GetSpaceId() == utils.ShareStorageSpaceID {
|
if ref, err := storagespace.ParseReference(strings.TrimPrefix(p, "/")); err == nil && ref.GetResourceId().GetSpaceId() == utils.ShareStorageSpaceID {
|
||||||
appendToOK(prop.Raw("oc:shareid", ref.GetResourceId().GetOpaqueId()))
|
appendToOK(prop.Raw("oc:shareid", ref.GetResourceId().GetOpaqueId()))
|
||||||
}
|
}
|
||||||
case "dDC": // desktop
|
case "dDC": // desktop
|
||||||
|
|||||||
Generated
Vendored
+23
-53
@@ -273,7 +273,7 @@ func (h *Handler) listPublicShares(r *http.Request, filters []*link.ListPublicSh
|
|||||||
return ocsDataPayload, nil, errors.New("bad request")
|
return ocsDataPayload, nil, errors.New("bad request")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) isPublicShare(r *http.Request, oid string) bool {
|
func (h *Handler) isPublicShare(r *http.Request, oid string) (*link.PublicShare, bool) {
|
||||||
logger := appctx.GetLogger(r.Context())
|
logger := appctx.GetLogger(r.Context())
|
||||||
client, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
client, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -291,19 +291,19 @@ func (h *Handler) isPublicShare(r *http.Request, oid string) bool {
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Err(err)
|
logger.Err(err)
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return psRes.GetShare() != nil
|
return psRes.GetShare(), psRes.GetShare() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shareID string) {
|
func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, share *link.PublicShare) {
|
||||||
updates := []*link.UpdatePublicShareRequest_Update{}
|
updates := []*link.UpdatePublicShareRequest_Update{}
|
||||||
logger := appctx.GetLogger(r.Context())
|
logger := appctx.GetLogger(r.Context())
|
||||||
|
|
||||||
gwC, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
gwC, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Str("shareID", shareID).Msg("updatePublicShare")
|
log.Err(err).Str("shareID", share.GetId().GetOpaqueId()).Msg("updatePublicShare")
|
||||||
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "error getting a connection to the gateway service", nil)
|
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "error getting a connection to the gateway service", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -317,21 +317,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
before, err := gwC.GetPublicShare(r.Context(), &link.GetPublicShareRequest{
|
createdByUser := publicshare.IsCreatedByUser(*share, user)
|
||||||
Ref: &link.PublicShareReference{
|
|
||||||
Spec: &link.PublicShareReference_Id{
|
|
||||||
Id: &link.PublicShareId{
|
|
||||||
OpaqueId: shareID,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "failed to get public share", nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
createdByUser := publicshare.IsCreatedByUser(*before.Share, user)
|
|
||||||
|
|
||||||
// NOTE: you are allowed to update a link TO a public link without the `PublicLink.Write` permission if you created it yourself
|
// NOTE: you are allowed to update a link TO a public link without the `PublicLink.Write` permission if you created it yourself
|
||||||
if (permKey != nil && *permKey != 0) || !createdByUser {
|
if (permKey != nil && *permKey != 0) || !createdByUser {
|
||||||
@@ -355,9 +341,9 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !createdByUser {
|
if !createdByUser {
|
||||||
sRes, err := gwC.Stat(r.Context(), &provider.StatRequest{Ref: &provider.Reference{ResourceId: before.Share.ResourceId}})
|
sRes, err := gwC.Stat(r.Context(), &provider.StatRequest{Ref: &provider.Reference{ResourceId: share.ResourceId}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Interface("resource_id", before.Share.ResourceId).Msg("failed to stat shared resource")
|
log.Err(err).Interface("resource_id", share.ResourceId).Msg("failed to stat shared resource")
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "failed to get public share", nil)
|
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "failed to get public share", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -382,7 +368,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar
|
|||||||
newName, ok := r.Form["name"]
|
newName, ok := r.Form["name"]
|
||||||
if ok {
|
if ok {
|
||||||
updatesFound = true
|
updatesFound = true
|
||||||
if newName[0] != before.Share.DisplayName {
|
if newName[0] != share.DisplayName {
|
||||||
updates = append(updates, &link.UpdatePublicShareRequest_Update{
|
updates = append(updates, &link.UpdatePublicShareRequest_Update{
|
||||||
Type: link.UpdatePublicShareRequest_Update_TYPE_DISPLAYNAME,
|
Type: link.UpdatePublicShareRequest_Update_TYPE_DISPLAYNAME,
|
||||||
DisplayName: newName[0],
|
DisplayName: newName[0],
|
||||||
@@ -404,7 +390,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar
|
|||||||
publicSharePermissions := &link.PublicSharePermissions{
|
publicSharePermissions := &link.PublicSharePermissions{
|
||||||
Permissions: newPermissions,
|
Permissions: newPermissions,
|
||||||
}
|
}
|
||||||
beforePerm, _ := json.Marshal(before.GetShare().Permissions)
|
beforePerm, _ := json.Marshal(share.Permissions)
|
||||||
afterPerm, _ := json.Marshal(publicSharePermissions)
|
afterPerm, _ := json.Marshal(publicSharePermissions)
|
||||||
if string(beforePerm) != string(afterPerm) {
|
if string(beforePerm) != string(afterPerm) {
|
||||||
logger.Info().Str("shares", "update").Msgf("updating permissions from %v to: %v", string(beforePerm), string(afterPerm))
|
logger.Info().Str("shares", "update").Msgf("updating permissions from %v to: %v", string(beforePerm), string(afterPerm))
|
||||||
@@ -418,7 +404,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
statReq := provider.StatRequest{Ref: &provider.Reference{ResourceId: before.Share.ResourceId}}
|
statReq := provider.StatRequest{Ref: &provider.Reference{ResourceId: share.ResourceId}}
|
||||||
statRes, err := gwC.Stat(r.Context(), &statReq)
|
statRes, err := gwC.Stat(r.Context(), &statReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug().Err(err).Str("shares", "update public share").Msg("error during stat")
|
log.Debug().Err(err).Str("shares", "update public share").Msg("error during stat")
|
||||||
@@ -446,7 +432,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeExpiration, _ := json.Marshal(before.Share.Expiration)
|
beforeExpiration, _ := json.Marshal(share.Expiration)
|
||||||
afterExpiration, _ := json.Marshal(newExpiration)
|
afterExpiration, _ := json.Marshal(newExpiration)
|
||||||
if string(afterExpiration) != string(beforeExpiration) {
|
if string(afterExpiration) != string(beforeExpiration) {
|
||||||
logger.Debug().Str("shares", "update").Msgf("updating expire date from %v to: %v", string(beforeExpiration), string(afterExpiration))
|
logger.Debug().Str("shares", "update").Msgf("updating expire date from %v to: %v", string(beforeExpiration), string(afterExpiration))
|
||||||
@@ -473,47 +459,45 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
publicShare := before.Share
|
|
||||||
|
|
||||||
// Updates are atomical. See: https://github.com/cs3org/cs3apis/pull/67#issuecomment-617651428 so in order to get the latest updated version
|
// Updates are atomical. See: https://github.com/cs3org/cs3apis/pull/67#issuecomment-617651428 so in order to get the latest updated version
|
||||||
if len(updates) > 0 {
|
if len(updates) > 0 {
|
||||||
uRes := &link.UpdatePublicShareResponse{Share: before.Share}
|
uRes := &link.UpdatePublicShareResponse{Share: share}
|
||||||
for k := range updates {
|
for k := range updates {
|
||||||
uRes, err = gwC.UpdatePublicShare(r.Context(), &link.UpdatePublicShareRequest{
|
uRes, err = gwC.UpdatePublicShare(r.Context(), &link.UpdatePublicShareRequest{
|
||||||
Ref: &link.PublicShareReference{
|
Ref: &link.PublicShareReference{
|
||||||
Spec: &link.PublicShareReference_Id{
|
Spec: &link.PublicShareReference_Id{
|
||||||
Id: &link.PublicShareId{
|
Id: &link.PublicShareId{
|
||||||
OpaqueId: shareID,
|
OpaqueId: share.Id.OpaqueId,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Update: updates[k],
|
Update: updates[k],
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Str("shareID", shareID).Msg("sending update request to public link provider")
|
log.Err(err).Str("shareID", share.Id.OpaqueId).Msg("sending update request to public link provider")
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "Error sending update request to public link provider", err)
|
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "Error sending update request to public link provider", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if uRes.Status.Code != rpc.Code_CODE_OK {
|
if uRes.Status.Code != rpc.Code_CODE_OK {
|
||||||
log.Debug().Str("shareID", shareID).Msgf("sending update request to public link provider failed: %s", uRes.Status.Message)
|
log.Debug().Str("shareID", share.Id.OpaqueId).Msgf("sending update request to public link provider failed: %s", uRes.Status.Message)
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, fmt.Sprintf("Error sending update request to public link provider: %s", uRes.Status.Message), nil)
|
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, fmt.Sprintf("Error sending update request to public link provider: %s", uRes.Status.Message), nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
publicShare = uRes.Share
|
share = uRes.Share
|
||||||
} else if !updatesFound {
|
} else if !updatesFound {
|
||||||
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "No updates specified in request", nil)
|
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "No updates specified in request", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s := conversions.PublicShare2ShareData(publicShare, r, h.publicURL)
|
s := conversions.PublicShare2ShareData(share, r, h.publicURL)
|
||||||
h.addFileInfo(r.Context(), s, statRes.Info)
|
h.addFileInfo(r.Context(), s, statRes.Info)
|
||||||
h.mapUserIds(r.Context(), gwC, s)
|
h.mapUserIds(r.Context(), gwC, s)
|
||||||
|
|
||||||
response.WriteOCSSuccess(w, r, s)
|
response.WriteOCSSuccess(w, r, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) removePublicShare(w http.ResponseWriter, r *http.Request, shareID string) {
|
func (h *Handler) removePublicShare(w http.ResponseWriter, r *http.Request, share *link.PublicShare) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
c, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
c, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
||||||
@@ -522,25 +506,11 @@ func (h *Handler) removePublicShare(w http.ResponseWriter, r *http.Request, shar
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
before, err := c.GetPublicShare(r.Context(), &link.GetPublicShareRequest{
|
|
||||||
Ref: &link.PublicShareReference{
|
|
||||||
Spec: &link.PublicShareReference_Id{
|
|
||||||
Id: &link.PublicShareId{
|
|
||||||
OpaqueId: shareID,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "failed to get public share", nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
u := ctxpkg.ContextMustGetUser(ctx)
|
u := ctxpkg.ContextMustGetUser(ctx)
|
||||||
if !publicshare.IsCreatedByUser(*before.Share, u) {
|
if !publicshare.IsCreatedByUser(*share, u) {
|
||||||
sRes, err := c.Stat(r.Context(), &provider.StatRequest{Ref: &provider.Reference{ResourceId: before.Share.ResourceId}})
|
sRes, err := c.Stat(r.Context(), &provider.StatRequest{Ref: &provider.Reference{ResourceId: share.ResourceId}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Interface("resource_id", before.Share.ResourceId).Msg("failed to stat shared resource")
|
log.Err(err).Interface("resource_id", share.ResourceId).Msg("failed to stat shared resource")
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "failed to get public share", nil)
|
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "failed to get public share", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -555,7 +525,7 @@ func (h *Handler) removePublicShare(w http.ResponseWriter, r *http.Request, shar
|
|||||||
Ref: &link.PublicShareReference{
|
Ref: &link.PublicShareReference{
|
||||||
Spec: &link.PublicShareReference_Id{
|
Spec: &link.PublicShareReference_Id{
|
||||||
Id: &link.PublicShareId{
|
Id: &link.PublicShareId{
|
||||||
OpaqueId: shareID,
|
OpaqueId: share.GetId().GetOpaqueId(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
Vendored
+34
-44
@@ -679,16 +679,21 @@ func (h *Handler) UpdateShare(w http.ResponseWriter, r *http.Request) {
|
|||||||
shareID := chi.URLParam(r, "shareid")
|
shareID := chi.URLParam(r, "shareid")
|
||||||
// FIXME: isPublicShare is already doing a GetShare and GetPublicShare,
|
// FIXME: isPublicShare is already doing a GetShare and GetPublicShare,
|
||||||
// we should just reuse that object when doing updates
|
// we should just reuse that object when doing updates
|
||||||
if h.isPublicShare(r, shareID) {
|
if share, ok := h.isPublicShare(r, shareID); ok {
|
||||||
h.updatePublicShare(w, r, shareID)
|
h.updatePublicShare(w, r, share)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.updateShare(w, r, shareID) // TODO PUT is used with incomplete data to update a share}
|
|
||||||
|
if share, ok := h.isUserShare(r, shareID); ok {
|
||||||
|
h.updateShare(w, r, share) // TODO PUT is used with incomplete data to update a share}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "cannot find share", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID string) {
|
func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, share *collaboration.Share) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
sublog := appctx.GetLogger(ctx).With().Str("shareID", shareID).Logger()
|
sublog := appctx.GetLogger(ctx).With().Str("shareID", share.GetId().GetOpaqueId()).Logger()
|
||||||
|
|
||||||
client, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
client, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -696,28 +701,7 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
shareR, err := client.GetShare(r.Context(), &collaboration.GetShareRequest{
|
info, status, err := h.getResourceInfoByID(ctx, client, share.ResourceId)
|
||||||
Ref: &collaboration.ShareReference{
|
|
||||||
Spec: &collaboration.ShareReference_Id{
|
|
||||||
Id: &collaboration.ShareId{
|
|
||||||
OpaqueId: shareID,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error sending a grpc update share request", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if shareR.Status.GetCode() != rpc.Code_CODE_OK {
|
|
||||||
// TODO: error code from shareR response
|
|
||||||
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "cant find requested share", fmt.Errorf("Can't find share %s. Response code: %v", shareID, shareR.Status.GetCode()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
info, status, err := h.getResourceInfoByID(ctx, client, shareR.Share.ResourceId)
|
|
||||||
if err != nil || status.Code != rpc.Code_CODE_OK {
|
if err != nil || status.Code != rpc.Code_CODE_OK {
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err)
|
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err)
|
||||||
return
|
return
|
||||||
@@ -729,7 +713,7 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
shareR.Share.Permissions = &collaboration.SharePermissions{Permissions: role.CS3ResourcePermissions()}
|
share.Permissions = &collaboration.SharePermissions{Permissions: role.CS3ResourcePermissions()}
|
||||||
|
|
||||||
var fieldMaskPaths = []string{"permissions"}
|
var fieldMaskPaths = []string{"permissions"}
|
||||||
|
|
||||||
@@ -747,16 +731,16 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st
|
|||||||
Nanos: uint32(expiration.UnixNano() % int64(time.Second)),
|
Nanos: uint32(expiration.UnixNano() % int64(time.Second)),
|
||||||
}
|
}
|
||||||
|
|
||||||
shareR.Share.Expiration = expirationTs
|
share.Expiration = expirationTs
|
||||||
fieldMaskPaths = append(fieldMaskPaths, "expiration")
|
fieldMaskPaths = append(fieldMaskPaths, "expiration")
|
||||||
} else if r.Form.Has("expireDate") {
|
} else if r.Form.Has("expireDate") {
|
||||||
// If the expiration parameter was sent but is empty, then the expiration should be removed.
|
// If the expiration parameter was sent but is empty, then the expiration should be removed.
|
||||||
shareR.Share.Expiration = nil
|
share.Expiration = nil
|
||||||
fieldMaskPaths = append(fieldMaskPaths, "expiration")
|
fieldMaskPaths = append(fieldMaskPaths, "expiration")
|
||||||
}
|
}
|
||||||
|
|
||||||
uReq := &collaboration.UpdateShareRequest{
|
uReq := &collaboration.UpdateShareRequest{
|
||||||
Share: shareR.Share,
|
Share: share,
|
||||||
UpdateMask: &fieldmaskpb.FieldMask{
|
UpdateMask: &fieldmaskpb.FieldMask{
|
||||||
Paths: fieldMaskPaths,
|
Paths: fieldMaskPaths,
|
||||||
},
|
},
|
||||||
@@ -777,10 +761,10 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st
|
|||||||
}
|
}
|
||||||
|
|
||||||
if currentUser, ok := ctxpkg.ContextGetUser(ctx); ok {
|
if currentUser, ok := ctxpkg.ContextGetUser(ctx); ok {
|
||||||
h.statCache.RemoveStat(currentUser.Id, shareR.Share.ResourceId)
|
h.statCache.RemoveStat(currentUser.Id, share.ResourceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
share, err := conversions.CS3Share2ShareData(ctx, uRes.Share)
|
resultshare, err := conversions.CS3Share2ShareData(ctx, uRes.Share)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err)
|
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err)
|
||||||
return
|
return
|
||||||
@@ -807,24 +791,30 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
h.addFileInfo(r.Context(), share, statRes.Info)
|
h.addFileInfo(r.Context(), resultshare, statRes.Info)
|
||||||
h.mapUserIds(ctx, client, share)
|
h.mapUserIds(ctx, client, resultshare)
|
||||||
|
|
||||||
response.WriteOCSSuccess(w, r, share)
|
response.WriteOCSSuccess(w, r, resultshare)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveShare handles DELETE requests on /apps/files_sharing/api/v1/shares/(shareid)
|
// RemoveShare handles DELETE requests on /apps/files_sharing/api/v1/shares/(shareid)
|
||||||
func (h *Handler) RemoveShare(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) RemoveShare(w http.ResponseWriter, r *http.Request) {
|
||||||
shareID := chi.URLParam(r, "shareid")
|
shareID := chi.URLParam(r, "shareid")
|
||||||
switch {
|
if share, ok := h.isPublicShare(r, shareID); ok {
|
||||||
case h.isPublicShare(r, shareID):
|
h.removePublicShare(w, r, share)
|
||||||
h.removePublicShare(w, r, shareID)
|
return
|
||||||
case h.isUserShare(r, shareID):
|
|
||||||
h.removeUserShare(w, r, shareID)
|
|
||||||
default:
|
|
||||||
// The request is a remove space member request.
|
|
||||||
h.removeSpaceMember(w, r, shareID)
|
|
||||||
}
|
}
|
||||||
|
if share, ok := h.isUserShare(r, shareID); ok {
|
||||||
|
h.removeUserShare(w, r, share)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if prov, ok := h.isSpaceShare(r, shareID); ok {
|
||||||
|
// The request is a remove space member request.
|
||||||
|
h.removeSpaceMember(w, r, shareID, prov)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "cannot find share", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListShares handles GET requests on /apps/files_sharing/api/v1/shares
|
// ListShares handles GET requests on /apps/files_sharing/api/v1/shares
|
||||||
|
|||||||
Generated
Vendored
+16
-8
@@ -143,7 +143,21 @@ func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *p
|
|||||||
response.WriteOCSSuccess(w, r, nil)
|
response.WriteOCSSuccess(w, r, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spaceID string) {
|
func (h *Handler) isSpaceShare(r *http.Request, spaceID string) (*registry.ProviderInfo, bool) {
|
||||||
|
ref, err := storagespace.ParseReference(spaceID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ref.ResourceId.OpaqueId == "" {
|
||||||
|
ref.ResourceId.OpaqueId = ref.ResourceId.SpaceId
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := h.findProvider(r.Context(), &ref)
|
||||||
|
return p, err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spaceID string, prov *registry.ProviderInfo) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
shareWith := r.URL.Query().Get("shareWith")
|
shareWith := r.URL.Query().Get("shareWith")
|
||||||
@@ -168,13 +182,7 @@ func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spac
|
|||||||
ref.ResourceId.OpaqueId = ref.ResourceId.SpaceId
|
ref.ResourceId.OpaqueId = ref.ResourceId.SpaceId
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := h.findProvider(ctx, &ref)
|
providerClient, err := h.getStorageProviderClient(prov)
|
||||||
if err != nil {
|
|
||||||
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
providerClient, err := h.getStorageProviderClient(p)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider client", err)
|
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider client", err)
|
||||||
return
|
return
|
||||||
|
|||||||
Generated
Vendored
+7
-22
@@ -129,7 +129,7 @@ func (h *Handler) createUserShare(w http.ResponseWriter, r *http.Request, statIn
|
|||||||
return share, nil
|
return share, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) isUserShare(r *http.Request, oid string) bool {
|
func (h *Handler) isUserShare(r *http.Request, oid string) (*collaboration.Share, bool) {
|
||||||
logger := appctx.GetLogger(r.Context())
|
logger := appctx.GetLogger(r.Context())
|
||||||
client, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
client, err := pool.GetGatewayServiceClient(h.gatewayAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -147,13 +147,13 @@ func (h *Handler) isUserShare(r *http.Request, oid string) bool {
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Err(err)
|
logger.Err(err)
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return getShareRes.GetShare() != nil
|
return getShareRes.GetShare(), getShareRes.GetShare() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, shareID string) {
|
func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, share *collaboration.Share) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
uClient, err := h.getClient()
|
uClient, err := h.getClient()
|
||||||
@@ -164,26 +164,11 @@ func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, shareI
|
|||||||
|
|
||||||
shareRef := &collaboration.ShareReference{
|
shareRef := &collaboration.ShareReference{
|
||||||
Spec: &collaboration.ShareReference_Id{
|
Spec: &collaboration.ShareReference_Id{
|
||||||
Id: &collaboration.ShareId{
|
Id: share.Id,
|
||||||
OpaqueId: shareID,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Get the share, so that we can include it in the response.
|
|
||||||
getShareResp, err := uClient.GetShare(ctx, &collaboration.GetShareRequest{Ref: shareRef})
|
|
||||||
if err != nil {
|
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error sending a grpc delete share request", err)
|
|
||||||
return
|
|
||||||
} else if getShareResp.Status.Code != rpc.Code_CODE_OK {
|
|
||||||
if getShareResp.Status.Code == rpc.Code_CODE_NOT_FOUND {
|
|
||||||
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "not found", nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "deleting share failed", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := conversions.CS3Share2ShareData(ctx, getShareResp.Share)
|
data, err := conversions.CS3Share2ShareData(ctx, share)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "deleting share failed", err)
|
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "deleting share failed", err)
|
||||||
return
|
return
|
||||||
@@ -207,7 +192,7 @@ func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, shareI
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if currentUser, ok := ctxpkg.ContextGetUser(ctx); ok {
|
if currentUser, ok := ctxpkg.ContextGetUser(ctx); ok {
|
||||||
h.statCache.RemoveStat(currentUser.Id, getShareResp.Share.ResourceId)
|
h.statCache.RemoveStat(currentUser.Id, share.ResourceId)
|
||||||
}
|
}
|
||||||
response.WriteOCSSuccess(w, r, data)
|
response.WriteOCSSuccess(w, r, data)
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-5
@@ -22,6 +22,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -534,9 +535,10 @@ func (r *registry) findProvidersForResource(ctx context.Context, id string, find
|
|||||||
|
|
||||||
// findProvidersForAbsolutePathReference takes a path and returns the storage provider with the longest matching path prefix
|
// findProvidersForAbsolutePathReference takes a path and returns the storage provider with the longest matching path prefix
|
||||||
// FIXME use regex to return the correct provider when multiple are configured
|
// FIXME use regex to return the correct provider when multiple are configured
|
||||||
func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, path string, unique, unrestricted bool, _ string) []*registrypb.ProviderInfo {
|
func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, requestedPath string, unique, unrestricted bool, _ string) []*registrypb.ProviderInfo {
|
||||||
currentUser := ctxpkg.ContextMustGetUser(ctx)
|
currentUser := ctxpkg.ContextMustGetUser(ctx)
|
||||||
|
|
||||||
|
pathSegments := strings.Split(strings.TrimPrefix(requestedPath, string(os.PathSeparator)), string(os.PathSeparator))
|
||||||
deepestMountPath := ""
|
deepestMountPath := ""
|
||||||
var deepestMountSpace *providerpb.StorageSpace
|
var deepestMountSpace *providerpb.StorageSpace
|
||||||
var deepestMountPathProvider *registrypb.ProviderInfo
|
var deepestMountPathProvider *registrypb.ProviderInfo
|
||||||
@@ -549,12 +551,42 @@ func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, pa
|
|||||||
var spaces []*providerpb.StorageSpace
|
var spaces []*providerpb.StorageSpace
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
// check if any space in the provider has a valid mountpoint
|
||||||
|
containsRelatedSpace := false
|
||||||
|
|
||||||
|
spaceLoop:
|
||||||
|
for _, space := range provider.Spaces {
|
||||||
|
spacePath, _ := space.SpacePath(currentUser, nil)
|
||||||
|
spacePathSegments := strings.Split(strings.TrimPrefix(spacePath, string(os.PathSeparator)), string(os.PathSeparator))
|
||||||
|
|
||||||
|
for i, segment := range spacePathSegments {
|
||||||
|
if i >= len(pathSegments) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if pathSegments[i] != segment {
|
||||||
|
if segment != "" && !strings.Contains(segment, "{{") {
|
||||||
|
// Mount path points elsewhere -> irrelevant
|
||||||
|
continue spaceLoop
|
||||||
|
}
|
||||||
|
// Encountered a template which couldn't be filled -> potentially relevant
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
containsRelatedSpace = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if !containsRelatedSpace {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// when listing paths also return mountpoints
|
// when listing paths also return mountpoints
|
||||||
filters := []*providerpb.ListStorageSpacesRequest_Filter{
|
filters := []*providerpb.ListStorageSpacesRequest_Filter{
|
||||||
{
|
{
|
||||||
Type: providerpb.ListStorageSpacesRequest_Filter_TYPE_PATH,
|
Type: providerpb.ListStorageSpacesRequest_Filter_TYPE_PATH,
|
||||||
Term: &providerpb.ListStorageSpacesRequest_Filter_Path{
|
Term: &providerpb.ListStorageSpacesRequest_Filter_Path{
|
||||||
Path: strings.TrimPrefix(path, p.ProviderPath),
|
Path: strings.TrimPrefix(requestedPath, p.ProviderPath), // FIXME this no longer has an effect as the p.Providerpath is always empty
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -595,14 +627,14 @@ func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, pa
|
|||||||
|
|
||||||
// determine deepest mount point
|
// determine deepest mount point
|
||||||
switch {
|
switch {
|
||||||
case spacePath == path && unique:
|
case spacePath == requestedPath && unique:
|
||||||
validSpaces = append(validSpaces, space)
|
validSpaces = append(validSpaces, space)
|
||||||
|
|
||||||
deepestMountPath = spacePath
|
deepestMountPath = spacePath
|
||||||
deepestMountSpace = space
|
deepestMountSpace = space
|
||||||
deepestMountPathProvider = p
|
deepestMountPathProvider = p
|
||||||
|
|
||||||
case !unique && isSubpath(spacePath, path):
|
case !unique && isSubpath(spacePath, requestedPath):
|
||||||
// and add all providers below and exactly matching the path
|
// and add all providers below and exactly matching the path
|
||||||
// requested /foo, mountPath /foo/sub
|
// requested /foo, mountPath /foo/sub
|
||||||
validSpaces = append(validSpaces, space)
|
validSpaces = append(validSpaces, space)
|
||||||
@@ -612,7 +644,7 @@ func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, pa
|
|||||||
deepestMountPathProvider = p
|
deepestMountPathProvider = p
|
||||||
}
|
}
|
||||||
|
|
||||||
case isSubpath(path, spacePath) && len(spacePath) > len(deepestMountPath):
|
case isSubpath(requestedPath, spacePath) && len(spacePath) > len(deepestMountPath):
|
||||||
// eg. three providers: /foo, /foo/sub, /foo/sub/bar
|
// eg. three providers: /foo, /foo/sub, /foo/sub/bar
|
||||||
// requested /foo/sub/mob
|
// requested /foo/sub/mob
|
||||||
deepestMountPath = spacePath
|
deepestMountPath = spacePath
|
||||||
|
|||||||
Vendored
+1
-1
@@ -349,7 +349,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1
|
|||||||
github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1
|
github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1
|
||||||
github.com/cs3org/go-cs3apis/cs3/tx/v1beta1
|
github.com/cs3org/go-cs3apis/cs3/tx/v1beta1
|
||||||
github.com/cs3org/go-cs3apis/cs3/types/v1beta1
|
github.com/cs3org/go-cs3apis/cs3/types/v1beta1
|
||||||
# github.com/cs3org/reva/v2 v2.13.4-0.20230523132457-4fb99464ab8d
|
# github.com/cs3org/reva/v2 v2.13.4-0.20230525110514-9334e2174492
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
github.com/cs3org/reva/v2/cmd/revad/internal/grace
|
github.com/cs3org/reva/v2/cmd/revad/internal/grace
|
||||||
github.com/cs3org/reva/v2/cmd/revad/runtime
|
github.com/cs3org/reva/v2/cmd/revad/runtime
|
||||||
|
|||||||
Reference in New Issue
Block a user