github.com/cs3org/reva/v2@v2.27.7/pkg/storage/fs/owncloudsql/spaces.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package owncloudsql
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  	"strconv"
    25  	"strings"
    26  
    27  	userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
    28  	provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    29  	types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
    30  	ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
    31  	"github.com/cs3org/reva/v2/pkg/errtypes"
    32  	"github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/filecache"
    33  	"github.com/cs3org/reva/v2/pkg/storagespace"
    34  	"github.com/cs3org/reva/v2/pkg/utils"
    35  )
    36  
    37  // ListStorageSpaces lists storage spaces according to the provided filters
    38  func (fs *owncloudsqlfs) ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter, unrestricted bool) ([]*provider.StorageSpace, error) {
    39  	var (
    40  		spaceID = "*"
    41  		// uid     *userpb.UserId
    42  	)
    43  
    44  	filteringUnsupportedSpaceTypes := false
    45  
    46  	for i := range filter {
    47  		switch filter[i].Type {
    48  		case provider.ListStorageSpacesRequest_Filter_TYPE_SPACE_TYPE:
    49  			t := filter[i].GetSpaceType()
    50  			filteringUnsupportedSpaceTypes = (t != "personal" && !strings.HasPrefix(t, "+"))
    51  		case provider.ListStorageSpacesRequest_Filter_TYPE_ID:
    52  			_, spaceID, _, _ = storagespace.SplitID(filter[i].GetId().OpaqueId)
    53  		case provider.ListStorageSpacesRequest_Filter_TYPE_USER:
    54  			// uid = filter[i].GetUser()
    55  		}
    56  	}
    57  	if filteringUnsupportedSpaceTypes {
    58  		// owncloudsql only supports personal spaces, no need to search for something else
    59  		return []*provider.StorageSpace{}, nil
    60  	}
    61  
    62  	spaces := []*provider.StorageSpace{}
    63  	if spaceID == "*" {
    64  		u, ok := ctxpkg.ContextGetUser(ctx)
    65  		if !ok {
    66  			return nil, errtypes.UserRequired("error getting user from context")
    67  		}
    68  		// if uid != nil && utils.UserIDEqual(uid, u.Id) {
    69  		//       return nil, errtypes.PermissionDenied("cannot access space of other user?")
    70  		// }
    71  		space, err := fs.getPersonalSpace(ctx, u)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  		spaces = append(spaces, space)
    76  	} else {
    77  		id, err := strconv.Atoi(spaceID)
    78  		if err != nil {
    79  			// non-numeric space id -> this request is not for us
    80  			return []*provider.StorageSpace{}, nil
    81  		}
    82  		space, err := fs.getSpaceByNumericID(ctx, id)
    83  		if err != nil {
    84  			return nil, err
    85  		}
    86  		spaces = append(spaces, space)
    87  	}
    88  	return spaces, nil
    89  }
    90  
    91  // CreateStorageSpace creates a storage space
    92  func (fs *owncloudsqlfs) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) {
    93  	return nil, errtypes.NotSupported("unimplemented: CreateStorageSpace")
    94  }
    95  
    96  // UpdateStorageSpace updates a storage space
    97  func (fs *owncloudsqlfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
    98  	return nil, errtypes.NotSupported("update storage space")
    99  }
   100  
   101  // DeleteStorageSpace deletes a storage space
   102  func (fs *owncloudsqlfs) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) error {
   103  	return errtypes.NotSupported("delete storage space")
   104  }
   105  
   106  //  Note: currently unused but will be used later
   107  // func (fs *owncloudsqlfs) listAllPersonalSpaces(ctx context.Context) ([]*provider.StorageSpace, error) {
   108  // 	storages, err := fs.filecache.ListStorages(true)
   109  // 	if err != nil {
   110  // 		return nil, err
   111  // 	}
   112  // 	spaces := []*provider.StorageSpace{}
   113  // 	for _, storage := range storages {
   114  // 		space, err := fs.storageToSpace(ctx, storage)
   115  // 		if err != nil {
   116  // 			return nil, err
   117  // 		}
   118  // 		spaces = append(spaces, space)
   119  // 	}
   120  // 	return spaces, nil
   121  // }
   122  
   123  func (fs *owncloudsqlfs) getPersonalSpace(ctx context.Context, owner *userpb.User) (*provider.StorageSpace, error) {
   124  	storageID, err := fs.filecache.GetNumericStorageID(ctx, "home::"+owner.Username)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	storage, err := fs.filecache.GetStorage(ctx, storageID)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  	root, err := fs.filecache.Get(ctx, storage.NumericID, "")
   133  	if err != nil {
   134  		return nil, err
   135  	}
   136  
   137  	space := &provider.StorageSpace{
   138  		Id: &provider.StorageSpaceId{OpaqueId: strconv.Itoa(storage.NumericID)},
   139  		Root: &provider.ResourceId{
   140  			// return ownclouds numeric storage id as the space id!
   141  			SpaceId:  strconv.Itoa(storage.NumericID),
   142  			OpaqueId: strconv.Itoa(root.ID),
   143  		},
   144  		Name:      owner.Username,
   145  		SpaceType: "personal",
   146  		Mtime:     &types.Timestamp{Seconds: uint64(root.MTime)},
   147  		Owner:     owner,
   148  	}
   149  	space.Opaque = utils.AppendPlainToOpaque(space.Opaque, "spaceAlias", "personal/"+owner.Username)
   150  	space.Opaque = utils.AppendPlainToOpaque(space.Opaque, "etag", fmt.Sprintf(`"%s"`, root.Etag))
   151  	return space, nil
   152  }
   153  
   154  func (fs *owncloudsqlfs) getSpaceByNumericID(ctx context.Context, spaceID int) (*provider.StorageSpace, error) {
   155  	storage, err := fs.filecache.GetStorage(ctx, spaceID)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  	if !strings.HasPrefix(storage.ID, "home::") {
   160  		return nil, fmt.Errorf("only personal spaces are supported")
   161  	}
   162  
   163  	return fs.storageToSpace(ctx, storage)
   164  }
   165  
   166  func (fs *owncloudsqlfs) storageToSpace(ctx context.Context, storage *filecache.Storage) (*provider.StorageSpace, error) {
   167  	root, err := fs.filecache.Get(ctx, storage.NumericID, "")
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  	ownerName := strings.TrimPrefix(storage.ID, "home::")
   172  	owner, err := fs.getUser(ctx, ownerName)
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  
   177  	space := &provider.StorageSpace{
   178  		Id: &provider.StorageSpaceId{OpaqueId: strconv.Itoa(storage.NumericID)},
   179  		Root: &provider.ResourceId{
   180  			// return ownclouds numeric storage id as the space id!
   181  			SpaceId:  strconv.Itoa(storage.NumericID),
   182  			OpaqueId: strconv.Itoa(root.ID),
   183  		},
   184  		Name:      owner.Username,
   185  		SpaceType: "personal",
   186  		Mtime:     &types.Timestamp{Seconds: uint64(root.MTime)},
   187  		Owner:     owner,
   188  	}
   189  	space.Opaque = utils.AppendPlainToOpaque(space.Opaque, "spaceAlias", "personal/"+owner.Username)
   190  	space.Opaque = utils.AppendPlainToOpaque(space.Opaque, "etag", fmt.Sprintf(`"%s"`, root.Etag))
   191  	return space, nil
   192  }