5252use OCP \Files \IRootFolder ;
5353use OCP \Files \Mount \IMountManager ;
5454use OCP \Files \Node ;
55+ use OCP \Files \NotFoundException ;
5556use OCP \HintException ;
5657use OCP \IConfig ;
5758use OCP \IDateTimeZone ;
@@ -1155,6 +1156,89 @@ protected function deleteChildren(IShare $share) {
11551156 return $ deletedShares ;
11561157 }
11571158
1159+ /** Promote re-shares into direct shares so that target user keeps access */
1160+ protected function promoteReshares (IShare $ share ): void {
1161+ try {
1162+ $ node = $ share ->getNode ();
1163+ } catch (NotFoundException ) {
1164+ /* Skip if node not found */
1165+ return ;
1166+ }
1167+
1168+ $ userIds = [];
1169+
1170+ if ($ share ->getShareType () === IShare::TYPE_USER ) {
1171+ $ userIds [] = $ share ->getSharedWith ();
1172+ } elseif ($ share ->getShareType () === IShare::TYPE_GROUP ) {
1173+ $ group = $ this ->groupManager ->get ($ share ->getSharedWith ());
1174+ $ users = $ group ?->getUsers() ?? [];
1175+
1176+ foreach ($ users as $ user ) {
1177+ /* Skip share owner */
1178+ if ($ user ->getUID () === $ share ->getShareOwner () || $ user ->getUID () === $ share ->getSharedBy ()) {
1179+ continue ;
1180+ }
1181+ $ userIds [] = $ user ->getUID ();
1182+ }
1183+ } else {
1184+ /* We only support user and group shares */
1185+ return ;
1186+ }
1187+
1188+ $ reshareRecords = [];
1189+ $ shareTypes = [
1190+ IShare::TYPE_GROUP ,
1191+ IShare::TYPE_USER ,
1192+ IShare::TYPE_LINK ,
1193+ IShare::TYPE_REMOTE ,
1194+ IShare::TYPE_EMAIL ,
1195+ ];
1196+
1197+ foreach ($ userIds as $ userId ) {
1198+ foreach ($ shareTypes as $ shareType ) {
1199+ $ provider = $ this ->factory ->getProviderForType ($ shareType );
1200+ if ($ node instanceof Folder) {
1201+ /* We need to get all shares by this user to get subshares */
1202+ $ shares = $ provider ->getSharesBy ($ userId , $ shareType , null , false , -1 , 0 );
1203+
1204+ foreach ($ shares as $ share ) {
1205+ try {
1206+ $ path = $ share ->getNode ()->getPath ();
1207+ } catch (NotFoundException ) {
1208+ /* Ignore share of non-existing node */
1209+ continue ;
1210+ }
1211+ if ($ node ->getRelativePath ($ path ) !== null ) {
1212+ /* If relative path is not null it means the shared node is the same or in a subfolder */
1213+ $ reshareRecords [] = $ share ;
1214+ }
1215+ }
1216+ } else {
1217+ $ shares = $ provider ->getSharesBy ($ userId , $ shareType , $ node , false , -1 , 0 );
1218+ foreach ($ shares as $ child ) {
1219+ $ reshareRecords [] = $ child ;
1220+ }
1221+ }
1222+ }
1223+ }
1224+
1225+ foreach ($ reshareRecords as $ child ) {
1226+ try {
1227+ /* Check if the share is still valid (means the resharer still has access to the file through another mean) */
1228+ $ this ->generalCreateChecks ($ child );
1229+ } catch (GenericShareException $ e ) {
1230+ /* The check is invalid, promote it to a direct share from the sharer of parent share */
1231+ $ this ->logger ->debug ('Promote reshare because of exception ' . $ e ->getMessage (), ['exception ' => $ e , 'fullId ' => $ child ->getFullId ()]);
1232+ try {
1233+ $ child ->setSharedBy ($ share ->getSharedBy ());
1234+ $ this ->updateShare ($ child );
1235+ } catch (GenericShareException |\InvalidArgumentException $ e ) {
1236+ $ this ->logger ->warning ('Failed to promote reshare because of exception ' . $ e ->getMessage (), ['exception ' => $ e , 'fullId ' => $ child ->getFullId ()]);
1237+ }
1238+ }
1239+ }
1240+ }
1241+
11581242 /**
11591243 * Delete a share
11601244 *
@@ -1179,6 +1263,9 @@ public function deleteShare(IShare $share) {
11791263 $ provider ->delete ($ share );
11801264
11811265 $ this ->dispatcher ->dispatchTyped (new ShareDeletedEvent ($ share ));
1266+
1267+ // Promote reshares of the deleted share
1268+ $ this ->promoteReshares ($ share );
11821269 }
11831270
11841271
0 commit comments