Completed
Push — master ( ac2c4e...49a025 )
by
unknown
37:44 queued 12:59
created
apps/files_sharing/lib/MountProvider.php 2 patches
Indentation   +247 added lines, -247 removed lines patch added patch discarded remove patch
@@ -23,251 +23,251 @@
 block discarded – undo
23 23
 use Psr\Log\LoggerInterface;
24 24
 
25 25
 class MountProvider implements IMountProvider {
26
-	/**
27
-	 * @param IConfig $config
28
-	 * @param IManager $shareManager
29
-	 * @param LoggerInterface $logger
30
-	 */
31
-	public function __construct(
32
-		protected IConfig $config,
33
-		protected IManager $shareManager,
34
-		protected LoggerInterface $logger,
35
-		protected IEventDispatcher $eventDispatcher,
36
-		protected ICacheFactory $cacheFactory,
37
-		protected IMountManager $mountManager,
38
-	) {
39
-	}
40
-
41
-	/**
42
-	 * Get all mountpoints applicable for the user and check for shares where we need to update the etags
43
-	 *
44
-	 * @param IUser $user
45
-	 * @param IStorageFactory $loader
46
-	 * @return IMountPoint[]
47
-	 */
48
-	public function getMountsForUser(IUser $user, IStorageFactory $loader) {
49
-		$shares = array_merge(
50
-			$this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_USER, null, -1),
51
-			$this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_GROUP, null, -1),
52
-			$this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_CIRCLE, null, -1),
53
-			$this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_ROOM, null, -1),
54
-			$this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_DECK, null, -1),
55
-			$this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_SCIENCEMESH, null, -1),
56
-		);
57
-
58
-		// filter out excluded shares and group shares that includes self
59
-		$shares = array_filter($shares, function (IShare $share) use ($user) {
60
-			return $share->getPermissions() > 0 && $share->getShareOwner() !== $user->getUID() && $share->getSharedBy() !== $user->getUID();
61
-		});
62
-
63
-		$superShares = $this->buildSuperShares($shares, $user);
64
-
65
-		$allMounts = $this->mountManager->getAll();
66
-		$mounts = [];
67
-		$view = new View('/' . $user->getUID() . '/files');
68
-		$ownerViews = [];
69
-		$sharingDisabledForUser = $this->shareManager->sharingDisabledForUser($user->getUID());
70
-		/** @var CappedMemoryCache<bool> $folderExistCache */
71
-		$foldersExistCache = new CappedMemoryCache();
72
-
73
-		$validShareCache = $this->cacheFactory->createLocal('share-valid-mountpoint-max');
74
-		$maxValidatedShare = $validShareCache->get($user->getUID()) ?? 0;
75
-		$newMaxValidatedShare = $maxValidatedShare;
76
-
77
-		foreach ($superShares as $share) {
78
-			try {
79
-				/** @var IShare $parentShare */
80
-				$parentShare = $share[0];
81
-
82
-				if ($parentShare->getStatus() !== IShare::STATUS_ACCEPTED
83
-					&& ($parentShare->getShareType() === IShare::TYPE_GROUP
84
-						|| $parentShare->getShareType() === IShare::TYPE_USERGROUP
85
-						|| $parentShare->getShareType() === IShare::TYPE_USER)) {
86
-					continue;
87
-				}
88
-
89
-				$owner = $parentShare->getShareOwner();
90
-				if (!isset($ownerViews[$owner])) {
91
-					$ownerViews[$owner] = new View('/' . $parentShare->getShareOwner() . '/files');
92
-				}
93
-				$shareId = (int)$parentShare->getId();
94
-				$mount = new SharedMount(
95
-					'\OCA\Files_Sharing\SharedStorage',
96
-					$allMounts,
97
-					[
98
-						'user' => $user->getUID(),
99
-						// parent share
100
-						'superShare' => $parentShare,
101
-						// children/component of the superShare
102
-						'groupedShares' => $share[1],
103
-						'ownerView' => $ownerViews[$owner],
104
-						'sharingDisabledForUser' => $sharingDisabledForUser
105
-					],
106
-					$loader,
107
-					$view,
108
-					$foldersExistCache,
109
-					$this->eventDispatcher,
110
-					$user,
111
-					($shareId <= $maxValidatedShare),
112
-				);
113
-
114
-				$newMaxValidatedShare = max($shareId, $newMaxValidatedShare);
115
-
116
-				$event = new ShareMountedEvent($mount);
117
-				$this->eventDispatcher->dispatchTyped($event);
118
-
119
-				$mounts[$mount->getMountPoint()] = $allMounts[$mount->getMountPoint()] = $mount;
120
-				foreach ($event->getAdditionalMounts() as $additionalMount) {
121
-					$allMounts[$additionalMount->getMountPoint()] = $mounts[$additionalMount->getMountPoint()] = $additionalMount;
122
-				}
123
-			} catch (\Exception $e) {
124
-				$this->logger->error(
125
-					'Error while trying to create shared mount',
126
-					[
127
-						'app' => 'files_sharing',
128
-						'exception' => $e,
129
-					],
130
-				);
131
-			}
132
-		}
133
-
134
-		$validShareCache->set($user->getUID(), $newMaxValidatedShare, 24 * 60 * 60);
135
-
136
-		// array_filter removes the null values from the array
137
-		return array_values(array_filter($mounts));
138
-	}
139
-
140
-	/**
141
-	 * Groups shares by path (nodeId) and target path
142
-	 *
143
-	 * @param IShare[] $shares
144
-	 * @return IShare[][] array of grouped shares, each element in the
145
-	 *                    array is a group which itself is an array of shares
146
-	 */
147
-	private function groupShares(array $shares) {
148
-		$tmp = [];
149
-
150
-		foreach ($shares as $share) {
151
-			if (!isset($tmp[$share->getNodeId()])) {
152
-				$tmp[$share->getNodeId()] = [];
153
-			}
154
-			$tmp[$share->getNodeId()][] = $share;
155
-		}
156
-
157
-		$result = [];
158
-		// sort by stime, the super share will be based on the least recent share
159
-		foreach ($tmp as &$tmp2) {
160
-			@usort($tmp2, function ($a, $b) {
161
-				$aTime = $a->getShareTime()->getTimestamp();
162
-				$bTime = $b->getShareTime()->getTimestamp();
163
-				if ($aTime === $bTime) {
164
-					return $a->getId() < $b->getId() ? -1 : 1;
165
-				}
166
-				return $aTime < $bTime ? -1 : 1;
167
-			});
168
-			$result[] = $tmp2;
169
-		}
170
-
171
-		return array_values($result);
172
-	}
173
-
174
-	/**
175
-	 * Build super shares (virtual share) by grouping them by node id and target,
176
-	 * then for each group compute the super share and return it along with the matching
177
-	 * grouped shares. The most permissive permissions are used based on the permissions
178
-	 * of all shares within the group.
179
-	 *
180
-	 * @param IShare[] $allShares
181
-	 * @param IUser $user user
182
-	 * @return array Tuple of [superShare, groupedShares]
183
-	 */
184
-	private function buildSuperShares(array $allShares, IUser $user) {
185
-		$result = [];
186
-
187
-		$groupedShares = $this->groupShares($allShares);
188
-
189
-		/** @var IShare[] $shares */
190
-		foreach ($groupedShares as $shares) {
191
-			if (count($shares) === 0) {
192
-				continue;
193
-			}
194
-
195
-			$superShare = $this->shareManager->newShare();
196
-
197
-			// compute super share based on first entry of the group
198
-			$superShare->setId($shares[0]->getId())
199
-				->setShareOwner($shares[0]->getShareOwner())
200
-				->setNodeId($shares[0]->getNodeId())
201
-				->setShareType($shares[0]->getShareType())
202
-				->setTarget($shares[0]->getTarget());
203
-
204
-			// Gather notes from all the shares.
205
-			// Since these are readly available here, storing them
206
-			// enables the DAV FilesPlugin to avoid executing many
207
-			// DB queries to retrieve the same information.
208
-			$allNotes = implode("\n", array_map(function ($sh) {
209
-				return $sh->getNote();
210
-			}, $shares));
211
-			$superShare->setNote($allNotes);
212
-
213
-			// use most permissive permissions
214
-			// this covers the case where there are multiple shares for the same
215
-			// file e.g. from different groups and different permissions
216
-			$superPermissions = 0;
217
-			$superAttributes = $this->shareManager->newShare()->newAttributes();
218
-			$status = IShare::STATUS_PENDING;
219
-			foreach ($shares as $share) {
220
-				$superPermissions |= $share->getPermissions();
221
-				$status = max($status, $share->getStatus());
222
-				// update permissions
223
-				$superPermissions |= $share->getPermissions();
224
-
225
-				// update share permission attributes
226
-				$attributes = $share->getAttributes();
227
-				if ($attributes !== null) {
228
-					foreach ($attributes->toArray() as $attribute) {
229
-						if ($superAttributes->getAttribute($attribute['scope'], $attribute['key']) === true) {
230
-							// if super share attribute is already enabled, it is most permissive
231
-							continue;
232
-						}
233
-						// update supershare attributes with subshare attribute
234
-						$superAttributes->setAttribute($attribute['scope'], $attribute['key'], $attribute['value']);
235
-					}
236
-				}
237
-
238
-				// adjust target, for database consistency if needed
239
-				if ($share->getTarget() !== $superShare->getTarget()) {
240
-					$share->setTarget($superShare->getTarget());
241
-					try {
242
-						$this->shareManager->moveShare($share, $user->getUID());
243
-					} catch (\InvalidArgumentException $e) {
244
-						// ignore as it is not important and we don't want to
245
-						// block FS setup
246
-
247
-						// the subsequent code anyway only uses the target of the
248
-						// super share
249
-
250
-						// such issue can usually happen when dealing with
251
-						// null groups which usually appear with group backend
252
-						// caching inconsistencies
253
-						$this->logger->debug(
254
-							'Could not adjust share target for share ' . $share->getId() . ' to make it consistent: ' . $e->getMessage(),
255
-							['app' => 'files_sharing']
256
-						);
257
-					}
258
-				}
259
-				if (!is_null($share->getNodeCacheEntry())) {
260
-					$superShare->setNodeCacheEntry($share->getNodeCacheEntry());
261
-				}
262
-			}
263
-
264
-			$superShare->setPermissions($superPermissions);
265
-			$superShare->setStatus($status);
266
-			$superShare->setAttributes($superAttributes);
267
-
268
-			$result[] = [$superShare, $shares];
269
-		}
270
-
271
-		return $result;
272
-	}
26
+    /**
27
+     * @param IConfig $config
28
+     * @param IManager $shareManager
29
+     * @param LoggerInterface $logger
30
+     */
31
+    public function __construct(
32
+        protected IConfig $config,
33
+        protected IManager $shareManager,
34
+        protected LoggerInterface $logger,
35
+        protected IEventDispatcher $eventDispatcher,
36
+        protected ICacheFactory $cacheFactory,
37
+        protected IMountManager $mountManager,
38
+    ) {
39
+    }
40
+
41
+    /**
42
+     * Get all mountpoints applicable for the user and check for shares where we need to update the etags
43
+     *
44
+     * @param IUser $user
45
+     * @param IStorageFactory $loader
46
+     * @return IMountPoint[]
47
+     */
48
+    public function getMountsForUser(IUser $user, IStorageFactory $loader) {
49
+        $shares = array_merge(
50
+            $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_USER, null, -1),
51
+            $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_GROUP, null, -1),
52
+            $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_CIRCLE, null, -1),
53
+            $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_ROOM, null, -1),
54
+            $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_DECK, null, -1),
55
+            $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_SCIENCEMESH, null, -1),
56
+        );
57
+
58
+        // filter out excluded shares and group shares that includes self
59
+        $shares = array_filter($shares, function (IShare $share) use ($user) {
60
+            return $share->getPermissions() > 0 && $share->getShareOwner() !== $user->getUID() && $share->getSharedBy() !== $user->getUID();
61
+        });
62
+
63
+        $superShares = $this->buildSuperShares($shares, $user);
64
+
65
+        $allMounts = $this->mountManager->getAll();
66
+        $mounts = [];
67
+        $view = new View('/' . $user->getUID() . '/files');
68
+        $ownerViews = [];
69
+        $sharingDisabledForUser = $this->shareManager->sharingDisabledForUser($user->getUID());
70
+        /** @var CappedMemoryCache<bool> $folderExistCache */
71
+        $foldersExistCache = new CappedMemoryCache();
72
+
73
+        $validShareCache = $this->cacheFactory->createLocal('share-valid-mountpoint-max');
74
+        $maxValidatedShare = $validShareCache->get($user->getUID()) ?? 0;
75
+        $newMaxValidatedShare = $maxValidatedShare;
76
+
77
+        foreach ($superShares as $share) {
78
+            try {
79
+                /** @var IShare $parentShare */
80
+                $parentShare = $share[0];
81
+
82
+                if ($parentShare->getStatus() !== IShare::STATUS_ACCEPTED
83
+                    && ($parentShare->getShareType() === IShare::TYPE_GROUP
84
+                        || $parentShare->getShareType() === IShare::TYPE_USERGROUP
85
+                        || $parentShare->getShareType() === IShare::TYPE_USER)) {
86
+                    continue;
87
+                }
88
+
89
+                $owner = $parentShare->getShareOwner();
90
+                if (!isset($ownerViews[$owner])) {
91
+                    $ownerViews[$owner] = new View('/' . $parentShare->getShareOwner() . '/files');
92
+                }
93
+                $shareId = (int)$parentShare->getId();
94
+                $mount = new SharedMount(
95
+                    '\OCA\Files_Sharing\SharedStorage',
96
+                    $allMounts,
97
+                    [
98
+                        'user' => $user->getUID(),
99
+                        // parent share
100
+                        'superShare' => $parentShare,
101
+                        // children/component of the superShare
102
+                        'groupedShares' => $share[1],
103
+                        'ownerView' => $ownerViews[$owner],
104
+                        'sharingDisabledForUser' => $sharingDisabledForUser
105
+                    ],
106
+                    $loader,
107
+                    $view,
108
+                    $foldersExistCache,
109
+                    $this->eventDispatcher,
110
+                    $user,
111
+                    ($shareId <= $maxValidatedShare),
112
+                );
113
+
114
+                $newMaxValidatedShare = max($shareId, $newMaxValidatedShare);
115
+
116
+                $event = new ShareMountedEvent($mount);
117
+                $this->eventDispatcher->dispatchTyped($event);
118
+
119
+                $mounts[$mount->getMountPoint()] = $allMounts[$mount->getMountPoint()] = $mount;
120
+                foreach ($event->getAdditionalMounts() as $additionalMount) {
121
+                    $allMounts[$additionalMount->getMountPoint()] = $mounts[$additionalMount->getMountPoint()] = $additionalMount;
122
+                }
123
+            } catch (\Exception $e) {
124
+                $this->logger->error(
125
+                    'Error while trying to create shared mount',
126
+                    [
127
+                        'app' => 'files_sharing',
128
+                        'exception' => $e,
129
+                    ],
130
+                );
131
+            }
132
+        }
133
+
134
+        $validShareCache->set($user->getUID(), $newMaxValidatedShare, 24 * 60 * 60);
135
+
136
+        // array_filter removes the null values from the array
137
+        return array_values(array_filter($mounts));
138
+    }
139
+
140
+    /**
141
+     * Groups shares by path (nodeId) and target path
142
+     *
143
+     * @param IShare[] $shares
144
+     * @return IShare[][] array of grouped shares, each element in the
145
+     *                    array is a group which itself is an array of shares
146
+     */
147
+    private function groupShares(array $shares) {
148
+        $tmp = [];
149
+
150
+        foreach ($shares as $share) {
151
+            if (!isset($tmp[$share->getNodeId()])) {
152
+                $tmp[$share->getNodeId()] = [];
153
+            }
154
+            $tmp[$share->getNodeId()][] = $share;
155
+        }
156
+
157
+        $result = [];
158
+        // sort by stime, the super share will be based on the least recent share
159
+        foreach ($tmp as &$tmp2) {
160
+            @usort($tmp2, function ($a, $b) {
161
+                $aTime = $a->getShareTime()->getTimestamp();
162
+                $bTime = $b->getShareTime()->getTimestamp();
163
+                if ($aTime === $bTime) {
164
+                    return $a->getId() < $b->getId() ? -1 : 1;
165
+                }
166
+                return $aTime < $bTime ? -1 : 1;
167
+            });
168
+            $result[] = $tmp2;
169
+        }
170
+
171
+        return array_values($result);
172
+    }
173
+
174
+    /**
175
+     * Build super shares (virtual share) by grouping them by node id and target,
176
+     * then for each group compute the super share and return it along with the matching
177
+     * grouped shares. The most permissive permissions are used based on the permissions
178
+     * of all shares within the group.
179
+     *
180
+     * @param IShare[] $allShares
181
+     * @param IUser $user user
182
+     * @return array Tuple of [superShare, groupedShares]
183
+     */
184
+    private function buildSuperShares(array $allShares, IUser $user) {
185
+        $result = [];
186
+
187
+        $groupedShares = $this->groupShares($allShares);
188
+
189
+        /** @var IShare[] $shares */
190
+        foreach ($groupedShares as $shares) {
191
+            if (count($shares) === 0) {
192
+                continue;
193
+            }
194
+
195
+            $superShare = $this->shareManager->newShare();
196
+
197
+            // compute super share based on first entry of the group
198
+            $superShare->setId($shares[0]->getId())
199
+                ->setShareOwner($shares[0]->getShareOwner())
200
+                ->setNodeId($shares[0]->getNodeId())
201
+                ->setShareType($shares[0]->getShareType())
202
+                ->setTarget($shares[0]->getTarget());
203
+
204
+            // Gather notes from all the shares.
205
+            // Since these are readly available here, storing them
206
+            // enables the DAV FilesPlugin to avoid executing many
207
+            // DB queries to retrieve the same information.
208
+            $allNotes = implode("\n", array_map(function ($sh) {
209
+                return $sh->getNote();
210
+            }, $shares));
211
+            $superShare->setNote($allNotes);
212
+
213
+            // use most permissive permissions
214
+            // this covers the case where there are multiple shares for the same
215
+            // file e.g. from different groups and different permissions
216
+            $superPermissions = 0;
217
+            $superAttributes = $this->shareManager->newShare()->newAttributes();
218
+            $status = IShare::STATUS_PENDING;
219
+            foreach ($shares as $share) {
220
+                $superPermissions |= $share->getPermissions();
221
+                $status = max($status, $share->getStatus());
222
+                // update permissions
223
+                $superPermissions |= $share->getPermissions();
224
+
225
+                // update share permission attributes
226
+                $attributes = $share->getAttributes();
227
+                if ($attributes !== null) {
228
+                    foreach ($attributes->toArray() as $attribute) {
229
+                        if ($superAttributes->getAttribute($attribute['scope'], $attribute['key']) === true) {
230
+                            // if super share attribute is already enabled, it is most permissive
231
+                            continue;
232
+                        }
233
+                        // update supershare attributes with subshare attribute
234
+                        $superAttributes->setAttribute($attribute['scope'], $attribute['key'], $attribute['value']);
235
+                    }
236
+                }
237
+
238
+                // adjust target, for database consistency if needed
239
+                if ($share->getTarget() !== $superShare->getTarget()) {
240
+                    $share->setTarget($superShare->getTarget());
241
+                    try {
242
+                        $this->shareManager->moveShare($share, $user->getUID());
243
+                    } catch (\InvalidArgumentException $e) {
244
+                        // ignore as it is not important and we don't want to
245
+                        // block FS setup
246
+
247
+                        // the subsequent code anyway only uses the target of the
248
+                        // super share
249
+
250
+                        // such issue can usually happen when dealing with
251
+                        // null groups which usually appear with group backend
252
+                        // caching inconsistencies
253
+                        $this->logger->debug(
254
+                            'Could not adjust share target for share ' . $share->getId() . ' to make it consistent: ' . $e->getMessage(),
255
+                            ['app' => 'files_sharing']
256
+                        );
257
+                    }
258
+                }
259
+                if (!is_null($share->getNodeCacheEntry())) {
260
+                    $superShare->setNodeCacheEntry($share->getNodeCacheEntry());
261
+                }
262
+            }
263
+
264
+            $superShare->setPermissions($superPermissions);
265
+            $superShare->setStatus($status);
266
+            $superShare->setAttributes($superAttributes);
267
+
268
+            $result[] = [$superShare, $shares];
269
+        }
270
+
271
+        return $result;
272
+    }
273 273
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -56,7 +56,7 @@  discard block
 block discarded – undo
