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 }