Skip to content

Commit

Permalink
further work
Browse files Browse the repository at this point in the history
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
  • Loading branch information
butonic committed Nov 5, 2021
1 parent 1df7cc2 commit 965bf36
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 122 deletions.
2 changes: 1 addition & 1 deletion internal/grpc/services/gateway/authprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest
}, nil
}

if createHomeRes.Status.Code != rpc.Code_CODE_OK {
if createHomeRes.Status.Code != rpc.Code_CODE_OK && createHomeRes.Status.Code != rpc.Code_CODE_ALREADY_EXISTS {
err := status.NewErrorFromCode(createHomeRes.Status.Code, "gateway")
log.Err(err).Msg("error calling Createhome")
return &gateway.AuthenticateResponse{
Expand Down
105 changes: 6 additions & 99 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import (
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/rgrpc/status"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/pkg/storage/utils/etag"
"github.com/cs3org/reva/pkg/utils"
"github.com/golang-jwt/jwt"
"github.com/google/uuid"
Expand Down Expand Up @@ -109,7 +108,8 @@ func (s *svc) CreateHome(ctx context.Context, req *provider.CreateHomeRequest) (

u := ctxpkg.ContextMustGetUser(ctx)
res, err := storageProviderClient.CreateStorageSpace(ctx, &provider.CreateStorageSpaceRequest{
Type: "personal",
Type: "personal",
// TODO sendt Id = u.Id.Opaqueid
Owner: u,
Name: u.DisplayName,
})
Expand All @@ -119,7 +119,7 @@ func (s *svc) CreateHome(ctx context.Context, req *provider.CreateHomeRequest) (
Status: status.NewInternal(ctx, err, "error calling CreateHome"),
}, nil
}
if res.Status.Code != rpc.Code_CODE_OK {
if res.Status.Code != rpc.Code_CODE_OK && res.Status.Code != rpc.Code_CODE_ALREADY_EXISTS {
return &provider.CreateHomeResponse{
Status: res.Status,
}, nil
Expand Down Expand Up @@ -1247,80 +1247,6 @@ func (s *svc) statHome(ctx context.Context) (*provider.StatResponse, error) {
}, nil
}

statSharedFolder, err := s.statSharesFolder(ctx)
if err != nil {
return &provider.StatResponse{
Status: status.NewInternal(ctx, err, "gateway: error stating shares folder"),
}, nil
}
if statSharedFolder.Status.Code != rpc.Code_CODE_OK {
// If shares folder is not found, skip updating the etag
if statSharedFolder.Status.Code == rpc.Code_CODE_NOT_FOUND {
return statRes, nil
}
// otherwise return stat of share folder
return &provider.StatResponse{
Status: statSharedFolder.Status,
}, nil
}

if etagIface, err := s.etagCache.Get(statRes.Info.Owner.OpaqueId + ":" + statRes.Info.Path); err == nil {
resMtime := utils.TSToTime(statRes.Info.Mtime)
resEtag := etagIface.(etagWithTS)
// Use the updated etag if the home folder has been modified
if resMtime.Before(resEtag.Timestamp) {
statRes.Info.Etag = resEtag.Etag
}
} else {
statRes.Info.Etag = etag.GenerateEtagFromResources(statRes.Info, []*provider.ResourceInfo{statSharedFolder.Info})
if s.c.EtagCacheTTL > 0 {
_ = s.etagCache.Set(statRes.Info.Owner.OpaqueId+":"+statRes.Info.Path, etagWithTS{statRes.Info.Etag, time.Now()})
}
}

return statRes, nil
}

func (s *svc) statSharesFolder(ctx context.Context) (*provider.StatResponse, error) {
statRes, err := s.stat(ctx, &provider.StatRequest{Ref: &provider.Reference{Path: s.getSharedFolder(ctx)}})
if err != nil {
return &provider.StatResponse{
Status: status.NewInternal(ctx, err, "gateway: error stating shares folder"),
}, nil
}

if statRes.Status.Code != rpc.Code_CODE_OK {
return &provider.StatResponse{
Status: statRes.Status,
}, nil
}

lsRes, err := s.listSharesFolder(ctx)
if err != nil {
return &provider.StatResponse{
Status: status.NewInternal(ctx, err, "gateway: error listing shares folder"),
}, nil
}
if lsRes.Status.Code != rpc.Code_CODE_OK {
return &provider.StatResponse{
Status: lsRes.Status,
}, nil
}

if etagIface, err := s.etagCache.Get(statRes.Info.Owner.OpaqueId + ":" + statRes.Info.Path); err == nil {
resMtime := utils.TSToTime(statRes.Info.Mtime)
resEtag := etagIface.(etagWithTS)
// Use the updated etag if the shares folder has been modified, i.e., a new
// reference has been created.
if resMtime.Before(resEtag.Timestamp) {
statRes.Info.Etag = resEtag.Etag
}
} else {
statRes.Info.Etag = etag.GenerateEtagFromResources(statRes.Info, lsRes.Infos)
if s.c.EtagCacheTTL > 0 {
_ = s.etagCache.Set(statRes.Info.Owner.OpaqueId+":"+statRes.Info.Path, etagWithTS{statRes.Info.Etag, time.Now()})
}
}
return statRes, nil
}

Expand Down Expand Up @@ -1429,10 +1355,6 @@ func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.St
return s.statHome(ctx)
}

if s.isSharedFolder(ctx, p) {
return s.statSharesFolder(ctx)
}

if !s.inSharedFolder(ctx, p) {
if res != nil {
return res, nil
Expand Down Expand Up @@ -1643,24 +1565,6 @@ func (s *svc) listHome(ctx context.Context, req *provider.ListContainerRequest)
}, nil
}

for i := range lcr.Infos {
if s.isSharedFolder(ctx, lcr.Infos[i].GetPath()) {
statSharedFolder, err := s.statSharesFolder(ctx)
if err != nil {
return &provider.ListContainerResponse{
Status: status.NewInternal(ctx, err, "gateway: error stating shares folder"),
}, nil
}
if statSharedFolder.Status.Code != rpc.Code_CODE_OK {
return &provider.ListContainerResponse{
Status: statSharedFolder.Status,
}, nil
}
lcr.Infos[i] = statSharedFolder.Info
break
}
}

return lcr, nil
}

Expand Down Expand Up @@ -1994,16 +1898,19 @@ func (s *svc) getPath(ctx context.Context, ref *provider.Reference, keys ...stri

// /home/MyShares/
func (s *svc) isSharedFolder(ctx context.Context, p string) bool {
return false
return s.split(ctx, p, 2)
}

// /home/MyShares/photos/
func (s *svc) isShareName(ctx context.Context, p string) bool {
return false
return s.split(ctx, p, 3)
}

// /home/MyShares/photos/Ibiza/beach.png
func (s *svc) isShareChild(ctx context.Context, p string) bool {
return false
return s.split(ctx, p, 4)
}

Expand Down
18 changes: 17 additions & 1 deletion internal/grpc/services/storageprovider/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,24 @@ func (s *service) CreateHome(ctx context.Context, req *provider.CreateHomeReques
// CreateStorageSpace creates a storage space
func (s *service) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) {
resp, err := s.storage.CreateStorageSpace(ctx, req)

if err != nil {
return nil, err
var st *rpc.Status
switch err.(type) {
case errtypes.IsNotFound:
st = status.NewNotFound(ctx, "not found when listing spaces")
case errtypes.PermissionDenied:
st = status.NewPermissionDenied(ctx, err, "permission denied")
case errtypes.NotSupported:
st = status.NewUnimplemented(ctx, err, "not implemented")
case errtypes.AlreadyExists:
st = status.NewAlreadyExists(ctx, err, "already exists")
default:
st = status.NewInternal(ctx, err, "error listing spaces")
}
return &provider.CreateStorageSpaceResponse{
Status: st,
}, nil
}

resp.StorageSpace.Root = &provider.ResourceId{StorageId: s.mountID, OpaqueId: resp.StorageSpace.Id.OpaqueId}
Expand Down
18 changes: 9 additions & 9 deletions pkg/storage/registry/spaces/spaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,15 @@ func (r *registry) FindProviders(ctx context.Context, ref *provider.Reference) (
}
}
if utils.IsAbsolutePathReference(ref) {
u := ctxpkg.ContextMustGetUser(ctx)
currentUser := ctxpkg.ContextMustGetUser(ctx)
// check if the alias is known for this user
spaceType, rest := router.ShiftPath(ref.Path)
spaceName, _ := router.ShiftPath(rest)
alias := filepath.Join("/", spaceType, spaceName)
if _, ok := r.aliases[u.Id.OpaqueId]; !ok {
r.aliases[u.Id.OpaqueId] = make(map[string]*spaceAndProvider)
if _, ok := r.aliases[currentUser.Id.OpaqueId]; !ok {
r.aliases[currentUser.Id.OpaqueId] = make(map[string]*spaceAndProvider)
}
if spaceAndAddr, ok := r.aliases[u.Id.OpaqueId][alias]; ok {
if spaceAndAddr, ok := r.aliases[currentUser.Id.OpaqueId][alias]; ok {
// best case, just return cached provider
return spaceAndAddr.providers, nil
}
Expand All @@ -221,23 +221,23 @@ func (r *registry) FindProviders(ctx context.Context, ref *provider.Reference) (
return nil, err
}
// assume a personal storage where the current user is owner is his /home
if space.SpaceType == "personal" && space.Owner != nil && utils.UserEqual(space.Owner.Id, u.Id) {
if space.SpaceType == "personal" && space.Owner != nil && utils.UserEqual(space.Owner.Id, currentUser.Id) {
p.ProviderPath = "/home"
} else {
p.ProviderPath = filepath.Join("/", space.SpaceType, filepath.Base(path))
}
// cache result, TODO only for 30sec?
//if _, ok := r.aliases[u.Id.OpaqueId][p.ProviderPath]; !ok {
r.aliases[u.Id.OpaqueId][p.ProviderPath] = &spaceAndProvider{
//if _, ok := r.aliases[currentUser.Id.OpaqueId][p.ProviderPath]; !ok {
r.aliases[currentUser.Id.OpaqueId][p.ProviderPath] = &spaceAndProvider{
space, []*registrypb.ProviderInfo{p},
}
/*} /*else {
// add an additional storage provider, eg for load balancing
r.aliases[u.Id.OpaqueId][p.ProviderPath].providers = append(r.aliases[u.Id.OpaqueId][p.ProviderPath].providers, p)
r.aliases[currentUser.Id.OpaqueId][p.ProviderPath].providers = append(r.aliases[currentUser.Id.OpaqueId][p.ProviderPath].providers, p)
}*/
}

if spaceAndAddr, ok := r.aliases[u.Id.OpaqueId][alias]; ok {
if spaceAndAddr, ok := r.aliases[currentUser.Id.OpaqueId][alias]; ok {
return spaceAndAddr.providers, nil
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/utils/decomposedfs/decomposedfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ func (fs *Decomposedfs) CreateHome(ctx context.Context) (err error) {
}

// add storage space
if err := fs.createStorageSpace(ctx, "personal", h.ID); err != nil {
if err := fs.createStorageSpace(ctx, "personal", h.ID, h.ID); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/utils/decomposedfs/grants.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (fs *Decomposedfs) AddGrant(ctx context.Context, ref *provider.Reference, g

// when a grant is added to a space, do not add a new space under "shares"
if spaceGrant := ctx.Value(SpaceGrant); spaceGrant == nil {
err := fs.createStorageSpace(ctx, "share", node.ID)
err := fs.createStorageSpace(ctx, "share", node.ID, node.ID)
if err != nil {
return err
}
Expand Down
18 changes: 12 additions & 6 deletions pkg/storage/utils/decomposedfs/spaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
ocsconv "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions"
"github.com/cs3org/reva/pkg/appctx"
ctxpkg "github.com/cs3org/reva/pkg/ctx"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/storage/utils/decomposedfs/node"
"github.com/cs3org/reva/pkg/storage/utils/decomposedfs/xattrs"
"github.com/cs3org/reva/pkg/utils"
Expand All @@ -57,14 +58,19 @@ func (fs *Decomposedfs) CreateStorageSpace(ctx context.Context, req *provider.Cr

// "everything is a resource" this is the unique ID for the Space resource.
spaceID := uuid.New().String()
// TODO clarify if we want to enforce a single personal storage space or if we want to allow sending the spaceid
// TODO enforce a uuid?
if req.Type == "personal" {
spaceID = req.Owner.Id.OpaqueId
}

n, err := r.Child(ctx, spaceID)
if err != nil {
return nil, err
}

if n.Exists {
return nil, fmt.Errorf("decomposedfs: spaces: invalid duplicated node with id `%s`", n.ID)
return nil, errtypes.AlreadyExists("decomposedfs: spaces: space already exists")
}

if err := fs.tp.CreateDir(ctx, n); err != nil {
Expand Down Expand Up @@ -92,7 +98,7 @@ func (fs *Decomposedfs) CreateStorageSpace(ctx context.Context, req *provider.Cr
return nil, err
}

err = fs.createStorageSpace(ctx, req.Type, n.ID)
err = fs.createStorageSpace(ctx, req.Type, spaceID, n.ID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -298,20 +304,20 @@ func (fs *Decomposedfs) createHiddenSpaceFolder(ctx context.Context, r *node.Nod
return fs.tp.CreateDir(ctx, hiddenSpace)
}

func (fs *Decomposedfs) createStorageSpace(ctx context.Context, spaceType, nodeID string) error {
func (fs *Decomposedfs) createStorageSpace(ctx context.Context, spaceType, spaceID, rootID string) error {
// create space type dir
if err := os.MkdirAll(filepath.Join(fs.o.Root, "spaces", spaceType), 0700); err != nil {
return err
}

// we can reuse the node id as the space id
err := os.Symlink("../../nodes/"+nodeID, filepath.Join(fs.o.Root, "spaces", spaceType, nodeID))
err := os.Symlink("../../nodes/"+rootID, filepath.Join(fs.o.Root, "spaces", spaceType, spaceID))
if err != nil {
if isAlreadyExists(err) {
appctx.GetLogger(ctx).Debug().Err(err).Str("node", nodeID).Str("spacetype", spaceType).Msg("symlink already exists")
appctx.GetLogger(ctx).Debug().Err(err).Str("space", spaceID).Str("node", rootID).Str("spacetype", spaceType).Msg("symlink already exists")
} else {
// TODO how should we handle error cases here?
appctx.GetLogger(ctx).Error().Err(err).Str("node", nodeID).Str("spacetype", spaceType).Msg("could not create symlink")
appctx.GetLogger(ctx).Error().Err(err).Str("space", spaceID).Str("node", rootID).Str("spacetype", spaceType).Msg("could not create symlink")
}
}

Expand Down
8 changes: 4 additions & 4 deletions tests/oc-integration-tests/local/gateway.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,19 @@ bearer = "localhost:20099" # started with the frontend.toml
driver = "spaces"

[grpc.services.storageregistry.drivers.spaces]
home_provider = "/personal"
home_provider = "/home"

[grpc.services.storageregistry.drivers.spaces.rules]

#"/spaces" = {"address" = "localhost:11500"}

# mount a home storage provider that uses a context based path wrapper
# to jail users into their home dir
#"/home" = {"address" = "localhost:12000"}
"/home" = {"address" = "localhost:12000"}

# mount a storage provider without a path wrapper for direct access to users.
"/personal" = {"address" = "localhost:11000"}
"123e4567-e89b-12d3-a456-426655440000" = {"address" = "localhost:11000"}
#"/personal" = {"address" = "localhost:11000"}
"123e4567-e89b-12d3-a456-426655440000" = {"address" = "localhost:12000"}

# the /virtual namespace is only accessible via the frontend-global service
#"/virtual/[a-k]" = {"address" = "localhost:11100"}
Expand Down

0 comments on commit 965bf36

Please sign in to comment.