2222
2323use OC \Files \View ;
2424use OC \Share20 \Manager ;
25+ use OC \Share20 \ShareAttributes ;
2526use OCP \Files \File ;
2627use OC \Share20 \Share ;
2728use OCP \DB \QueryBuilder \IExpressionBuilder ;
3940use OCP \ILogger ;
4041use OCP \IUser ;
4142use OCP \IUserManager ;
43+ use OCP \IUserSession ;
4244use OCP \Security \IHasher ;
4345use OCP \Security \ISecureRandom ;
4446use OCP \Share \Exceptions \ShareNotFound ;
47+ use OCP \Share \IAttributes ;
4548use OCP \Share \IProviderFactory ;
4649use OCP \Share \IShare ;
4750use OCP \Share \IShareProvider ;
@@ -88,6 +91,8 @@ class ManagerTest extends \Test\TestCase {
8891 protected $ view ;
8992 /** @var IDBConnection | \PHPUnit\Framework\MockObject\MockObject */
9093 protected $ connection ;
94+ /** @var IUserSession | \PHPUnit\Framework\MockObject\MockObject */
95+ protected $ userSession ;
9196
9297 public function setUp (): void {
9398 parent ::setUp ();
@@ -103,6 +108,7 @@ public function setUp(): void {
103108 $ this ->eventDispatcher = new EventDispatcher ();
104109 $ this ->view = $ this ->createMock (View::class);
105110 $ this ->connection = $ this ->createMock (IDBConnection::class);
111+ $ this ->userSession = $ this ->createMock (IUserSession::class);
106112
107113 $ this ->l = $ this ->createMock ('\OCP\IL10N ' );
108114 $ this ->l ->method ('t ' )
@@ -125,7 +131,8 @@ public function setUp(): void {
125131 $ this ->rootFolder ,
126132 $ this ->eventDispatcher ,
127133 $ this ->view ,
128- $ this ->connection
134+ $ this ->connection ,
135+ $ this ->userSession
129136 );
130137
131138 $ this ->defaultProvider = $ this ->getMockBuilder ('\OC\Share20\DefaultShareProvider ' )
@@ -822,26 +829,18 @@ public function dataGeneralChecks() {
822829 $ data [] = [$ this ->createShare (null , \OCP \Share::SHARE_TYPE_GROUP , $ rootFolder , $ group0 , $ user0 , $ user0 , 2 , null , null ), 'You can \'t share your root folder ' , true ];
823830 $ data [] = [$ this ->createShare (null , \OCP \Share::SHARE_TYPE_LINK , $ rootFolder , null , $ user0 , $ user0 , 16 , null , null ), 'You can \'t share your root folder ' , true ];
824831
825- /**
826- * Basic share (not re-share) with enough permission inputs
827- */
828- $ ownerUser = $ this ->createMock (IUser::class);
829- $ ownerUser ->method ('getUID ' )->willReturn ('user1 ' );
830832 $ fileFullPermission = $ this ->createMock (File::class);
831833 $ fileFullPermission ->method ('getPermissions ' )->willReturn (31 );
832- $ fileFullPermission ->method ('getOwner ' )->willReturn ($ ownerUser );
833834 $ fileFullPermission ->method ('isShareable ' )->willReturn (true );
835+
834836 $ data [] = [$ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ fileFullPermission , $ user0 , $ user1 , $ user1 , null , null , null ), 'A share requires permissions ' , true ];
835837
836- /**
837- * Normal share (not re-share) with not enough permission input
838- */
839- $ fileLessPermission = $ this ->createMock (File::class);
840- $ fileLessPermission ->method ('getPermissions ' )->willReturn (1 );
841- $ fileLessPermission ->method ('getOwner ' )->willReturn ($ ownerUser );
842- $ fileLessPermission ->method ('isShareable ' )->willReturn (true );
843- $ fileLessPermission ->method ('getPath ' )->willReturn ('/user1/sharedfile ' );
844- $ data [] = [$ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ fileLessPermission , $ user0 , $ user1 , $ user1 , 17 , null , null ), 'Cannot increase permissions of /user1/sharedfile ' , true ];
838+ $ data [] = [$ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ fileFullPermission , $ user0 , $ user1 , $ user1 , -1 , null , null ), 'Invalid permissions ' , true ];
839+ $ data [] = [$ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ fileFullPermission , $ user0 , $ user1 , $ user1 , 100 , null , null ), 'Invalid permissions ' , true ];
840+
841+ $ data [] = [$ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ fileFullPermission , $ user0 , $ user1 , $ user1 , 0 , null , null ), 'Cannot remove all permissions ' , true ];
842+
843+ $ data [] = [$ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ fileFullPermission , $ user0 , $ user1 , $ user1 , 31 , null , null ), null , false ];
845844
846845 return $ data ;
847846 }
@@ -883,9 +882,118 @@ public function testGeneralChecks($share, $exceptionMessage, $exception) {
883882 $ this ->assertSame ($ exception , $ thrown );
884883 }
885884
885+ public function dataShareNotEnoughPermissions () {
886+ $ file = $ this ->createMock (File::class);
887+ $ file ->method ('getPermissions ' )->willReturn (17 );
888+ $ file ->method ('getName ' )->willReturn ('sharedfile ' );
889+ $ file ->method ('getPath ' )->willReturn ('/user1/sharedfile ' );
890+
891+ // Normal share (not re-share) should just use share node permission
892+ // exception when trying to share with more permission than share has
893+ $ share = $ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ file , 'user0 ' , 'user1 ' , 'user1 ' , 31 , null , null );
894+ $ data [] = [$ share , null , 'Cannot set the requested share permissions for sharedfile ' , true ];
895+
896+ // Federated reshare should just use share node permission
897+ // exception when trying to share with more permission than node has
898+ $ fileExternalStorage = $ this ->createMock ('OCA\Files_Sharing\External\Storage ' );
899+ $ fileExternalStorage ->method ('instanceOfStorage ' )
900+ ->willReturnCallback (function ($ storageClass ) {
901+ return ($ storageClass === 'OCA\Files_Sharing\External\Storage ' );
902+ });
903+ $ fileExternal = $ this ->createMock (File::class);
904+ $ fileExternal ->method ('getStorage ' )->willReturn ($ fileExternalStorage );
905+ $ share = $ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ file , 'user0 ' , 'user1 ' , 'user2 ' , 31 , null , null );
906+ $ data [] = [$ share , $ fileExternal , 'Cannot set the requested share permissions for sharedfile ' , true ];
907+
908+ // Normal reshare should just use supershare node permission
909+ // exception when trying to share with more permission than supershare has
910+ $ superShare = $ this ->createMock (IShare::class);
911+ $ superShare ->method ('getPermissions ' )->willReturn (1 );
912+ $ fileReshareStorage = $ this ->createMock ('OCA\Files_Sharing\SharedStorage ' );
913+ $ fileReshareStorage ->method ('instanceOfStorage ' )
914+ ->willReturnCallback (function ($ storageClass ) {
915+ return ($ storageClass === 'OCA\Files_Sharing\SharedStorage ' );
916+ });
917+ $ fileReshareStorage ->method ('getShare ' )->willReturn ($ superShare );
918+ $ fileReshare = $ this ->createMock (File::class);
919+ $ fileReshare ->method ('getStorage ' )->willReturn ($ fileReshareStorage );
920+ $ share = $ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ file , 'user0 ' , 'user1 ' , 'user2 ' , 17 , null , null );
921+ $ data [] = [$ share , $ fileReshare , 'Cannot set the requested share permissions for sharedfile ' , true ];
922+
923+ // Normal reshare should just use supershare node attributes
924+ // exception when trying to share with more attributes than supershare has
925+ $ superShareAttributes = new ShareAttributes ();
926+ $ shareAttributes = new ShareAttributes ();
927+ $ shareAttributes ->setAttribute ('test ' , 'test ' , true );
928+ $ superShare = $ this ->createMock (IShare::class);
929+ $ superShare ->method ('getPermissions ' )->willReturn (17 );
930+ $ superShare ->method ('getAttributes ' )->willReturn ($ superShareAttributes );
931+ $ fileReshareStorage = $ this ->createMock ('OCA\Files_Sharing\SharedStorage ' );
932+ $ fileReshareStorage ->method ('instanceOfStorage ' )
933+ ->willReturnCallback (function ($ storageClass ) {
934+ return ($ storageClass === 'OCA\Files_Sharing\SharedStorage ' );
935+ });
936+ $ fileReshareStorage ->method ('getShare ' )->willReturn ($ superShare );
937+ $ fileReshare = $ this ->createMock (File::class);
938+ $ fileReshare ->method ('getStorage ' )->willReturn ($ fileReshareStorage );
939+ $ share = $ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ file , 'user0 ' , 'user1 ' , 'user2 ' , 17 , null , null , $ shareAttributes );
940+ $ data [] = [$ share , $ fileReshare , 'Cannot set the requested share attributes for sharedfile ' , true ];
941+
942+ return $ data ;
943+ }
944+
945+ /**
946+ * @dataProvider dataShareNotEnoughPermissions
947+ *
948+ * @param $share
949+ * @param $superShareNode
950+ * @param $exceptionMessage
951+ * @param $exception
952+ */
953+ public function testShareNotEnoughPermissions ($ share , $ superShareNode , $ exceptionMessage , $ exception ) {
954+ $ sharer = $ this ->createMock (IUser::class);
955+ $ sharer ->method ('getUID ' )->willReturn ($ share ->getSharedBy ());
956+ $ this ->userSession ->method ('getUser ' )->willReturn ($ sharer );
957+
958+ $ userFolder = $ this ->createMock (Folder::class);
959+ $ userFolder ->method ('getById ' )->willReturn ([$ superShareNode ]);
960+ $ this ->rootFolder ->method ('getUserFolder ' )->willReturn ($ userFolder );
961+
962+ try {
963+ $ this ->invokePrivate ($ this ->manager , 'validatePermissions ' , [$ share ]);
964+ $ thrown = false ;
965+ } catch (\OCP \Share \Exceptions \GenericShareException $ e ) {
966+ $ this ->assertEquals ($ exceptionMessage , $ e ->getHint ());
967+ $ thrown = true ;
968+ }
969+
970+ $ this ->assertSame ($ exception , $ thrown );
971+ }
972+
973+ /**
974+ * Non-movable mount share can be shared with delete and update permission
975+ * even if permission for file do not have this permission
976+ */
977+ public function testShareNonMovableMountPermissions () {
978+ $ nonMovableMountPoint = $ this ->createMock (IMountPoint::class);
979+ $ file = $ this ->createMock (File::class);
980+ $ file ->method ('getPermissions ' )->willReturn (1 );
981+ $ file ->method ('getMountPoint ' )->willReturn ($ nonMovableMountPoint );
982+ $ share = $ this ->createShare (null , \OCP \Share::SHARE_TYPE_USER , $ file , 'user0 ' , 'user1 ' , 'user1 ' , 11 , null , null );
983+
984+ try {
985+ $ this ->invokePrivate ($ this ->manager , 'validatePermissions ' , [$ share ]);
986+ $ thrown = false ;
987+ } catch (\Exception $ e ) {
988+ $ thrown = true ;
989+ }
990+
991+ $ this ->assertSame (false , $ thrown );
992+ }
993+
886994 /**
887995 */
888- public function testvalidateExpirationDateInPast () {
996+ public function testValidateExpirationDateInPast () {
889997 $ this ->expectException (\OCP \Share \Exceptions \GenericShareException::class);
890998 $ this ->expectExceptionMessage ('Expiration date is in the past ' );
891999
@@ -3523,6 +3631,102 @@ public function testGetAllSharedWith() {
35233631 $ this ->assertSame ($ shares , [$ share1 , $ share2 ]);
35243632 }
35253633
3634+ /**
3635+ * @dataProvider strictSubsetOfAttributesDataProvider
3636+ *
3637+ * @param IAttributes $allowedAttributes
3638+ * @param IAttributes $newAttributes
3639+ * @param boolean $expected
3640+ */
3641+ public function testStrictSubsetOfAttributes ($ allowedAttributes , $ newAttributes , $ expected ) {
3642+ $ this ->assertEquals (
3643+ $ expected ,
3644+ $ this ->invokePrivate (
3645+ $ this ->manager ,
3646+ 'strictSubsetOfAttributes ' ,
3647+ [$ allowedAttributes , $ newAttributes ]
3648+ )
3649+ );
3650+ }
3651+
3652+ public function strictSubsetOfAttributesDataProvider () {
3653+ // no exception - supershare and share are equal
3654+ $ superShareAttributes = new ShareAttributes ();
3655+ $ shareAttributes = new ShareAttributes ();
3656+ $ data [] = [$ superShareAttributes ,$ shareAttributes , true ];
3657+
3658+ // no exception - supershare and share are equal
3659+ $ superShareAttributes = new ShareAttributes ();
3660+ $ superShareAttributes ->setAttribute ('test ' , 'test ' , true );
3661+ $ shareAttributes = new ShareAttributes ();
3662+ $ shareAttributes ->setAttribute ('test ' , 'test ' , true );
3663+ $ data [] = [$ superShareAttributes ,$ shareAttributes , true ];
3664+
3665+ // no exception - disabling attribute that supershare has enabled
3666+ $ superShareAttributes = new ShareAttributes ();
3667+ $ superShareAttributes ->setAttribute ('test ' , 'test ' , true );
3668+ $ shareAttributes = new ShareAttributes ();
3669+ $ shareAttributes ->setAttribute ('test ' , 'test ' , false );
3670+ $ data [] = [$ superShareAttributes ,$ shareAttributes , true ];
3671+
3672+ // exception - adding an attribute while supershare has none
3673+ $ superShareAttributes = new ShareAttributes ();
3674+ $ shareAttributes = new ShareAttributes ();
3675+ $ shareAttributes ->setAttribute ('test ' , 'test ' , true );
3676+ $ data [] = [$ superShareAttributes ,$ shareAttributes , false ];
3677+
3678+ // exception - enabling attribute that supershare has disabled
3679+ $ superShareAttributes = new ShareAttributes ();
3680+ $ superShareAttributes ->setAttribute ('test ' , 'test ' , false );
3681+ $ shareAttributes = new ShareAttributes ();
3682+ $ shareAttributes ->setAttribute ('test ' , 'test ' , true );
3683+ $ data [] = [$ superShareAttributes ,$ shareAttributes , false ];
3684+
3685+ // exception - removing attribute of that supershare has enabled
3686+ $ superShareAttributes = new ShareAttributes ();
3687+ $ superShareAttributes ->setAttribute ('test ' , 'test ' , true );
3688+ $ shareAttributes = new ShareAttributes ();
3689+ $ data [] = [$ superShareAttributes ,$ shareAttributes , false ];
3690+
3691+ // exception - removing attribute of that supershare has disabled
3692+ $ superShareAttributes = new ShareAttributes ();
3693+ $ superShareAttributes ->setAttribute ('test ' , 'test ' , false );
3694+ $ shareAttributes = new ShareAttributes ();
3695+ $ data [] = [$ superShareAttributes ,$ shareAttributes , false ];
3696+
3697+ // exception - removing one of attributes of supershare
3698+ $ superShareAttributes = new ShareAttributes ();
3699+ $ superShareAttributes ->setAttribute ('test ' , 'test1 ' , false );
3700+ $ superShareAttributes ->setAttribute ('test ' , 'test2 ' , false );
3701+ $ shareAttributes = new ShareAttributes ();
3702+ $ shareAttributes ->setAttribute ('test ' , 'test1 ' , false );
3703+ $ data [] = [$ superShareAttributes ,$ shareAttributes , false ];
3704+
3705+ // exception - disabling one of attributes of supershare
3706+ $ superShareAttributes = new ShareAttributes ();
3707+ $ superShareAttributes ->setAttribute ('test ' , 'test1 ' , false );
3708+ $ superShareAttributes ->setAttribute ('test ' , 'test2 ' , false );
3709+ $ shareAttributes = new ShareAttributes ();
3710+ $ shareAttributes ->setAttribute ('test ' , 'test1 ' , false );
3711+ $ shareAttributes ->setAttribute ('test ' , 'test2 ' , true );
3712+ $ data [] = [$ superShareAttributes ,$ shareAttributes , false ];
3713+
3714+ // exception - swaping one of attributes of supershare
3715+ $ superShareAttributes = new ShareAttributes ();
3716+ $ superShareAttributes ->setAttribute ('test ' , 'test1 ' , false );
3717+ $ superShareAttributes ->setAttribute ('test ' , 'test01 ' , false );
3718+ $ superShareAttributes ->setAttribute ('test ' , 'test3 ' , true );
3719+ $ superShareAttributes ->setAttribute ('test ' , 'test4 ' , null );
3720+ $ shareAttributes = new ShareAttributes ();
3721+ $ shareAttributes ->setAttribute ('test ' , 'test1 ' , false );
3722+ $ shareAttributes ->setAttribute ('test ' , 'test10 ' , false );
3723+ $ superShareAttributes ->setAttribute ('test ' , 'test3 ' , null );
3724+ $ superShareAttributes ->setAttribute ('test ' , 'test4 ' , true );
3725+ $ data [] = [$ superShareAttributes ,$ shareAttributes , false ];
3726+
3727+ return $ data ;
3728+ }
3729+
35263730 /**
35273731 * @dataProvider strictSubsetOfPermissionsDataProvider
35283732 *
0 commit comments