github.com/cs3org/reva/v2@v2.27.7/pkg/share/manager/owncloudsql/owncloudsql_test.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_test 20 21 import ( 22 "context" 23 "database/sql" 24 "os" 25 "strconv" 26 27 user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 28 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 29 collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" 30 provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 31 ruser "github.com/cs3org/reva/v2/pkg/ctx" 32 "github.com/cs3org/reva/v2/pkg/share" 33 sqlmanager "github.com/cs3org/reva/v2/pkg/share/manager/owncloudsql" 34 mocks "github.com/cs3org/reva/v2/pkg/share/manager/owncloudsql/mocks" 35 "google.golang.org/protobuf/types/known/fieldmaskpb" 36 37 _ "github.com/mattn/go-sqlite3" 38 "github.com/stretchr/testify/mock" 39 40 . "github.com/onsi/ginkgo/v2" 41 . "github.com/onsi/gomega" 42 ) 43 44 var _ = Describe("SQL manager", func() { 45 var ( 46 mgr share.Manager 47 ctx context.Context 48 testDbFile *os.File 49 sqldb *sql.DB 50 51 loginAs = func(user *userpb.User) { 52 ctx = ruser.ContextSetUser(context.Background(), user) 53 } 54 admin = &userpb.User{ 55 Id: &userpb.UserId{ 56 Idp: "idp", 57 OpaqueId: "userid", 58 Type: userpb.UserType_USER_TYPE_PRIMARY, 59 }, 60 Username: "admin", 61 } 62 otherUser = &userpb.User{ 63 Id: &userpb.UserId{ 64 Idp: "idp", 65 OpaqueId: "userid", 66 Type: userpb.UserType_USER_TYPE_PRIMARY, 67 }, 68 Username: "einstein", 69 Groups: []string{"users"}, 70 } 71 yetAnotherUser = &userpb.User{ 72 Id: &userpb.UserId{ 73 Idp: "idp", 74 OpaqueId: "userid2", 75 Type: userpb.UserType_USER_TYPE_PRIMARY, 76 }, 77 Username: "marie", 78 Groups: []string{"users"}, 79 } 80 81 shareRef = &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{ 82 Id: &collaboration.ShareId{ 83 OpaqueId: "1", 84 }, 85 }} 86 87 insertShare = func(shareType int, owner string, grantee string, parent int, source int, fileTarget string, permissions int, accepted int) (int, error) { 88 var parentVal interface{} 89 if parent >= 0 { 90 parentVal = parent 91 } 92 stmtString := "INSERT INTO oc_share (share_type,uid_owner,uid_initiator,item_type,item_source,file_source,parent,permissions,stime,share_with,file_target,accepted) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)" 93 stmtValues := []interface{}{shareType, owner, owner, "folder", source, source, parentVal, permissions, 1631779730, grantee, fileTarget, accepted} 94 95 stmt, err := sqldb.Prepare(stmtString) 96 if err != nil { 97 return -1, err 98 } 99 result, err := stmt.ExecContext(ctx, stmtValues...) 100 if err != nil { 101 return -1, err 102 } 103 id, err := result.LastInsertId() 104 return int(id), err 105 } 106 ) 107 108 AfterEach(func() { 109 os.Remove(testDbFile.Name()) 110 }) 111 112 BeforeEach(func() { 113 var err error 114 testDbFile, err = os.CreateTemp("", "example") 115 Expect(err).ToNot(HaveOccurred()) 116 117 dbData, err := os.ReadFile("test.db") 118 Expect(err).ToNot(HaveOccurred()) 119 120 _, err = testDbFile.Write(dbData) 121 Expect(err).ToNot(HaveOccurred()) 122 err = testDbFile.Close() 123 Expect(err).ToNot(HaveOccurred()) 124 125 sqldb, err = sql.Open("sqlite3", testDbFile.Name()) 126 Expect(err).ToNot(HaveOccurred()) 127 128 userConverter := &mocks.UserConverter{} 129 userConverter.On("UserIDToUserName", mock.Anything, mock.Anything).Return("username", nil) 130 userConverter.On("UserNameToUserID", mock.Anything, mock.Anything).Return( 131 func(_ context.Context, username string) *userpb.UserId { 132 return &userpb.UserId{ 133 OpaqueId: username, 134 } 135 }, 136 func(_ context.Context, username string) error { return nil }) 137 userConverter.On("GetUser", mock.Anything, mock.Anything).Return(nil, nil) 138 mgr, err = sqlmanager.New("sqlite3", sqldb, "abcde", userConverter) 139 Expect(err).ToNot(HaveOccurred()) 140 141 loginAs(admin) 142 }) 143 144 It("creates manager instances", func() { 145 Expect(mgr).ToNot(BeNil()) 146 }) 147 148 Describe("GetShare", func() { 149 It("returns the share", func() { 150 share, err := mgr.GetShare(ctx, shareRef) 151 Expect(err).ToNot(HaveOccurred()) 152 Expect(share).ToNot(BeNil()) 153 }) 154 155 It("returns an error if the share does not exis", func() { 156 share, err := mgr.GetShare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{ 157 Id: &collaboration.ShareId{ 158 OpaqueId: "2", 159 }, 160 }}) 161 Expect(err).To(HaveOccurred()) 162 Expect(share).To(BeNil()) 163 }) 164 }) 165 166 Describe("Share", func() { 167 It("creates a share", func() { 168 grant := &collaboration.ShareGrant{ 169 Grantee: &provider.Grantee{ 170 Type: provider.GranteeType_GRANTEE_TYPE_USER, 171 Id: &provider.Grantee_UserId{UserId: &user.UserId{ 172 OpaqueId: "someone", 173 }}, 174 }, 175 Permissions: &collaboration.SharePermissions{ 176 Permissions: &provider.ResourcePermissions{ 177 GetPath: true, 178 InitiateFileDownload: true, 179 ListFileVersions: true, 180 ListContainer: true, 181 Stat: true, 182 }, 183 }, 184 } 185 info := &provider.ResourceInfo{ 186 Id: &provider.ResourceId{ 187 SpaceId: "/", 188 OpaqueId: "something", 189 }, 190 } 191 share, err := mgr.Share(ctx, info, grant) 192 193 Expect(err).ToNot(HaveOccurred()) 194 Expect(share).ToNot(BeNil()) 195 Expect(share.Id.OpaqueId).To(Equal("2")) 196 }) 197 }) 198 199 Describe("ListShares", func() { 200 It("lists shares", func() { 201 shares, err := mgr.ListShares(ctx, []*collaboration.Filter{}) 202 Expect(err).ToNot(HaveOccurred()) 203 Expect(len(shares)).To(Equal(1)) 204 share := shares[0] 205 Expect(share.ResourceId.SpaceId).To(Equal("1")) 206 207 shares, err = mgr.ListShares(ctx, []*collaboration.Filter{ 208 { 209 Type: collaboration.Filter_TYPE_RESOURCE_ID, 210 Term: &collaboration.Filter_ResourceId{ 211 ResourceId: &provider.ResourceId{ 212 SpaceId: "/", 213 OpaqueId: "somethingElse", 214 }, 215 }, 216 }, 217 }) 218 Expect(err).ToNot(HaveOccurred()) 219 Expect(len(shares)).To(Equal(0)) 220 }) 221 }) 222 223 Describe("ListReceivedShares", func() { 224 Context("with a pending group share (non-autoaccept) and an accepted child share", func() { 225 It("only returns one share (of type group share)", func() { 226 loginAs(otherUser) 227 parentID, err := insertShare( 228 1, // group share 229 "admin", // owner/initiator 230 "users", // grantee 231 -1, // parent 232 20, // source 233 "/groupshared", // file_target 234 31, // permissions, 235 0, // accepted 236 ) 237 Expect(err).ToNot(HaveOccurred()) 238 _, err = insertShare( 239 2, // group child share 240 "admin", // owner/initiator 241 "einstein", // grantee 242 parentID, // parent 243 20, // source 244 "/mygroupshared", // file_target 245 31, // permissions, 246 0, // accepted 247 ) 248 Expect(err).ToNot(HaveOccurred()) 249 250 shares, err := mgr.ListReceivedShares(ctx, []*collaboration.Filter{}, nil) 251 Expect(err).ToNot(HaveOccurred()) 252 Expect(len(shares)).To(Equal(2)) 253 groupShare := shares[1] 254 Expect(groupShare.MountPoint.Path).To(Equal("mygroupshared")) 255 Expect(groupShare.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 256 Expect(groupShare.Share.Id.OpaqueId).To(Equal(strconv.Itoa(parentID))) 257 Expect(groupShare.Share.Grantee.Type).To(Equal(provider.GranteeType_GRANTEE_TYPE_GROUP)) 258 Expect(groupShare.Share.Grantee.GetGroupId().OpaqueId).To(Equal("users")) 259 }) 260 }) 261 262 Context("with an accepted group share", func() { 263 It("lists the group share too", func() { 264 loginAs(otherUser) 265 _, err := insertShare( 266 1, // group share 267 "admin", // owner/initiator 268 "users", // grantee 269 -1, // parent 270 20, // source 271 "/shared", // file_target 272 31, // permissions, 273 0, // accepted 274 ) 275 Expect(err).ToNot(HaveOccurred()) 276 277 shares, err := mgr.ListReceivedShares(ctx, []*collaboration.Filter{}, nil) 278 Expect(err).ToNot(HaveOccurred()) 279 Expect(len(shares)).To(Equal(2)) 280 groupShare := shares[1] 281 Expect(groupShare.MountPoint.Path).To(Equal("shared")) 282 Expect(groupShare.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 283 Expect(groupShare.Share.Grantee.Type).To(Equal(provider.GranteeType_GRANTEE_TYPE_GROUP)) 284 }) 285 286 It("lists the child share information if the user changed the mountpoint", func() { 287 loginAs(otherUser) 288 parentID, err := insertShare( 289 1, // group share 290 "admin", // owner/initiator 291 "users", // grantee 292 -1, // parent 293 20, // source 294 "/groupshared", // file_target 295 31, // permissions, 296 1, // accepted 297 ) 298 Expect(err).ToNot(HaveOccurred()) 299 _, err = insertShare( 300 2, // group child share 301 "admin", // owner/initiator 302 "einstein", // grantee 303 parentID, // parent 304 20, // source 305 "/mygroupshared", // file_target 306 31, // permissions, 307 0, // accepted 308 ) 309 Expect(err).ToNot(HaveOccurred()) 310 311 shares, err := mgr.ListReceivedShares(ctx, []*collaboration.Filter{}, nil) 312 Expect(err).ToNot(HaveOccurred()) 313 Expect(len(shares)).To(Equal(2)) 314 groupShare := shares[1] 315 Expect(groupShare.MountPoint.Path).To(Equal("mygroupshared")) 316 Expect(groupShare.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 317 Expect(groupShare.Share.Id.OpaqueId).To(Equal(strconv.Itoa(parentID))) 318 Expect(groupShare.Share.Grantee.Type).To(Equal(provider.GranteeType_GRANTEE_TYPE_GROUP)) 319 Expect(groupShare.Share.Grantee.GetGroupId().OpaqueId).To(Equal("users")) 320 }) 321 322 It("does not lists group shares named like the user", func() { 323 loginAs(otherUser) 324 _, err := insertShare( 325 1, // group share 326 "admin", // owner/initiator 327 "einstein", // grantee 328 -1, // parent 329 20, // source 330 "/shared", // file_target 331 31, // permissions, 332 0, // accepted 333 ) 334 Expect(err).ToNot(HaveOccurred()) 335 336 shares, err := mgr.ListReceivedShares(ctx, []*collaboration.Filter{}, nil) 337 Expect(err).ToNot(HaveOccurred()) 338 Expect(len(shares)).To(Equal(1)) 339 }) 340 }) 341 342 It("lists received shares", func() { 343 loginAs(otherUser) 344 shares, err := mgr.ListReceivedShares(ctx, []*collaboration.Filter{}, nil) 345 Expect(err).ToNot(HaveOccurred()) 346 Expect(len(shares)).To(Equal(1)) 347 }) 348 349 It("works with filters", func() { 350 loginAs(otherUser) 351 shares, err := mgr.ListReceivedShares(ctx, []*collaboration.Filter{{Type: collaboration.Filter_TYPE_EXCLUDE_DENIALS}}, nil) 352 Expect(err).ToNot(HaveOccurred()) 353 Expect(len(shares)).To(Equal(1)) 354 }) 355 }) 356 357 Describe("GetReceivedShare", func() { 358 It("returns the received share", func() { 359 loginAs(otherUser) 360 share, err := mgr.GetReceivedShare(ctx, shareRef) 361 Expect(err).ToNot(HaveOccurred()) 362 Expect(share).ToNot(BeNil()) 363 }) 364 }) 365 366 Describe("UpdateReceivedShare", func() { 367 It("returns an error when no valid field is set in the mask", func() { 368 loginAs(otherUser) 369 370 share, err := mgr.GetReceivedShare(ctx, shareRef) 371 Expect(err).ToNot(HaveOccurred()) 372 Expect(share).ToNot(BeNil()) 373 Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 374 375 share.State = collaboration.ShareState_SHARE_STATE_REJECTED 376 _, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"foo"}}, nil) 377 Expect(err).To(HaveOccurred()) 378 }) 379 380 It("updates the state when the state is set in the mask", func() { 381 loginAs(otherUser) 382 383 share, err := mgr.GetReceivedShare(ctx, shareRef) 384 Expect(err).ToNot(HaveOccurred()) 385 Expect(share).ToNot(BeNil()) 386 Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 387 388 share.State = collaboration.ShareState_SHARE_STATE_REJECTED 389 390 share, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"mount_point"}}, nil) 391 Expect(err).ToNot(HaveOccurred()) 392 Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 393 394 share.State = collaboration.ShareState_SHARE_STATE_REJECTED 395 share, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"state"}}, nil) 396 Expect(err).ToNot(HaveOccurred()) 397 Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_REJECTED)) 398 399 share, err = mgr.GetReceivedShare(ctx, shareRef) 400 Expect(err).ToNot(HaveOccurred()) 401 Expect(share).ToNot(BeNil()) 402 Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_REJECTED)) 403 }) 404 405 It("updates the mount_point when the mount_point is set in the mask", func() { 406 loginAs(otherUser) 407 408 share, err := mgr.GetReceivedShare(ctx, shareRef) 409 Expect(err).ToNot(HaveOccurred()) 410 Expect(share).ToNot(BeNil()) 411 Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 412 413 share.MountPoint = &provider.Reference{Path: "foo"} 414 415 share, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"state"}}, nil) 416 Expect(err).ToNot(HaveOccurred()) 417 Expect(share.MountPoint.Path).To(Equal("shared")) 418 419 share.MountPoint = &provider.Reference{Path: "foo"} 420 share, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"mount_point"}}, nil) 421 Expect(err).ToNot(HaveOccurred()) 422 Expect(share.MountPoint.Path).To(Equal("foo")) 423 424 share, err = mgr.GetReceivedShare(ctx, shareRef) 425 Expect(err).ToNot(HaveOccurred()) 426 Expect(share).ToNot(BeNil()) 427 Expect(share.MountPoint.Path).To(Equal("foo")) 428 }) 429 430 Context("with a group share", func() { 431 It("updates the child share with the custom information", func() { 432 loginAs(otherUser) 433 parentID, err := insertShare( 434 1, // group share 435 "admin", // owner/initiator 436 "users", // grantee 437 -1, // parent 438 20, // source 439 "/groupshared", // file_target 440 31, // permissions, 441 1, // accepted 442 ) 443 Expect(err).ToNot(HaveOccurred()) 444 _, err = insertShare( 445 2, // group child share 446 "admin", // owner/initiator 447 "einstein", // grantee 448 parentID, // parent 449 20, // source 450 "/mygroupshared", // file_target 451 31, // permissions, 452 0, // accepted 453 ) 454 Expect(err).ToNot(HaveOccurred()) 455 parentRef := &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{ 456 Id: &collaboration.ShareId{ 457 OpaqueId: strconv.Itoa(parentID), 458 }, 459 }} 460 461 share, err := mgr.GetReceivedShare(ctx, parentRef) 462 Expect(err).ToNot(HaveOccurred()) 463 Expect(share).ToNot(BeNil()) 464 Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 465 466 share.MountPoint = &provider.Reference{Path: "foo"} 467 468 By("overriding the child share information for the current user") 469 share, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"mount_point"}}, nil) 470 Expect(err).ToNot(HaveOccurred()) 471 Expect(share.MountPoint.Path).To(Equal("foo")) 472 473 share, err = mgr.GetReceivedShare(ctx, parentRef) 474 Expect(err).ToNot(HaveOccurred()) 475 Expect(share).ToNot(BeNil()) 476 Expect(share.MountPoint.Path).To(Equal("foo")) 477 478 By("not overriding the parent share information") 479 loginAs(yetAnotherUser) 480 share, err = mgr.GetReceivedShare(ctx, parentRef) 481 Expect(err).ToNot(HaveOccurred()) 482 Expect(share.MountPoint.Path).To(Equal("groupshared")) 483 }) 484 }) 485 }) 486 487 Describe("Unshare", func() { 488 It("deletes shares", func() { 489 loginAs(otherUser) 490 shares, err := mgr.ListReceivedShares(ctx, []*collaboration.Filter{}, nil) 491 Expect(err).ToNot(HaveOccurred()) 492 Expect(len(shares)).To(Equal(1)) 493 494 loginAs(admin) 495 err = mgr.Unshare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{ 496 Id: &collaboration.ShareId{ 497 OpaqueId: shares[0].Share.Id.OpaqueId, 498 }, 499 }}) 500 Expect(err).ToNot(HaveOccurred()) 501 502 loginAs(otherUser) 503 shares, err = mgr.ListReceivedShares(ctx, []*collaboration.Filter{}, nil) 504 Expect(err).ToNot(HaveOccurred()) 505 Expect(len(shares)).To(Equal(0)) 506 }) 507 }) 508 509 Describe("UpdateShare", func() { 510 It("updates permissions", func() { 511 share, err := mgr.GetShare(ctx, shareRef) 512 Expect(err).ToNot(HaveOccurred()) 513 Expect(share.Permissions.Permissions.Delete).To(BeTrue()) 514 515 share, err = mgr.UpdateShare(ctx, shareRef, &collaboration.SharePermissions{ 516 Permissions: &provider.ResourcePermissions{ 517 InitiateFileUpload: true, 518 RestoreFileVersion: true, 519 RestoreRecycleItem: true, 520 }}, nil, nil) 521 Expect(err).ToNot(HaveOccurred()) 522 Expect(share.Permissions.Permissions.Delete).To(BeFalse()) 523 524 share, err = mgr.GetShare(ctx, shareRef) 525 Expect(err).ToNot(HaveOccurred()) 526 Expect(share.Permissions.Permissions.Delete).To(BeFalse()) 527 }) 528 }) 529 })