56 56
 		);
57 57
 
58 58
 		// filter out excluded shares and group shares that includes self
59
-		$shares = array_filter($shares, function (IShare $share) use ($user) {
59
+		$shares = array_filter($shares, function(IShare $share) use ($user) {
60 60
 			return $share->getPermissions() > 0 && $share->getShareOwner() !== $user->getUID() && $share->getSharedBy() !== $user->getUID();
61 61
 		});
62 62
 
@@ -64,7 +64,7 @@  discard block
 block discarded – undo
64 64
 
65 65
 		$allMounts = $this->mountManager->getAll();
66 66
 		$mounts = [];
67
-		$view = new View('/' . $user->getUID() . '/files');
67
+		$view = new View('/'.$user->getUID().'/files');
68 68
 		$ownerViews = [];
69 69
 		$sharingDisabledForUser = $this->shareManager->sharingDisabledForUser($user->getUID());
70 70
 		/** @var CappedMemoryCache<bool> $folderExistCache */
@@ -88,9 +88,9 @@  discard block
 block discarded – undo
88 88
 
89 89
 				$owner = $parentShare->getShareOwner();
90 90
 				if (!isset($ownerViews[$owner])) {
91
-					$ownerViews[$owner] = new View('/' . $parentShare->getShareOwner() . '/files');
91
+					$ownerViews[$owner] = new View('/'.$parentShare->getShareOwner().'/files');
92 92
 				}
93
-				$shareId = (int)$parentShare->getId();
93
+				$shareId = (int) $parentShare->getId();
94 94
 				$mount = new SharedMount(
95 95
 					'\OCA\Files_Sharing\SharedStorage',
96 96
 					$allMounts,
@@ -157,7 +157,7 @@  discard block
 block discarded – undo
157 157
 		$result = [];
158 158
 		// sort by stime, the super share will be based on the least recent share
159 159
 		foreach ($tmp as &$tmp2) {
160
-			@usort($tmp2, function ($a, $b) {
160
+			@usort($tmp2, function($a, $b) {
161 161
 				$aTime = $a->getShareTime()->getTimestamp();
162 162
 				$bTime = $b->getShareTime()->getTimestamp();
163 163
 				if ($aTime === $bTime) {
@@ -205,7 +205,7 @@  discard block
 block discarded – undo
205 205
 			// Since these are readly available here, storing them
206 206
 			// enables the DAV FilesPlugin to avoid executing many
207 207
 			// DB queries to retrieve the same information.
208
-			$allNotes = implode("\n", array_map(function ($sh) {
208
+			$allNotes = implode("\n", array_map(function($sh) {
209 209
 				return $sh->getNote();
210 210
 			}, $shares));
211 211
 			$superShare->setNote($allNotes);
@@ -251,7 +251,7 @@  discard block
 block discarded – undo
251 251
 						// null groups which usually appear with group backend
252 252
 						// caching inconsistencies
253 253
 						$this->logger->debug(
254
-							'Could not adjust share target for share ' . $share->getId() . ' to make it consistent: ' . $e->getMessage(),
254
+							'Could not adjust share target for share '.$share->getId().' to make it consistent: '.$e->getMessage(),
255 255
 							['app' => 'files_sharing']
256 256
 						);
257 257
 					}
Please login to merge, or discard this patch.