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  })