bump reva to v2.15.1-0.20230809113840-3ceaf17cf7fb (#6978)

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
Jörn Friedrich Dreyer
2023-08-09 16:01:46 +02:00
committed by GitHub
parent fecd836159
commit bae37cf20b
22 changed files with 1390 additions and 1405 deletions

3
go.mod
View File

@@ -13,7 +13,7 @@ require (
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/coreos/go-oidc/v3 v3.6.0
github.com/cs3org/go-cs3apis v0.0.0-20230516150832-730ac860c71d
github.com/cs3org/reva/v2 v2.15.1-0.20230731132956-0fb5212d0551
github.com/cs3org/reva/v2 v2.15.1-0.20230809113840-3ceaf17cf7fb
github.com/disintegration/imaging v1.6.2
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
github.com/egirna/icap-client v0.1.1
@@ -160,7 +160,6 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/crewjam/httperr v0.2.0 // indirect
github.com/crewjam/saml v0.4.13 // indirect
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect

6
go.sum
View File

@@ -864,10 +864,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/saml v0.4.13 h1:TYHggH/hwP7eArqiXSJUvtOPNzQDyQ7vwmwEqlFWhMc=
github.com/crewjam/saml v0.4.13/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA=
github.com/cs3org/reva/v2 v2.15.1-0.20230731132956-0fb5212d0551 h1:8/cX/Fjo0SWzuHH+7SUK2w9t/9yR449woDR2wTzNW7k=
github.com/cs3org/reva/v2 v2.15.1-0.20230731132956-0fb5212d0551/go.mod h1:4UKDbqt/GHQDdNr2fv4XQVlnz6KC9DQdpV2P2fY2Mkg=
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/cs3org/reva/v2 v2.15.1-0.20230809113840-3ceaf17cf7fb h1:ObjTDMACxkuV7pxK8zGwhqqka2ze4KI8zcNF4H6k4Yk=
github.com/cs3org/reva/v2 v2.15.1-0.20230809113840-3ceaf17cf7fb/go.mod h1:F5wAUTPMvq+ze77PU/xl7qhc21YsEIfcl2RuI4H7yJo=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=

View File

@@ -387,8 +387,6 @@ _ocdav: api compatibility, return correct status code_
- [coreApiAuthWebDav/webDavSpecialURLs.feature:16](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L16)
- [coreApiAuthWebDav/webDavSpecialURLs.feature:27](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L27)
- [coreApiAuthWebDav/webDavSpecialURLs.feature:58](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L58)
- [coreApiAuthWebDav/webDavSpecialURLs.feature:69](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L69)
- [coreApiAuthWebDav/webDavSpecialURLs.feature:79](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L79)
- [coreApiAuthWebDav/webDavSpecialURLs.feature:91](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L91)
- [coreApiAuthWebDav/webDavSpecialURLs.feature:103](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L103)

View File

@@ -39,7 +39,6 @@ import (
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/juliangruber/go-intersect"
"github.com/mitchellh/mapstructure"
"github.com/rs/zerolog/log"
"google.golang.org/grpc"
)
@@ -111,10 +110,8 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) {
for {
select {
case <-t.C:
log.Debug().Msg("app provider tick, registering Provider")
service.registerProvider()
case <-service.context.Done():
log.Debug().Msg("app provider stopped")
t.Stop()
}
}

View File

@@ -840,7 +840,7 @@ func requiresExplicitFetching(n *xml.Name) bool {
switch n.Space {
case net.NsDav:
switch n.Local {
case "quota-available-bytes", "quota-used-bytes":
case "quota-available-bytes", "quota-used-bytes", "lockdiscovery":
// A <DAV:allprop> PROPFIND request SHOULD NOT return DAV:quota-available-bytes and DAV:quota-used-bytes
// from https://www.rfc-editor.org/rfc/rfc4331.html#section-2
return true
@@ -1663,21 +1663,14 @@ func (c *countingReader) Read(p []byte) (int, error) {
}
func metadataKeyOf(n *xml.Name) string {
switch n.Space {
case net.NsDav:
if n.Local == "quota-available-bytes" {
return "quota"
}
case net.NsOwncloud:
if n.Local == "share-types" {
return "share-types"
}
if n.Local == "tags" {
return "tags"
}
switch n.Local {
case "quota-available-bytes":
return "quota"
case "share-types", "tags", "lockdiscovery":
return n.Local
default:
return fmt.Sprintf("%s/%s", n.Space, n.Local)
}
return fmt.Sprintf("%s/%s", n.Space, n.Local)
}
// UnmarshalXML appends the property names enclosed within start to pn.

View File

@@ -414,9 +414,17 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "missing resource information", fmt.Errorf("error getting resource information"))
return
}
if statRes.GetStatus().GetCode() != rpc.Code_CODE_OK {
if statRes.GetStatus().GetCode() == rpc.Code_CODE_NOT_FOUND {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "update public share: resource not found", err)
return
}
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc stat request failed for stat when updating a public share", err)
return
}
// empty permissions mean internal link here - NOT denial. Hence we need an extra check
if !sufficientPermissions(statRes.Info.PermissionSet, newPermissions, true) {
if !sufficientPermissions(statRes.GetInfo().GetPermissionSet(), newPermissions, true) {
response.WriteOCSError(w, r, http.StatusForbidden, "no share permission", nil)
return
}

View File

@@ -245,6 +245,11 @@ func (h *Handler) listUserShares(r *http.Request, filters []*collaboration.Filte
h.addFileInfo(ctx, data, info)
h.mapUserIds(ctx, client, data)
// Filter out a share if ShareWith is not found because the user or group already deleted
if data.ShareWith == "" {
continue
}
log.Debug().Interface("share", s).Interface("info", info).Interface("shareData", data).Msg("mapped")
ocsDataPayload = append(ocsDataPayload, data)
}

View File

@@ -44,6 +44,18 @@ import (
"go.opentelemetry.io/otel/trace"
)
func init() {
// register method with chi before any routing is set up
chi.RegisterMethod(ocdav.MethodPropfind)
chi.RegisterMethod(ocdav.MethodProppatch)
chi.RegisterMethod(ocdav.MethodLock)
chi.RegisterMethod(ocdav.MethodUnlock)
chi.RegisterMethod(ocdav.MethodCopy)
chi.RegisterMethod(ocdav.MethodMove)
chi.RegisterMethod(ocdav.MethodMkcol)
chi.RegisterMethod(ocdav.MethodReport)
}
const (
// ServerName to use when announcing the service to the registry
ServerName = "ocdav"
@@ -73,17 +85,6 @@ func Service(opts ...Option) (micro.Service, error) {
return nil, err
}
// Comment back in after resolving the issue in go-chi.
// See comment in line 87.
// register additional webdav verbs
// chi.RegisterMethod(ocdav.MethodPropfind)
// chi.RegisterMethod(ocdav.MethodProppatch)
// chi.RegisterMethod(ocdav.MethodLock)
// chi.RegisterMethod(ocdav.MethodUnlock)
// chi.RegisterMethod(ocdav.MethodCopy)
// chi.RegisterMethod(ocdav.MethodMove)
// chi.RegisterMethod(ocdav.MethodMkcol)
// chi.RegisterMethod(ocdav.MethodReport)
r := chi.NewRouter()
tp := sopts.TraceProvider
@@ -107,10 +108,6 @@ func Service(opts ...Option) (micro.Service, error) {
}
r.Handle("/*", revaService.Handler())
// This is a workaround for the go-chi concurrent map read write issue.
// After the issue has been solved upstream in go-chi we should switch
// back to using `chi.RegisterMethod`.
r.MethodNotAllowed(http.HandlerFunc(revaService.Handler().ServeHTTP))
_ = chi.Walk(r, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
sopts.Logger.Debug().Str("service", "ocdav").Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint")

File diff suppressed because it is too large Load Diff

View File

@@ -337,17 +337,6 @@ func (m *Manager) Share(ctx context.Context, md *provider.ResourceInfo, g *colla
eg.Go(func() error {
err := m.Cache.Add(ctx, md.Id.StorageId, md.Id.SpaceId, shareID, s)
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := m.Cache.Sync(ctx, md.Id.StorageId, md.Id.SpaceId); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = m.Cache.Add(ctx, md.Id.StorageId, md.Id.SpaceId, shareID, s)
// TODO try more often?
}
if err != nil {
span.RecordError(err)
@@ -359,17 +348,6 @@ func (m *Manager) Share(ctx context.Context, md *provider.ResourceInfo, g *colla
eg.Go(func() error {
err := m.CreatedCache.Add(ctx, s.GetCreator().GetOpaqueId(), shareID)
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := m.CreatedCache.Sync(ctx, s.GetCreator().GetOpaqueId()); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = m.CreatedCache.Add(ctx, s.GetCreator().GetOpaqueId(), shareID)
// TODO try more often?
}
if err != nil {
span.RecordError(err)
@@ -391,16 +369,6 @@ func (m *Manager) Share(ctx context.Context, md *provider.ResourceInfo, g *colla
State: collaboration.ShareState_SHARE_STATE_PENDING,
}
err := m.UserReceivedStates.Add(ctx, userid, spaceID, rs)
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := m.UserReceivedStates.Sync(ctx, s.GetCreator().GetOpaqueId()); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = m.UserReceivedStates.Add(ctx, userid, spaceID, rs)
// TODO try more often?
}
if err != nil {
span.RecordError(err)
@@ -413,16 +381,6 @@ func (m *Manager) Share(ctx context.Context, md *provider.ResourceInfo, g *colla
eg.Go(func() error {
groupid := g.Grantee.GetGroupId().GetOpaqueId()
err := m.GroupReceivedCache.Add(ctx, groupid, shareID)
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := m.GroupReceivedCache.Sync(ctx, groupid); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = m.GroupReceivedCache.Add(ctx, groupid, shareID)
// TODO try more often?
}
if err != nil {
span.RecordError(err)
@@ -445,13 +403,11 @@ func (m *Manager) Share(ctx context.Context, md *provider.ResourceInfo, g *colla
// getByID must be called in a lock-controlled block.
func (m *Manager) getByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.Share, error) {
storageID, spaceID, _ := shareid.Decode(id.OpaqueId)
// sync cache, maybe our data is outdated
err := m.Cache.Sync(ctx, storageID, spaceID)
share, err := m.Cache.Get(ctx, storageID, spaceID, id.OpaqueId)
if err != nil {
return nil, err
}
share := m.Cache.Get(storageID, spaceID, id.OpaqueId)
if share == nil {
return nil, errtypes.NotFound(id.String())
}
@@ -460,12 +416,10 @@ func (m *Manager) getByID(ctx context.Context, id *collaboration.ShareId) (*coll
// getByKey must be called in a lock-controlled block.
func (m *Manager) getByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.Share, error) {
err := m.Cache.Sync(ctx, key.ResourceId.StorageId, key.ResourceId.SpaceId)
spaceShares, err := m.Cache.ListSpace(ctx, key.ResourceId.StorageId, key.ResourceId.SpaceId)
if err != nil {
return nil, err
}
spaceShares := m.Cache.ListSpace(key.ResourceId.StorageId, key.ResourceId.SpaceId)
for _, share := range spaceShares.Shares {
if utils.GranteeEqual(key.Grantee, share.Grantee) && utils.ResourceIDEqual(share.ResourceId, key.ResourceId) {
return share, nil
@@ -678,15 +632,11 @@ func (m *Manager) listSharesByIDs(ctx context.Context, user *userv1beta1.User, f
var ss []*collaboration.Share
for providerID, spaces := range providerSpaces {
for spaceID := range spaces {
err := m.Cache.Sync(ctx, providerID, spaceID)
shares, err := m.Cache.ListSpace(ctx, providerID, spaceID)
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return nil, err
}
shares := m.Cache.ListSpace(providerID, spaceID)
for _, s := range shares.Shares {
if share.IsExpired(s) {
if err := m.removeShare(ctx, s); err != nil {
@@ -737,20 +687,20 @@ func (m *Manager) listCreatedShares(ctx context.Context, user *userv1beta1.User,
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "listCreatedShares")
defer span.End()
var ss []*collaboration.Share
if err := m.CreatedCache.Sync(ctx, user.Id.OpaqueId); err != nil {
list, err := m.CreatedCache.List(ctx, user.Id.OpaqueId)
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return ss, err
return nil, err
}
for ssid, spaceShareIDs := range m.CreatedCache.List(user.Id.OpaqueId) {
var ss []*collaboration.Share
for ssid, spaceShareIDs := range list {
storageID, spaceID, _ := shareid.Decode(ssid)
err := m.Cache.Sync(ctx, storageID, spaceID)
spaceShares, err := m.Cache.ListSpace(ctx, storageID, spaceID)
if err != nil {
continue
}
spaceShares := m.Cache.ListSpace(storageID, spaceID)
for shareid := range spaceShareIDs.IDs {
s := spaceShares.Shares[shareid]
if s == nil {
@@ -800,10 +750,11 @@ func (m *Manager) ListReceivedShares(ctx context.Context, filters []*collaborati
// first collect all spaceids the user has access to as a group member
for _, group := range user.Groups {
if err := m.GroupReceivedCache.Sync(ctx, group); err != nil {
list, err := m.GroupReceivedCache.List(ctx, group)
if err != nil {
continue // ignore error, cache will be updated on next read
}
for ssid, spaceShareIDs := range m.GroupReceivedCache.List(group) {
for ssid, spaceShareIDs := range list {
// add a pending entry, the state will be updated
// when reading the received shares below if they have already been accepted or denied
var rs *receivedsharecache.Space
@@ -825,6 +776,7 @@ func (m *Manager) ListReceivedShares(ctx context.Context, filters []*collaborati
}
// add all spaces the user has receved shares for, this includes mount points and share state for groups
// TODO: rewrite this code to not use the internal strucs anymore (e.g. by adding a List method). Sync can then be made private.
_ = m.UserReceivedStates.Sync(ctx, user.Id.OpaqueId) // ignore error, cache will be updated on next read
if m.UserReceivedStates.ReceivedSpaces[user.Id.OpaqueId] != nil {
@@ -872,13 +824,9 @@ func (m *Manager) ListReceivedShares(ctx context.Context, filters []*collaborati
g.Go(func() error {
for w := range work {
storageID, spaceID, _ := shareid.Decode(w.ssid)
err := m.Cache.Sync(ctx, storageID, spaceID)
if err != nil {
continue
}
for shareID, state := range w.rspace.States {
s := m.Cache.Get(storageID, spaceID, shareID)
if s == nil {
s, err := m.Cache.Get(ctx, storageID, spaceID, shareID)
if err != nil || s == nil {
continue
}
if share.IsExpired(s) {
@@ -952,9 +900,8 @@ func (m *Manager) convert(ctx context.Context, userID string, s *collaboration.S
storageID, spaceID, _ := shareid.Decode(s.Id.OpaqueId)
_ = m.UserReceivedStates.Sync(ctx, userID) // ignore error, cache will be updated on next read
state := m.UserReceivedStates.Get(userID, storageID+shareid.IDDelimiter+spaceID, s.Id.GetOpaqueId())
if state != nil {
state, err := m.UserReceivedStates.Get(ctx, userID, storageID+shareid.IDDelimiter+spaceID, s.Id.GetOpaqueId())
if err == nil && state != nil {
rs.State = state.State
rs.MountPoint = state.MountPoint
}
@@ -1031,14 +978,6 @@ func (m *Manager) UpdateReceivedShare(ctx context.Context, receivedShare *collab
userID := ctxpkg.ContextMustGetUser(ctx)
err = m.UserReceivedStates.Add(ctx, userID.GetId().GetOpaqueId(), rs.Share.ResourceId.StorageId+shareid.IDDelimiter+rs.Share.ResourceId.SpaceId, rs)
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
// when persisting fails, download, readd and persist again
if err := m.UserReceivedStates.Sync(ctx, userID.GetId().GetOpaqueId()); err != nil {
return nil, err
}
err = m.UserReceivedStates.Add(ctx, userID.GetId().GetOpaqueId(), rs.Share.ResourceId.StorageId+shareid.IDDelimiter+rs.Share.ResourceId.SpaceId, rs)
// TODO try more often?
}
if err != nil {
return nil, err
}
@@ -1120,29 +1059,13 @@ func (m *Manager) removeShare(ctx context.Context, s *collaboration.Share) error
eg.Go(func() error {
storageID, spaceID, _ := shareid.Decode(s.Id.OpaqueId)
err := m.Cache.Remove(ctx, storageID, spaceID, s.Id.OpaqueId)
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := m.Cache.Sync(ctx, storageID, spaceID); err != nil {
return err
}
err = m.Cache.Remove(ctx, storageID, spaceID, s.Id.OpaqueId)
// TODO try more often?
}
return err
})
eg.Go(func() error {
// remove from created cache
err := m.CreatedCache.Remove(ctx, s.GetCreator().GetOpaqueId(), s.Id.OpaqueId)
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := m.CreatedCache.Sync(ctx, s.GetCreator().GetOpaqueId()); err != nil {
return err
}
err = m.CreatedCache.Remove(ctx, s.GetCreator().GetOpaqueId(), s.Id.OpaqueId)
// TODO try more often?
}
return err
return m.CreatedCache.Remove(ctx, s.GetCreator().GetOpaqueId(), s.Id.OpaqueId)
})
// TODO remove from grantee cache

View File

@@ -127,6 +127,13 @@ func (c *Cache) Add(ctx context.Context, storageID, spaceID, shareID string, sha
unlock := c.LockSpace(spaceID)
defer unlock()
if c.Providers[storageID] == nil || c.Providers[storageID].Spaces[spaceID] == nil {
err := c.syncWithLock(ctx, storageID, spaceID)
if err != nil {
return err
}
}
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "Add")
defer span.End()
span.SetAttributes(attribute.String("cs3.storageid", storageID), attribute.String("cs3.spaceid", spaceID), attribute.String("cs3.shareid", shareID))
@@ -140,9 +147,25 @@ func (c *Cache) Add(ctx context.Context, storageID, spaceID, shareID string, sha
return fmt.Errorf("missing share id")
}
c.initializeIfNeeded(storageID, spaceID)
c.Providers[storageID].Spaces[spaceID].Shares[shareID] = share
return c.Persist(ctx, storageID, spaceID)
persistFunc := func() error {
c.Providers[storageID].Spaces[spaceID].Shares[shareID] = share
return c.Persist(ctx, storageID, spaceID)
}
err := persistFunc()
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := c.syncWithLock(ctx, storageID, spaceID); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = persistFunc()
}
return err
}
// Remove removes a share from the cache
@@ -150,38 +173,68 @@ func (c *Cache) Remove(ctx context.Context, storageID, spaceID, shareID string)
unlock := c.LockSpace(spaceID)
defer unlock()
if c.Providers[storageID] == nil || c.Providers[storageID].Spaces[spaceID] == nil {
err := c.syncWithLock(ctx, storageID, spaceID)
if err != nil {
return err
}
}
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "Remove")
defer span.End()
span.SetAttributes(attribute.String("cs3.storageid", storageID), attribute.String("cs3.spaceid", spaceID), attribute.String("cs3.shareid", shareID))
if c.Providers[storageID] == nil ||
c.Providers[storageID].Spaces[spaceID] == nil {
return nil
}
delete(c.Providers[storageID].Spaces[spaceID].Shares, shareID)
persistFunc := func() error {
if c.Providers[storageID] == nil ||
c.Providers[storageID].Spaces[spaceID] == nil {
return nil
}
delete(c.Providers[storageID].Spaces[spaceID].Shares, shareID)
return c.Persist(ctx, storageID, spaceID)
return c.Persist(ctx, storageID, spaceID)
}
err := persistFunc()
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := c.syncWithLock(ctx, storageID, spaceID); err != nil {
return err
}
err = persistFunc()
}
return err
}
// Get returns one entry from the cache
func (c *Cache) Get(storageID, spaceID, shareID string) *collaboration.Share {
func (c *Cache) Get(ctx context.Context, storageID, spaceID, shareID string) (*collaboration.Share, error) {
// sync cache, maybe our data is outdated
err := c.Sync(ctx, storageID, spaceID)
if err != nil {
return nil, err
}
if c.Providers[storageID] == nil ||
c.Providers[storageID].Spaces[spaceID] == nil {
return nil
return nil, nil
}
return c.Providers[storageID].Spaces[spaceID].Shares[shareID]
return c.Providers[storageID].Spaces[spaceID].Shares[shareID], nil
}
// ListSpace returns the list of shares in a given space
func (c *Cache) ListSpace(storageID, spaceID string) *Shares {
if c.Providers[storageID] == nil || c.Providers[storageID].Spaces[spaceID] == nil {
return &Shares{}
func (c *Cache) ListSpace(ctx context.Context, storageID, spaceID string) (*Shares, error) {
// sync cache, maybe our data is outdated
err := c.Sync(ctx, storageID, spaceID)
if err != nil {
return nil, err
}
return c.Providers[storageID].Spaces[spaceID]
if c.Providers[storageID] == nil || c.Providers[storageID].Spaces[spaceID] == nil {
return &Shares{}, nil
}
return c.Providers[storageID].Spaces[spaceID], nil
}
// PersistWithTime persists the data of one space if it has not been modified since the given mtime
func (c *Cache) PersistWithTime(ctx context.Context, storageID, spaceID string, mtime time.Time) error {
// Persist persists the data of one space
func (c *Cache) Persist(ctx context.Context, storageID, spaceID string) error {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "PersistWithTime")
defer span.End()
span.SetAttributes(attribute.String("cs3.storageid", storageID), attribute.String("cs3.spaceid", spaceID))
@@ -192,7 +245,7 @@ func (c *Cache) PersistWithTime(ctx context.Context, storageID, spaceID string,
}
oldMtime := c.Providers[storageID].Spaces[spaceID].Mtime
c.Providers[storageID].Spaces[spaceID].Mtime = mtime
c.Providers[storageID].Spaces[spaceID].Mtime = time.Now()
// FIXME there is a race when between this time now and the below Uploed another process also updates the file -> we need a lock
createdBytes, err := json.Marshal(c.Providers[storageID].Spaces[spaceID])
@@ -213,7 +266,8 @@ func (c *Cache) PersistWithTime(ctx context.Context, storageID, spaceID string,
if err = c.storage.Upload(ctx, metadata.UploadRequest{
Path: jsonPath,
Content: createdBytes,
IfUnmodifiedSince: c.Providers[storageID].Spaces[spaceID].Mtime,
IfUnmodifiedSince: oldMtime,
MTime: c.Providers[storageID].Spaces[spaceID].Mtime,
}); err != nil {
c.Providers[storageID].Spaces[spaceID].Mtime = oldMtime
span.RecordError(err)
@@ -224,16 +278,15 @@ func (c *Cache) PersistWithTime(ctx context.Context, storageID, spaceID string,
return nil
}
// Persist persists the data of one space
func (c *Cache) Persist(ctx context.Context, storageID, spaceID string) error {
return c.PersistWithTime(ctx, storageID, spaceID, time.Now())
}
// Sync updates the in-memory data with the data from the storage if it is outdated
func (c *Cache) Sync(ctx context.Context, storageID, spaceID string) error {
unlock := c.LockSpace(spaceID)
defer unlock()
return c.syncWithLock(ctx, storageID, spaceID)
}
func (c *Cache) syncWithLock(ctx context.Context, storageID, spaceID string) error {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "Sync")
defer span.End()

View File

@@ -95,38 +95,62 @@ func (c *Cache) Add(ctx context.Context, userID, spaceID string, rs *collaborati
unlock := c.lockUser(userID)
defer unlock()
if c.ReceivedSpaces[userID] == nil {
err := c.syncWithLock(ctx, userID)
if err != nil {
return err
}
}
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "Add")
defer span.End()
span.SetAttributes(attribute.String("cs3.userid", userID), attribute.String("cs3.spaceid", spaceID))
if c.ReceivedSpaces[userID] == nil {
c.ReceivedSpaces[userID] = &Spaces{
Spaces: map[string]*Space{},
persistFunc := func() error {
if c.ReceivedSpaces[userID] == nil {
c.ReceivedSpaces[userID] = &Spaces{
Spaces: map[string]*Space{},
}
}
if c.ReceivedSpaces[userID].Spaces[spaceID] == nil {
c.ReceivedSpaces[userID].Spaces[spaceID] = &Space{}
}
}
if c.ReceivedSpaces[userID].Spaces[spaceID] == nil {
c.ReceivedSpaces[userID].Spaces[spaceID] = &Space{}
}
receivedSpace := c.ReceivedSpaces[userID].Spaces[spaceID]
receivedSpace.Mtime = time.Now()
if receivedSpace.States == nil {
receivedSpace.States = map[string]*State{}
}
receivedSpace.States[rs.Share.Id.GetOpaqueId()] = &State{
State: rs.State,
MountPoint: rs.MountPoint,
}
receivedSpace := c.ReceivedSpaces[userID].Spaces[spaceID]
receivedSpace.Mtime = time.Now()
if receivedSpace.States == nil {
receivedSpace.States = map[string]*State{}
}
receivedSpace.States[rs.Share.Id.GetOpaqueId()] = &State{
State: rs.State,
MountPoint: rs.MountPoint,
}
return c.persist(ctx, userID)
return c.persist(ctx, userID)
}
err := persistFunc()
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := c.syncWithLock(ctx, userID); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = persistFunc()
}
return err
}
// Get returns one entry from the cache
func (c *Cache) Get(userID, spaceID, shareID string) *State {
if c.ReceivedSpaces[userID] == nil || c.ReceivedSpaces[userID].Spaces[spaceID] == nil {
return nil
func (c *Cache) Get(ctx context.Context, userID, spaceID, shareID string) (*State, error) {
err := c.Sync(ctx, userID)
if err != nil {
return nil, err
}
return c.ReceivedSpaces[userID].Spaces[spaceID].States[shareID]
if c.ReceivedSpaces[userID] == nil || c.ReceivedSpaces[userID].Spaces[spaceID] == nil {
return nil, nil
}
return c.ReceivedSpaces[userID].Spaces[spaceID].States[shareID], nil
}
// Sync updates the in-memory data with the data from the storage if it is outdated
@@ -134,6 +158,10 @@ func (c *Cache) Sync(ctx context.Context, userID string) error {
unlock := c.lockUser(userID)
defer unlock()
return c.syncWithLock(ctx, userID)
}
func (c *Cache) syncWithLock(ctx context.Context, userID string) error {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "Sync")
defer span.End()
span.SetAttributes(attribute.String("cs3.userid", userID))
@@ -222,7 +250,8 @@ func (c *Cache) persist(ctx context.Context, userID string) error {
if err = c.storage.Upload(ctx, metadata.UploadRequest{
Path: jsonPath,
Content: createdBytes,
IfUnmodifiedSince: c.ReceivedSpaces[userID].Mtime,
IfUnmodifiedSince: oldMtime,
MTime: c.ReceivedSpaces[userID].Mtime,
}); err != nil {
c.ReceivedSpaces[userID].Mtime = oldMtime
span.RecordError(err)

View File

@@ -92,6 +92,13 @@ func (c *Cache) Add(ctx context.Context, userid, shareID string) error {
unlock := c.lockUser(userid)
defer unlock()
if c.UserShares[userid] == nil {
err := c.syncWithLock(ctx, userid)
if err != nil {
return err
}
}
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "Add")
defer span.End()
span.SetAttributes(attribute.String("cs3.userid", userid), attribute.String("cs3.shareid", shareID))
@@ -99,22 +106,37 @@ func (c *Cache) Add(ctx context.Context, userid, shareID string) error {
storageid, spaceid, _ := shareid.Decode(shareID)
ssid := storageid + shareid.IDDelimiter + spaceid
now := time.Now()
if c.UserShares[userid] == nil {
c.UserShares[userid] = &UserShareCache{
UserShares: map[string]*SpaceShareIDs{},
persistFunc := func() error {
now := time.Now()
if c.UserShares[userid] == nil {
c.UserShares[userid] = &UserShareCache{
UserShares: map[string]*SpaceShareIDs{},
}
}
}
if c.UserShares[userid].UserShares[ssid] == nil {
c.UserShares[userid].UserShares[ssid] = &SpaceShareIDs{
IDs: map[string]struct{}{},
if c.UserShares[userid].UserShares[ssid] == nil {
c.UserShares[userid].UserShares[ssid] = &SpaceShareIDs{
IDs: map[string]struct{}{},
}
}
// add share id
c.UserShares[userid].UserShares[ssid].Mtime = now
c.UserShares[userid].UserShares[ssid].IDs[shareID] = struct{}{}
return c.Persist(ctx, userid)
}
// add share id
c.UserShares[userid].Mtime = now
c.UserShares[userid].UserShares[ssid].Mtime = now
c.UserShares[userid].UserShares[ssid].IDs[shareID] = struct{}{}
return c.Persist(ctx, userid)
err := persistFunc()
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := c.syncWithLock(ctx, userid); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = persistFunc()
// TODO try more often?
}
return err
}
// Remove removes a share for the given user
@@ -122,6 +144,13 @@ func (c *Cache) Remove(ctx context.Context, userid, shareID string) error {
unlock := c.lockUser(userid)
defer unlock()
if c.UserShares[userid] == nil {
err := c.syncWithLock(ctx, userid)
if err != nil {
return err
}
}
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "Remove")
defer span.End()
span.SetAttributes(attribute.String("cs3.userid", userid), attribute.String("cs3.shareid", shareID))
@@ -129,29 +158,44 @@ func (c *Cache) Remove(ctx context.Context, userid, shareID string) error {
storageid, spaceid, _ := shareid.Decode(shareID)
ssid := storageid + shareid.IDDelimiter + spaceid
now := time.Now()
if c.UserShares[userid] == nil {
c.UserShares[userid] = &UserShareCache{
Mtime: now,
UserShares: map[string]*SpaceShareIDs{},
persistFunc := func() error {
if c.UserShares[userid] == nil {
c.UserShares[userid] = &UserShareCache{
UserShares: map[string]*SpaceShareIDs{},
}
}
if c.UserShares[userid].UserShares[ssid] != nil {
// remove share id
c.UserShares[userid].UserShares[ssid].Mtime = time.Now()
delete(c.UserShares[userid].UserShares[ssid].IDs, shareID)
}
return c.Persist(ctx, userid)
}
if c.UserShares[userid].UserShares[ssid] != nil {
// remove share id
c.UserShares[userid].Mtime = now
c.UserShares[userid].UserShares[ssid].Mtime = now
delete(c.UserShares[userid].UserShares[ssid].IDs, shareID)
err := persistFunc()
if _, ok := err.(errtypes.IsPreconditionFailed); ok {
if err := c.syncWithLock(ctx, userid); err != nil {
return err
}
err = persistFunc()
}
return c.Persist(ctx, userid)
return err
}
// List return the list of spaces/shares for the given user/group
func (c *Cache) List(userid string) map[string]SpaceShareIDs {
func (c *Cache) List(ctx context.Context, userid string) (map[string]SpaceShareIDs, error) {
unlock := c.lockUser(userid)
defer unlock()
if err := c.syncWithLock(ctx, userid); err != nil {
return nil, err
}
r := map[string]SpaceShareIDs{}
if c.UserShares[userid] == nil {
return r
return r, nil
}
for ssid, cached := range c.UserShares[userid].UserShares {
@@ -160,14 +204,10 @@ func (c *Cache) List(userid string) map[string]SpaceShareIDs {
IDs: cached.IDs,
}
}
return r
return r, nil
}
// Sync updates the in-memory data with the data from the storage if it is outdated
func (c *Cache) Sync(ctx context.Context, userID string) error {
unlock := c.lockUser(userID)
defer unlock()
func (c *Cache) syncWithLock(ctx context.Context, userID string) error {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "Sync")
defer span.End()
span.SetAttributes(attribute.String("cs3.userid", userID))
@@ -253,7 +293,8 @@ func (c *Cache) Persist(ctx context.Context, userid string) error {
if err = c.storage.Upload(ctx, metadata.UploadRequest{
Path: jsonPath,
Content: createdBytes,
IfUnmodifiedSince: c.UserShares[userid].Mtime,
IfUnmodifiedSince: oldMtime,
MTime: c.UserShares[userid].Mtime,
}); err != nil {
c.UserShares[userid].Mtime = oldMtime
span.RecordError(err)

View File

@@ -71,9 +71,9 @@ func (bs *Blobstore) Upload(node *node.Node, source string) error {
}
defer reader.Close()
_, err1 := bs.client.PutObject(context.Background(), bs.bucket, bs.path(node), reader, node.Blobsize, minio.PutObjectOptions{ContentType: "application/octet-stream"})
_, err = bs.client.PutObject(context.Background(), bs.bucket, bs.path(node), reader, node.Blobsize, minio.PutObjectOptions{ContentType: "application/octet-stream", SendContentMd5: true})
if err1 != nil {
if err != nil {
return errors.Wrapf(err, "could not store object '%s' into bucket '%s'", bs.path(node), bs.bucket)
}
return nil

View File

@@ -60,7 +60,7 @@ func init() {
// Define keys and values used in the node metadata
const (
LockdiscoveryKey = "DAV:lockdiscovery"
LockdiscoveryKey = "lockdiscovery"
FavoriteKey = "http://owncloud.org/ns/favorite"
ShareTypesKey = "http://owncloud.org/ns/share-types"
ChecksumsKey = "http://owncloud.org/ns/checksums"

View File

@@ -292,6 +292,7 @@ func (upload *Upload) FinishUpload(_ context.Context) error {
err = upload.Finalize()
Cleanup(upload, err != nil, false)
if err != nil {
log.Error().Err(err).Msg("failed to upload")
return err
}
}

View File

@@ -25,6 +25,7 @@ import (
"io"
"net/http"
"os"
"strconv"
"time"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
@@ -34,7 +35,6 @@ import (
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/errtypes"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
"go.opentelemetry.io/otel"
@@ -149,6 +149,7 @@ func (cs3 *CS3) Upload(ctx context.Context, req UploadRequest) error {
}
ifuReq := &provider.InitiateFileUploadRequest{
Opaque: &types.Opaque{},
Ref: &provider.Reference{
ResourceId: cs3.SpaceRoot,
Path: utils.MakeRelativePath(req.Path),
@@ -165,13 +166,17 @@ func (cs3 *CS3) Upload(ctx context.Context, req UploadRequest) error {
IfUnmodifiedSince: utils.TimeToTS(req.IfUnmodifiedSince),
}
}
if req.MTime != (time.Time{}) {
// The format of the X-OC-Mtime header is <epoch>.<nanoseconds>, e.g. '1691053416.934129485'
ifuReq.Opaque = utils.AppendPlainToOpaque(ifuReq.Opaque, "X-OC-Mtime", strconv.Itoa(int(req.MTime.Unix()))+"."+strconv.Itoa(req.MTime.Nanosecond()))
}
res, err := client.InitiateFileUpload(ctx, ifuReq)
if err != nil {
return err
}
if res.Status.Code != rpc.Code_CODE_OK {
return status.NewErrorFromCode(res.Status.Code, "cs3 metadata SimpleUpload")
return errtypes.NewErrtypeFromStatus(res.Status)
}
var endpoint string

View File

@@ -37,6 +37,7 @@ type UploadRequest struct {
IfMatchEtag string
IfUnmodifiedSince time.Time
MTime time.Time
}
// Storage is the interface to maintain metadata in a storage

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019 Cubewise CODE
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,25 +0,0 @@
# go-mime
Get the mime type / content type of a file from its extension without external dependencies
# Usage
```
go get github.com/cubewise-code/go-mime
```
```go
import (
"github.com/cubewise-code/go-mime"
)
// Get the file extension
ext := filepath.Ext(fileName)
// An empty string is returned if the extension is not found
contentType := gomime.TypeByExtension(ext)
```
# Why
We wanted a simple mime library that gives a consistent result on each environment. The golang mime package (https://golang.org/pkg/mime/) loads the list of mime types using the OS, meaning you get a different list depending on OS and OS version. On Windows this depends on the programs installed and whether the user running the process has access to the registry.
# Mime Source
The mime list are sourced from here: https://github.com/micnic/mime.json

File diff suppressed because it is too large Load Diff

5
vendor/modules.txt vendored
View File

@@ -352,7 +352,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/tx/v1beta1
github.com/cs3org/go-cs3apis/cs3/types/v1beta1
# github.com/cs3org/reva/v2 v2.15.1-0.20230731132956-0fb5212d0551
# github.com/cs3org/reva/v2 v2.15.1-0.20230809113840-3ceaf17cf7fb
## explicit; go 1.20
github.com/cs3org/reva/v2/cmd/revad/internal/grace
github.com/cs3org/reva/v2/cmd/revad/runtime
@@ -702,9 +702,6 @@ github.com/cs3org/reva/v2/pkg/user/manager/registry
github.com/cs3org/reva/v2/pkg/utils
github.com/cs3org/reva/v2/pkg/utils/ldap
github.com/cs3org/reva/v2/tests/cs3mocks/mocks
# github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8
## explicit
github.com/cubewise-code/go-mime
# github.com/davecgh/go-spew v1.1.1
## explicit
github.com/davecgh/go-spew/spew