Completed
Push — master ( 453450...6f0537 )
by
unknown
37:16
created
apps/twofactor_backupcodes/lib/Migration/Version1002Date20170607113030.php 1 patch
Indentation   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -16,73 +16,73 @@
 block discarded – undo
16 16
 
17 17
 class Version1002Date20170607113030 extends SimpleMigrationStep {
18 18
 
19
-	/**
20
-	 * @param IDBConnection $connection
21
-	 */
22
-	public function __construct(
23
-		protected IDBConnection $connection,
24
-	) {
25
-	}
19
+    /**
20
+     * @param IDBConnection $connection
21
+     */
22
+    public function __construct(
23
+        protected IDBConnection $connection,
24
+    ) {
25
+    }
26 26
 
27
-	/**
28
-	 * @param IOutput $output
29
-	 * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
30
-	 * @param array $options
31
-	 * @since 13.0.0
32
-	 */
33
-	public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
34
-		/** @var ISchemaWrapper $schema */
35
-		$schema = $schemaClosure();
27
+    /**
28
+     * @param IOutput $output
29
+     * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
30
+     * @param array $options
31
+     * @since 13.0.0
32
+     */
33
+    public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
34
+        /** @var ISchemaWrapper $schema */
35
+        $schema = $schemaClosure();
36 36
 
37
-		if (!$schema->hasTable('twofactor_backup_codes')) {
38
-			// Legacy table does not exist
39
-			return;
40
-		}
37
+        if (!$schema->hasTable('twofactor_backup_codes')) {
38
+            // Legacy table does not exist
39
+            return;
40
+        }
41 41
 
42
-		$insert = $this->connection->getQueryBuilder();
43
-		$insert->insert('twofactor_backupcodes')
44
-			->values([
45
-				// Inserting with id might fail: 'id' => $insert->createParameter('id'),
46
-				'user_id' => $insert->createParameter('user_id'),
47
-				'code' => $insert->createParameter('code'),
48
-				'used' => $insert->createParameter('used'),
49
-			]);
42
+        $insert = $this->connection->getQueryBuilder();
43
+        $insert->insert('twofactor_backupcodes')
44
+            ->values([
45
+                // Inserting with id might fail: 'id' => $insert->createParameter('id'),
46
+                'user_id' => $insert->createParameter('user_id'),
47
+                'code' => $insert->createParameter('code'),
48
+                'used' => $insert->createParameter('used'),
49
+            ]);
50 50
 
51
-		$query = $this->connection->getQueryBuilder();
52
-		$query->select('*')
53
-			->from('twofactor_backup_codes')
54
-			->orderBy('id', 'ASC');
55
-		$result = $query->executeQuery();
51
+        $query = $this->connection->getQueryBuilder();
52
+        $query->select('*')
53
+            ->from('twofactor_backup_codes')
54
+            ->orderBy('id', 'ASC');
55
+        $result = $query->executeQuery();
56 56
 
57
-		$output->startProgress();
58
-		while ($row = $result->fetchAssociative()) {
59
-			$output->advance();
57
+        $output->startProgress();
58
+        while ($row = $result->fetchAssociative()) {
59
+            $output->advance();
60 60
 
61
-			$insert
62
-				// Inserting with id might fail: ->setParameter('id', $row['id'], IQueryBuilder::PARAM_INT)
63
-				->setParameter('user_id', $row['user_id'], IQueryBuilder::PARAM_STR)
64
-				->setParameter('code', $row['code'], IQueryBuilder::PARAM_STR)
65
-				->setParameter('used', $row['used'], IQueryBuilder::PARAM_INT)
66
-				->executeStatement();
67
-		}
68
-		$output->finishProgress();
69
-	}
61
+            $insert
62
+                // Inserting with id might fail: ->setParameter('id', $row['id'], IQueryBuilder::PARAM_INT)
63
+                ->setParameter('user_id', $row['user_id'], IQueryBuilder::PARAM_STR)
64
+                ->setParameter('code', $row['code'], IQueryBuilder::PARAM_STR)
65
+                ->setParameter('used', $row['used'], IQueryBuilder::PARAM_INT)
66
+                ->executeStatement();
67
+        }
68
+        $output->finishProgress();
69
+    }
70 70
 
71
-	/**
72
-	 * @param IOutput $output
73
-	 * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
74
-	 * @param array $options
75
-	 * @return null|ISchemaWrapper
76
-	 * @since 13.0.0
77
-	 */
78
-	public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
79
-		/** @var ISchemaWrapper $schema */
80
-		$schema = $schemaClosure();
71
+    /**
72
+     * @param IOutput $output
73
+     * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
74
+     * @param array $options
75
+     * @return null|ISchemaWrapper
76
+     * @since 13.0.0
77
+     */
78
+    public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
79
+        /** @var ISchemaWrapper $schema */
80
+        $schema = $schemaClosure();
81 81
 
82
-		if ($schema->hasTable('twofactor_backup_codes')) {
83
-			$schema->dropTable('twofactor_backup_codes');
84
-			return $schema;
85
-		}
86
-		return null;
87
-	}
82
+        if ($schema->hasTable('twofactor_backup_codes')) {
83
+            $schema->dropTable('twofactor_backup_codes');
84
+            return $schema;
85
+        }
86
+        return null;
87
+    }
88 88
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Mapping/AbstractMapping.php 2 patches
Indentation   +485 added lines, -485 removed lines patch added patch discarded remove patch
@@ -23,507 +23,507 @@
 block discarded – undo
23 23
  * @package OCA\User_LDAP\Mapping
24 24
  */
25 25
 abstract class AbstractMapping {
26
-	/**
27
-	 * returns the DB table name which holds the mappings
28
-	 *
29
-	 * @return string
30
-	 */
31
-	abstract protected function getTableName(bool $includePrefix = true);
32
-
33
-	/**
34
-	 * A month worth of cache time for as good as never changing mapping data.
35
-	 * Implemented when it was found that name-to-DN lookups are quite frequent.
36
-	 */
37
-	protected const LOCAL_CACHE_TTL = 2592000;
38
-
39
-	/**
40
-	 * A week worth of cache time for rarely changing user count data.
41
-	 */
42
-	protected const LOCAL_USER_COUNT_TTL = 604800;
43
-
44
-	/**
45
-	 * By default, the local cache is only used up to a certain amount of objects.
46
-	 * This constant holds this number. The amount of entries would amount up to
47
-	 * 1 MiB (worst case) per mappings table.
48
-	 * Setting `use_local_mapping_cache` for `user_ldap` to `yes` or `no`
49
-	 * deliberately enables or disables this mechanism.
50
-	 */
51
-	protected const LOCAL_CACHE_OBJECT_THRESHOLD = 2000;
52
-
53
-	protected ?ICache $localNameToDnCache = null;
54
-
55
-	/** @var array caches Names (value) by DN (key) */
56
-	protected array $cache = [];
57
-
58
-	/**
59
-	 * @param IDBConnection $dbc
60
-	 */
61
-	public function __construct(
62
-		protected IDBConnection $dbc,
63
-		protected ICacheFactory $cacheFactory,
64
-		protected IAppConfig $config,
65
-		protected bool $isCLI,
66
-	) {
67
-		$this->initLocalCache();
68
-	}
69
-
70
-	protected function initLocalCache(): void {
71
-		if ($this->isCLI || !$this->cacheFactory->isLocalCacheAvailable()) {
72
-			return;
73
-		}
74
-
75
-		$useLocalCache = $this->config->getValueString('user_ldap', 'use_local_mapping_cache', 'auto', false);
76
-		if ($useLocalCache !== 'yes' && $useLocalCache !== 'auto') {
77
-			return;
78
-		}
79
-
80
-		$section = \str_contains($this->getTableName(), 'user') ? 'u/' : 'g/';
81
-		$this->localNameToDnCache = $this->cacheFactory->createLocal('ldap/map/' . $section);
82
-
83
-		// We use the cache as well to store whether it shall be used. If the
84
-		// answer was no, we unset it again.
85
-		if ($useLocalCache === 'auto' && !$this->useCacheByUserCount()) {
86
-			$this->localNameToDnCache = null;
87
-		}
88
-	}
89
-
90
-	protected function useCacheByUserCount(): bool {
91
-		$use = $this->localNameToDnCache->get('use');
92
-		if ($use !== null) {
93
-			return $use;
94
-		}
95
-
96
-		$qb = $this->dbc->getQueryBuilder();
97
-		$q = $qb->selectAlias($qb->createFunction('COUNT(owncloud_name)'), 'count')
98
-			->from($this->getTableName());
99
-		$q->setMaxResults(self::LOCAL_CACHE_OBJECT_THRESHOLD + 1);
100
-		$result = $q->executeQuery();
101
-		$row = $result->fetchAssociative();
102
-		$result->closeCursor();
103
-
104
-		$use = (int)$row['count'] <= self::LOCAL_CACHE_OBJECT_THRESHOLD;
105
-		$this->localNameToDnCache->set('use', $use, self::LOCAL_USER_COUNT_TTL);
106
-		return $use;
107
-	}
108
-
109
-	/**
110
-	 * checks whether a provided string represents an existing table col
111
-	 *
112
-	 * @param string $col
113
-	 * @return bool
114
-	 */
115
-	public function isColNameValid($col) {
116
-		switch ($col) {
117
-			case 'ldap_dn':
118
-			case 'ldap_dn_hash':
119
-			case 'owncloud_name':
120
-			case 'directory_uuid':
121
-				return true;
122
-			default:
123
-				return false;
124
-		}
125
-	}
126
-
127
-	/**
128
-	 * Gets the value of one column based on a provided value of another column
129
-	 *
130
-	 * @param string $fetchCol
131
-	 * @param string $compareCol
132
-	 * @param string $search
133
-	 * @return string|false
134
-	 * @throws \Exception
135
-	 */
136
-	protected function getXbyY($fetchCol, $compareCol, $search) {
137
-		if (!$this->isColNameValid($fetchCol)) {
138
-			//this is used internally only, but we don't want to risk
139
-			//having SQL injection at all.
140
-			throw new \Exception('Invalid Column Name');
141
-		}
142
-		$qb = $this->dbc->getQueryBuilder();
143
-		$qb->select($fetchCol)
144
-			->from($this->getTableName())
145
-			->where($qb->expr()->eq($compareCol, $qb->createNamedParameter($search)));
146
-
147
-		try {
148
-			$res = $qb->executeQuery();
149
-			$data = $res->fetchOne();
150
-			$res->closeCursor();
151
-			return $data;
152
-		} catch (Exception $e) {
153
-			return false;
154
-		}
155
-	}
156
-
157
-	/**
158
-	 * Performs a DELETE or UPDATE query to the database.
159
-	 *
160
-	 * @param IPreparedStatement $statement
161
-	 * @param array $parameters
162
-	 * @return bool true if at least one row was modified, false otherwise
163
-	 */
164
-	protected function modify(IPreparedStatement $statement, $parameters) {
165
-		try {
166
-			$result = $statement->execute($parameters);
167
-			$updated = $result->rowCount() > 0;
168
-			$result->closeCursor();
169
-			return $updated;
170
-		} catch (Exception $e) {
171
-			return false;
172
-		}
173
-	}
174
-
175
-	/**
176
-	 * Gets the LDAP DN based on the provided name.
177
-	 */
178
-	public function getDNByName(string $name): string|false {
179
-		$dn = array_search($name, $this->cache, true);
180
-		if ($dn === false) {
181
-			$dn = $this->localNameToDnCache?->get($name);
182
-			if ($dn === null) {
183
-				$dn = $this->getXbyY('ldap_dn', 'owncloud_name', $name);
184
-				if ($dn !== false) {
185
-					$this->cache[$dn] = $name;
186
-				}
187
-				$this->localNameToDnCache?->set($name, $dn, self::LOCAL_CACHE_TTL);
188
-			}
189
-		}
190
-		return $dn ?? false;
191
-	}
192
-
193
-	/**
194
-	 * Updates the DN based on the given UUID
195
-	 *
196
-	 * @param string $fdn
197
-	 * @param string $uuid
198
-	 * @return bool
199
-	 */
200
-	public function setDNbyUUID($fdn, $uuid) {
201
-		$oldDn = $this->getDnByUUID($uuid);
202
-		$statement = $this->dbc->prepare('
26
+    /**
27
+     * returns the DB table name which holds the mappings
28
+     *
29
+     * @return string
30
+     */
31
+    abstract protected function getTableName(bool $includePrefix = true);
32
+
33
+    /**
34
+     * A month worth of cache time for as good as never changing mapping data.
35
+     * Implemented when it was found that name-to-DN lookups are quite frequent.
36
+     */
37
+    protected const LOCAL_CACHE_TTL = 2592000;
38
+
39
+    /**
40
+     * A week worth of cache time for rarely changing user count data.
41
+     */
42
+    protected const LOCAL_USER_COUNT_TTL = 604800;
43
+
44
+    /**
45
+     * By default, the local cache is only used up to a certain amount of objects.
46
+     * This constant holds this number. The amount of entries would amount up to
47
+     * 1 MiB (worst case) per mappings table.
48
+     * Setting `use_local_mapping_cache` for `user_ldap` to `yes` or `no`
49
+     * deliberately enables or disables this mechanism.
50
+     */
51
+    protected const LOCAL_CACHE_OBJECT_THRESHOLD = 2000;
52
+
53
+    protected ?ICache $localNameToDnCache = null;
54
+
55
+    /** @var array caches Names (value) by DN (key) */
56
+    protected array $cache = [];
57
+
58
+    /**
59
+     * @param IDBConnection $dbc
60
+     */
61
+    public function __construct(
62
+        protected IDBConnection $dbc,
63
+        protected ICacheFactory $cacheFactory,
64
+        protected IAppConfig $config,
65
+        protected bool $isCLI,
66
+    ) {
67
+        $this->initLocalCache();
68
+    }
69
+
70
+    protected function initLocalCache(): void {
71
+        if ($this->isCLI || !$this->cacheFactory->isLocalCacheAvailable()) {
72
+            return;
73
+        }
74
+
75
+        $useLocalCache = $this->config->getValueString('user_ldap', 'use_local_mapping_cache', 'auto', false);
76
+        if ($useLocalCache !== 'yes' && $useLocalCache !== 'auto') {
77
+            return;
78
+        }
79
+
80
+        $section = \str_contains($this->getTableName(), 'user') ? 'u/' : 'g/';
81
+        $this->localNameToDnCache = $this->cacheFactory->createLocal('ldap/map/' . $section);
82
+
83
+        // We use the cache as well to store whether it shall be used. If the
84
+        // answer was no, we unset it again.
85
+        if ($useLocalCache === 'auto' && !$this->useCacheByUserCount()) {
86
+            $this->localNameToDnCache = null;
87
+        }
88
+    }
89
+
90
+    protected function useCacheByUserCount(): bool {
91
+        $use = $this->localNameToDnCache->get('use');
92
+        if ($use !== null) {
93
+            return $use;
94
+        }
95
+
96
+        $qb = $this->dbc->getQueryBuilder();
97
+        $q = $qb->selectAlias($qb->createFunction('COUNT(owncloud_name)'), 'count')
98
+            ->from($this->getTableName());
99
+        $q->setMaxResults(self::LOCAL_CACHE_OBJECT_THRESHOLD + 1);
100
+        $result = $q->executeQuery();
101
+        $row = $result->fetchAssociative();
102
+        $result->closeCursor();
103
+
104
+        $use = (int)$row['count'] <= self::LOCAL_CACHE_OBJECT_THRESHOLD;
105
+        $this->localNameToDnCache->set('use', $use, self::LOCAL_USER_COUNT_TTL);
106
+        return $use;
107
+    }
108
+
109
+    /**
110
+     * checks whether a provided string represents an existing table col
111
+     *
112
+     * @param string $col
113
+     * @return bool
114
+     */
115
+    public function isColNameValid($col) {
116
+        switch ($col) {
117
+            case 'ldap_dn':
118
+            case 'ldap_dn_hash':
119
+            case 'owncloud_name':
120
+            case 'directory_uuid':
121
+                return true;
122
+            default:
123
+                return false;
124
+        }
125
+    }
126
+
127
+    /**
128
+     * Gets the value of one column based on a provided value of another column
129
+     *
130
+     * @param string $fetchCol
131
+     * @param string $compareCol
132
+     * @param string $search
133
+     * @return string|false
134
+     * @throws \Exception
135
+     */
136
+    protected function getXbyY($fetchCol, $compareCol, $search) {
137
+        if (!$this->isColNameValid($fetchCol)) {
138
+            //this is used internally only, but we don't want to risk
139
+            //having SQL injection at all.
140
+            throw new \Exception('Invalid Column Name');
141
+        }
142
+        $qb = $this->dbc->getQueryBuilder();
143
+        $qb->select($fetchCol)
144
+            ->from($this->getTableName())
145
+            ->where($qb->expr()->eq($compareCol, $qb->createNamedParameter($search)));
146
+
147
+        try {
148
+            $res = $qb->executeQuery();
149
+            $data = $res->fetchOne();
150
+            $res->closeCursor();
151
+            return $data;
152
+        } catch (Exception $e) {
153
+            return false;
154
+        }
155
+    }
156
+
157
+    /**
158
+     * Performs a DELETE or UPDATE query to the database.
159
+     *
160
+     * @param IPreparedStatement $statement
161
+     * @param array $parameters
162
+     * @return bool true if at least one row was modified, false otherwise
163
+     */
164
+    protected function modify(IPreparedStatement $statement, $parameters) {
165
+        try {
166
+            $result = $statement->execute($parameters);
167
+            $updated = $result->rowCount() > 0;
168
+            $result->closeCursor();
169
+            return $updated;
170
+        } catch (Exception $e) {
171
+            return false;
172
+        }
173
+    }
174
+
175
+    /**
176
+     * Gets the LDAP DN based on the provided name.
177
+     */
178
+    public function getDNByName(string $name): string|false {
179
+        $dn = array_search($name, $this->cache, true);
180
+        if ($dn === false) {
181
+            $dn = $this->localNameToDnCache?->get($name);
182
+            if ($dn === null) {
183
+                $dn = $this->getXbyY('ldap_dn', 'owncloud_name', $name);
184
+                if ($dn !== false) {
185
+                    $this->cache[$dn] = $name;
186
+                }
187
+                $this->localNameToDnCache?->set($name, $dn, self::LOCAL_CACHE_TTL);
188
+            }
189
+        }
190
+        return $dn ?? false;
191
+    }
192
+
193
+    /**
194
+     * Updates the DN based on the given UUID
195
+     *
196
+     * @param string $fdn
197
+     * @param string $uuid
198
+     * @return bool
199
+     */
200
+    public function setDNbyUUID($fdn, $uuid) {
201
+        $oldDn = $this->getDnByUUID($uuid);
202
+        $statement = $this->dbc->prepare('
203 203
 			UPDATE `' . $this->getTableName() . '`
204 204
 			SET `ldap_dn_hash` = ?, `ldap_dn` = ?
205 205
 			WHERE `directory_uuid` = ?
206 206
 		');
207 207
 
208
-		$r = $this->modify($statement, [$this->getDNHash($fdn), $fdn, $uuid]);
209
-		if ($r) {
210
-			if (is_string($oldDn) && isset($this->cache[$oldDn])) {
211
-				$userId = $this->cache[$oldDn];
212
-			}
213
-			$userId = $userId ?? $this->getNameByUUID($uuid);
214
-			if ($userId) {
215
-				$this->cache[$fdn] = $userId;
216
-				$this->localNameToDnCache?->set($userId, $fdn, self::LOCAL_CACHE_TTL);
217
-			}
218
-			unset($this->cache[$oldDn]);
219
-		}
220
-
221
-		return $r;
222
-	}
223
-
224
-	/**
225
-	 * Updates the UUID based on the given DN
226
-	 *
227
-	 * required by Migration/UUIDFix
228
-	 *
229
-	 * @param $uuid
230
-	 * @param $fdn
231
-	 * @return bool
232
-	 */
233
-	public function setUUIDbyDN($uuid, $fdn): bool {
234
-		$statement = $this->dbc->prepare('
208
+        $r = $this->modify($statement, [$this->getDNHash($fdn), $fdn, $uuid]);
209
+        if ($r) {
210
+            if (is_string($oldDn) && isset($this->cache[$oldDn])) {
211
+                $userId = $this->cache[$oldDn];
212
+            }
213
+            $userId = $userId ?? $this->getNameByUUID($uuid);
214
+            if ($userId) {
215
+                $this->cache[$fdn] = $userId;
216
+                $this->localNameToDnCache?->set($userId, $fdn, self::LOCAL_CACHE_TTL);
217
+            }
218
+            unset($this->cache[$oldDn]);
219
+        }
220
+
221
+        return $r;
222
+    }
223
+
224
+    /**
225
+     * Updates the UUID based on the given DN
226
+     *
227
+     * required by Migration/UUIDFix
228
+     *
229
+     * @param $uuid
230
+     * @param $fdn
231
+     * @return bool
232
+     */
233
+    public function setUUIDbyDN($uuid, $fdn): bool {
234
+        $statement = $this->dbc->prepare('
235 235
 			UPDATE `' . $this->getTableName() . '`
236 236
 			SET `directory_uuid` = ?
237 237
 			WHERE `ldap_dn_hash` = ?
238 238
 		');
239 239
 
240
-		unset($this->cache[$fdn]);
241
-
242
-		return $this->modify($statement, [$uuid, $this->getDNHash($fdn)]);
243
-	}
244
-
245
-	/**
246
-	 * Get the hash to store in database column ldap_dn_hash for a given dn
247
-	 */
248
-	protected function getDNHash(string $fdn): string {
249
-		return hash('sha256', $fdn, false);
250
-	}
251
-
252
-	/**
253
-	 * Gets the name based on the provided LDAP DN.
254
-	 *
255
-	 * @param string $fdn
256
-	 * @return string|false
257
-	 */
258
-	public function getNameByDN($fdn) {
259
-		if (!isset($this->cache[$fdn])) {
260
-			$this->cache[$fdn] = $this->getXbyY('owncloud_name', 'ldap_dn_hash', $this->getDNHash($fdn));
261
-		}
262
-		return $this->cache[$fdn];
263
-	}
264
-
265
-	/**
266
-	 * @param array<string> $hashList
267
-	 */
268
-	protected function prepareListOfIdsQuery(array $hashList): IQueryBuilder {
269
-		$qb = $this->dbc->getQueryBuilder();
270
-		$qb->select('owncloud_name', 'ldap_dn_hash', 'ldap_dn')
271
-			->from($this->getTableName(false))
272
-			->where($qb->expr()->in('ldap_dn_hash', $qb->createNamedParameter($hashList, IQueryBuilder::PARAM_STR_ARRAY)));
273
-		return $qb;
274
-	}
275
-
276
-	protected function collectResultsFromListOfIdsQuery(IQueryBuilder $qb, array &$results): void {
277
-		$stmt = $qb->executeQuery();
278
-		while ($entry = $stmt->fetchAssociative()) {
279
-			$results[$entry['ldap_dn']] = $entry['owncloud_name'];
280
-			$this->cache[$entry['ldap_dn']] = $entry['owncloud_name'];
281
-		}
282
-		$stmt->closeCursor();
283
-	}
284
-
285
-	/**
286
-	 * @param array<string> $fdns
287
-	 * @return array<string,string>
288
-	 */
289
-	public function getListOfIdsByDn(array $fdns): array {
290
-		$totalDBParamLimit = 65000;
291
-		$sliceSize = 1000;
292
-		$maxSlices = $this->dbc->getDatabaseProvider() === IDBConnection::PLATFORM_SQLITE ? 9 : $totalDBParamLimit / $sliceSize;
293
-		$results = [];
294
-
295
-		$slice = 1;
296
-		$fdns = array_map([$this, 'getDNHash'], $fdns);
297
-		$fdnsSlice = count($fdns) > $sliceSize ? array_slice($fdns, 0, $sliceSize) : $fdns;
298
-		$qb = $this->prepareListOfIdsQuery($fdnsSlice);
299
-
300
-		while (isset($fdnsSlice[999])) {
301
-			// Oracle does not allow more than 1000 values in the IN list,
302
-			// but allows slicing
303
-			$slice++;
304
-			$fdnsSlice = array_slice($fdns, $sliceSize * ($slice - 1), $sliceSize);
305
-
306
-			/** @see https://github.com/vimeo/psalm/issues/4995 */
307
-			/** @psalm-suppress TypeDoesNotContainType */
308
-			if (!isset($qb)) {
309
-				$qb = $this->prepareListOfIdsQuery($fdnsSlice);
310
-				continue;
311
-			}
312
-
313
-			if (!empty($fdnsSlice)) {
314
-				$qb->orWhere($qb->expr()->in('ldap_dn_hash', $qb->createNamedParameter($fdnsSlice, IQueryBuilder::PARAM_STR_ARRAY)));
315
-			}
316
-
317
-			if ($slice % $maxSlices === 0) {
318
-				$this->collectResultsFromListOfIdsQuery($qb, $results);
319
-				unset($qb);
320
-			}
321
-		}
322
-
323
-		if (isset($qb)) {
324
-			$this->collectResultsFromListOfIdsQuery($qb, $results);
325
-		}
326
-
327
-		return $results;
328
-	}
329
-
330
-	/**
331
-	 * Searches mapped names by the giving string in the name column
332
-	 *
333
-	 * @return string[]
334
-	 */
335
-	public function getNamesBySearch(string $search, string $prefixMatch = '', string $postfixMatch = ''): array {
336
-		$statement = $this->dbc->prepare('
240
+        unset($this->cache[$fdn]);
241
+
242
+        return $this->modify($statement, [$uuid, $this->getDNHash($fdn)]);
243
+    }
244
+
245
+    /**
246
+     * Get the hash to store in database column ldap_dn_hash for a given dn
247
+     */
248
+    protected function getDNHash(string $fdn): string {
249
+        return hash('sha256', $fdn, false);
250
+    }
251
+
252
+    /**
253
+     * Gets the name based on the provided LDAP DN.
254
+     *
255
+     * @param string $fdn
256
+     * @return string|false
257
+     */
258
+    public function getNameByDN($fdn) {
259
+        if (!isset($this->cache[$fdn])) {
260
+            $this->cache[$fdn] = $this->getXbyY('owncloud_name', 'ldap_dn_hash', $this->getDNHash($fdn));
261
+        }
262
+        return $this->cache[$fdn];
263
+    }
264
+
265
+    /**
266
+     * @param array<string> $hashList
267
+     */
268
+    protected function prepareListOfIdsQuery(array $hashList): IQueryBuilder {
269
+        $qb = $this->dbc->getQueryBuilder();
270
+        $qb->select('owncloud_name', 'ldap_dn_hash', 'ldap_dn')
271
+            ->from($this->getTableName(false))
272
+            ->where($qb->expr()->in('ldap_dn_hash', $qb->createNamedParameter($hashList, IQueryBuilder::PARAM_STR_ARRAY)));
273
+        return $qb;
274
+    }
275
+
276
+    protected function collectResultsFromListOfIdsQuery(IQueryBuilder $qb, array &$results): void {
277
+        $stmt = $qb->executeQuery();
278
+        while ($entry = $stmt->fetchAssociative()) {
279
+            $results[$entry['ldap_dn']] = $entry['owncloud_name'];
280
+            $this->cache[$entry['ldap_dn']] = $entry['owncloud_name'];
281
+        }
282
+        $stmt->closeCursor();
283
+    }
284
+
285
+    /**
286
+     * @param array<string> $fdns
287
+     * @return array<string,string>
288
+     */
289
+    public function getListOfIdsByDn(array $fdns): array {
290
+        $totalDBParamLimit = 65000;
291
+        $sliceSize = 1000;
292
+        $maxSlices = $this->dbc->getDatabaseProvider() === IDBConnection::PLATFORM_SQLITE ? 9 : $totalDBParamLimit / $sliceSize;
293
+        $results = [];
294
+
295
+        $slice = 1;
296
+        $fdns = array_map([$this, 'getDNHash'], $fdns);
297
+        $fdnsSlice = count($fdns) > $sliceSize ? array_slice($fdns, 0, $sliceSize) : $fdns;
298
+        $qb = $this->prepareListOfIdsQuery($fdnsSlice);
299
+
300
+        while (isset($fdnsSlice[999])) {
301
+            // Oracle does not allow more than 1000 values in the IN list,
302
+            // but allows slicing
303
+            $slice++;
304
+            $fdnsSlice = array_slice($fdns, $sliceSize * ($slice - 1), $sliceSize);
305
+
306
+            /** @see https://github.com/vimeo/psalm/issues/4995 */
307
+            /** @psalm-suppress TypeDoesNotContainType */
308
+            if (!isset($qb)) {
309
+                $qb = $this->prepareListOfIdsQuery($fdnsSlice);
310
+                continue;
311
+            }
312
+
313
+            if (!empty($fdnsSlice)) {
314
+                $qb->orWhere($qb->expr()->in('ldap_dn_hash', $qb->createNamedParameter($fdnsSlice, IQueryBuilder::PARAM_STR_ARRAY)));
315
+            }
316
+
317
+            if ($slice % $maxSlices === 0) {
318
+                $this->collectResultsFromListOfIdsQuery($qb, $results);
319
+                unset($qb);
320
+            }
321
+        }
322
+
323
+        if (isset($qb)) {
324
+            $this->collectResultsFromListOfIdsQuery($qb, $results);
325
+        }
326
+
327
+        return $results;
328
+    }
329
+
330
+    /**
331
+     * Searches mapped names by the giving string in the name column
332
+     *
333
+     * @return string[]
334
+     */
335
+    public function getNamesBySearch(string $search, string $prefixMatch = '', string $postfixMatch = ''): array {
336
+        $statement = $this->dbc->prepare('
337 337
 			SELECT `owncloud_name`
338 338
 			FROM `' . $this->getTableName() . '`
339 339
 			WHERE `owncloud_name` LIKE ?
340 340
 		');
341 341
 
342
-		try {
343
-			$res = $statement->execute([$prefixMatch . $this->dbc->escapeLikeParameter($search) . $postfixMatch]);
344
-		} catch (Exception $e) {
345
-			return [];
346
-		}
347
-		$names = [];
348
-		while ($row = $res->fetchAssociative()) {
349
-			$names[] = $row['owncloud_name'];
350
-		}
351
-		return $names;
352
-	}
353
-
354
-	/**
355
-	 * Gets the name based on the provided LDAP UUID.
356
-	 *
357
-	 * @param string $uuid
358
-	 * @return string|false
359
-	 */
360
-	public function getNameByUUID($uuid) {
361
-		return $this->getXbyY('owncloud_name', 'directory_uuid', $uuid);
362
-	}
363
-
364
-	public function getDnByUUID($uuid) {
365
-		return $this->getXbyY('ldap_dn', 'directory_uuid', $uuid);
366
-	}
367
-
368
-	/**
369
-	 * Gets the UUID based on the provided LDAP DN
370
-	 *
371
-	 * @param string $dn
372
-	 * @return false|string
373
-	 * @throws \Exception
374
-	 */
375
-	public function getUUIDByDN($dn) {
376
-		return $this->getXbyY('directory_uuid', 'ldap_dn_hash', $this->getDNHash($dn));
377
-	}
378
-
379
-	public function getList(int $offset = 0, ?int $limit = null, bool $invalidatedOnly = false): array {
380
-		$select = $this->dbc->getQueryBuilder();
381
-		$select->selectAlias('ldap_dn', 'dn')
382
-			->selectAlias('owncloud_name', 'name')
383
-			->selectAlias('directory_uuid', 'uuid')
384
-			->from($this->getTableName())
385
-			->setMaxResults($limit)
386
-			->setFirstResult($offset);
387
-
388
-		if ($invalidatedOnly) {
389
-			$select->where($select->expr()->like('directory_uuid', $select->createNamedParameter('invalidated_%')));
390
-		}
391
-
392
-		$result = $select->executeQuery();
393
-		$entries = $result->fetchAllAssociative();
394
-		$result->closeCursor();
395
-
396
-		return $entries;
397
-	}
398
-
399
-	/**
400
-	 * attempts to map the given entry
401
-	 *
402
-	 * @param string $fdn fully distinguished name (from LDAP)
403
-	 * @param string $name
404
-	 * @param string $uuid a unique identifier as used in LDAP
405
-	 * @return bool
406
-	 */
407
-	public function map($fdn, $name, $uuid) {
408
-		if (mb_strlen($fdn) > 4000) {
409
-			Server::get(LoggerInterface::class)->error(
410
-				'Cannot map, because the DN exceeds 4000 characters: {dn}',
411
-				[
412
-					'app' => 'user_ldap',
413
-					'dn' => $fdn,
414
-				]
415
-			);
416
-			return false;
417
-		}
418
-
419
-		$row = [
420
-			'ldap_dn_hash' => $this->getDNHash($fdn),
421
-			'ldap_dn' => $fdn,
422
-			'owncloud_name' => $name,
423
-			'directory_uuid' => $uuid
424
-		];
425
-
426
-		try {
427
-			$result = $this->dbc->insertIfNotExist($this->getTableName(), $row);
428
-			if ((bool)$result === true) {
429
-				$this->cache[$fdn] = $name;
430
-				$this->localNameToDnCache?->set($name, $fdn, self::LOCAL_CACHE_TTL);
431
-			}
432
-			// insertIfNotExist returns values as int
433
-			return (bool)$result;
434
-		} catch (\Exception $e) {
435
-			return false;
436
-		}
437
-	}
438
-
439
-	/**
440
-	 * removes a mapping based on the owncloud_name of the entry
441
-	 *
442
-	 * @param string $name
443
-	 * @return bool
444
-	 */
445
-	public function unmap($name) {
446
-		$statement = $this->dbc->prepare('
342
+        try {
343
+            $res = $statement->execute([$prefixMatch . $this->dbc->escapeLikeParameter($search) . $postfixMatch]);
344
+        } catch (Exception $e) {
345
+            return [];
346
+        }
347
+        $names = [];
348
+        while ($row = $res->fetchAssociative()) {
349
+            $names[] = $row['owncloud_name'];
350
+        }
351
+        return $names;
352
+    }
353
+
354
+    /**
355
+     * Gets the name based on the provided LDAP UUID.
356
+     *
357
+     * @param string $uuid
358
+     * @return string|false
359
+     */
360
+    public function getNameByUUID($uuid) {
361
+        return $this->getXbyY('owncloud_name', 'directory_uuid', $uuid);
362
+    }
363
+
364
+    public function getDnByUUID($uuid) {
365
+        return $this->getXbyY('ldap_dn', 'directory_uuid', $uuid);
366
+    }
367
+
368
+    /**
369
+     * Gets the UUID based on the provided LDAP DN
370
+     *
371
+     * @param string $dn
372
+     * @return false|string
373
+     * @throws \Exception
374
+     */
375
+    public function getUUIDByDN($dn) {
376
+        return $this->getXbyY('directory_uuid', 'ldap_dn_hash', $this->getDNHash($dn));
377
+    }
378
+
379
+    public function getList(int $offset = 0, ?int $limit = null, bool $invalidatedOnly = false): array {
380
+        $select = $this->dbc->getQueryBuilder();
381
+        $select->selectAlias('ldap_dn', 'dn')
382
+            ->selectAlias('owncloud_name', 'name')
383
+            ->selectAlias('directory_uuid', 'uuid')
384
+            ->from($this->getTableName())
385
+            ->setMaxResults($limit)
386
+            ->setFirstResult($offset);
387
+
388
+        if ($invalidatedOnly) {
389
+            $select->where($select->expr()->like('directory_uuid', $select->createNamedParameter('invalidated_%')));
390
+        }
391
+
392
+        $result = $select->executeQuery();
393
+        $entries = $result->fetchAllAssociative();
394
+        $result->closeCursor();
395
+
396
+        return $entries;
397
+    }
398
+
399
+    /**
400
+     * attempts to map the given entry
401
+     *
402
+     * @param string $fdn fully distinguished name (from LDAP)
403
+     * @param string $name
404
+     * @param string $uuid a unique identifier as used in LDAP
405
+     * @return bool
406
+     */
407
+    public function map($fdn, $name, $uuid) {
408
+        if (mb_strlen($fdn) > 4000) {
409
+            Server::get(LoggerInterface::class)->error(
410
+                'Cannot map, because the DN exceeds 4000 characters: {dn}',
411
+                [
412
+                    'app' => 'user_ldap',
413
+                    'dn' => $fdn,
414
+                ]
415
+            );
416
+            return false;
417
+        }
418
+
419
+        $row = [
420
+            'ldap_dn_hash' => $this->getDNHash($fdn),
421
+            'ldap_dn' => $fdn,
422
+            'owncloud_name' => $name,
423
+            'directory_uuid' => $uuid
424
+        ];
425
+
426
+        try {
427
+            $result = $this->dbc->insertIfNotExist($this->getTableName(), $row);
428
+            if ((bool)$result === true) {
429
+                $this->cache[$fdn] = $name;
430
+                $this->localNameToDnCache?->set($name, $fdn, self::LOCAL_CACHE_TTL);
431
+            }
432
+            // insertIfNotExist returns values as int
433
+            return (bool)$result;
434
+        } catch (\Exception $e) {
435
+            return false;
436
+        }
437
+    }
438
+
439
+    /**
440
+     * removes a mapping based on the owncloud_name of the entry
441
+     *
442
+     * @param string $name
443
+     * @return bool
444
+     */
445
+    public function unmap($name) {
446
+        $statement = $this->dbc->prepare('
447 447
 			DELETE FROM `' . $this->getTableName() . '`
448 448
 			WHERE `owncloud_name` = ?');
449 449
 
450
-		$dn = array_search($name, $this->cache);
451
-		if ($dn !== false) {
452
-			unset($this->cache[$dn]);
453
-		}
454
-		$this->localNameToDnCache?->remove($name);
455
-
456
-		return $this->modify($statement, [$name]);
457
-	}
458
-
459
-	/**
460
-	 * Truncates the mapping table
461
-	 *
462
-	 * @return bool
463
-	 */
464
-	public function clear() {
465
-		$sql = $this->dbc
466
-			->getDatabasePlatform()
467
-			->getTruncateTableSQL('`' . $this->getTableName() . '`');
468
-		try {
469
-			$this->dbc->executeQuery($sql);
470
-			$this->localNameToDnCache?->clear();
471
-
472
-			return true;
473
-		} catch (Exception $e) {
474
-			return false;
475
-		}
476
-	}
477
-
478
-	/**
479
-	 * clears the mapping table one by one and executing a callback with
480
-	 * each row's id (=owncloud_name col)
481
-	 *
482
-	 * @param callable $preCallback
483
-	 * @param callable $postCallback
484
-	 * @return bool true on success, false when at least one row was not
485
-	 *              deleted
486
-	 */
487
-	public function clearCb(callable $preCallback, callable $postCallback): bool {
488
-		$picker = $this->dbc->getQueryBuilder();
489
-		$picker->select('owncloud_name')
490
-			->from($this->getTableName());
491
-		$cursor = $picker->executeQuery();
492
-		$result = true;
493
-		while (($id = $cursor->fetchOne()) !== false) {
494
-			$preCallback($id);
495
-			if ($isUnmapped = $this->unmap($id)) {
496
-				$postCallback($id);
497
-			}
498
-			$result = $result && $isUnmapped;
499
-		}
500
-		$cursor->closeCursor();
501
-		return $result;
502
-	}
503
-
504
-	/**
505
-	 * returns the number of entries in the mappings table
506
-	 *
507
-	 * @return int
508
-	 */
509
-	public function count(): int {
510
-		$query = $this->dbc->getQueryBuilder();
511
-		$query->select($query->func()->count('ldap_dn_hash'))
512
-			->from($this->getTableName());
513
-		$res = $query->executeQuery();
514
-		$count = $res->fetchOne();
515
-		$res->closeCursor();
516
-		return (int)$count;
517
-	}
518
-
519
-	public function countInvalidated(): int {
520
-		$query = $this->dbc->getQueryBuilder();
521
-		$query->select($query->func()->count('ldap_dn_hash'))
522
-			->from($this->getTableName())
523
-			->where($query->expr()->like('directory_uuid', $query->createNamedParameter('invalidated_%')));
524
-		$res = $query->executeQuery();
525
-		$count = $res->fetchOne();
526
-		$res->closeCursor();
527
-		return (int)$count;
528
-	}
450
+        $dn = array_search($name, $this->cache);
451
+        if ($dn !== false) {
452
+            unset($this->cache[$dn]);
453
+        }
454
+        $this->localNameToDnCache?->remove($name);
455
+
456
+        return $this->modify($statement, [$name]);
457
+    }
458
+
459
+    /**
460
+     * Truncates the mapping table
461
+     *
462
+     * @return bool
463
+     */
464
+    public function clear() {
465
+        $sql = $this->dbc
466
+            ->getDatabasePlatform()
467
+            ->getTruncateTableSQL('`' . $this->getTableName() . '`');
468
+        try {
469
+            $this->dbc->executeQuery($sql);
470
+            $this->localNameToDnCache?->clear();
471
+
472
+            return true;
473
+        } catch (Exception $e) {
474
+            return false;
475
+        }
476
+    }
477
+
478
+    /**
479
+     * clears the mapping table one by one and executing a callback with
480
+     * each row's id (=owncloud_name col)
481
+     *
482
+     * @param callable $preCallback
483
+     * @param callable $postCallback
484
+     * @return bool true on success, false when at least one row was not
485
+     *              deleted
486
+     */
487
+    public function clearCb(callable $preCallback, callable $postCallback): bool {
488
+        $picker = $this->dbc->getQueryBuilder();
489
+        $picker->select('owncloud_name')
490
+            ->from($this->getTableName());
491
+        $cursor = $picker->executeQuery();
492
+        $result = true;
493
+        while (($id = $cursor->fetchOne()) !== false) {
494
+            $preCallback($id);
495
+            if ($isUnmapped = $this->unmap($id)) {
496
+                $postCallback($id);
497
+            }
498
+            $result = $result && $isUnmapped;
499
+        }
500
+        $cursor->closeCursor();
501
+        return $result;
502
+    }
503
+
504
+    /**
505
+     * returns the number of entries in the mappings table
506
+     *
507
+     * @return int
508
+     */
509
+    public function count(): int {
510
+        $query = $this->dbc->getQueryBuilder();
511
+        $query->select($query->func()->count('ldap_dn_hash'))
512
+            ->from($this->getTableName());
513
+        $res = $query->executeQuery();
514
+        $count = $res->fetchOne();
515
+        $res->closeCursor();
516
+        return (int)$count;
517
+    }
518
+
519
+    public function countInvalidated(): int {
520
+        $query = $this->dbc->getQueryBuilder();
521
+        $query->select($query->func()->count('ldap_dn_hash'))
522
+            ->from($this->getTableName())
523
+            ->where($query->expr()->like('directory_uuid', $query->createNamedParameter('invalidated_%')));
524
+        $res = $query->executeQuery();
525
+        $count = $res->fetchOne();
526
+        $res->closeCursor();
527
+        return (int)$count;
528
+    }
529 529
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
 		}
79 79
 
80 80
 		$section = \str_contains($this->getTableName(), 'user') ? 'u/' : 'g/';
81
-		$this->localNameToDnCache = $this->cacheFactory->createLocal('ldap/map/' . $section);
81
+		$this->localNameToDnCache = $this->cacheFactory->createLocal('ldap/map/'.$section);
82 82
 
83 83
 		// We use the cache as well to store whether it shall be used. If the
84 84
 		// answer was no, we unset it again.
@@ -101,7 +101,7 @@  discard block
 block discarded – undo
101 101
 		$row = $result->fetchAssociative();
102 102
 		$result->closeCursor();
103 103
 
104
-		$use = (int)$row['count'] <= self::LOCAL_CACHE_OBJECT_THRESHOLD;
104
+		$use = (int) $row['count'] <= self::LOCAL_CACHE_OBJECT_THRESHOLD;
105 105
 		$this->localNameToDnCache->set('use', $use, self::LOCAL_USER_COUNT_TTL);
106 106
 		return $use;
107 107
 	}
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
 	/**
176 176
 	 * Gets the LDAP DN based on the provided name.
177 177
 	 */
178
-	public function getDNByName(string $name): string|false {
178
+	public function getDNByName(string $name): string | false {
179 179
 		$dn = array_search($name, $this->cache, true);
180 180
 		if ($dn === false) {
181 181
 			$dn = $this->localNameToDnCache?->get($name);
@@ -200,7 +200,7 @@  discard block
 block discarded – undo
200 200
 	public function setDNbyUUID($fdn, $uuid) {
201 201
 		$oldDn = $this->getDnByUUID($uuid);
202 202
 		$statement = $this->dbc->prepare('
203
-			UPDATE `' . $this->getTableName() . '`
203
+			UPDATE `' . $this->getTableName().'`
204 204
 			SET `ldap_dn_hash` = ?, `ldap_dn` = ?
205 205
 			WHERE `directory_uuid` = ?
206 206
 		');
@@ -232,7 +232,7 @@  discard block
 block discarded – undo
232 232
 	 */
233 233
 	public function setUUIDbyDN($uuid, $fdn): bool {
234 234
 		$statement = $this->dbc->prepare('
235
-			UPDATE `' . $this->getTableName() . '`
235
+			UPDATE `' . $this->getTableName().'`
236 236
 			SET `directory_uuid` = ?
237 237
 			WHERE `ldap_dn_hash` = ?
238 238
 		');
@@ -335,12 +335,12 @@  discard block
 block discarded – undo
335 335
 	public function getNamesBySearch(string $search, string $prefixMatch = '', string $postfixMatch = ''): array {
336 336
 		$statement = $this->dbc->prepare('
337 337
 			SELECT `owncloud_name`
338
-			FROM `' . $this->getTableName() . '`
338
+			FROM `' . $this->getTableName().'`
339 339
 			WHERE `owncloud_name` LIKE ?
340 340
 		');
341 341
 
342 342
 		try {
343
-			$res = $statement->execute([$prefixMatch . $this->dbc->escapeLikeParameter($search) . $postfixMatch]);
343
+			$res = $statement->execute([$prefixMatch.$this->dbc->escapeLikeParameter($search).$postfixMatch]);
344 344
 		} catch (Exception $e) {
345 345
 			return [];
346 346
 		}
@@ -425,12 +425,12 @@  discard block
 block discarded – undo
425 425
 
426 426
 		try {
427 427
 			$result = $this->dbc->insertIfNotExist($this->getTableName(), $row);
428
-			if ((bool)$result === true) {
428
+			if ((bool) $result === true) {
429 429
 				$this->cache[$fdn] = $name;
430 430
 				$this->localNameToDnCache?->set($name, $fdn, self::LOCAL_CACHE_TTL);
431 431
 			}
432 432
 			// insertIfNotExist returns values as int
433
-			return (bool)$result;
433
+			return (bool) $result;
434 434
 		} catch (\Exception $e) {
435 435
 			return false;
436 436
 		}
@@ -444,7 +444,7 @@  discard block
 block discarded – undo
444 444
 	 */
445 445
 	public function unmap($name) {
446 446
 		$statement = $this->dbc->prepare('
447
-			DELETE FROM `' . $this->getTableName() . '`
447
+			DELETE FROM `' . $this->getTableName().'`
448 448
 			WHERE `owncloud_name` = ?');
449 449
 
450 450
 		$dn = array_search($name, $this->cache);
@@ -464,7 +464,7 @@  discard block
 block discarded – undo
464 464
 	public function clear() {
465 465
 		$sql = $this->dbc
466 466
 			->getDatabasePlatform()
467
-			->getTruncateTableSQL('`' . $this->getTableName() . '`');
467
+			->getTruncateTableSQL('`'.$this->getTableName().'`');
468 468
 		try {
469 469
 			$this->dbc->executeQuery($sql);
470 470
 			$this->localNameToDnCache?->clear();
@@ -513,7 +513,7 @@  discard block
 block discarded – undo
513 513
 		$res = $query->executeQuery();
514 514
 		$count = $res->fetchOne();
515 515
 		$res->closeCursor();
516
-		return (int)$count;
516
+		return (int) $count;
517 517
 	}
518 518
 
519 519
 	public function countInvalidated(): int {
@@ -524,6 +524,6 @@  discard block
 block discarded – undo
524 524
 		$res = $query->executeQuery();
525 525
 		$count = $res->fetchOne();
526 526
 		$res->closeCursor();
527
-		return (int)$count;
527
+		return (int) $count;
528 528
 	}
529 529
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Db/GroupMembershipMapper.php 1 patch
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -17,56 +17,56 @@
 block discarded – undo
17 17
  * @template-extends QBMapper<GroupMembership>
18 18
  */
19 19
 class GroupMembershipMapper extends QBMapper {
20
-	public function __construct(IDBConnection $db) {
21
-		parent::__construct($db, 'ldap_group_membership', GroupMembership::class);
22
-	}
20
+    public function __construct(IDBConnection $db) {
21
+        parent::__construct($db, 'ldap_group_membership', GroupMembership::class);
22
+    }
23 23
 
24
-	/**
25
-	 * @return string[]
26
-	 */
27
-	public function getKnownGroups(): array {
28
-		$query = $this->db->getQueryBuilder();
29
-		$result = $query->selectDistinct('groupid')
30
-			->from($this->getTableName())
31
-			->executeQuery();
24
+    /**
25
+     * @return string[]
26
+     */
27
+    public function getKnownGroups(): array {
28
+        $query = $this->db->getQueryBuilder();
29
+        $result = $query->selectDistinct('groupid')
30
+            ->from($this->getTableName())
31
+            ->executeQuery();
32 32
 
33
-		$groups = array_column($result->fetchAllAssociative(), 'groupid');
34
-		$result->closeCursor();
35
-		return $groups;
36
-	}
33
+        $groups = array_column($result->fetchAllAssociative(), 'groupid');
34
+        $result->closeCursor();
35
+        return $groups;
36
+    }
37 37
 
38
-	/**
39
-	 * @return GroupMembership[]
40
-	 */
41
-	public function findGroupMemberships(string $groupid): array {
42
-		$qb = $this->db->getQueryBuilder();
43
-		$select = $qb->select('*')
44
-			->from($this->getTableName())
45
-			->where($qb->expr()->eq('groupid', $qb->createNamedParameter($groupid)));
38
+    /**
39
+     * @return GroupMembership[]
40
+     */
41
+    public function findGroupMemberships(string $groupid): array {
42
+        $qb = $this->db->getQueryBuilder();
43
+        $select = $qb->select('*')
44
+            ->from($this->getTableName())
45
+            ->where($qb->expr()->eq('groupid', $qb->createNamedParameter($groupid)));
46 46
 
47
-		return $this->findEntities($select);
48
-	}
47
+        return $this->findEntities($select);
48
+    }
49 49
 
50
-	/**
51
-	 * @return GroupMembership[]
52
-	 */
53
-	public function findGroupMembershipsForUser(string $userid): array {
54
-		$qb = $this->db->getQueryBuilder();
55
-		$select = $qb->select('*')
56
-			->from($this->getTableName())
57
-			->where($qb->expr()->eq('userid', $qb->createNamedParameter($userid)));
50
+    /**
51
+     * @return GroupMembership[]
52
+     */
53
+    public function findGroupMembershipsForUser(string $userid): array {
54
+        $qb = $this->db->getQueryBuilder();
55
+        $select = $qb->select('*')
56
+            ->from($this->getTableName())
57
+            ->where($qb->expr()->eq('userid', $qb->createNamedParameter($userid)));
58 58
 
59
-		return $this->findEntities($select);
60
-	}
59
+        return $this->findEntities($select);
60
+    }
61 61
 
62
-	public function deleteGroups(array $removedGroups): void {
63
-		$query = $this->db->getQueryBuilder();
64
-		$query->delete($this->getTableName())
65
-			->where($query->expr()->in('groupid', $query->createParameter('groupids')));
62
+    public function deleteGroups(array $removedGroups): void {
63
+        $query = $this->db->getQueryBuilder();
64
+        $query->delete($this->getTableName())
65
+            ->where($query->expr()->in('groupid', $query->createParameter('groupids')));
66 66
 
67
-		foreach (array_chunk($removedGroups, 1000) as $removedGroupsChunk) {
68
-			$query->setParameter('groupids', $removedGroupsChunk, IQueryBuilder::PARAM_STR_ARRAY);
69
-			$query->executeStatement();
70
-		}
71
-	}
67
+        foreach (array_chunk($removedGroups, 1000) as $removedGroupsChunk) {
68
+            $query->setParameter('groupids', $removedGroupsChunk, IQueryBuilder::PARAM_STR_ARRAY);
69
+            $query->executeStatement();
70
+        }
71
+    }
72 72
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Migration/Version1190Date20230706134108.php 1 patch
Indentation   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -17,92 +17,92 @@
 block discarded – undo
17 17
 use OCP\Migration\SimpleMigrationStep;
18 18
 
19 19
 class Version1190Date20230706134108 extends SimpleMigrationStep {
20
-	public function __construct(
21
-		private IDBConnection $dbc,
22
-	) {
23
-	}
20
+    public function __construct(
21
+        private IDBConnection $dbc,
22
+    ) {
23
+    }
24 24
 
25
-	public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
26
-	}
25
+    public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
26
+    }
27 27
 
28
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
29
-		/** @var ISchemaWrapper $schema */
30
-		$schema = $schemaClosure();
28
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
29
+        /** @var ISchemaWrapper $schema */
30
+        $schema = $schemaClosure();
31 31
 
32
-		if (!$schema->hasTable('ldap_group_membership')) {
33
-			$table = $schema->createTable('ldap_group_membership');
34
-			$table->addColumn('id', Types::BIGINT, [
35
-				'autoincrement' => true,
36
-				'notnull' => true,
37
-			]);
38
-			$table->addColumn('groupid', Types::STRING, [
39
-				'notnull' => true,
40
-				'length' => 255,
41
-				'default' => '',
42
-			]);
43
-			$table->addColumn('userid', Types::STRING, [
44
-				'notnull' => true,
45
-				'length' => 64,
46
-				'default' => '',
47
-			]);
48
-			$table->setPrimaryKey(['id']);
49
-			$table->addUniqueIndex(['groupid', 'userid'], 'user_ldap_membership_unique');
50
-			return $schema;
51
-		} else {
52
-			return null;
53
-		}
54
-	}
32
+        if (!$schema->hasTable('ldap_group_membership')) {
33
+            $table = $schema->createTable('ldap_group_membership');
34
+            $table->addColumn('id', Types::BIGINT, [
35
+                'autoincrement' => true,
36
+                'notnull' => true,
37
+            ]);
38
+            $table->addColumn('groupid', Types::STRING, [
39
+                'notnull' => true,
40
+                'length' => 255,
41
+                'default' => '',
42
+            ]);
43
+            $table->addColumn('userid', Types::STRING, [
44
+                'notnull' => true,
45
+                'length' => 64,
46
+                'default' => '',
47
+            ]);
48
+            $table->setPrimaryKey(['id']);
49
+            $table->addUniqueIndex(['groupid', 'userid'], 'user_ldap_membership_unique');
50
+            return $schema;
51
+        } else {
52
+            return null;
53
+        }
54
+    }
55 55
 
56
-	public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
57
-		/** @var ISchemaWrapper $schema */
58
-		$schema = $schemaClosure();
56
+    public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
57
+        /** @var ISchemaWrapper $schema */
58
+        $schema = $schemaClosure();
59 59
 
60
-		if (!$schema->hasTable('ldap_group_members')) {
61
-			// Old table does not exist
62
-			return;
63
-		}
60
+        if (!$schema->hasTable('ldap_group_members')) {
61
+            // Old table does not exist
62
+            return;
63
+        }
64 64
 
65
-		$output->startProgress();
66
-		$this->copyGroupMembershipData();
67
-		$output->finishProgress();
68
-	}
65
+        $output->startProgress();
66
+        $this->copyGroupMembershipData();
67
+        $output->finishProgress();
68
+    }
69 69
 
70
-	protected function copyGroupMembershipData(): void {
71
-		$insert = $this->dbc->getQueryBuilder();
72
-		$insert->insert('ldap_group_membership')
73
-			->values([
74
-				'userid' => $insert->createParameter('userid'),
75
-				'groupid' => $insert->createParameter('groupid'),
76
-			]);
70
+    protected function copyGroupMembershipData(): void {
71
+        $insert = $this->dbc->getQueryBuilder();
72
+        $insert->insert('ldap_group_membership')
73
+            ->values([
74
+                'userid' => $insert->createParameter('userid'),
75
+                'groupid' => $insert->createParameter('groupid'),
76
+            ]);
77 77
 
78
-		$query = $this->dbc->getQueryBuilder();
79
-		$query->select('*')
80
-			->from('ldap_group_members');
78
+        $query = $this->dbc->getQueryBuilder();
79
+        $query->select('*')
80
+            ->from('ldap_group_members');
81 81
 
82
-		$result = $query->executeQuery();
83
-		while ($row = $result->fetchAssociative()) {
84
-			$knownUsers = unserialize($row['owncloudusers']);
85
-			if (!is_array($knownUsers)) {
86
-				/* Unserialize failed or data was incorrect in database, ignore */
87
-				continue;
88
-			}
89
-			$knownUsers = array_unique($knownUsers);
90
-			foreach ($knownUsers as $knownUser) {
91
-				try {
92
-					$insert
93
-						->setParameter('groupid', $row['owncloudname'])
94
-						->setParameter('userid', $knownUser)
95
-					;
82
+        $result = $query->executeQuery();
83
+        while ($row = $result->fetchAssociative()) {
84
+            $knownUsers = unserialize($row['owncloudusers']);
85
+            if (!is_array($knownUsers)) {
86
+                /* Unserialize failed or data was incorrect in database, ignore */
87
+                continue;
88
+            }
89
+            $knownUsers = array_unique($knownUsers);
90
+            foreach ($knownUsers as $knownUser) {
91
+                try {
92
+                    $insert
93
+                        ->setParameter('groupid', $row['owncloudname'])
94
+                        ->setParameter('userid', $knownUser)
95
+                    ;
96 96
 
97
-					$insert->executeStatement();
98
-				} catch (\OCP\DB\Exception $e) {
99
-					/*
97
+                    $insert->executeStatement();
98
+                } catch (\OCP\DB\Exception $e) {
99
+                    /*
100 100
 					 * If it fails on unique constaint violation it may just be left over value from previous half-migration
101 101
 					 * If it fails on something else, ignore as well, data will be filled by background job later anyway
102 102
 					 */
103
-				}
104
-			}
105
-		}
106
-		$result->closeCursor();
107
-	}
103
+                }
104
+            }
105
+        }
106
+        $result->closeCursor();
107
+    }
108 108
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Migration/Version1130Date20211102154716.php 1 patch
Indentation   +219 added lines, -219 removed lines patch added patch discarded remove patch
@@ -22,245 +22,245 @@
 block discarded – undo
22 22
 
23 23
 class Version1130Date20211102154716 extends SimpleMigrationStep {
24 24
 
25
-	/** @var string[] */
26
-	private $hashColumnAddedToTables = [];
25
+    /** @var string[] */
26
+    private $hashColumnAddedToTables = [];
27 27
 
28
-	public function __construct(
29
-		private IDBConnection $dbc,
30
-		private LoggerInterface $logger,
31
-	) {
32
-	}
28
+    public function __construct(
29
+        private IDBConnection $dbc,
30
+        private LoggerInterface $logger,
31
+    ) {
32
+    }
33 33
 
34
-	public function getName() {
35
-		return 'Adjust LDAP user and group ldap_dn column lengths and add ldap_dn_hash columns';
36
-	}
34
+    public function getName() {
35
+        return 'Adjust LDAP user and group ldap_dn column lengths and add ldap_dn_hash columns';
36
+    }
37 37
 
38
-	public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
39
-		foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
40
-			$this->processDuplicateUUIDs($tableName);
41
-		}
38
+    public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
39
+        foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
40
+            $this->processDuplicateUUIDs($tableName);
41
+        }
42 42
 
43
-		/** @var ISchemaWrapper $schema */
44
-		$schema = $schemaClosure();
45
-		if ($schema->hasTable('ldap_group_mapping_backup')) {
46
-			// Previous upgrades of a broken release might have left an incomplete
47
-			// ldap_group_mapping_backup table. No need to recreate, but it
48
-			// should be empty.
49
-			// TRUNCATE is not available from Query Builder, but faster than DELETE FROM.
50
-			$sql = $this->dbc->getDatabasePlatform()->getTruncateTableSQL('`*PREFIX*ldap_group_mapping_backup`', false);
51
-			$this->dbc->executeStatement($sql);
52
-		}
53
-	}
43
+        /** @var ISchemaWrapper $schema */
44
+        $schema = $schemaClosure();
45
+        if ($schema->hasTable('ldap_group_mapping_backup')) {
46
+            // Previous upgrades of a broken release might have left an incomplete
47
+            // ldap_group_mapping_backup table. No need to recreate, but it
48
+            // should be empty.
49
+            // TRUNCATE is not available from Query Builder, but faster than DELETE FROM.
50
+            $sql = $this->dbc->getDatabasePlatform()->getTruncateTableSQL('`*PREFIX*ldap_group_mapping_backup`', false);
51
+            $this->dbc->executeStatement($sql);
52
+        }
53
+    }
54 54
 
55
-	/**
56
-	 * @param IOutput $output
57
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
58
-	 * @param array $options
59
-	 * @return null|ISchemaWrapper
60
-	 */
61
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
62
-		/** @var ISchemaWrapper $schema */
63
-		$schema = $schemaClosure();
55
+    /**
56
+     * @param IOutput $output
57
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
58
+     * @param array $options
59
+     * @return null|ISchemaWrapper
60
+     */
61
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
62
+        /** @var ISchemaWrapper $schema */
63
+        $schema = $schemaClosure();
64 64
 
65
-		$changeSchema = false;
66
-		foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
67
-			$table = $schema->getTable($tableName);
68
-			if (!$table->hasColumn('ldap_dn_hash')) {
69
-				$table->addColumn('ldap_dn_hash', Types::STRING, [
70
-					'notnull' => false,
71
-					'length' => 64,
72
-				]);
73
-				$changeSchema = true;
74
-				$this->hashColumnAddedToTables[] = $tableName;
75
-			}
76
-			$column = $table->getColumn('ldap_dn');
77
-			if ($tableName === 'ldap_user_mapping') {
78
-				if ($column->getLength() < 4000) {
79
-					$column->setLength(4000);
80
-					$changeSchema = true;
81
-				}
65
+        $changeSchema = false;
66
+        foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
67
+            $table = $schema->getTable($tableName);
68
+            if (!$table->hasColumn('ldap_dn_hash')) {
69
+                $table->addColumn('ldap_dn_hash', Types::STRING, [
70
+                    'notnull' => false,
71
+                    'length' => 64,
72
+                ]);
73
+                $changeSchema = true;
74
+                $this->hashColumnAddedToTables[] = $tableName;
75
+            }
76
+            $column = $table->getColumn('ldap_dn');
77
+            if ($tableName === 'ldap_user_mapping') {
78
+                if ($column->getLength() < 4000) {
79
+                    $column->setLength(4000);
80
+                    $changeSchema = true;
81
+                }
82 82
 
83
-				if ($table->hasIndex('ldap_dn_users')) {
84
-					$table->dropIndex('ldap_dn_users');
85
-					$changeSchema = true;
86
-				}
87
-				if (!$table->hasIndex('ldap_user_dn_hashes')) {
88
-					$table->addUniqueIndex(['ldap_dn_hash'], 'ldap_user_dn_hashes');
89
-					$changeSchema = true;
90
-				}
91
-				if (!$table->hasIndex('ldap_user_directory_uuid')) {
92
-					$table->addUniqueIndex(['directory_uuid'], 'ldap_user_directory_uuid');
93
-					$changeSchema = true;
94
-				}
95
-			} elseif (!$schema->hasTable('ldap_group_mapping_backup')) {
96
-				// We need to copy the table twice to be able to change primary key, prepare the backup table
97
-				$table2 = $schema->createTable('ldap_group_mapping_backup');
98
-				$table2->addColumn('ldap_dn', Types::STRING, [
99
-					'notnull' => true,
100
-					'length' => 4000,
101
-					'default' => '',
102
-				]);
103
-				$table2->addColumn('owncloud_name', Types::STRING, [
104
-					'notnull' => true,
105
-					'length' => 64,
106
-					'default' => '',
107
-				]);
108
-				$table2->addColumn('directory_uuid', Types::STRING, [
109
-					'notnull' => true,
110
-					'length' => 255,
111
-					'default' => '',
112
-				]);
113
-				$table2->addColumn('ldap_dn_hash', Types::STRING, [
114
-					'notnull' => false,
115
-					'length' => 64,
116
-				]);
117
-				$table2->setPrimaryKey(['owncloud_name'], 'lgm_backup_primary');
118
-				$changeSchema = true;
119
-			}
120
-		}
83
+                if ($table->hasIndex('ldap_dn_users')) {
84
+                    $table->dropIndex('ldap_dn_users');
85
+                    $changeSchema = true;
86
+                }
87
+                if (!$table->hasIndex('ldap_user_dn_hashes')) {
88
+                    $table->addUniqueIndex(['ldap_dn_hash'], 'ldap_user_dn_hashes');
89
+                    $changeSchema = true;
90
+                }
91
+                if (!$table->hasIndex('ldap_user_directory_uuid')) {
92
+                    $table->addUniqueIndex(['directory_uuid'], 'ldap_user_directory_uuid');
93
+                    $changeSchema = true;
94
+                }
95
+            } elseif (!$schema->hasTable('ldap_group_mapping_backup')) {
96
+                // We need to copy the table twice to be able to change primary key, prepare the backup table
97
+                $table2 = $schema->createTable('ldap_group_mapping_backup');
98
+                $table2->addColumn('ldap_dn', Types::STRING, [
99
+                    'notnull' => true,
100
+                    'length' => 4000,
101
+                    'default' => '',
102
+                ]);
103
+                $table2->addColumn('owncloud_name', Types::STRING, [
104
+                    'notnull' => true,
105
+                    'length' => 64,
106
+                    'default' => '',
107
+                ]);
108
+                $table2->addColumn('directory_uuid', Types::STRING, [
109
+                    'notnull' => true,
110
+                    'length' => 255,
111
+                    'default' => '',
112
+                ]);
113
+                $table2->addColumn('ldap_dn_hash', Types::STRING, [
114
+                    'notnull' => false,
115
+                    'length' => 64,
116
+                ]);
117
+                $table2->setPrimaryKey(['owncloud_name'], 'lgm_backup_primary');
118
+                $changeSchema = true;
119
+            }
120
+        }
121 121
 
122
-		return $changeSchema ? $schema : null;
123
-	}
122
+        return $changeSchema ? $schema : null;
123
+    }
124 124
 
125
-	/**
126
-	 * @param IOutput $output
127
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
128
-	 * @param array $options
129
-	 */
130
-	public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
131
-		$this->handleDNHashes('ldap_group_mapping');
132
-		$this->handleDNHashes('ldap_user_mapping');
133
-	}
125
+    /**
126
+     * @param IOutput $output
127
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
128
+     * @param array $options
129
+     */
130
+    public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
131
+        $this->handleDNHashes('ldap_group_mapping');
132
+        $this->handleDNHashes('ldap_user_mapping');
133
+    }
134 134
 
135
-	protected function handleDNHashes(string $table): void {
136
-		$select = $this->getSelectQuery($table);
137
-		$update = $this->getUpdateQuery($table);
135
+    protected function handleDNHashes(string $table): void {
136
+        $select = $this->getSelectQuery($table);
137
+        $update = $this->getUpdateQuery($table);
138 138
 
139
-		$result = $select->executeQuery();
140
-		while ($row = $result->fetchAssociative()) {
141
-			$dnHash = hash('sha256', $row['ldap_dn'], false);
142
-			$update->setParameter('name', $row['owncloud_name']);
143
-			$update->setParameter('dn_hash', $dnHash);
144
-			try {
145
-				$update->executeStatement();
146
-			} catch (Exception $e) {
147
-				$this->logger->error('Failed to add hash "{dnHash}" ("{name}" of {table})',
148
-					[
149
-						'app' => 'user_ldap',
150
-						'name' => $row['owncloud_name'],
151
-						'dnHash' => $dnHash,
152
-						'table' => $table,
153
-						'exception' => $e,
154
-					]
155
-				);
156
-			}
157
-		}
158
-		$result->closeCursor();
159
-	}
139
+        $result = $select->executeQuery();
140
+        while ($row = $result->fetchAssociative()) {
141
+            $dnHash = hash('sha256', $row['ldap_dn'], false);
142
+            $update->setParameter('name', $row['owncloud_name']);
143
+            $update->setParameter('dn_hash', $dnHash);
144
+            try {
145
+                $update->executeStatement();
146
+            } catch (Exception $e) {
147
+                $this->logger->error('Failed to add hash "{dnHash}" ("{name}" of {table})',
148
+                    [
149
+                        'app' => 'user_ldap',
150
+                        'name' => $row['owncloud_name'],
151
+                        'dnHash' => $dnHash,
152
+                        'table' => $table,
153
+                        'exception' => $e,
154
+                    ]
155
+                );
156
+            }
157
+        }
158
+        $result->closeCursor();
159
+    }
160 160
 
161
-	protected function getSelectQuery(string $table): IQueryBuilder {
162
-		$qb = $this->dbc->getQueryBuilder();
163
-		$qb->select('owncloud_name', 'ldap_dn')
164
-			->from($table);
161
+    protected function getSelectQuery(string $table): IQueryBuilder {
162
+        $qb = $this->dbc->getQueryBuilder();
163
+        $qb->select('owncloud_name', 'ldap_dn')
164
+            ->from($table);
165 165
 
166
-		// when added we may run into risk that it's read from a DB node
167
-		// where the column is not present. Then the where clause is also
168
-		// not necessary since all rows qualify.
169
-		if (!in_array($table, $this->hashColumnAddedToTables, true)) {
170
-			$qb->where($qb->expr()->isNull('ldap_dn_hash'));
171
-		}
166
+        // when added we may run into risk that it's read from a DB node
167
+        // where the column is not present. Then the where clause is also
168
+        // not necessary since all rows qualify.
169
+        if (!in_array($table, $this->hashColumnAddedToTables, true)) {
170
+            $qb->where($qb->expr()->isNull('ldap_dn_hash'));
171
+        }
172 172
 
173
-		return $qb;
174
-	}
173
+        return $qb;
174
+    }
175 175
 
176
-	protected function getUpdateQuery(string $table): IQueryBuilder {
177
-		$qb = $this->dbc->getQueryBuilder();
178
-		$qb->update($table)
179
-			->set('ldap_dn_hash', $qb->createParameter('dn_hash'))
180
-			->where($qb->expr()->eq('owncloud_name', $qb->createParameter('name')));
181
-		return $qb;
182
-	}
176
+    protected function getUpdateQuery(string $table): IQueryBuilder {
177
+        $qb = $this->dbc->getQueryBuilder();
178
+        $qb->update($table)
179
+            ->set('ldap_dn_hash', $qb->createParameter('dn_hash'))
180
+            ->where($qb->expr()->eq('owncloud_name', $qb->createParameter('name')));
181
+        return $qb;
182
+    }
183 183
 
184
-	/**
185
-	 * @throws Exception
186
-	 */
187
-	protected function processDuplicateUUIDs(string $table): void {
188
-		$uuids = $this->getDuplicatedUuids($table);
189
-		$idsWithUuidToInvalidate = [];
190
-		foreach ($uuids as $uuid) {
191
-			array_push($idsWithUuidToInvalidate, ...$this->getNextcloudIdsByUuid($table, $uuid));
192
-		}
193
-		$this->invalidateUuids($table, $idsWithUuidToInvalidate);
194
-	}
184
+    /**
185
+     * @throws Exception
186
+     */
187
+    protected function processDuplicateUUIDs(string $table): void {
188
+        $uuids = $this->getDuplicatedUuids($table);
189
+        $idsWithUuidToInvalidate = [];
190
+        foreach ($uuids as $uuid) {
191
+            array_push($idsWithUuidToInvalidate, ...$this->getNextcloudIdsByUuid($table, $uuid));
192
+        }
193
+        $this->invalidateUuids($table, $idsWithUuidToInvalidate);
194
+    }
195 195
 
196
-	/**
197
-	 * @throws Exception
198
-	 */
199
-	protected function invalidateUuids(string $table, array $idList): void {
200
-		$update = $this->dbc->getQueryBuilder();
201
-		$update->update($table)
202
-			->set('directory_uuid', $update->createParameter('invalidatedUuid'))
203
-			->where($update->expr()->eq('owncloud_name', $update->createParameter('nextcloudId')));
196
+    /**
197
+     * @throws Exception
198
+     */
199
+    protected function invalidateUuids(string $table, array $idList): void {
200
+        $update = $this->dbc->getQueryBuilder();
201
+        $update->update($table)
202
+            ->set('directory_uuid', $update->createParameter('invalidatedUuid'))
203
+            ->where($update->expr()->eq('owncloud_name', $update->createParameter('nextcloudId')));
204 204
 
205
-		while ($nextcloudId = array_shift($idList)) {
206
-			$update->setParameter('nextcloudId', $nextcloudId);
207
-			$update->setParameter('invalidatedUuid', 'invalidated_' . \bin2hex(\random_bytes(6)));
208
-			try {
209
-				$update->executeStatement();
210
-				$this->logger->warning(
211
-					'LDAP user or group with ID {nid} has a duplicated UUID value which therefore was invalidated. You may double-check your LDAP configuration and trigger an update of the UUID.',
212
-					[
213
-						'app' => 'user_ldap',
214
-						'nid' => $nextcloudId,
215
-					]
216
-				);
217
-			} catch (Exception $e) {
218
-				// Catch possible, but unlikely duplications if new invalidated errors.
219
-				// There is the theoretical chance of an infinity loop is, when
220
-				// the constraint violation has a different background. I cannot
221
-				// think of one at the moment.
222
-				if ($e->getReason() !== Exception::REASON_CONSTRAINT_VIOLATION) {
223
-					throw $e;
224
-				}
225
-				$idList[] = $nextcloudId;
226
-			}
227
-		}
228
-	}
205
+        while ($nextcloudId = array_shift($idList)) {
206
+            $update->setParameter('nextcloudId', $nextcloudId);
207
+            $update->setParameter('invalidatedUuid', 'invalidated_' . \bin2hex(\random_bytes(6)));
208
+            try {
209
+                $update->executeStatement();
210
+                $this->logger->warning(
211
+                    'LDAP user or group with ID {nid} has a duplicated UUID value which therefore was invalidated. You may double-check your LDAP configuration and trigger an update of the UUID.',
212
+                    [
213
+                        'app' => 'user_ldap',
214
+                        'nid' => $nextcloudId,
215
+                    ]
216
+                );
217
+            } catch (Exception $e) {
218
+                // Catch possible, but unlikely duplications if new invalidated errors.
219
+                // There is the theoretical chance of an infinity loop is, when
220
+                // the constraint violation has a different background. I cannot
221
+                // think of one at the moment.
222
+                if ($e->getReason() !== Exception::REASON_CONSTRAINT_VIOLATION) {
223
+                    throw $e;
224
+                }
225
+                $idList[] = $nextcloudId;
226
+            }
227
+        }
228
+    }
229 229
 
230
-	/**
231
-	 * @throws \OCP\DB\Exception
232
-	 * @return array<string>
233
-	 */
234
-	protected function getNextcloudIdsByUuid(string $table, string $uuid): array {
235
-		$select = $this->dbc->getQueryBuilder();
236
-		$select->select('owncloud_name')
237
-			->from($table)
238
-			->where($select->expr()->eq('directory_uuid', $select->createNamedParameter($uuid)));
230
+    /**
231
+     * @throws \OCP\DB\Exception
232
+     * @return array<string>
233
+     */
234
+    protected function getNextcloudIdsByUuid(string $table, string $uuid): array {
235
+        $select = $this->dbc->getQueryBuilder();
236
+        $select->select('owncloud_name')
237
+            ->from($table)
238
+            ->where($select->expr()->eq('directory_uuid', $select->createNamedParameter($uuid)));
239 239
 
240
-		$result = $select->executeQuery();
241
-		$idList = [];
242
-		while (($id = $result->fetchOne()) !== false) {
243
-			$idList[] = $id;
244
-		}
245
-		$result->closeCursor();
246
-		return $idList;
247
-	}
240
+        $result = $select->executeQuery();
241
+        $idList = [];
242
+        while (($id = $result->fetchOne()) !== false) {
243
+            $idList[] = $id;
244
+        }
245
+        $result->closeCursor();
246
+        return $idList;
247
+    }
248 248
 
249
-	/**
250
-	 * @return Generator<string>
251
-	 * @throws \OCP\DB\Exception
252
-	 */
253
-	protected function getDuplicatedUuids(string $table): Generator {
254
-		$select = $this->dbc->getQueryBuilder();
255
-		$select->select('directory_uuid')
256
-			->from($table)
257
-			->groupBy('directory_uuid')
258
-			->having($select->expr()->gt($select->func()->count('owncloud_name'), $select->createNamedParameter(1)));
249
+    /**
250
+     * @return Generator<string>
251
+     * @throws \OCP\DB\Exception
252
+     */
253
+    protected function getDuplicatedUuids(string $table): Generator {
254
+        $select = $this->dbc->getQueryBuilder();
255
+        $select->select('directory_uuid')
256
+            ->from($table)
257
+            ->groupBy('directory_uuid')
258
+            ->having($select->expr()->gt($select->func()->count('owncloud_name'), $select->createNamedParameter(1)));
259 259
 
260
-		$result = $select->executeQuery();
261
-		while (($uuid = $result->fetchOne()) !== false) {
262
-			yield $uuid;
263
-		}
264
-		$result->closeCursor();
265
-	}
260
+        $result = $select->executeQuery();
261
+        while (($uuid = $result->fetchOne()) !== false) {
262
+            yield $uuid;
263
+        }
264
+        $result->closeCursor();
265
+    }
266 266
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Migration/GroupMappingMigration.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -14,37 +14,37 @@
 block discarded – undo
14 14
 
15 15
 abstract class GroupMappingMigration extends SimpleMigrationStep {
16 16
 
17
-	public function __construct(
18
-		private IDBConnection $dbc,
19
-	) {
20
-	}
21
-
22
-	protected function copyGroupMappingData(string $sourceTable, string $destinationTable): void {
23
-		$insert = $this->dbc->getQueryBuilder();
24
-		$insert->insert($destinationTable)
25
-			->values([
26
-				'ldap_dn' => $insert->createParameter('ldap_dn'),
27
-				'owncloud_name' => $insert->createParameter('owncloud_name'),
28
-				'directory_uuid' => $insert->createParameter('directory_uuid'),
29
-				'ldap_dn_hash' => $insert->createParameter('ldap_dn_hash'),
30
-			]);
31
-
32
-		$query = $this->dbc->getQueryBuilder();
33
-		$query->select('*')
34
-			->from($sourceTable);
35
-
36
-
37
-		$result = $query->executeQuery();
38
-		while ($row = $result->fetchAssociative()) {
39
-			$insert
40
-				->setParameter('ldap_dn', $row['ldap_dn'])
41
-				->setParameter('owncloud_name', $row['owncloud_name'])
42
-				->setParameter('directory_uuid', $row['directory_uuid'])
43
-				->setParameter('ldap_dn_hash', $row['ldap_dn_hash'])
44
-			;
45
-
46
-			$insert->executeStatement();
47
-		}
48
-		$result->closeCursor();
49
-	}
17
+    public function __construct(
18
+        private IDBConnection $dbc,
19
+    ) {
20
+    }
21
+
22
+    protected function copyGroupMappingData(string $sourceTable, string $destinationTable): void {
23
+        $insert = $this->dbc->getQueryBuilder();
24
+        $insert->insert($destinationTable)
25
+            ->values([
26
+                'ldap_dn' => $insert->createParameter('ldap_dn'),
27
+                'owncloud_name' => $insert->createParameter('owncloud_name'),
28
+                'directory_uuid' => $insert->createParameter('directory_uuid'),
29
+                'ldap_dn_hash' => $insert->createParameter('ldap_dn_hash'),
30
+            ]);
31
+
32
+        $query = $this->dbc->getQueryBuilder();
33
+        $query->select('*')
34
+            ->from($sourceTable);
35
+
36
+
37
+        $result = $query->executeQuery();
38
+        while ($row = $result->fetchAssociative()) {
39
+            $insert
40
+                ->setParameter('ldap_dn', $row['ldap_dn'])
41
+                ->setParameter('owncloud_name', $row['owncloud_name'])
42
+                ->setParameter('directory_uuid', $row['directory_uuid'])
43
+                ->setParameter('ldap_dn_hash', $row['ldap_dn_hash'])
44
+            ;
45
+
46
+            $insert->executeStatement();
47
+        }
48
+        $result->closeCursor();
49
+    }
50 50
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Migration/Version1120Date20210917155206.php 1 patch
Indentation   +106 added lines, -106 removed lines patch added patch discarded remove patch
@@ -22,110 +22,110 @@
 block discarded – undo
22 22
 
23 23
 class Version1120Date20210917155206 extends SimpleMigrationStep {
24 24
 
25
-	public function __construct(
26
-		private IDBConnection $dbc,
27
-		private IUserManager $userManager,
28
-		private LoggerInterface $logger,
29
-	) {
30
-	}
31
-
32
-	public function getName() {
33
-		return 'Adjust LDAP user and group id column lengths to match server lengths';
34
-	}
35
-
36
-	/**
37
-	 * @param IOutput $output
38
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
39
-	 * @param array $options
40
-	 */
41
-	public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
42
-		// ensure that there is no user or group id longer than 64char in LDAP table
43
-		$this->handleIDs('ldap_group_mapping', false);
44
-		$this->handleIDs('ldap_user_mapping', true);
45
-	}
46
-
47
-	/**
48
-	 * @param IOutput $output
49
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
50
-	 * @param array $options
51
-	 * @return null|ISchemaWrapper
52
-	 */
53
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
54
-		/** @var ISchemaWrapper $schema */
55
-		$schema = $schemaClosure();
56
-
57
-		$changeSchema = false;
58
-		foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
59
-			$table = $schema->getTable($tableName);
60
-			$column = $table->getColumn('owncloud_name');
61
-			if ($column->getLength() > 64) {
62
-				$column->setLength(64);
63
-				$changeSchema = true;
64
-			}
65
-		}
66
-
67
-		return $changeSchema ? $schema : null;
68
-	}
69
-
70
-	protected function handleIDs(string $table, bool $emitHooks) {
71
-		$select = $this->getSelectQuery($table);
72
-		$update = $this->getUpdateQuery($table);
73
-
74
-		$result = $select->executeQuery();
75
-		while ($row = $result->fetchAssociative()) {
76
-			$newId = hash('sha256', $row['owncloud_name'], false);
77
-			if ($emitHooks) {
78
-				$this->emitUnassign($row['owncloud_name'], true);
79
-			}
80
-			$update->setParameter('uuid', $row['directory_uuid']);
81
-			$update->setParameter('newId', $newId);
82
-			try {
83
-				$update->executeStatement();
84
-				if ($emitHooks) {
85
-					$this->emitUnassign($row['owncloud_name'], false);
86
-					$this->emitAssign($newId);
87
-				}
88
-			} catch (Exception $e) {
89
-				$this->logger->error('Failed to shorten owncloud_name "{oldId}" to "{newId}" (UUID: "{uuid}" of {table})',
90
-					[
91
-						'app' => 'user_ldap',
92
-						'oldId' => $row['owncloud_name'],
93
-						'newId' => $newId,
94
-						'uuid' => $row['directory_uuid'],
95
-						'table' => $table,
96
-						'exception' => $e,
97
-					]
98
-				);
99
-			}
100
-		}
101
-		$result->closeCursor();
102
-	}
103
-
104
-	protected function getSelectQuery(string $table): IQueryBuilder {
105
-		$qb = $this->dbc->getQueryBuilder();
106
-		$qb->select('owncloud_name', 'directory_uuid')
107
-			->from($table)
108
-			->where($qb->expr()->gt($qb->func()->octetLength('owncloud_name'), $qb->createNamedParameter('64'), IQueryBuilder::PARAM_INT));
109
-		return $qb;
110
-	}
111
-
112
-	protected function getUpdateQuery(string $table): IQueryBuilder {
113
-		$qb = $this->dbc->getQueryBuilder();
114
-		$qb->update($table)
115
-			->set('owncloud_name', $qb->createParameter('newId'))
116
-			->where($qb->expr()->eq('directory_uuid', $qb->createParameter('uuid')));
117
-		return $qb;
118
-	}
119
-
120
-	protected function emitUnassign(string $oldId, bool $pre): void {
121
-		if ($this->userManager instanceof PublicEmitter) {
122
-			$this->userManager->emit('\OC\User', $pre ? 'pre' : 'post' . 'UnassignedUserId', [$oldId]);
123
-		}
124
-	}
125
-
126
-	protected function emitAssign(string $newId): void {
127
-		if ($this->userManager instanceof PublicEmitter) {
128
-			$this->userManager->emit('\OC\User', 'assignedUserId', [$newId]);
129
-		}
130
-	}
25
+    public function __construct(
26
+        private IDBConnection $dbc,
27
+        private IUserManager $userManager,
28
+        private LoggerInterface $logger,
29
+    ) {
30
+    }
31
+
32
+    public function getName() {
33
+        return 'Adjust LDAP user and group id column lengths to match server lengths';
34
+    }
35
+
36
+    /**
37
+     * @param IOutput $output
38
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
39
+     * @param array $options
40
+     */
41
+    public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
42
+        // ensure that there is no user or group id longer than 64char in LDAP table
43
+        $this->handleIDs('ldap_group_mapping', false);
44
+        $this->handleIDs('ldap_user_mapping', true);
45
+    }
46
+
47
+    /**
48
+     * @param IOutput $output
49
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
50
+     * @param array $options
51
+     * @return null|ISchemaWrapper
52
+     */
53
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
54
+        /** @var ISchemaWrapper $schema */
55
+        $schema = $schemaClosure();
56
+
57
+        $changeSchema = false;
58
+        foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
59
+            $table = $schema->getTable($tableName);
60
+            $column = $table->getColumn('owncloud_name');
61
+            if ($column->getLength() > 64) {
62
+                $column->setLength(64);
63
+                $changeSchema = true;
64
+            }
65
+        }
66
+
67
+        return $changeSchema ? $schema : null;
68
+    }
69
+
70
+    protected function handleIDs(string $table, bool $emitHooks) {
71
+        $select = $this->getSelectQuery($table);
72
+        $update = $this->getUpdateQuery($table);
73
+
74
+        $result = $select->executeQuery();
75
+        while ($row = $result->fetchAssociative()) {
76
+            $newId = hash('sha256', $row['owncloud_name'], false);
77
+            if ($emitHooks) {
78
+                $this->emitUnassign($row['owncloud_name'], true);
79
+            }
80
+            $update->setParameter('uuid', $row['directory_uuid']);
81
+            $update->setParameter('newId', $newId);
82
+            try {
83
+                $update->executeStatement();
84
+                if ($emitHooks) {
85
+                    $this->emitUnassign($row['owncloud_name'], false);
86
+                    $this->emitAssign($newId);
87
+                }
88
+            } catch (Exception $e) {
89
+                $this->logger->error('Failed to shorten owncloud_name "{oldId}" to "{newId}" (UUID: "{uuid}" of {table})',
90
+                    [
91
+                        'app' => 'user_ldap',
92
+                        'oldId' => $row['owncloud_name'],
93
+                        'newId' => $newId,
94
+                        'uuid' => $row['directory_uuid'],
95
+                        'table' => $table,
96
+                        'exception' => $e,
97
+                    ]
98
+                );
99
+            }
100
+        }
101
+        $result->closeCursor();
102
+    }
103
+
104
+    protected function getSelectQuery(string $table): IQueryBuilder {
105
+        $qb = $this->dbc->getQueryBuilder();
106
+        $qb->select('owncloud_name', 'directory_uuid')
107
+            ->from($table)
108
+            ->where($qb->expr()->gt($qb->func()->octetLength('owncloud_name'), $qb->createNamedParameter('64'), IQueryBuilder::PARAM_INT));
109
+        return $qb;
110
+    }
111
+
112
+    protected function getUpdateQuery(string $table): IQueryBuilder {
113
+        $qb = $this->dbc->getQueryBuilder();
114
+        $qb->update($table)
115
+            ->set('owncloud_name', $qb->createParameter('newId'))
116
+            ->where($qb->expr()->eq('directory_uuid', $qb->createParameter('uuid')));
117
+        return $qb;
118
+    }
119
+
120
+    protected function emitUnassign(string $oldId, bool $pre): void {
121
+        if ($this->userManager instanceof PublicEmitter) {
122
+            $this->userManager->emit('\OC\User', $pre ? 'pre' : 'post' . 'UnassignedUserId', [$oldId]);
123
+        }
124
+    }
125
+
126
+    protected function emitAssign(string $newId): void {
127
+        if ($this->userManager instanceof PublicEmitter) {
128
+            $this->userManager->emit('\OC\User', 'assignedUserId', [$newId]);
129
+        }
130
+    }
131 131
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/tests/FederatedShareProviderTest.php 1 patch
Indentation   +912 added lines, -912 removed lines patch added patch discarded remove patch
@@ -39,916 +39,916 @@
 block discarded – undo
39 39
  */
40 40
 #[\PHPUnit\Framework\Attributes\Group('DB')]
41 41
 class FederatedShareProviderTest extends \Test\TestCase {
42
-	protected IDBConnection $connection;
43
-	protected AddressHandler&MockObject $addressHandler;
44
-	protected Notifications&MockObject $notifications;
45
-	protected TokenHandler&MockObject $tokenHandler;
46
-	protected IL10N $l;
47
-	protected LoggerInterface $logger;
48
-	protected IRootFolder&MockObject $rootFolder;
49
-	protected IConfig&MockObject $config;
50
-	protected IUserManager&MockObject $userManager;
51
-	protected \OCP\GlobalScale\IConfig&MockObject $gsConfig;
52
-	protected IManager $shareManager;
53
-	protected FederatedShareProvider $provider;
54
-	protected IContactsManager&MockObject $contactsManager;
55
-	private ICloudIdManager $cloudIdManager;
56
-	private ICloudFederationProviderManager&MockObject $cloudFederationProviderManager;
57
-
58
-	protected function setUp(): void {
59
-		parent::setUp();
60
-
61
-		$this->connection = Server::get(IDBConnection::class);
62
-		$this->notifications = $this->createMock(Notifications::class);
63
-		$this->tokenHandler = $this->createMock(TokenHandler::class);
64
-		$this->l = $this->createMock(IL10N::class);
65
-		$this->l->method('t')
66
-			->willReturnCallback(function ($text, $parameters = []) {
67
-				return vsprintf($text, $parameters);
68
-			});
69
-		$this->logger = $this->createMock(LoggerInterface::class);
70
-		$this->rootFolder = $this->createMock(IRootFolder::class);
71
-		$this->config = $this->createMock(IConfig::class);
72
-		$this->userManager = $this->createMock(IUserManager::class);
73
-		//$this->addressHandler = new AddressHandler(\OC::$server->getURLGenerator(), $this->l);
74
-		$this->addressHandler = $this->createMock(AddressHandler::class);
75
-		$this->contactsManager = $this->createMock(IContactsManager::class);
76
-		$this->cloudIdManager = new CloudIdManager(
77
-			$this->createMock(ICacheFactory::class),
78
-			$this->createMock(IEventDispatcher::class),
79
-			$this->contactsManager,
80
-			$this->createMock(IURLGenerator::class),
81
-			$this->userManager,
82
-		);
83
-		$this->gsConfig = $this->createMock(\OCP\GlobalScale\IConfig::class);
84
-
85
-		$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
86
-
87
-		$this->cloudFederationProviderManager = $this->createMock(ICloudFederationProviderManager::class);
88
-
89
-		$this->provider = new FederatedShareProvider(
90
-			$this->connection,
91
-			$this->addressHandler,
92
-			$this->notifications,
93
-			$this->tokenHandler,
94
-			$this->l,
95
-			$this->rootFolder,
96
-			$this->config,
97
-			$this->userManager,
98
-			$this->cloudIdManager,
99
-			$this->gsConfig,
100
-			$this->cloudFederationProviderManager,
101
-			$this->logger,
102
-		);
103
-
104
-		$this->shareManager = Server::get(IManager::class);
105
-	}
106
-
107
-	protected function tearDown(): void {
108
-		$this->connection->getQueryBuilder()->delete('share')->executeStatement();
109
-
110
-		parent::tearDown();
111
-	}
112
-
113
-	public static function dataTestCreate(): array {
114
-		return [
115
-			[null, null],
116
-			[new \DateTime('2020-03-01T01:02:03'), '2020-03-01 01:02:03'],
117
-		];
118
-	}
119
-
120
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestCreate')]
121
-	public function testCreate(?\DateTime $expirationDate, ?string $expectedDataDate): void {
122
-		$share = $this->shareManager->newShare();
123
-
124
-		/** @var File&MockObject $node */
125
-		$node = $this->createMock(File::class);
126
-		$node->method('getId')->willReturn(42);
127
-		$node->method('getName')->willReturn('myFile');
128
-
129
-		$share->setSharedWith('[email protected]')
130
-			->setSharedBy('sharedBy')
131
-			->setShareOwner('shareOwner')
132
-			->setPermissions(19)
133
-			->setShareType(IShare::TYPE_REMOTE)
134
-			->setExpirationDate($expirationDate)
135
-			->setNode($node);
136
-
137
-		$this->tokenHandler->method('generateToken')->willReturn('token');
138
-
139
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
140
-			->willReturn('http://localhost/');
141
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
142
-			->willReturn(['user', 'server.com']);
143
-
144
-		$this->notifications->expects($this->once())
145
-			->method('sendRemoteShare')
146
-			->with(
147
-				$this->equalTo('token'),
148
-				$this->equalTo('[email protected]'),
149
-				$this->equalTo('myFile'),
150
-				$this->anything(),
151
-				'shareOwner',
152
-				'shareOwner@http://localhost',
153
-				'sharedBy',
154
-				'sharedBy@http://localhost'
155
-			)
156
-			->willReturn(true);
157
-
158
-		$this->rootFolder->expects($this->never())->method($this->anything());
159
-
160
-		$this->contactsManager->expects($this->any())
161
-			->method('search')
162
-			->willReturn([]);
163
-
164
-		$share = $this->provider->create($share);
165
-
166
-		$qb = $this->connection->getQueryBuilder();
167
-		$stmt = $qb->select('*')
168
-			->from('share')
169
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
170
-			->executeQuery();
171
-
172
-		$data = $stmt->fetchAssociative();
173
-		$stmt->closeCursor();
174
-
175
-		$expected = [
176
-			'share_type' => IShare::TYPE_REMOTE,
177
-			'share_with' => '[email protected]',
178
-			'uid_owner' => 'shareOwner',
179
-			'uid_initiator' => 'sharedBy',
180
-			'item_type' => 'file',
181
-			'item_source' => 42,
182
-			'file_source' => 42,
183
-			'permissions' => 19,
184
-			'accepted' => 0,
185
-			'token' => 'token',
186
-			'expiration' => $expectedDataDate,
187
-		];
188
-		foreach (array_keys($expected) as $key) {
189
-			$this->assertEquals($expected[$key], $data[$key], "Assert that value for key '$key' is the same");
190
-		}
191
-
192
-		$this->assertEquals($data['id'], $share->getId());
193
-		$this->assertEquals(IShare::TYPE_REMOTE, $share->getShareType());
194
-		$this->assertEquals('[email protected]', $share->getSharedWith());
195
-		$this->assertEquals('sharedBy', $share->getSharedBy());
196
-		$this->assertEquals('shareOwner', $share->getShareOwner());
197
-		$this->assertEquals('file', $share->getNodeType());
198
-		$this->assertEquals(42, $share->getNodeId());
199
-		$this->assertEquals(19, $share->getPermissions());
200
-		$this->assertEquals('token', $share->getToken());
201
-		$this->assertEquals($expirationDate, $share->getExpirationDate());
202
-	}
203
-
204
-	public function testCreateCouldNotFindServer(): void {
205
-		$share = $this->shareManager->newShare();
206
-
207
-		$node = $this->createMock(File::class);
208
-		$node->method('getId')->willReturn(42);
209
-		$node->method('getName')->willReturn('myFile');
210
-
211
-		$share->setSharedWith('[email protected]')
212
-			->setSharedBy('sharedBy')
213
-			->setShareOwner('shareOwner')
214
-			->setPermissions(19)
215
-			->setShareType(IShare::TYPE_REMOTE)
216
-			->setNode($node);
217
-
218
-		$this->tokenHandler->method('generateToken')->willReturn('token');
219
-
220
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
221
-			->willReturn('http://localhost/');
222
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
223
-			->willReturn(['user', 'server.com']);
224
-
225
-		$this->notifications->expects($this->once())
226
-			->method('sendRemoteShare')
227
-			->with(
228
-				$this->equalTo('token'),
229
-				$this->equalTo('[email protected]'),
230
-				$this->equalTo('myFile'),
231
-				$this->anything(),
232
-				'shareOwner',
233
-				'shareOwner@http://localhost',
234
-				'sharedBy',
235
-				'sharedBy@http://localhost'
236
-			)->willReturn(false);
237
-
238
-		$this->rootFolder->method('getById')
239
-			->with('42')
240
-			->willReturn([$node]);
241
-
242
-		$this->contactsManager->expects($this->any())
243
-			->method('search')
244
-			->willReturn([]);
245
-
246
-		try {
247
-			$share = $this->provider->create($share);
248
-			$this->fail();
249
-		} catch (\Exception $e) {
250
-			$this->assertEquals('Sharing myFile failed, could not find [email protected], maybe the server is currently unreachable or uses a self-signed certificate.', $e->getMessage());
251
-		}
252
-
253
-		$qb = $this->connection->getQueryBuilder();
254
-		$stmt = $qb->select('*')
255
-			->from('share')
256
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
257
-			->executeQuery();
258
-
259
-		$data = $stmt->fetchAssociative();
260
-		$stmt->closeCursor();
261
-
262
-		$this->assertFalse($data);
263
-	}
264
-
265
-	public function testCreateException(): void {
266
-		$share = $this->shareManager->newShare();
267
-
268
-		$node = $this->createMock(File::class);
269
-		$node->method('getId')->willReturn(42);
270
-		$node->method('getName')->willReturn('myFile');
271
-
272
-		$share->setSharedWith('[email protected]')
273
-			->setSharedBy('sharedBy')
274
-			->setShareOwner('shareOwner')
275
-			->setPermissions(19)
276
-			->setShareType(IShare::TYPE_REMOTE)
277
-			->setNode($node);
278
-
279
-		$this->tokenHandler->method('generateToken')->willReturn('token');
280
-
281
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
282
-			->willReturn('http://localhost/');
283
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
284
-			->willReturn(['user', 'server.com']);
285
-
286
-		$this->notifications->expects($this->once())
287
-			->method('sendRemoteShare')
288
-			->with(
289
-				$this->equalTo('token'),
290
-				$this->equalTo('[email protected]'),
291
-				$this->equalTo('myFile'),
292
-				$this->anything(),
293
-				'shareOwner',
294
-				'shareOwner@http://localhost',
295
-				'sharedBy',
296
-				'sharedBy@http://localhost'
297
-			)->willThrowException(new \Exception('dummy'));
298
-
299
-		$this->rootFolder->method('getById')
300
-			->with('42')
301
-			->willReturn([$node]);
302
-
303
-		$this->contactsManager->expects($this->any())
304
-			->method('search')
305
-			->willReturn([]);
306
-
307
-		try {
308
-			$share = $this->provider->create($share);
309
-			$this->fail();
310
-		} catch (\Exception $e) {
311
-			$this->assertEquals('Sharing myFile failed, could not find [email protected], maybe the server is currently unreachable or uses a self-signed certificate.', $e->getMessage());
312
-		}
313
-
314
-		$qb = $this->connection->getQueryBuilder();
315
-		$stmt = $qb->select('*')
316
-			->from('share')
317
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
318
-			->executeQuery();
319
-
320
-		$data = $stmt->fetchAssociative();
321
-		$stmt->closeCursor();
322
-
323
-		$this->assertFalse($data);
324
-	}
325
-
326
-	public function testCreateShareWithSelf(): void {
327
-		$share = $this->shareManager->newShare();
328
-
329
-		$node = $this->createMock(File::class);
330
-		$node->method('getId')->willReturn(42);
331
-		$node->method('getName')->willReturn('myFile');
332
-
333
-		$this->addressHandler->expects($this->any())->method('compareAddresses')
334
-			->willReturn(true);
335
-
336
-		$shareWith = 'sharedBy@localhost';
337
-
338
-		$share->setSharedWith($shareWith)
339
-			->setSharedBy('sharedBy')
340
-			->setShareOwner('shareOwner')
341
-			->setPermissions(19)
342
-			->setNode($node);
343
-
344
-		$this->contactsManager->expects($this->any())
345
-			->method('search')
346
-			->willReturn([]);
347
-
348
-		$this->rootFolder->expects($this->never())->method($this->anything());
349
-
350
-		try {
351
-			$share = $this->provider->create($share);
352
-			$this->fail();
353
-		} catch (\Exception $e) {
354
-			$this->assertEquals('Not allowed to create a federated share to the same account', $e->getMessage());
355
-		}
356
-
357
-		$qb = $this->connection->getQueryBuilder();
358
-		$stmt = $qb->select('*')
359
-			->from('share')
360
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
361
-			->executeQuery();
362
-
363
-		$data = $stmt->fetchAssociative();
364
-		$stmt->closeCursor();
365
-
366
-		$this->assertFalse($data);
367
-	}
368
-
369
-	public function testCreateAlreadyShared(): void {
370
-		$share = $this->shareManager->newShare();
371
-
372
-		$node = $this->createMock(File::class);
373
-		$node->method('getId')->willReturn(42);
374
-		$node->method('getName')->willReturn('myFile');
375
-
376
-
377
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
378
-			->willReturn(['user', 'server.com']);
379
-
380
-		$share->setSharedWith('[email protected]')
381
-			->setSharedBy('sharedBy')
382
-			->setShareOwner('shareOwner')
383
-			->setPermissions(19)
384
-			->setShareType(IShare::TYPE_REMOTE)
385
-			->setNode($node);
386
-
387
-		$this->tokenHandler->method('generateToken')->willReturn('token');
388
-
389
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
390
-			->willReturn('http://localhost/');
391
-
392
-		$this->notifications->expects($this->once())
393
-			->method('sendRemoteShare')
394
-			->with(
395
-				$this->equalTo('token'),
396
-				$this->equalTo('[email protected]'),
397
-				$this->equalTo('myFile'),
398
-				$this->anything(),
399
-				'shareOwner',
400
-				'shareOwner@http://localhost',
401
-				'sharedBy',
402
-				'sharedBy@http://localhost'
403
-			)->willReturn(true);
404
-
405
-		$this->rootFolder->expects($this->never())->method($this->anything());
406
-
407
-		$this->contactsManager->expects($this->any())
408
-			->method('search')
409
-			->willReturn([]);
410
-
411
-		$this->provider->create($share);
412
-
413
-		try {
414
-			$this->provider->create($share);
415
-		} catch (\Exception $e) {
416
-			$this->assertEquals('Sharing myFile failed, because this item is already shared with the account [email protected]', $e->getMessage());
417
-		}
418
-	}
419
-
420
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestUpdate')]
421
-	public function testUpdate(string $owner, string $sharedBy, ?\DateTime $expirationDate): void {
422
-		$this->provider = $this->getMockBuilder(FederatedShareProvider::class)
423
-			->setConstructorArgs(
424
-				[
425
-					$this->connection,
426
-					$this->addressHandler,
427
-					$this->notifications,
428
-					$this->tokenHandler,
429
-					$this->l,
430
-					$this->rootFolder,
431
-					$this->config,
432
-					$this->userManager,
433
-					$this->cloudIdManager,
434
-					$this->gsConfig,
435
-					$this->cloudFederationProviderManager,
436
-					$this->logger,
437
-				]
438
-			)
439
-			->onlyMethods(['sendPermissionUpdate'])
440
-			->getMock();
441
-
442
-		$share = $this->shareManager->newShare();
443
-
444
-		$node = $this->createMock(File::class);
445
-		$node->method('getId')->willReturn(42);
446
-		$node->method('getName')->willReturn('myFile');
447
-
448
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
449
-			->willReturn(['user', 'server.com']);
450
-
451
-		$share->setSharedWith('[email protected]')
452
-			->setSharedBy($sharedBy)
453
-			->setShareOwner($owner)
454
-			->setPermissions(19)
455
-			->setShareType(IShare::TYPE_REMOTE)
456
-			->setExpirationDate(new \DateTime('2019-02-01T01:02:03'))
457
-			->setNode($node);
458
-
459
-		$this->tokenHandler->method('generateToken')->willReturn('token');
460
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
461
-			->willReturn('http://localhost/');
462
-
463
-		$this->notifications->expects($this->once())
464
-			->method('sendRemoteShare')
465
-			->with(
466
-				$this->equalTo('token'),
467
-				$this->equalTo('[email protected]'),
468
-				$this->equalTo('myFile'),
469
-				$this->anything(),
470
-				$owner,
471
-				$owner . '@http://localhost',
472
-				$sharedBy,
473
-				$sharedBy . '@http://localhost'
474
-			)->willReturn(true);
475
-
476
-		if ($owner === $sharedBy) {
477
-			$this->provider->expects($this->never())->method('sendPermissionUpdate');
478
-		} else {
479
-			$this->provider->expects($this->once())->method('sendPermissionUpdate');
480
-		}
481
-
482
-		$this->rootFolder->expects($this->never())->method($this->anything());
483
-
484
-		$this->contactsManager->expects($this->any())
485
-			->method('search')
486
-			->willReturn([]);
487
-
488
-		$share = $this->provider->create($share);
489
-
490
-		$share->setPermissions(1);
491
-		$share->setExpirationDate($expirationDate);
492
-		$this->provider->update($share);
493
-
494
-		$share = $this->provider->getShareById($share->getId());
495
-
496
-		$this->assertEquals(1, $share->getPermissions());
497
-		$this->assertEquals($expirationDate, $share->getExpirationDate());
498
-	}
499
-
500
-	public static function dataTestUpdate(): array {
501
-		return [
502
-			['sharedBy', 'shareOwner', new \DateTime('2020-03-01T01:02:03')],
503
-			['shareOwner', 'shareOwner', null],
504
-		];
505
-	}
506
-
507
-	public function testGetSharedBy(): void {
508
-		$node = $this->createMock(File::class);
509
-		$node->method('getId')->willReturn(42);
510
-		$node->method('getName')->willReturn('myFile');
511
-
512
-		$this->addressHandler->expects($this->never())->method('splitUserRemote');
513
-
514
-		$this->addressHandler->method('generateRemoteURL')
515
-			->willReturn('remoteurl.com');
516
-
517
-		$this->tokenHandler->method('generateToken')->willReturn('token');
518
-		$this->notifications
519
-			->method('sendRemoteShare')
520
-			->willReturn(true);
521
-
522
-		$this->rootFolder->expects($this->never())->method($this->anything());
523
-
524
-		$this->contactsManager->expects($this->any())
525
-			->method('search')
526
-			->willReturn([]);
527
-
528
-		$share = $this->shareManager->newShare();
529
-		$share->setSharedWith('[email protected]')
530
-			->setSharedBy('sharedBy')
531
-			->setShareOwner('shareOwner')
532
-			->setPermissions(19)
533
-			->setShareType(IShare::TYPE_REMOTE)
534
-			->setNode($node);
535
-		$this->provider->create($share);
536
-
537
-		$share2 = $this->shareManager->newShare();
538
-		$share2->setSharedWith('[email protected]')
539
-			->setSharedBy('sharedBy2')
540
-			->setShareOwner('shareOwner')
541
-			->setPermissions(19)
542
-			->setShareType(IShare::TYPE_REMOTE)
543
-			->setNode($node);
544
-		$this->provider->create($share2);
545
-
546
-		$shares = $this->provider->getSharesBy('sharedBy', IShare::TYPE_REMOTE, null, false, -1, 0);
547
-
548
-		$this->assertCount(1, $shares);
549
-		$this->assertEquals('[email protected]', $shares[0]->getSharedWith());
550
-		$this->assertEquals('sharedBy', $shares[0]->getSharedBy());
551
-	}
552
-
553
-	public function testGetSharedByWithNode(): void {
554
-		$node = $this->createMock(File::class);
555
-		$node->method('getId')->willReturn(42);
556
-		$node->method('getName')->willReturn('myFile');
557
-
558
-		$this->tokenHandler->method('generateToken')->willReturn('token');
559
-		$this->notifications
560
-			->method('sendRemoteShare')
561
-			->willReturn(true);
562
-
563
-		$this->rootFolder->expects($this->never())->method($this->anything());
564
-
565
-		$this->addressHandler->method('generateRemoteURL')
566
-			->willReturn('remoteurl.com');
567
-
568
-		$this->contactsManager->expects($this->any())
569
-			->method('search')
570
-			->willReturn([]);
571
-
572
-		$share = $this->shareManager->newShare();
573
-		$share->setSharedWith('[email protected]')
574
-			->setSharedBy('sharedBy')
575
-			->setShareOwner('shareOwner')
576
-			->setPermissions(19)
577
-			->setShareType(IShare::TYPE_REMOTE)
578
-			->setNode($node);
579
-		$this->provider->create($share);
580
-
581
-		$node2 = $this->getMockBuilder(File::class)->getMock();
582
-		$node2->method('getId')->willReturn(43);
583
-		$node2->method('getName')->willReturn('myOtherFile');
584
-
585
-		$share2 = $this->shareManager->newShare();
586
-		$share2->setSharedWith('[email protected]')
587
-			->setSharedBy('sharedBy')
588
-			->setShareOwner('shareOwner')
589
-			->setPermissions(19)
590
-			->setShareType(IShare::TYPE_REMOTE)
591
-			->setNode($node2);
592
-		$this->provider->create($share2);
593
-
594
-		$shares = $this->provider->getSharesBy('sharedBy', IShare::TYPE_REMOTE, $node2, false, -1, 0);
595
-
596
-		$this->assertCount(1, $shares);
597
-		$this->assertEquals(43, $shares[0]->getNodeId());
598
-	}
599
-
600
-	public function testGetSharedByWithReshares(): void {
601
-		$node = $this->createMock(File::class);
602
-		$node->method('getId')->willReturn(42);
603
-		$node->method('getName')->willReturn('myFile');
604
-
605
-		$this->tokenHandler->method('generateToken')->willReturn('token');
606
-		$this->notifications
607
-			->method('sendRemoteShare')
608
-			->willReturn(true);
609
-
610
-		$this->rootFolder->expects($this->never())->method($this->anything());
611
-
612
-		$this->addressHandler->method('generateRemoteURL')
613
-			->willReturn('remoteurl.com');
614
-
615
-		$this->contactsManager->expects($this->any())
616
-			->method('search')
617
-			->willReturn([]);
618
-
619
-		$share = $this->shareManager->newShare();
620
-		$share->setSharedWith('[email protected]')
621
-			->setSharedBy('shareOwner')
622
-			->setShareOwner('shareOwner')
623
-			->setPermissions(19)
624
-			->setShareType(IShare::TYPE_REMOTE)
625
-			->setNode($node);
626
-		$this->provider->create($share);
627
-
628
-		$share2 = $this->shareManager->newShare();
629
-		$share2->setSharedWith('[email protected]')
630
-			->setSharedBy('sharedBy')
631
-			->setShareOwner('shareOwner')
632
-			->setPermissions(19)
633
-			->setShareType(IShare::TYPE_REMOTE)
634
-			->setNode($node);
635
-		$this->provider->create($share2);
636
-
637
-		$shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_REMOTE, null, true, -1, 0);
638
-
639
-		$this->assertCount(2, $shares);
640
-	}
641
-
642
-	public function testGetSharedByWithLimit(): void {
643
-		$node = $this->createMock(File::class);
644
-		$node->method('getId')->willReturn(42);
645
-		$node->method('getName')->willReturn('myFile');
646
-
647
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
648
-			->willReturnCallback(function ($uid) {
649
-				if ($uid === '[email protected]') {
650
-					return ['user', 'server.com'];
651
-				}
652
-				return ['user2', 'server.com'];
653
-			});
654
-
655
-		$this->tokenHandler->method('generateToken')->willReturn('token');
656
-		$this->notifications
657
-			->method('sendRemoteShare')
658
-			->willReturn(true);
659
-
660
-		$this->rootFolder->expects($this->never())->method($this->anything());
661
-
662
-		$this->addressHandler->method('generateRemoteURL')
663
-			->willReturn('remoteurl.com');
664
-
665
-		$this->contactsManager->expects($this->any())
666
-			->method('search')
667
-			->willReturn([]);
668
-
669
-		$share = $this->shareManager->newShare();
670
-		$share->setSharedWith('[email protected]')
671
-			->setSharedBy('sharedBy')
672
-			->setShareOwner('shareOwner')
673
-			->setPermissions(19)
674
-			->setShareType(IShare::TYPE_REMOTE)
675
-			->setNode($node);
676
-		$this->provider->create($share);
677
-
678
-		$share2 = $this->shareManager->newShare();
679
-		$share2->setSharedWith('[email protected]')
680
-			->setSharedBy('sharedBy')
681
-			->setShareOwner('shareOwner')
682
-			->setPermissions(19)
683
-			->setShareType(IShare::TYPE_REMOTE)
684
-			->setNode($node);
685
-		$this->provider->create($share2);
686
-
687
-		$shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_REMOTE, null, true, 1, 1);
688
-
689
-		$this->assertCount(1, $shares);
690
-		$this->assertEquals('[email protected]', $shares[0]->getSharedWith());
691
-	}
692
-
693
-	public static function dataDeleteUser(): array {
694
-		return [
695
-			['a', 'b', 'c', 'a', true],
696
-			['a', 'b', 'c', 'b', false],
697
-			// The recipient is non local.
698
-			['a', 'b', 'c', 'c', false],
699
-			['a', 'b', 'c', 'd', false],
700
-		];
701
-	}
702
-
703
-	/**
704
-	 *
705
-	 * @param string $owner The owner of the share (uid)
706
-	 * @param string $initiator The initiator of the share (uid)
707
-	 * @param string $recipient The recipient of the share (uid/gid/pass)
708
-	 * @param string $deletedUser The user that is deleted
709
-	 * @param bool $rowDeleted Is the row deleted in this setup
710
-	 */
711
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataDeleteUser')]
712
-	public function testDeleteUser(string $owner, string $initiator, string $recipient, string $deletedUser, bool $rowDeleted): void {
713
-		$qb = $this->connection->getQueryBuilder();
714
-		$qb->insert('share')
715
-			->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
716
-			->setValue('uid_owner', $qb->createNamedParameter($owner))
717
-			->setValue('uid_initiator', $qb->createNamedParameter($initiator))
718
-			->setValue('share_with', $qb->createNamedParameter($recipient))
719
-			->setValue('item_type', $qb->createNamedParameter('file'))
720
-			->setValue('item_source', $qb->createNamedParameter(42))
721
-			->setValue('file_source', $qb->createNamedParameter(42))
722
-			->executeStatement();
723
-
724
-		$id = $qb->getLastInsertId();
725
-
726
-		$this->provider->userDeleted($deletedUser, IShare::TYPE_REMOTE);
727
-
728
-		$qb = $this->connection->getQueryBuilder();
729
-		$qb->select('*')
730
-			->from('share')
731
-			->where(
732
-				$qb->expr()->eq('id', $qb->createNamedParameter($id))
733
-			);
734
-		$cursor = $qb->executeQuery();
735
-		$data = $cursor->fetchAllAssociative();
736
-		$cursor->closeCursor();
737
-
738
-		$this->assertCount($rowDeleted ? 0 : 1, $data);
739
-	}
740
-
741
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsOutgoingServer2serverShareEnabled')]
742
-	public function testIsOutgoingServer2serverShareEnabled(bool $internalOnly, string $isEnabled, bool $expected): void {
743
-		$this->gsConfig->expects($this->once())->method('onlyInternalFederation')
744
-			->willReturn($internalOnly);
745
-		$this->config->expects($this->any())->method('getAppValue')
746
-			->with('files_sharing', 'outgoing_server2server_share_enabled', 'yes')
747
-			->willReturn($isEnabled);
748
-
749
-		$this->assertSame($expected,
750
-			$this->provider->isOutgoingServer2serverShareEnabled()
751
-		);
752
-	}
753
-
754
-	public static function dataTestIsOutgoingServer2serverShareEnabled(): array {
755
-		return [
756
-			[false, 'yes', true],
757
-			[false, 'no', false],
758
-			[true, 'yes', false],
759
-			[true, 'no', false],
760
-		];
761
-	}
762
-
763
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsIncomingServer2serverShareEnabled')]
764
-	public function testIsIncomingServer2serverShareEnabled(bool $onlyInternal, string $isEnabled, bool $expected): void {
765
-		$this->gsConfig->expects($this->once())->method('onlyInternalFederation')
766
-			->willReturn($onlyInternal);
767
-		$this->config->expects($this->any())->method('getAppValue')
768
-			->with('files_sharing', 'incoming_server2server_share_enabled', 'yes')
769
-			->willReturn($isEnabled);
770
-
771
-		$this->assertSame($expected,
772
-			$this->provider->isIncomingServer2serverShareEnabled()
773
-		);
774
-	}
775
-
776
-	public static function dataTestIsIncomingServer2serverShareEnabled(): array {
777
-		return [
778
-			[false, 'yes', true],
779
-			[false, 'no', false],
780
-			[true, 'yes', false],
781
-			[true, 'no', false],
782
-		];
783
-	}
784
-
785
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsLookupServerQueriesEnabled')]
786
-	public function testIsLookupServerQueriesEnabled(bool $gsEnabled, string $isEnabled, bool $expected): void {
787
-		$this->gsConfig->expects($this->once())->method('isGlobalScaleEnabled')
788
-			->willReturn($gsEnabled);
789
-		$this->config->expects($this->any())->method('getAppValue')
790
-			->with('files_sharing', 'lookupServerEnabled', 'no')
791
-			->willReturn($isEnabled);
792
-
793
-		$this->assertSame($expected,
794
-			$this->provider->isLookupServerQueriesEnabled()
795
-		);
796
-	}
797
-
798
-
799
-	public static function dataTestIsLookupServerQueriesEnabled(): array {
800
-		return [
801
-			[true, 'yes', true],
802
-			[true, 'no', true],
803
-			// TODO: reenable if we use the lookup server for non-global scale
804
-			// [false, 'yes', true],
805
-			// [false, 'no', false],
806
-			[false, 'no', false],
807
-			[false, 'yes', false],
808
-		];
809
-	}
810
-
811
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsLookupServerUploadEnabled')]
812
-	public function testIsLookupServerUploadEnabled(bool $gsEnabled, string $isEnabled, bool $expected): void {
813
-		$this->gsConfig->expects($this->once())->method('isGlobalScaleEnabled')
814
-			->willReturn($gsEnabled);
815
-		$this->config->expects($this->any())->method('getAppValue')
816
-			->with('files_sharing', 'lookupServerUploadEnabled', 'no')
817
-			->willReturn($isEnabled);
818
-
819
-		$this->assertSame($expected,
820
-			$this->provider->isLookupServerUploadEnabled()
821
-		);
822
-	}
823
-
824
-	public static function dataTestIsLookupServerUploadEnabled(): array {
825
-		return [
826
-			[true, 'yes', false],
827
-			[true, 'no', false],
828
-			// TODO: reenable if we use the lookup server again
829
-			// [false, 'yes', true],
830
-			// [false, 'no', false],
831
-			[false, 'yes', false],
832
-			[false, 'no', false],
833
-		];
834
-	}
835
-
836
-	public function testGetSharesInFolder(): void {
837
-		$userManager = Server::get(IUserManager::class);
838
-		$rootFolder = Server::get(IRootFolder::class);
839
-
840
-		$u1 = $userManager->createUser('testFed', md5((string)time()));
841
-		$u2 = $userManager->createUser('testFed2', md5((string)time()));
842
-
843
-		$folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
844
-		$file1 = $folder1->newFile('bar1');
845
-		$file2 = $folder1->newFile('bar2');
846
-
847
-		$this->tokenHandler->method('generateToken')->willReturn('token');
848
-		$this->notifications
849
-			->method('sendRemoteShare')
850
-			->willReturn(true);
851
-
852
-		$this->addressHandler->method('generateRemoteURL')
853
-			->willReturn('remoteurl.com');
854
-
855
-		$this->contactsManager->expects($this->any())
856
-			->method('search')
857
-			->willReturn([]);
858
-
859
-		$share1 = $this->shareManager->newShare();
860
-		$share1->setSharedWith('[email protected]')
861
-			->setSharedBy($u1->getUID())
862
-			->setShareOwner($u1->getUID())
863
-			->setPermissions(Constants::PERMISSION_READ)
864
-			->setShareType(IShare::TYPE_REMOTE)
865
-			->setNode($file1);
866
-		$this->provider->create($share1);
867
-
868
-		$share2 = $this->shareManager->newShare();
869
-		$share2->setSharedWith('[email protected]')
870
-			->setSharedBy($u2->getUID())
871
-			->setShareOwner($u1->getUID())
872
-			->setPermissions(Constants::PERMISSION_READ)
873
-			->setShareType(IShare::TYPE_REMOTE)
874
-			->setNode($file2);
875
-		$this->provider->create($share2);
876
-
877
-		$result = $this->provider->getSharesInFolder($u1->getUID(), $folder1, false);
878
-		$this->assertCount(1, $result);
879
-		$this->assertCount(1, $result[$file1->getId()]);
880
-
881
-		$result = $this->provider->getSharesInFolder($u1->getUID(), $folder1, true);
882
-		$this->assertCount(2, $result);
883
-		$this->assertCount(1, $result[$file1->getId()]);
884
-		$this->assertCount(1, $result[$file2->getId()]);
885
-
886
-		$u1->delete();
887
-		$u2->delete();
888
-	}
889
-
890
-	public function testGetAccessList(): void {
891
-		$userManager = Server::get(IUserManager::class);
892
-		$rootFolder = Server::get(IRootFolder::class);
893
-
894
-		$u1 = $userManager->createUser('testFed', md5((string)time()));
895
-
896
-		$folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
897
-		$file1 = $folder1->newFile('bar1');
898
-
899
-		$this->tokenHandler->expects($this->exactly(2))
900
-			->method('generateToken')
901
-			->willReturnOnConsecutiveCalls('token1', 'token2');
902
-		$this->notifications->expects($this->atLeastOnce())
903
-			->method('sendRemoteShare')
904
-			->willReturn(true);
905
-
906
-		$this->contactsManager->expects($this->any())
907
-			->method('search')
908
-			->willReturn([]);
909
-
910
-		$result = $this->provider->getAccessList([$file1], true);
911
-		$this->assertEquals(['remote' => []], $result);
912
-
913
-		$result = $this->provider->getAccessList([$file1], false);
914
-		$this->assertEquals(['remote' => false], $result);
915
-
916
-		$this->addressHandler->method('generateRemoteURL')
917
-			->willReturn('remoteurl.com');
918
-
919
-		$share1 = $this->shareManager->newShare();
920
-		$share1->setSharedWith('[email protected]')
921
-			->setSharedBy($u1->getUID())
922
-			->setShareOwner($u1->getUID())
923
-			->setPermissions(Constants::PERMISSION_READ)
924
-			->setShareType(IShare::TYPE_REMOTE)
925
-			->setNode($file1);
926
-		$this->provider->create($share1);
927
-
928
-		$share2 = $this->shareManager->newShare();
929
-		$share2->setSharedWith('foobar@localhost')
930
-			->setSharedBy($u1->getUID())
931
-			->setShareOwner($u1->getUID())
932
-			->setPermissions(Constants::PERMISSION_READ)
933
-			->setShareType(IShare::TYPE_REMOTE)
934
-			->setNode($file1);
935
-		$this->provider->create($share2);
936
-
937
-		$result = $this->provider->getAccessList([$file1], true);
938
-		$this->assertEquals(['remote' => [
939
-			'[email protected]' => [
940
-				'token' => 'token1',
941
-				'node_id' => $file1->getId(),
942
-			],
943
-			'foobar@localhost' => [
944
-				'token' => 'token2',
945
-				'node_id' => $file1->getId(),
946
-			],
947
-		]], $result);
948
-
949
-		$result = $this->provider->getAccessList([$file1], false);
950
-		$this->assertEquals(['remote' => true], $result);
951
-
952
-		$u1->delete();
953
-	}
42
+    protected IDBConnection $connection;
43
+    protected AddressHandler&MockObject $addressHandler;
44
+    protected Notifications&MockObject $notifications;
45
+    protected TokenHandler&MockObject $tokenHandler;
46
+    protected IL10N $l;
47
+    protected LoggerInterface $logger;
48
+    protected IRootFolder&MockObject $rootFolder;
49
+    protected IConfig&MockObject $config;
50
+    protected IUserManager&MockObject $userManager;
51
+    protected \OCP\GlobalScale\IConfig&MockObject $gsConfig;
52
+    protected IManager $shareManager;
53
+    protected FederatedShareProvider $provider;
54
+    protected IContactsManager&MockObject $contactsManager;
55
+    private ICloudIdManager $cloudIdManager;
56
+    private ICloudFederationProviderManager&MockObject $cloudFederationProviderManager;
57
+
58
+    protected function setUp(): void {
59
+        parent::setUp();
60
+
61
+        $this->connection = Server::get(IDBConnection::class);
62
+        $this->notifications = $this->createMock(Notifications::class);
63
+        $this->tokenHandler = $this->createMock(TokenHandler::class);
64
+        $this->l = $this->createMock(IL10N::class);
65
+        $this->l->method('t')
66
+            ->willReturnCallback(function ($text, $parameters = []) {
67
+                return vsprintf($text, $parameters);
68
+            });
69
+        $this->logger = $this->createMock(LoggerInterface::class);
70
+        $this->rootFolder = $this->createMock(IRootFolder::class);
71
+        $this->config = $this->createMock(IConfig::class);
72
+        $this->userManager = $this->createMock(IUserManager::class);
73
+        //$this->addressHandler = new AddressHandler(\OC::$server->getURLGenerator(), $this->l);
74
+        $this->addressHandler = $this->createMock(AddressHandler::class);
75
+        $this->contactsManager = $this->createMock(IContactsManager::class);
76
+        $this->cloudIdManager = new CloudIdManager(
77
+            $this->createMock(ICacheFactory::class),
78
+            $this->createMock(IEventDispatcher::class),
79
+            $this->contactsManager,
80
+            $this->createMock(IURLGenerator::class),
81
+            $this->userManager,
82
+        );
83
+        $this->gsConfig = $this->createMock(\OCP\GlobalScale\IConfig::class);
84
+
85
+        $this->userManager->expects($this->any())->method('userExists')->willReturn(true);
86
+
87
+        $this->cloudFederationProviderManager = $this->createMock(ICloudFederationProviderManager::class);
88
+
89
+        $this->provider = new FederatedShareProvider(
90
+            $this->connection,
91
+            $this->addressHandler,
92
+            $this->notifications,
93
+            $this->tokenHandler,
94
+            $this->l,
95
+            $this->rootFolder,
96
+            $this->config,
97
+            $this->userManager,
98
+            $this->cloudIdManager,
99
+            $this->gsConfig,
100
+            $this->cloudFederationProviderManager,
101
+            $this->logger,
102
+        );
103
+
104
+        $this->shareManager = Server::get(IManager::class);
105
+    }
106
+
107
+    protected function tearDown(): void {
108
+        $this->connection->getQueryBuilder()->delete('share')->executeStatement();
109
+
110
+        parent::tearDown();
111
+    }
112
+
113
+    public static function dataTestCreate(): array {
114
+        return [
115
+            [null, null],
116
+            [new \DateTime('2020-03-01T01:02:03'), '2020-03-01 01:02:03'],
117
+        ];
118
+    }
119
+
120
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestCreate')]
121
+    public function testCreate(?\DateTime $expirationDate, ?string $expectedDataDate): void {
122
+        $share = $this->shareManager->newShare();
123
+
124
+        /** @var File&MockObject $node */
125
+        $node = $this->createMock(File::class);
126
+        $node->method('getId')->willReturn(42);
127
+        $node->method('getName')->willReturn('myFile');
128
+
129
+        $share->setSharedWith('[email protected]')
130
+            ->setSharedBy('sharedBy')
131
+            ->setShareOwner('shareOwner')
132
+            ->setPermissions(19)
133
+            ->setShareType(IShare::TYPE_REMOTE)
134
+            ->setExpirationDate($expirationDate)
135
+            ->setNode($node);
136
+
137
+        $this->tokenHandler->method('generateToken')->willReturn('token');
138
+
139
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
140
+            ->willReturn('http://localhost/');
141
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
142
+            ->willReturn(['user', 'server.com']);
143
+
144
+        $this->notifications->expects($this->once())
145
+            ->method('sendRemoteShare')
146
+            ->with(
147
+                $this->equalTo('token'),
148
+                $this->equalTo('[email protected]'),
149
+                $this->equalTo('myFile'),
150
+                $this->anything(),
151
+                'shareOwner',
152
+                'shareOwner@http://localhost',
153
+                'sharedBy',
154
+                'sharedBy@http://localhost'
155
+            )
156
+            ->willReturn(true);
157
+
158
+        $this->rootFolder->expects($this->never())->method($this->anything());
159
+
160
+        $this->contactsManager->expects($this->any())
161
+            ->method('search')
162
+            ->willReturn([]);
163
+
164
+        $share = $this->provider->create($share);
165
+
166
+        $qb = $this->connection->getQueryBuilder();
167
+        $stmt = $qb->select('*')
168
+            ->from('share')
169
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
170
+            ->executeQuery();
171
+
172
+        $data = $stmt->fetchAssociative();
173
+        $stmt->closeCursor();
174
+
175
+        $expected = [
176
+            'share_type' => IShare::TYPE_REMOTE,
177
+            'share_with' => '[email protected]',
178
+            'uid_owner' => 'shareOwner',
179
+            'uid_initiator' => 'sharedBy',
180
+            'item_type' => 'file',
181
+            'item_source' => 42,
182
+            'file_source' => 42,
183
+            'permissions' => 19,
184
+            'accepted' => 0,
185
+            'token' => 'token',
186
+            'expiration' => $expectedDataDate,
187
+        ];
188
+        foreach (array_keys($expected) as $key) {
189
+            $this->assertEquals($expected[$key], $data[$key], "Assert that value for key '$key' is the same");
190
+        }
191
+
192
+        $this->assertEquals($data['id'], $share->getId());
193
+        $this->assertEquals(IShare::TYPE_REMOTE, $share->getShareType());
194
+        $this->assertEquals('[email protected]', $share->getSharedWith());
195
+        $this->assertEquals('sharedBy', $share->getSharedBy());
196
+        $this->assertEquals('shareOwner', $share->getShareOwner());
197
+        $this->assertEquals('file', $share->getNodeType());
198
+        $this->assertEquals(42, $share->getNodeId());
199
+        $this->assertEquals(19, $share->getPermissions());
200
+        $this->assertEquals('token', $share->getToken());
201
+        $this->assertEquals($expirationDate, $share->getExpirationDate());
202
+    }
203
+
204
+    public function testCreateCouldNotFindServer(): void {
205
+        $share = $this->shareManager->newShare();
206
+
207
+        $node = $this->createMock(File::class);
208
+        $node->method('getId')->willReturn(42);
209
+        $node->method('getName')->willReturn('myFile');
210
+
211
+        $share->setSharedWith('[email protected]')
212
+            ->setSharedBy('sharedBy')
213
+            ->setShareOwner('shareOwner')
214
+            ->setPermissions(19)
215
+            ->setShareType(IShare::TYPE_REMOTE)
216
+            ->setNode($node);
217
+
218
+        $this->tokenHandler->method('generateToken')->willReturn('token');
219
+
220
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
221
+            ->willReturn('http://localhost/');
222
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
223
+            ->willReturn(['user', 'server.com']);
224
+
225
+        $this->notifications->expects($this->once())
226
+            ->method('sendRemoteShare')
227
+            ->with(
228
+                $this->equalTo('token'),
229
+                $this->equalTo('[email protected]'),
230
+                $this->equalTo('myFile'),
231
+                $this->anything(),
232
+                'shareOwner',
233
+                'shareOwner@http://localhost',
234
+                'sharedBy',
235
+                'sharedBy@http://localhost'
236
+            )->willReturn(false);
237
+
238
+        $this->rootFolder->method('getById')
239
+            ->with('42')
240
+            ->willReturn([$node]);
241
+
242
+        $this->contactsManager->expects($this->any())
243
+            ->method('search')
244
+            ->willReturn([]);
245
+
246
+        try {
247
+            $share = $this->provider->create($share);
248
+            $this->fail();
249
+        } catch (\Exception $e) {
250
+            $this->assertEquals('Sharing myFile failed, could not find [email protected], maybe the server is currently unreachable or uses a self-signed certificate.', $e->getMessage());
251
+        }
252
+
253
+        $qb = $this->connection->getQueryBuilder();
254
+        $stmt = $qb->select('*')
255
+            ->from('share')
256
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
257
+            ->executeQuery();
258
+
259
+        $data = $stmt->fetchAssociative();
260
+        $stmt->closeCursor();
261
+
262
+        $this->assertFalse($data);
263
+    }
264
+
265
+    public function testCreateException(): void {
266
+        $share = $this->shareManager->newShare();
267
+
268
+        $node = $this->createMock(File::class);
269
+        $node->method('getId')->willReturn(42);
270
+        $node->method('getName')->willReturn('myFile');
271
+
272
+        $share->setSharedWith('[email protected]')
273
+            ->setSharedBy('sharedBy')
274
+            ->setShareOwner('shareOwner')
275
+            ->setPermissions(19)
276
+            ->setShareType(IShare::TYPE_REMOTE)
277
+            ->setNode($node);
278
+
279
+        $this->tokenHandler->method('generateToken')->willReturn('token');
280
+
281
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
282
+            ->willReturn('http://localhost/');
283
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
284
+            ->willReturn(['user', 'server.com']);
285
+
286
+        $this->notifications->expects($this->once())
287
+            ->method('sendRemoteShare')
288
+            ->with(
289
+                $this->equalTo('token'),
290
+                $this->equalTo('[email protected]'),
291
+                $this->equalTo('myFile'),
292
+                $this->anything(),
293
+                'shareOwner',
294
+                'shareOwner@http://localhost',
295
+                'sharedBy',
296
+                'sharedBy@http://localhost'
297
+            )->willThrowException(new \Exception('dummy'));
298
+
299
+        $this->rootFolder->method('getById')
300
+            ->with('42')
301
+            ->willReturn([$node]);
302
+
303
+        $this->contactsManager->expects($this->any())
304
+            ->method('search')
305
+            ->willReturn([]);
306
+
307
+        try {
308
+            $share = $this->provider->create($share);
309
+            $this->fail();
310
+        } catch (\Exception $e) {
311
+            $this->assertEquals('Sharing myFile failed, could not find [email protected], maybe the server is currently unreachable or uses a self-signed certificate.', $e->getMessage());
312
+        }
313
+
314
+        $qb = $this->connection->getQueryBuilder();
315
+        $stmt = $qb->select('*')
316
+            ->from('share')
317
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
318
+            ->executeQuery();
319
+
320
+        $data = $stmt->fetchAssociative();
321
+        $stmt->closeCursor();
322
+
323
+        $this->assertFalse($data);
324
+    }
325
+
326
+    public function testCreateShareWithSelf(): void {
327
+        $share = $this->shareManager->newShare();
328
+
329
+        $node = $this->createMock(File::class);
330
+        $node->method('getId')->willReturn(42);
331
+        $node->method('getName')->willReturn('myFile');
332
+
333
+        $this->addressHandler->expects($this->any())->method('compareAddresses')
334
+            ->willReturn(true);
335
+
336
+        $shareWith = 'sharedBy@localhost';
337
+
338
+        $share->setSharedWith($shareWith)
339
+            ->setSharedBy('sharedBy')
340
+            ->setShareOwner('shareOwner')
341
+            ->setPermissions(19)
342
+            ->setNode($node);
343
+
344
+        $this->contactsManager->expects($this->any())
345
+            ->method('search')
346
+            ->willReturn([]);
347
+
348
+        $this->rootFolder->expects($this->never())->method($this->anything());
349
+
350
+        try {
351
+            $share = $this->provider->create($share);
352
+            $this->fail();
353
+        } catch (\Exception $e) {
354
+            $this->assertEquals('Not allowed to create a federated share to the same account', $e->getMessage());
355
+        }
356
+
357
+        $qb = $this->connection->getQueryBuilder();
358
+        $stmt = $qb->select('*')
359
+            ->from('share')
360
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
361
+            ->executeQuery();
362
+
363
+        $data = $stmt->fetchAssociative();
364
+        $stmt->closeCursor();
365
+
366
+        $this->assertFalse($data);
367
+    }
368
+
369
+    public function testCreateAlreadyShared(): void {
370
+        $share = $this->shareManager->newShare();
371
+
372
+        $node = $this->createMock(File::class);
373
+        $node->method('getId')->willReturn(42);
374
+        $node->method('getName')->willReturn('myFile');
375
+
376
+
377
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
378
+            ->willReturn(['user', 'server.com']);
379
+
380
+        $share->setSharedWith('[email protected]')
381
+            ->setSharedBy('sharedBy')
382
+            ->setShareOwner('shareOwner')
383
+            ->setPermissions(19)
384
+            ->setShareType(IShare::TYPE_REMOTE)
385
+            ->setNode($node);
386
+
387
+        $this->tokenHandler->method('generateToken')->willReturn('token');
388
+
389
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
390
+            ->willReturn('http://localhost/');
391
+
392
+        $this->notifications->expects($this->once())
393
+            ->method('sendRemoteShare')
394
+            ->with(
395
+                $this->equalTo('token'),
396
+                $this->equalTo('[email protected]'),
397
+                $this->equalTo('myFile'),
398
+                $this->anything(),
399
+                'shareOwner',
400
+                'shareOwner@http://localhost',
401
+                'sharedBy',
402
+                'sharedBy@http://localhost'
403
+            )->willReturn(true);
404
+
405
+        $this->rootFolder->expects($this->never())->method($this->anything());
406
+
407
+        $this->contactsManager->expects($this->any())
408
+            ->method('search')
409
+            ->willReturn([]);
410
+
411
+        $this->provider->create($share);
412
+
413
+        try {
414
+            $this->provider->create($share);
415
+        } catch (\Exception $e) {
416
+            $this->assertEquals('Sharing myFile failed, because this item is already shared with the account [email protected]', $e->getMessage());
417
+        }
418
+    }
419
+
420
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestUpdate')]
421
+    public function testUpdate(string $owner, string $sharedBy, ?\DateTime $expirationDate): void {
422
+        $this->provider = $this->getMockBuilder(FederatedShareProvider::class)
423
+            ->setConstructorArgs(
424
+                [
425
+                    $this->connection,
426
+                    $this->addressHandler,
427
+                    $this->notifications,
428
+                    $this->tokenHandler,
429
+                    $this->l,
430
+                    $this->rootFolder,
431
+                    $this->config,
432
+                    $this->userManager,
433
+                    $this->cloudIdManager,
434
+                    $this->gsConfig,
435
+                    $this->cloudFederationProviderManager,
436
+                    $this->logger,
437
+                ]
438
+            )
439
+            ->onlyMethods(['sendPermissionUpdate'])
440
+            ->getMock();
441
+
442
+        $share = $this->shareManager->newShare();
443
+
444
+        $node = $this->createMock(File::class);
445
+        $node->method('getId')->willReturn(42);
446
+        $node->method('getName')->willReturn('myFile');
447
+
448
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
449
+            ->willReturn(['user', 'server.com']);
450
+
451
+        $share->setSharedWith('[email protected]')
452
+            ->setSharedBy($sharedBy)
453
+            ->setShareOwner($owner)
454
+            ->setPermissions(19)
455
+            ->setShareType(IShare::TYPE_REMOTE)
456
+            ->setExpirationDate(new \DateTime('2019-02-01T01:02:03'))
457
+            ->setNode($node);
458
+
459
+        $this->tokenHandler->method('generateToken')->willReturn('token');
460
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
461
+            ->willReturn('http://localhost/');
462
+
463
+        $this->notifications->expects($this->once())
464
+            ->method('sendRemoteShare')
465
+            ->with(
466
+                $this->equalTo('token'),
467
+                $this->equalTo('[email protected]'),
468
+                $this->equalTo('myFile'),
469
+                $this->anything(),
470
+                $owner,
471
+                $owner . '@http://localhost',
472
+                $sharedBy,
473
+                $sharedBy . '@http://localhost'
474
+            )->willReturn(true);
475
+
476
+        if ($owner === $sharedBy) {
477
+            $this->provider->expects($this->never())->method('sendPermissionUpdate');
478
+        } else {
479
+            $this->provider->expects($this->once())->method('sendPermissionUpdate');
480
+        }
481
+
482
+        $this->rootFolder->expects($this->never())->method($this->anything());
483
+
484
+        $this->contactsManager->expects($this->any())
485
+            ->method('search')
486
+            ->willReturn([]);
487
+
488
+        $share = $this->provider->create($share);
489
+
490
+        $share->setPermissions(1);
491
+        $share->setExpirationDate($expirationDate);
492
+        $this->provider->update($share);
493
+
494
+        $share = $this->provider->getShareById($share->getId());
495
+
496
+        $this->assertEquals(1, $share->getPermissions());
497
+        $this->assertEquals($expirationDate, $share->getExpirationDate());
498
+    }
499
+
500
+    public static function dataTestUpdate(): array {
501
+        return [
502
+            ['sharedBy', 'shareOwner', new \DateTime('2020-03-01T01:02:03')],
503
+            ['shareOwner', 'shareOwner', null],
504
+        ];
505
+    }
506
+
507
+    public function testGetSharedBy(): void {
508
+        $node = $this->createMock(File::class);
509
+        $node->method('getId')->willReturn(42);
510
+        $node->method('getName')->willReturn('myFile');
511
+
512
+        $this->addressHandler->expects($this->never())->method('splitUserRemote');
513
+
514
+        $this->addressHandler->method('generateRemoteURL')
515
+            ->willReturn('remoteurl.com');
516
+
517
+        $this->tokenHandler->method('generateToken')->willReturn('token');
518
+        $this->notifications
519
+            ->method('sendRemoteShare')
520
+            ->willReturn(true);
521
+
522
+        $this->rootFolder->expects($this->never())->method($this->anything());
523
+
524
+        $this->contactsManager->expects($this->any())
525
+            ->method('search')
526
+            ->willReturn([]);
527
+
528
+        $share = $this->shareManager->newShare();
529
+        $share->setSharedWith('[email protected]')
530
+            ->setSharedBy('sharedBy')
531
+            ->setShareOwner('shareOwner')
532
+            ->setPermissions(19)
533
+            ->setShareType(IShare::TYPE_REMOTE)
534
+            ->setNode($node);
535
+        $this->provider->create($share);
536
+
537
+        $share2 = $this->shareManager->newShare();
538
+        $share2->setSharedWith('[email protected]')
539
+            ->setSharedBy('sharedBy2')
540
+            ->setShareOwner('shareOwner')
541
+            ->setPermissions(19)
542
+            ->setShareType(IShare::TYPE_REMOTE)
543
+            ->setNode($node);
544
+        $this->provider->create($share2);
545
+
546
+        $shares = $this->provider->getSharesBy('sharedBy', IShare::TYPE_REMOTE, null, false, -1, 0);
547
+
548
+        $this->assertCount(1, $shares);
549
+        $this->assertEquals('[email protected]', $shares[0]->getSharedWith());
550
+        $this->assertEquals('sharedBy', $shares[0]->getSharedBy());
551
+    }
552
+
553
+    public function testGetSharedByWithNode(): void {
554
+        $node = $this->createMock(File::class);
555
+        $node->method('getId')->willReturn(42);
556
+        $node->method('getName')->willReturn('myFile');
557
+
558
+        $this->tokenHandler->method('generateToken')->willReturn('token');
559
+        $this->notifications
560
+            ->method('sendRemoteShare')
561
+            ->willReturn(true);
562
+
563
+        $this->rootFolder->expects($this->never())->method($this->anything());
564
+
565
+        $this->addressHandler->method('generateRemoteURL')
566
+            ->willReturn('remoteurl.com');
567
+
568
+        $this->contactsManager->expects($this->any())
569
+            ->method('search')
570
+            ->willReturn([]);
571
+
572
+        $share = $this->shareManager->newShare();
573
+        $share->setSharedWith('[email protected]')
574
+            ->setSharedBy('sharedBy')
575
+            ->setShareOwner('shareOwner')
576
+            ->setPermissions(19)
577
+            ->setShareType(IShare::TYPE_REMOTE)
578
+            ->setNode($node);
579
+        $this->provider->create($share);
580
+
581
+        $node2 = $this->getMockBuilder(File::class)->getMock();
582
+        $node2->method('getId')->willReturn(43);
583
+        $node2->method('getName')->willReturn('myOtherFile');
584
+
585
+        $share2 = $this->shareManager->newShare();
586
+        $share2->setSharedWith('[email protected]')
587
+            ->setSharedBy('sharedBy')
588
+            ->setShareOwner('shareOwner')
589
+            ->setPermissions(19)
590
+            ->setShareType(IShare::TYPE_REMOTE)
591
+            ->setNode($node2);
592
+        $this->provider->create($share2);
593
+
594
+        $shares = $this->provider->getSharesBy('sharedBy', IShare::TYPE_REMOTE, $node2, false, -1, 0);
595
+
596
+        $this->assertCount(1, $shares);
597
+        $this->assertEquals(43, $shares[0]->getNodeId());
598
+    }
599
+
600
+    public function testGetSharedByWithReshares(): void {
601
+        $node = $this->createMock(File::class);
602
+        $node->method('getId')->willReturn(42);
603
+        $node->method('getName')->willReturn('myFile');
604
+
605
+        $this->tokenHandler->method('generateToken')->willReturn('token');
606
+        $this->notifications
607
+            ->method('sendRemoteShare')
608
+            ->willReturn(true);
609
+
610
+        $this->rootFolder->expects($this->never())->method($this->anything());
611
+
612
+        $this->addressHandler->method('generateRemoteURL')
613
+            ->willReturn('remoteurl.com');
614
+
615
+        $this->contactsManager->expects($this->any())
616
+            ->method('search')
617
+            ->willReturn([]);
618
+
619
+        $share = $this->shareManager->newShare();
620
+        $share->setSharedWith('[email protected]')
621
+            ->setSharedBy('shareOwner')
622
+            ->setShareOwner('shareOwner')
623
+            ->setPermissions(19)
624
+            ->setShareType(IShare::TYPE_REMOTE)
625
+            ->setNode($node);
626
+        $this->provider->create($share);
627
+
628
+        $share2 = $this->shareManager->newShare();
629
+        $share2->setSharedWith('[email protected]')
630
+            ->setSharedBy('sharedBy')
631
+            ->setShareOwner('shareOwner')
632
+            ->setPermissions(19)
633
+            ->setShareType(IShare::TYPE_REMOTE)
634
+            ->setNode($node);
635
+        $this->provider->create($share2);
636
+
637
+        $shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_REMOTE, null, true, -1, 0);
638
+
639
+        $this->assertCount(2, $shares);
640
+    }
641
+
642
+    public function testGetSharedByWithLimit(): void {
643
+        $node = $this->createMock(File::class);
644
+        $node->method('getId')->willReturn(42);
645
+        $node->method('getName')->willReturn('myFile');
646
+
647
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
648
+            ->willReturnCallback(function ($uid) {
649
+                if ($uid === '[email protected]') {
650
+                    return ['user', 'server.com'];
651
+                }
652
+                return ['user2', 'server.com'];
653
+            });
654
+
655
+        $this->tokenHandler->method('generateToken')->willReturn('token');
656
+        $this->notifications
657
+            ->method('sendRemoteShare')
658
+            ->willReturn(true);
659
+
660
+        $this->rootFolder->expects($this->never())->method($this->anything());
661
+
662
+        $this->addressHandler->method('generateRemoteURL')
663
+            ->willReturn('remoteurl.com');
664
+
665
+        $this->contactsManager->expects($this->any())
666
+            ->method('search')
667
+            ->willReturn([]);
668
+
669
+        $share = $this->shareManager->newShare();
670
+        $share->setSharedWith('[email protected]')
671
+            ->setSharedBy('sharedBy')
672
+            ->setShareOwner('shareOwner')
673
+            ->setPermissions(19)
674
+            ->setShareType(IShare::TYPE_REMOTE)
675
+            ->setNode($node);
676
+        $this->provider->create($share);
677
+
678
+        $share2 = $this->shareManager->newShare();
679
+        $share2->setSharedWith('[email protected]')
680
+            ->setSharedBy('sharedBy')
681
+            ->setShareOwner('shareOwner')
682
+            ->setPermissions(19)
683
+            ->setShareType(IShare::TYPE_REMOTE)
684
+            ->setNode($node);
685
+        $this->provider->create($share2);
686
+
687
+        $shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_REMOTE, null, true, 1, 1);
688
+
689
+        $this->assertCount(1, $shares);
690
+        $this->assertEquals('[email protected]', $shares[0]->getSharedWith());
691
+    }
692
+
693
+    public static function dataDeleteUser(): array {
694
+        return [
695
+            ['a', 'b', 'c', 'a', true],
696
+            ['a', 'b', 'c', 'b', false],
697
+            // The recipient is non local.
698
+            ['a', 'b', 'c', 'c', false],
699
+            ['a', 'b', 'c', 'd', false],
700
+        ];
701
+    }
702
+
703
+    /**
704
+     *
705
+     * @param string $owner The owner of the share (uid)
706
+     * @param string $initiator The initiator of the share (uid)
707
+     * @param string $recipient The recipient of the share (uid/gid/pass)
708
+     * @param string $deletedUser The user that is deleted
709
+     * @param bool $rowDeleted Is the row deleted in this setup
710
+     */
711
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataDeleteUser')]
712
+    public function testDeleteUser(string $owner, string $initiator, string $recipient, string $deletedUser, bool $rowDeleted): void {
713
+        $qb = $this->connection->getQueryBuilder();
714
+        $qb->insert('share')
715
+            ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
716
+            ->setValue('uid_owner', $qb->createNamedParameter($owner))
717
+            ->setValue('uid_initiator', $qb->createNamedParameter($initiator))
718
+            ->setValue('share_with', $qb->createNamedParameter($recipient))
719
+            ->setValue('item_type', $qb->createNamedParameter('file'))
720
+            ->setValue('item_source', $qb->createNamedParameter(42))
721
+            ->setValue('file_source', $qb->createNamedParameter(42))
722
+            ->executeStatement();
723
+
724
+        $id = $qb->getLastInsertId();
725
+
726
+        $this->provider->userDeleted($deletedUser, IShare::TYPE_REMOTE);
727
+
728
+        $qb = $this->connection->getQueryBuilder();
729
+        $qb->select('*')
730
+            ->from('share')
731
+            ->where(
732
+                $qb->expr()->eq('id', $qb->createNamedParameter($id))
733
+            );
734
+        $cursor = $qb->executeQuery();
735
+        $data = $cursor->fetchAllAssociative();
736
+        $cursor->closeCursor();
737
+
738
+        $this->assertCount($rowDeleted ? 0 : 1, $data);
739
+    }
740
+
741
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsOutgoingServer2serverShareEnabled')]
742
+    public function testIsOutgoingServer2serverShareEnabled(bool $internalOnly, string $isEnabled, bool $expected): void {
743
+        $this->gsConfig->expects($this->once())->method('onlyInternalFederation')
744
+            ->willReturn($internalOnly);
745
+        $this->config->expects($this->any())->method('getAppValue')
746
+            ->with('files_sharing', 'outgoing_server2server_share_enabled', 'yes')
747
+            ->willReturn($isEnabled);
748
+
749
+        $this->assertSame($expected,
750
+            $this->provider->isOutgoingServer2serverShareEnabled()
751
+        );
752
+    }
753
+
754
+    public static function dataTestIsOutgoingServer2serverShareEnabled(): array {
755
+        return [
756
+            [false, 'yes', true],
757
+            [false, 'no', false],
758
+            [true, 'yes', false],
759
+            [true, 'no', false],
760
+        ];
761
+    }
762
+
763
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsIncomingServer2serverShareEnabled')]
764
+    public function testIsIncomingServer2serverShareEnabled(bool $onlyInternal, string $isEnabled, bool $expected): void {
765
+        $this->gsConfig->expects($this->once())->method('onlyInternalFederation')
766
+            ->willReturn($onlyInternal);
767
+        $this->config->expects($this->any())->method('getAppValue')
768
+            ->with('files_sharing', 'incoming_server2server_share_enabled', 'yes')
769
+            ->willReturn($isEnabled);
770
+
771
+        $this->assertSame($expected,
772
+            $this->provider->isIncomingServer2serverShareEnabled()
773
+        );
774
+    }
775
+
776
+    public static function dataTestIsIncomingServer2serverShareEnabled(): array {
777
+        return [
778
+            [false, 'yes', true],
779
+            [false, 'no', false],
780
+            [true, 'yes', false],
781
+            [true, 'no', false],
782
+        ];
783
+    }
784
+
785
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsLookupServerQueriesEnabled')]
786
+    public function testIsLookupServerQueriesEnabled(bool $gsEnabled, string $isEnabled, bool $expected): void {
787
+        $this->gsConfig->expects($this->once())->method('isGlobalScaleEnabled')
788
+            ->willReturn($gsEnabled);
789
+        $this->config->expects($this->any())->method('getAppValue')
790
+            ->with('files_sharing', 'lookupServerEnabled', 'no')
791
+            ->willReturn($isEnabled);
792
+
793
+        $this->assertSame($expected,
794
+            $this->provider->isLookupServerQueriesEnabled()
795
+        );
796
+    }
797
+
798
+
799
+    public static function dataTestIsLookupServerQueriesEnabled(): array {
800
+        return [
801
+            [true, 'yes', true],
802
+            [true, 'no', true],
803
+            // TODO: reenable if we use the lookup server for non-global scale
804
+            // [false, 'yes', true],
805
+            // [false, 'no', false],
806
+            [false, 'no', false],
807
+            [false, 'yes', false],
808
+        ];
809
+    }
810
+
811
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsLookupServerUploadEnabled')]
812
+    public function testIsLookupServerUploadEnabled(bool $gsEnabled, string $isEnabled, bool $expected): void {
813
+        $this->gsConfig->expects($this->once())->method('isGlobalScaleEnabled')
814
+            ->willReturn($gsEnabled);
815
+        $this->config->expects($this->any())->method('getAppValue')
816
+            ->with('files_sharing', 'lookupServerUploadEnabled', 'no')
817
+            ->willReturn($isEnabled);
818
+
819
+        $this->assertSame($expected,
820
+            $this->provider->isLookupServerUploadEnabled()
821
+        );
822
+    }
823
+
824
+    public static function dataTestIsLookupServerUploadEnabled(): array {
825
+        return [
826
+            [true, 'yes', false],
827
+            [true, 'no', false],
828
+            // TODO: reenable if we use the lookup server again
829
+            // [false, 'yes', true],
830
+            // [false, 'no', false],
831
+            [false, 'yes', false],
832
+            [false, 'no', false],
833
+        ];
834
+    }
835
+
836
+    public function testGetSharesInFolder(): void {
837
+        $userManager = Server::get(IUserManager::class);
838
+        $rootFolder = Server::get(IRootFolder::class);
839
+
840
+        $u1 = $userManager->createUser('testFed', md5((string)time()));
841
+        $u2 = $userManager->createUser('testFed2', md5((string)time()));
842
+
843
+        $folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
844
+        $file1 = $folder1->newFile('bar1');
845
+        $file2 = $folder1->newFile('bar2');
846
+
847
+        $this->tokenHandler->method('generateToken')->willReturn('token');
848
+        $this->notifications
849
+            ->method('sendRemoteShare')
850
+            ->willReturn(true);
851
+
852
+        $this->addressHandler->method('generateRemoteURL')
853
+            ->willReturn('remoteurl.com');
854
+
855
+        $this->contactsManager->expects($this->any())
856
+            ->method('search')
857
+            ->willReturn([]);
858
+
859
+        $share1 = $this->shareManager->newShare();
860
+        $share1->setSharedWith('[email protected]')
861
+            ->setSharedBy($u1->getUID())
862
+            ->setShareOwner($u1->getUID())
863
+            ->setPermissions(Constants::PERMISSION_READ)
864
+            ->setShareType(IShare::TYPE_REMOTE)
865
+            ->setNode($file1);
866
+        $this->provider->create($share1);
867
+
868
+        $share2 = $this->shareManager->newShare();
869
+        $share2->setSharedWith('[email protected]')
870
+            ->setSharedBy($u2->getUID())
871
+            ->setShareOwner($u1->getUID())
872
+            ->setPermissions(Constants::PERMISSION_READ)
873
+            ->setShareType(IShare::TYPE_REMOTE)
874
+            ->setNode($file2);
875
+        $this->provider->create($share2);
876
+
877
+        $result = $this->provider->getSharesInFolder($u1->getUID(), $folder1, false);
878
+        $this->assertCount(1, $result);
879
+        $this->assertCount(1, $result[$file1->getId()]);
880
+
881
+        $result = $this->provider->getSharesInFolder($u1->getUID(), $folder1, true);
882
+        $this->assertCount(2, $result);
883
+        $this->assertCount(1, $result[$file1->getId()]);
884
+        $this->assertCount(1, $result[$file2->getId()]);
885
+
886
+        $u1->delete();
887
+        $u2->delete();
888
+    }
889
+
890
+    public function testGetAccessList(): void {
891
+        $userManager = Server::get(IUserManager::class);
892
+        $rootFolder = Server::get(IRootFolder::class);
893
+
894
+        $u1 = $userManager->createUser('testFed', md5((string)time()));
895
+
896
+        $folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
897
+        $file1 = $folder1->newFile('bar1');
898
+
899
+        $this->tokenHandler->expects($this->exactly(2))
900
+            ->method('generateToken')
901
+            ->willReturnOnConsecutiveCalls('token1', 'token2');
902
+        $this->notifications->expects($this->atLeastOnce())
903
+            ->method('sendRemoteShare')
904
+            ->willReturn(true);
905
+
906
+        $this->contactsManager->expects($this->any())
907
+            ->method('search')
908
+            ->willReturn([]);
909
+
910
+        $result = $this->provider->getAccessList([$file1], true);
911
+        $this->assertEquals(['remote' => []], $result);
912
+
913
+        $result = $this->provider->getAccessList([$file1], false);
914
+        $this->assertEquals(['remote' => false], $result);
915
+
916
+        $this->addressHandler->method('generateRemoteURL')
917
+            ->willReturn('remoteurl.com');
918
+
919
+        $share1 = $this->shareManager->newShare();
920
+        $share1->setSharedWith('[email protected]')
921
+            ->setSharedBy($u1->getUID())
922
+            ->setShareOwner($u1->getUID())
923
+            ->setPermissions(Constants::PERMISSION_READ)
924
+            ->setShareType(IShare::TYPE_REMOTE)
925
+            ->setNode($file1);
926
+        $this->provider->create($share1);
927
+
928
+        $share2 = $this->shareManager->newShare();
929
+        $share2->setSharedWith('foobar@localhost')
930
+            ->setSharedBy($u1->getUID())
931
+            ->setShareOwner($u1->getUID())
932
+            ->setPermissions(Constants::PERMISSION_READ)
933
+            ->setShareType(IShare::TYPE_REMOTE)
934
+            ->setNode($file1);
935
+        $this->provider->create($share2);
936
+
937
+        $result = $this->provider->getAccessList([$file1], true);
938
+        $this->assertEquals(['remote' => [
939
+            '[email protected]' => [
940
+                'token' => 'token1',
941
+                'node_id' => $file1->getId(),
942
+            ],
943
+            'foobar@localhost' => [
944
+                'token' => 'token2',
945
+                'node_id' => $file1->getId(),
946
+            ],
947
+        ]], $result);
948
+
949
+        $result = $this->provider->getAccessList([$file1], false);
950
+        $this->assertEquals(['remote' => true], $result);
951
+
952
+        $u1->delete();
953
+    }
954 954
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/FederatedShareProvider.php 2 patches
Indentation   +1041 added lines, -1041 removed lines patch added patch discarded remove patch
@@ -35,1055 +35,1055 @@
 block discarded – undo
35 35
  * @package OCA\FederatedFileSharing
36 36
  */
37 37
 class FederatedShareProvider implements IShareProvider, IShareProviderSupportsAllSharesInFolder {
38
-	public const SHARE_TYPE_REMOTE = 6;
39
-
40
-	/** @var string */
41
-	private $externalShareTable = 'share_external';
42
-
43
-	/** @var array list of supported share types */
44
-	private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
45
-
46
-	/**
47
-	 * DefaultShareProvider constructor.
48
-	 */
49
-	public function __construct(
50
-		private IDBConnection $dbConnection,
51
-		private AddressHandler $addressHandler,
52
-		private Notifications $notifications,
53
-		private TokenHandler $tokenHandler,
54
-		private IL10N $l,
55
-		private IRootFolder $rootFolder,
56
-		private IConfig $config,
57
-		private IUserManager $userManager,
58
-		private ICloudIdManager $cloudIdManager,
59
-		private \OCP\GlobalScale\IConfig $gsConfig,
60
-		private ICloudFederationProviderManager $cloudFederationProviderManager,
61
-		private LoggerInterface $logger,
62
-	) {
63
-	}
64
-
65
-	/**
66
-	 * Return the identifier of this provider.
67
-	 *
68
-	 * @return string Containing only [a-zA-Z0-9]
69
-	 */
70
-	public function identifier() {
71
-		return 'ocFederatedSharing';
72
-	}
73
-
74
-	/**
75
-	 * Share a path
76
-	 *
77
-	 * @param IShare $share
78
-	 * @return IShare The share object
79
-	 * @throws ShareNotFound
80
-	 * @throws \Exception
81
-	 */
82
-	public function create(IShare $share) {
83
-		$shareWith = $share->getSharedWith();
84
-		$itemSource = $share->getNodeId();
85
-		$itemType = $share->getNodeType();
86
-		$permissions = $share->getPermissions();
87
-		$sharedBy = $share->getSharedBy();
88
-		$shareType = $share->getShareType();
89
-		$expirationDate = $share->getExpirationDate();
90
-
91
-		if ($shareType === IShare::TYPE_REMOTE_GROUP
92
-			&& !$this->isOutgoingServer2serverGroupShareEnabled()
93
-		) {
94
-			$message = 'It is not allowed to send federated group shares from this server.';
95
-			$message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
96
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
97
-			throw new \Exception($message_t);
98
-		}
99
-
100
-		/*
38
+    public const SHARE_TYPE_REMOTE = 6;
39
+
40
+    /** @var string */
41
+    private $externalShareTable = 'share_external';
42
+
43
+    /** @var array list of supported share types */
44
+    private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
45
+
46
+    /**
47
+     * DefaultShareProvider constructor.
48
+     */
49
+    public function __construct(
50
+        private IDBConnection $dbConnection,
51
+        private AddressHandler $addressHandler,
52
+        private Notifications $notifications,
53
+        private TokenHandler $tokenHandler,
54
+        private IL10N $l,
55
+        private IRootFolder $rootFolder,
56
+        private IConfig $config,
57
+        private IUserManager $userManager,
58
+        private ICloudIdManager $cloudIdManager,
59
+        private \OCP\GlobalScale\IConfig $gsConfig,
60
+        private ICloudFederationProviderManager $cloudFederationProviderManager,
61
+        private LoggerInterface $logger,
62
+    ) {
63
+    }
64
+
65
+    /**
66
+     * Return the identifier of this provider.
67
+     *
68
+     * @return string Containing only [a-zA-Z0-9]
69
+     */
70
+    public function identifier() {
71
+        return 'ocFederatedSharing';
72
+    }
73
+
74
+    /**
75
+     * Share a path
76
+     *
77
+     * @param IShare $share
78
+     * @return IShare The share object
79
+     * @throws ShareNotFound
80
+     * @throws \Exception
81
+     */
82
+    public function create(IShare $share) {
83
+        $shareWith = $share->getSharedWith();
84
+        $itemSource = $share->getNodeId();
85
+        $itemType = $share->getNodeType();
86
+        $permissions = $share->getPermissions();
87
+        $sharedBy = $share->getSharedBy();
88
+        $shareType = $share->getShareType();
89
+        $expirationDate = $share->getExpirationDate();
90
+
91
+        if ($shareType === IShare::TYPE_REMOTE_GROUP
92
+            && !$this->isOutgoingServer2serverGroupShareEnabled()
93
+        ) {
94
+            $message = 'It is not allowed to send federated group shares from this server.';
95
+            $message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
96
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
97
+            throw new \Exception($message_t);
98
+        }
99
+
100
+        /*
101 101
 		 * Check if file is not already shared with the remote user
102 102
 		 */
103
-		$alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE, $share->getNode(), 1, 0);
104
-		$alreadySharedGroup = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
105
-		if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
106
-			$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
107
-			$message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with the account %2$s', [$share->getNode()->getName(), $shareWith]);
108
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
109
-			throw new \Exception($message_t);
110
-		}
111
-
112
-
113
-		// don't allow federated shares if source and target server are the same
114
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
115
-		$currentServer = $this->addressHandler->generateRemoteURL();
116
-		$currentUser = $sharedBy;
117
-		if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
118
-			$message = 'Not allowed to create a federated share to the same account.';
119
-			$message_t = $this->l->t('Not allowed to create a federated share to the same account');
120
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
121
-			throw new \Exception($message_t);
122
-		}
123
-
124
-		// Federated shares always have read permissions
125
-		if (($share->getPermissions() & Constants::PERMISSION_READ) === 0) {
126
-			$message = 'Federated shares require read permissions';
127
-			$message_t = $this->l->t('Federated shares require read permissions');
128
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
129
-			throw new \Exception($message_t);
130
-		}
131
-
132
-		$share->setSharedWith($cloudId->getId());
133
-
134
-		try {
135
-			$remoteShare = $this->getShareFromExternalShareTable($share);
136
-		} catch (ShareNotFound $e) {
137
-			$remoteShare = null;
138
-		}
139
-
140
-		if ($remoteShare) {
141
-			try {
142
-				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
143
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType, $expirationDate);
144
-				$share->setId($shareId);
145
-				[$token, $remoteId] = $this->askOwnerToReShare($shareWith, $share, $shareId);
146
-				// remote share was create successfully if we get a valid token as return
147
-				$send = is_string($token) && $token !== '';
148
-			} catch (\Exception $e) {
149
-				// fall back to old re-share behavior if the remote server
150
-				// doesn't support flat re-shares (was introduced with Nextcloud 9.1)
151
-				$this->removeShareFromTable($share);
152
-				$shareId = $this->createFederatedShare($share);
153
-			}
154
-			if ($send) {
155
-				$this->updateSuccessfulReshare($shareId, $token);
156
-				$this->storeRemoteId($shareId, $remoteId);
157
-			} else {
158
-				$this->removeShareFromTable($share);
159
-				$message_t = $this->l->t('File is already shared with %s', [$shareWith]);
160
-				throw new \Exception($message_t);
161
-			}
162
-		} else {
163
-			$shareId = $this->createFederatedShare($share);
164
-		}
165
-
166
-		$data = $this->getRawShare($shareId);
167
-		return $this->createShareObject($data);
168
-	}
169
-
170
-	/**
171
-	 * create federated share and inform the recipient
172
-	 *
173
-	 * @param IShare $share
174
-	 * @return int
175
-	 * @throws ShareNotFound
176
-	 * @throws \Exception
177
-	 */
178
-	protected function createFederatedShare(IShare $share) {
179
-		$token = $this->tokenHandler->generateToken();
180
-		$shareId = $this->addShareToDB(
181
-			$share->getNodeId(),
182
-			$share->getNodeType(),
183
-			$share->getSharedWith(),
184
-			$share->getSharedBy(),
185
-			$share->getShareOwner(),
186
-			$share->getPermissions(),
187
-			$token,
188
-			$share->getShareType(),
189
-			$share->getExpirationDate()
190
-		);
191
-
192
-		$failure = false;
193
-
194
-		try {
195
-			$sharedByFederatedId = $share->getSharedBy();
196
-			if ($this->userManager->userExists($sharedByFederatedId)) {
197
-				$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
198
-				$sharedByFederatedId = $cloudId->getId();
199
-			}
200
-			$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
201
-			$send = $this->notifications->sendRemoteShare(
202
-				$token,
203
-				$share->getSharedWith(),
204
-				$share->getNode()->getName(),
205
-				$shareId,
206
-				$share->getShareOwner(),
207
-				$ownerCloudId->getId(),
208
-				$share->getSharedBy(),
209
-				$sharedByFederatedId,
210
-				$share->getShareType()
211
-			);
212
-
213
-			if ($send === false) {
214
-				$failure = true;
215
-			}
216
-		} catch (\Exception $e) {
217
-			$this->logger->error('Failed to notify remote server of federated share, removing share.', [
218
-				'app' => 'federatedfilesharing',
219
-				'exception' => $e,
220
-			]);
221
-			$failure = true;
222
-		}
223
-
224
-		if ($failure) {
225
-			$this->removeShareFromTableById($shareId);
226
-			$message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
227
-				[$share->getNode()->getName(), $share->getSharedWith()]);
228
-			throw new \Exception($message_t);
229
-		}
230
-
231
-		return $shareId;
232
-	}
233
-
234
-	/**
235
-	 * @param string $shareWith
236
-	 * @param IShare $share
237
-	 * @param string $shareId internal share Id
238
-	 * @return array
239
-	 * @throws \Exception
240
-	 */
241
-	protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
242
-		$remoteShare = $this->getShareFromExternalShareTable($share);
243
-		$token = $remoteShare['share_token'];
244
-		$remoteId = $remoteShare['remote_id'];
245
-		$remote = $remoteShare['remote'];
246
-
247
-		[$token, $remoteId] = $this->notifications->requestReShare(
248
-			$token,
249
-			$remoteId,
250
-			$shareId,
251
-			$remote,
252
-			$shareWith,
253
-			$share->getPermissions(),
254
-			$share->getNode()->getName(),
255
-			$share->getShareType(),
256
-		);
257
-
258
-		return [$token, $remoteId];
259
-	}
260
-
261
-	/**
262
-	 * get federated share from the share_external table but exclude mounted link shares
263
-	 *
264
-	 * @param IShare $share
265
-	 * @return array
266
-	 * @throws ShareNotFound
267
-	 */
268
-	protected function getShareFromExternalShareTable(IShare $share) {
269
-		$query = $this->dbConnection->getQueryBuilder();
270
-		$query->select('*')->from($this->externalShareTable)
271
-			->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
272
-			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
273
-		$qResult = $query->executeQuery();
274
-		$result = $qResult->fetchAllAssociative();
275
-		$qResult->closeCursor();
276
-
277
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
278
-			return $result[0];
279
-		}
280
-
281
-		throw new ShareNotFound('share not found in share_external table');
282
-	}
283
-
284
-	/**
285
-	 * add share to the database and return the ID
286
-	 *
287
-	 * @param int $itemSource
288
-	 * @param string $itemType
289
-	 * @param string $shareWith
290
-	 * @param string $sharedBy
291
-	 * @param string $uidOwner
292
-	 * @param int $permissions
293
-	 * @param string $token
294
-	 * @param int $shareType
295
-	 * @param \DateTime $expirationDate
296
-	 * @return int
297
-	 */
298
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType, $expirationDate) {
299
-		$qb = $this->dbConnection->getQueryBuilder();
300
-		$qb->insert('share')
301
-			->setValue('share_type', $qb->createNamedParameter($shareType))
302
-			->setValue('item_type', $qb->createNamedParameter($itemType))
303
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
304
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
305
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
306
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
307
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
308
-			->setValue('permissions', $qb->createNamedParameter($permissions))
309
-			->setValue('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATETIME_MUTABLE))
310
-			->setValue('token', $qb->createNamedParameter($token))
311
-			->setValue('stime', $qb->createNamedParameter(time()));
312
-
313
-		/*
103
+        $alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE, $share->getNode(), 1, 0);
104
+        $alreadySharedGroup = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
105
+        if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
106
+            $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
107
+            $message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with the account %2$s', [$share->getNode()->getName(), $shareWith]);
108
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
109
+            throw new \Exception($message_t);
110
+        }
111
+
112
+
113
+        // don't allow federated shares if source and target server are the same
114
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
115
+        $currentServer = $this->addressHandler->generateRemoteURL();
116
+        $currentUser = $sharedBy;
117
+        if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
118
+            $message = 'Not allowed to create a federated share to the same account.';
119
+            $message_t = $this->l->t('Not allowed to create a federated share to the same account');
120
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
121
+            throw new \Exception($message_t);
122
+        }
123
+
124
+        // Federated shares always have read permissions
125
+        if (($share->getPermissions() & Constants::PERMISSION_READ) === 0) {
126
+            $message = 'Federated shares require read permissions';
127
+            $message_t = $this->l->t('Federated shares require read permissions');
128
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
129
+            throw new \Exception($message_t);
130
+        }
131
+
132
+        $share->setSharedWith($cloudId->getId());
133
+
134
+        try {
135
+            $remoteShare = $this->getShareFromExternalShareTable($share);
136
+        } catch (ShareNotFound $e) {
137
+            $remoteShare = null;
138
+        }
139
+
140
+        if ($remoteShare) {
141
+            try {
142
+                $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
143
+                $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType, $expirationDate);
144
+                $share->setId($shareId);
145
+                [$token, $remoteId] = $this->askOwnerToReShare($shareWith, $share, $shareId);
146
+                // remote share was create successfully if we get a valid token as return
147
+                $send = is_string($token) && $token !== '';
148
+            } catch (\Exception $e) {
149
+                // fall back to old re-share behavior if the remote server
150
+                // doesn't support flat re-shares (was introduced with Nextcloud 9.1)
151
+                $this->removeShareFromTable($share);
152
+                $shareId = $this->createFederatedShare($share);
153
+            }
154
+            if ($send) {
155
+                $this->updateSuccessfulReshare($shareId, $token);
156
+                $this->storeRemoteId($shareId, $remoteId);
157
+            } else {
158
+                $this->removeShareFromTable($share);
159
+                $message_t = $this->l->t('File is already shared with %s', [$shareWith]);
160
+                throw new \Exception($message_t);
161
+            }
162
+        } else {
163
+            $shareId = $this->createFederatedShare($share);
164
+        }
165
+
166
+        $data = $this->getRawShare($shareId);
167
+        return $this->createShareObject($data);
168
+    }
169
+
170
+    /**
171
+     * create federated share and inform the recipient
172
+     *
173
+     * @param IShare $share
174
+     * @return int
175
+     * @throws ShareNotFound
176
+     * @throws \Exception
177
+     */
178
+    protected function createFederatedShare(IShare $share) {
179
+        $token = $this->tokenHandler->generateToken();
180
+        $shareId = $this->addShareToDB(
181
+            $share->getNodeId(),
182
+            $share->getNodeType(),
183
+            $share->getSharedWith(),
184
+            $share->getSharedBy(),
185
+            $share->getShareOwner(),
186
+            $share->getPermissions(),
187
+            $token,
188
+            $share->getShareType(),
189
+            $share->getExpirationDate()
190
+        );
191
+
192
+        $failure = false;
193
+
194
+        try {
195
+            $sharedByFederatedId = $share->getSharedBy();
196
+            if ($this->userManager->userExists($sharedByFederatedId)) {
197
+                $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
198
+                $sharedByFederatedId = $cloudId->getId();
199
+            }
200
+            $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
201
+            $send = $this->notifications->sendRemoteShare(
202
+                $token,
203
+                $share->getSharedWith(),
204
+                $share->getNode()->getName(),
205
+                $shareId,
206
+                $share->getShareOwner(),
207
+                $ownerCloudId->getId(),
208
+                $share->getSharedBy(),
209
+                $sharedByFederatedId,
210
+                $share->getShareType()
211
+            );
212
+
213
+            if ($send === false) {
214
+                $failure = true;
215
+            }
216
+        } catch (\Exception $e) {
217
+            $this->logger->error('Failed to notify remote server of federated share, removing share.', [
218
+                'app' => 'federatedfilesharing',
219
+                'exception' => $e,
220
+            ]);
221
+            $failure = true;
222
+        }
223
+
224
+        if ($failure) {
225
+            $this->removeShareFromTableById($shareId);
226
+            $message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
227
+                [$share->getNode()->getName(), $share->getSharedWith()]);
228
+            throw new \Exception($message_t);
229
+        }
230
+
231
+        return $shareId;
232
+    }
233
+
234
+    /**
235
+     * @param string $shareWith
236
+     * @param IShare $share
237
+     * @param string $shareId internal share Id
238
+     * @return array
239
+     * @throws \Exception
240
+     */
241
+    protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
242
+        $remoteShare = $this->getShareFromExternalShareTable($share);
243
+        $token = $remoteShare['share_token'];
244
+        $remoteId = $remoteShare['remote_id'];
245
+        $remote = $remoteShare['remote'];
246
+
247
+        [$token, $remoteId] = $this->notifications->requestReShare(
248
+            $token,
249
+            $remoteId,
250
+            $shareId,
251
+            $remote,
252
+            $shareWith,
253
+            $share->getPermissions(),
254
+            $share->getNode()->getName(),
255
+            $share->getShareType(),
256
+        );
257
+
258
+        return [$token, $remoteId];
259
+    }
260
+
261
+    /**
262
+     * get federated share from the share_external table but exclude mounted link shares
263
+     *
264
+     * @param IShare $share
265
+     * @return array
266
+     * @throws ShareNotFound
267
+     */
268
+    protected function getShareFromExternalShareTable(IShare $share) {
269
+        $query = $this->dbConnection->getQueryBuilder();
270
+        $query->select('*')->from($this->externalShareTable)
271
+            ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
272
+            ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
273
+        $qResult = $query->executeQuery();
274
+        $result = $qResult->fetchAllAssociative();
275
+        $qResult->closeCursor();
276
+
277
+        if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
278
+            return $result[0];
279
+        }
280
+
281
+        throw new ShareNotFound('share not found in share_external table');
282
+    }
283
+
284
+    /**
285
+     * add share to the database and return the ID
286
+     *
287
+     * @param int $itemSource
288
+     * @param string $itemType
289
+     * @param string $shareWith
290
+     * @param string $sharedBy
291
+     * @param string $uidOwner
292
+     * @param int $permissions
293
+     * @param string $token
294
+     * @param int $shareType
295
+     * @param \DateTime $expirationDate
296
+     * @return int
297
+     */
298
+    private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType, $expirationDate) {
299
+        $qb = $this->dbConnection->getQueryBuilder();
300
+        $qb->insert('share')
301
+            ->setValue('share_type', $qb->createNamedParameter($shareType))
302
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
303
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
304
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
305
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
306
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
307
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
308
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
309
+            ->setValue('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATETIME_MUTABLE))
310
+            ->setValue('token', $qb->createNamedParameter($token))
311
+            ->setValue('stime', $qb->createNamedParameter(time()));
312
+
313
+        /*
314 314
 		 * Added to fix https://github.com/owncloud/core/issues/22215
315 315
 		 * Can be removed once we get rid of ajax/share.php
316 316
 		 */
317
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
318
-
319
-		$qb->executeStatement();
320
-		return $qb->getLastInsertId();
321
-	}
322
-
323
-	/**
324
-	 * Update a share
325
-	 *
326
-	 * @param IShare $share
327
-	 * @return IShare The share object
328
-	 */
329
-	public function update(IShare $share) {
330
-		/*
317
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
318
+
319
+        $qb->executeStatement();
320
+        return $qb->getLastInsertId();
321
+    }
322
+
323
+    /**
324
+     * Update a share
325
+     *
326
+     * @param IShare $share
327
+     * @return IShare The share object
328
+     */
329
+    public function update(IShare $share) {
330
+        /*
331 331
 		 * We allow updating the permissions of federated shares
332 332
 		 */
333
-		$qb = $this->dbConnection->getQueryBuilder();
334
-		$qb->update('share')
335
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
336
-			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
337
-			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
338
-			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
339
-			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
340
-			->executeStatement();
341
-
342
-		// send the updated permission to the owner/initiator, if they are not the same
343
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
344
-			$this->sendPermissionUpdate($share);
345
-		}
346
-
347
-		return $share;
348
-	}
349
-
350
-	/**
351
-	 * send the updated permission to the owner/initiator, if they are not the same
352
-	 *
353
-	 * @param IShare $share
354
-	 * @throws ShareNotFound
355
-	 * @throws HintException
356
-	 */
357
-	protected function sendPermissionUpdate(IShare $share) {
358
-		$remoteId = $this->getRemoteId($share);
359
-		// if the local user is the owner we send the permission change to the initiator
360
-		if ($this->userManager->userExists($share->getShareOwner())) {
361
-			[, $remote] = $this->addressHandler->splitUserRemote($share->getSharedBy());
362
-		} else { // ... if not we send the permission change to the owner
363
-			[, $remote] = $this->addressHandler->splitUserRemote($share->getShareOwner());
364
-		}
365
-		$this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
366
-	}
367
-
368
-
369
-	/**
370
-	 * update successful reShare with the correct token
371
-	 *
372
-	 * @param int $shareId
373
-	 * @param string $token
374
-	 */
375
-	protected function updateSuccessfulReShare($shareId, $token) {
376
-		$query = $this->dbConnection->getQueryBuilder();
377
-		$query->update('share')
378
-			->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
379
-			->set('token', $query->createNamedParameter($token))
380
-			->executeStatement();
381
-	}
382
-
383
-	/**
384
-	 * store remote ID in federated reShare table
385
-	 *
386
-	 * @param $shareId
387
-	 * @param $remoteId
388
-	 */
389
-	public function storeRemoteId(int $shareId, string $remoteId): void {
390
-		$query = $this->dbConnection->getQueryBuilder();
391
-		$query->insert('federated_reshares')
392
-			->values(
393
-				[
394
-					'share_id' => $query->createNamedParameter($shareId),
395
-					'remote_id' => $query->createNamedParameter($remoteId),
396
-				]
397
-			);
398
-		$query->executeStatement();
399
-	}
400
-
401
-	/**
402
-	 * get share ID on remote server for federated re-shares
403
-	 *
404
-	 * @param IShare $share
405
-	 * @return string
406
-	 * @throws ShareNotFound
407
-	 */
408
-	public function getRemoteId(IShare $share): string {
409
-		$query = $this->dbConnection->getQueryBuilder();
410
-		$query->select('remote_id')->from('federated_reshares')
411
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
412
-		$result = $query->executeQuery();
413
-		$data = $result->fetchAssociative();
414
-		$result->closeCursor();
415
-
416
-		if (!is_array($data) || !isset($data['remote_id'])) {
417
-			throw new ShareNotFound();
418
-		}
419
-
420
-		return (string)$data['remote_id'];
421
-	}
422
-
423
-	/**
424
-	 * @inheritdoc
425
-	 */
426
-	public function move(IShare $share, $recipient) {
427
-		/*
333
+        $qb = $this->dbConnection->getQueryBuilder();
334
+        $qb->update('share')
335
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
336
+            ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
337
+            ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
338
+            ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
339
+            ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
340
+            ->executeStatement();
341
+
342
+        // send the updated permission to the owner/initiator, if they are not the same
343
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
344
+            $this->sendPermissionUpdate($share);
345
+        }
346
+
347
+        return $share;
348
+    }
349
+
350
+    /**
351
+     * send the updated permission to the owner/initiator, if they are not the same
352
+     *
353
+     * @param IShare $share
354
+     * @throws ShareNotFound
355
+     * @throws HintException
356
+     */
357
+    protected function sendPermissionUpdate(IShare $share) {
358
+        $remoteId = $this->getRemoteId($share);
359
+        // if the local user is the owner we send the permission change to the initiator
360
+        if ($this->userManager->userExists($share->getShareOwner())) {
361
+            [, $remote] = $this->addressHandler->splitUserRemote($share->getSharedBy());
362
+        } else { // ... if not we send the permission change to the owner
363
+            [, $remote] = $this->addressHandler->splitUserRemote($share->getShareOwner());
364
+        }
365
+        $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
366
+    }
367
+
368
+
369
+    /**
370
+     * update successful reShare with the correct token
371
+     *
372
+     * @param int $shareId
373
+     * @param string $token
374
+     */
375
+    protected function updateSuccessfulReShare($shareId, $token) {
376
+        $query = $this->dbConnection->getQueryBuilder();
377
+        $query->update('share')
378
+            ->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
379
+            ->set('token', $query->createNamedParameter($token))
380
+            ->executeStatement();
381
+    }
382
+
383
+    /**
384
+     * store remote ID in federated reShare table
385
+     *
386
+     * @param $shareId
387
+     * @param $remoteId
388
+     */
389
+    public function storeRemoteId(int $shareId, string $remoteId): void {
390
+        $query = $this->dbConnection->getQueryBuilder();
391
+        $query->insert('federated_reshares')
392
+            ->values(
393
+                [
394
+                    'share_id' => $query->createNamedParameter($shareId),
395
+                    'remote_id' => $query->createNamedParameter($remoteId),
396
+                ]
397
+            );
398
+        $query->executeStatement();
399
+    }
400
+
401
+    /**
402
+     * get share ID on remote server for federated re-shares
403
+     *
404
+     * @param IShare $share
405
+     * @return string
406
+     * @throws ShareNotFound
407
+     */
408
+    public function getRemoteId(IShare $share): string {
409
+        $query = $this->dbConnection->getQueryBuilder();
410
+        $query->select('remote_id')->from('federated_reshares')
411
+            ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
412
+        $result = $query->executeQuery();
413
+        $data = $result->fetchAssociative();
414
+        $result->closeCursor();
415
+
416
+        if (!is_array($data) || !isset($data['remote_id'])) {
417
+            throw new ShareNotFound();
418
+        }
419
+
420
+        return (string)$data['remote_id'];
421
+    }
422
+
423
+    /**
424
+     * @inheritdoc
425
+     */
426
+    public function move(IShare $share, $recipient) {
427
+        /*
428 428
 		 * This function does nothing yet as it is just for outgoing
429 429
 		 * federated shares.
430 430
 		 */
431
-		return $share;
432
-	}
433
-
434
-	public function getChildren(IShare $parent): array {
435
-		$children = [];
436
-
437
-		$qb = $this->dbConnection->getQueryBuilder();
438
-		$qb->select('*')
439
-			->from('share')
440
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
441
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
442
-			->orderBy('id');
443
-
444
-		$cursor = $qb->executeQuery();
445
-		while ($data = $cursor->fetchAssociative()) {
446
-			$children[] = $this->createShareObject($data);
447
-		}
448
-		$cursor->closeCursor();
449
-
450
-		return $children;
451
-	}
452
-
453
-	/**
454
-	 * Delete a share (owner unShares the file)
455
-	 *
456
-	 * @param IShare $share
457
-	 * @throws ShareNotFound
458
-	 * @throws HintException
459
-	 */
460
-	public function delete(IShare $share) {
461
-		[, $remote] = $this->addressHandler->splitUserRemote($share->getSharedWith());
462
-
463
-		// if the local user is the owner we can send the unShare request directly...
464
-		if ($this->userManager->userExists($share->getShareOwner())) {
465
-			$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
466
-			$this->revokeShare($share, true);
467
-		} else { // ... if not we need to correct ID for the unShare request
468
-			$remoteId = $this->getRemoteId($share);
469
-			$this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
470
-			$this->revokeShare($share, false);
471
-		}
472
-
473
-		// only remove the share when all messages are send to not lose information
474
-		// about the share to early
475
-		$this->removeShareFromTable($share);
476
-	}
477
-
478
-	/**
479
-	 * in case of a re-share we need to send the other use (initiator or owner)
480
-	 * a message that the file was unshared
481
-	 *
482
-	 * @param IShare $share
483
-	 * @param bool $isOwner the user can either be the owner or the user who re-sahred it
484
-	 * @throws ShareNotFound
485
-	 * @throws HintException
486
-	 */
487
-	protected function revokeShare($share, $isOwner) {
488
-		if ($this->userManager->userExists($share->getShareOwner()) && $this->userManager->userExists($share->getSharedBy())) {
489
-			// If both the owner and the initiator of the share are local users we don't have to notify anybody else
490
-			return;
491
-		}
492
-
493
-		// also send a unShare request to the initiator, if this is a different user than the owner
494
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
495
-			if ($isOwner) {
496
-				[, $remote] = $this->addressHandler->splitUserRemote($share->getSharedBy());
497
-			} else {
498
-				[, $remote] = $this->addressHandler->splitUserRemote($share->getShareOwner());
499
-			}
500
-			$remoteId = $this->getRemoteId($share);
501
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
502
-		}
503
-	}
504
-
505
-	/**
506
-	 * remove share from table
507
-	 *
508
-	 * @param IShare $share
509
-	 */
510
-	public function removeShareFromTable(IShare $share) {
511
-		$this->removeShareFromTableById($share->getId());
512
-	}
513
-
514
-	/**
515
-	 * remove share from table
516
-	 *
517
-	 * @param string $shareId
518
-	 */
519
-	private function removeShareFromTableById($shareId) {
520
-		$qb = $this->dbConnection->getQueryBuilder();
521
-		$qb->delete('share')
522
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
523
-			->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
524
-		$qb->executeStatement();
525
-
526
-		$qb = $this->dbConnection->getQueryBuilder();
527
-		$qb->delete('federated_reshares')
528
-			->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
529
-		$qb->executeStatement();
530
-	}
531
-
532
-	/**
533
-	 * @inheritdoc
534
-	 */
535
-	public function deleteFromSelf(IShare $share, $recipient) {
536
-		// nothing to do here. Technically deleteFromSelf in the context of federated
537
-		// shares is a umount of an external storage. This is handled here
538
-		// apps/files_sharing/lib/external/manager.php
539
-		// TODO move this code over to this app
540
-	}
541
-
542
-	public function restore(IShare $share, string $recipient): IShare {
543
-		throw new GenericShareException('not implemented');
544
-	}
545
-
546
-
547
-	public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true) {
548
-		if (!$shallow) {
549
-			throw new \Exception('non-shallow getSharesInFolder is no longer supported');
550
-		}
551
-		return $this->getSharesInFolderInternal($userId, $node, $reshares);
552
-	}
553
-
554
-	public function getAllSharesInFolder(Folder $node): array {
555
-		return $this->getSharesInFolderInternal(null, $node, null);
556
-	}
557
-
558
-	/**
559
-	 * @return array<int, list<IShare>>
560
-	 */
561
-	private function getSharesInFolderInternal(?string $userId, Folder $node, ?bool $reshares): array {
562
-		$qb = $this->dbConnection->getQueryBuilder();
563
-		$qb->select('*')
564
-			->from('share', 's')
565
-			->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)))
566
-			->andWhere(
567
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
568
-			);
569
-
570
-		if ($userId !== null) {
571
-			/**
572
-			 * Reshares for this user are shares where they are the owner.
573
-			 */
574
-			if ($reshares !== true) {
575
-				$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
576
-			} else {
577
-				$qb->andWhere(
578
-					$qb->expr()->orX(
579
-						$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
580
-						$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
581
-					)
582
-				);
583
-			}
584
-		}
585
-
586
-		$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
587
-
588
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
589
-
590
-		$qb->orderBy('id');
591
-
592
-		$cursor = $qb->executeQuery();
593
-		$shares = [];
594
-		while ($data = $cursor->fetchAssociative()) {
595
-			$shares[$data['fileid']][] = $this->createShareObject($data);
596
-		}
597
-		$cursor->closeCursor();
598
-
599
-		return $shares;
600
-	}
601
-
602
-	/**
603
-	 * @inheritdoc
604
-	 */
605
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
606
-		$qb = $this->dbConnection->getQueryBuilder();
607
-		$qb->select('*')
608
-			->from('share');
609
-
610
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
611
-
612
-		/**
613
-		 * Reshares for this user are shares where they are the owner.
614
-		 */
615
-		if ($reshares === false) {
616
-			//Special case for old shares created via the web UI
617
-			$or1 = $qb->expr()->andX(
618
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
619
-				$qb->expr()->isNull('uid_initiator')
620
-			);
621
-
622
-			$qb->andWhere(
623
-				$qb->expr()->orX(
624
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
625
-					$or1
626
-				)
627
-			);
628
-		} else {
629
-			$qb->andWhere(
630
-				$qb->expr()->orX(
631
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
632
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
633
-				)
634
-			);
635
-		}
636
-
637
-		if ($node !== null) {
638
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
639
-		}
640
-
641
-		if ($limit !== -1) {
642
-			$qb->setMaxResults($limit);
643
-		}
644
-
645
-		$qb->setFirstResult($offset);
646
-		$qb->orderBy('id');
647
-
648
-		$cursor = $qb->executeQuery();
649
-		$shares = [];
650
-		while ($data = $cursor->fetchAssociative()) {
651
-			$shares[] = $this->createShareObject($data);
652
-		}
653
-		$cursor->closeCursor();
654
-
655
-		return $shares;
656
-	}
657
-
658
-	/**
659
-	 * @inheritdoc
660
-	 */
661
-	public function getShareById($id, $recipientId = null) {
662
-		$qb = $this->dbConnection->getQueryBuilder();
663
-
664
-		$qb->select('*')
665
-			->from('share')
666
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
667
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
668
-
669
-		$cursor = $qb->executeQuery();
670
-		$data = $cursor->fetchAssociative();
671
-		$cursor->closeCursor();
672
-
673
-		if ($data === false) {
674
-			throw new ShareNotFound('Can not find share with ID: ' . $id);
675
-		}
676
-
677
-		try {
678
-			$share = $this->createShareObject($data);
679
-		} catch (InvalidShare $e) {
680
-			throw new ShareNotFound();
681
-		}
682
-
683
-		return $share;
684
-	}
685
-
686
-	/**
687
-	 * Get shares for a given path
688
-	 *
689
-	 * @param Node $path
690
-	 * @return IShare[]
691
-	 */
692
-	public function getSharesByPath(Node $path) {
693
-		$qb = $this->dbConnection->getQueryBuilder();
694
-
695
-		// get federated user shares
696
-		$cursor = $qb->select('*')
697
-			->from('share')
698
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
699
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
700
-			->executeQuery();
701
-
702
-		$shares = [];
703
-		while ($data = $cursor->fetchAssociative()) {
704
-			$shares[] = $this->createShareObject($data);
705
-		}
706
-		$cursor->closeCursor();
707
-
708
-		return $shares;
709
-	}
710
-
711
-	/**
712
-	 * @inheritdoc
713
-	 */
714
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
715
-		/** @var IShare[] $shares */
716
-		$shares = [];
717
-
718
-		//Get shares directly with this user
719
-		$qb = $this->dbConnection->getQueryBuilder();
720
-		$qb->select('*')
721
-			->from('share');
722
-
723
-		// Order by id
724
-		$qb->orderBy('id');
725
-
726
-		// Set limit and offset
727
-		if ($limit !== -1) {
728
-			$qb->setMaxResults($limit);
729
-		}
730
-		$qb->setFirstResult($offset);
731
-
732
-		$qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
733
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
734
-
735
-		// Filter by node if provided
736
-		if ($node !== null) {
737
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
738
-		}
739
-
740
-		$cursor = $qb->executeQuery();
741
-
742
-		while ($data = $cursor->fetchAssociative()) {
743
-			$shares[] = $this->createShareObject($data);
744
-		}
745
-		$cursor->closeCursor();
746
-
747
-
748
-		return $shares;
749
-	}
750
-
751
-	/**
752
-	 * Get a share by token
753
-	 *
754
-	 * @param string $token
755
-	 * @return IShare
756
-	 * @throws ShareNotFound
757
-	 */
758
-	public function getShareByToken($token) {
759
-		$qb = $this->dbConnection->getQueryBuilder();
760
-
761
-		$cursor = $qb->select('*')
762
-			->from('share')
763
-			->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
764
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
765
-			->executeQuery();
766
-
767
-		$data = $cursor->fetchAssociative();
768
-
769
-		if ($data === false) {
770
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
771
-		}
772
-
773
-		try {
774
-			$share = $this->createShareObject($data);
775
-		} catch (InvalidShare $e) {
776
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
777
-		}
778
-
779
-		return $share;
780
-	}
781
-
782
-	/**
783
-	 * get database row of a give share
784
-	 *
785
-	 * @param $id
786
-	 * @return array
787
-	 * @throws ShareNotFound
788
-	 */
789
-	private function getRawShare($id) {
790
-		// Now fetch the inserted share and create a complete share object
791
-		$qb = $this->dbConnection->getQueryBuilder();
792
-		$qb->select('*')
793
-			->from('share')
794
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
795
-
796
-		$cursor = $qb->executeQuery();
797
-		$data = $cursor->fetchAssociative();
798
-		$cursor->closeCursor();
799
-
800
-		if ($data === false) {
801
-			throw new ShareNotFound;
802
-		}
803
-
804
-		return $data;
805
-	}
806
-
807
-	/**
808
-	 * Create a share object from an database row
809
-	 *
810
-	 * @param array $data
811
-	 * @return IShare
812
-	 * @throws InvalidShare
813
-	 * @throws ShareNotFound
814
-	 */
815
-	private function createShareObject($data) {
816
-		$share = new Share($this->rootFolder, $this->userManager);
817
-		$share->setId((int)$data['id'])
818
-			->setShareType((int)$data['share_type'])
819
-			->setPermissions((int)$data['permissions'])
820
-			->setTarget($data['file_target'])
821
-			->setMailSend((bool)$data['mail_send'])
822
-			->setStatus((int)$data['accepted'])
823
-			->setToken($data['token']);
824
-
825
-		$shareTime = new \DateTime();
826
-		$shareTime->setTimestamp((int)$data['stime']);
827
-		$share->setShareTime($shareTime);
828
-		$share->setSharedWith($data['share_with']);
829
-
830
-		if ($data['uid_initiator'] !== null) {
831
-			$share->setShareOwner($data['uid_owner']);
832
-			$share->setSharedBy($data['uid_initiator']);
833
-		} else {
834
-			//OLD SHARE
835
-			$share->setSharedBy($data['uid_owner']);
836
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
837
-
838
-			$owner = $path->getOwner();
839
-			$share->setShareOwner($owner->getUID());
840
-		}
841
-
842
-		$share->setNodeId((int)$data['file_source']);
843
-		$share->setNodeType($data['item_type']);
844
-
845
-		$share->setProviderId($this->identifier());
846
-
847
-		if ($data['expiration'] !== null) {
848
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
849
-			$share->setExpirationDate($expiration);
850
-		}
851
-
852
-		return $share;
853
-	}
854
-
855
-	/**
856
-	 * Get the node with file $id for $user
857
-	 *
858
-	 * @param string $userId
859
-	 * @param int $id
860
-	 * @return Node
861
-	 * @throws InvalidShare
862
-	 */
863
-	private function getNode($userId, $id) {
864
-		try {
865
-			$userFolder = $this->rootFolder->getUserFolder($userId);
866
-		} catch (NotFoundException $e) {
867
-			throw new InvalidShare();
868
-		}
869
-
870
-		$node = $userFolder->getFirstNodeById($id);
871
-
872
-		if (!$node) {
873
-			throw new InvalidShare();
874
-		}
875
-
876
-		return $node;
877
-	}
878
-
879
-	/**
880
-	 * A user is deleted from the system
881
-	 * So clean up the relevant shares.
882
-	 *
883
-	 * @param string $uid
884
-	 * @param int $shareType
885
-	 */
886
-	public function userDeleted($uid, $shareType) {
887
-		//TODO: probably a good idea to send unshare info to remote servers
888
-
889
-		$qb = $this->dbConnection->getQueryBuilder();
890
-		$qb->delete('share')
891
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
892
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
893
-			->executeStatement();
894
-
895
-		$qb = $this->dbConnection->getQueryBuilder();
896
-		$qb->delete('share_external')
897
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
898
-			->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($uid)))
899
-			->executeStatement();
900
-	}
901
-
902
-	public function groupDeleted($gid) {
903
-		$qb = $this->dbConnection->getQueryBuilder();
904
-		$qb->select('id')
905
-			->from('share_external')
906
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
907
-			// This is not a typo, the group ID is really stored in the 'user' column
908
-			->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($gid)));
909
-		$cursor = $qb->executeQuery();
910
-		$parentShareIds = $cursor->fetchFirstColumn();
911
-		$cursor->closeCursor();
912
-		if ($parentShareIds === []) {
913
-			return;
914
-		}
915
-
916
-		$qb = $this->dbConnection->getQueryBuilder();
917
-		$parentShareIdsParam = $qb->createNamedParameter($parentShareIds, IQueryBuilder::PARAM_INT_ARRAY);
918
-		$qb->delete('share_external')
919
-			->where($qb->expr()->in('id', $parentShareIdsParam))
920
-			->orWhere($qb->expr()->in('parent', $parentShareIdsParam))
921
-			->executeStatement();
922
-	}
923
-
924
-	public function userDeletedFromGroup($uid, $gid) {
925
-		$qb = $this->dbConnection->getQueryBuilder();
926
-		$qb->select('id')
927
-			->from('share_external')
928
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
929
-			// This is not a typo, the group ID is really stored in the 'user' column
930
-			->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($gid)));
931
-		$cursor = $qb->executeQuery();
932
-		$parentShareIds = $cursor->fetchFirstColumn();
933
-		$cursor->closeCursor();
934
-		if ($parentShareIds === []) {
935
-			return;
936
-		}
937
-
938
-		$qb = $this->dbConnection->getQueryBuilder();
939
-		$parentShareIdsParam = $qb->createNamedParameter($parentShareIds, IQueryBuilder::PARAM_INT_ARRAY);
940
-		$qb->delete('share_external')
941
-			->where($qb->expr()->in('parent', $parentShareIdsParam))
942
-			->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($uid)))
943
-			->executeStatement();
944
-	}
945
-
946
-	/**
947
-	 * Check if users from other Nextcloud instances are allowed to mount public links share by this instance
948
-	 */
949
-	public function isOutgoingServer2serverShareEnabled(): bool {
950
-		if ($this->gsConfig->onlyInternalFederation()) {
951
-			return false;
952
-		}
953
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
954
-		return $result === 'yes';
955
-	}
956
-
957
-	/**
958
-	 * Check if users are allowed to mount public links from other Nextclouds
959
-	 */
960
-	public function isIncomingServer2serverShareEnabled(): bool {
961
-		if ($this->gsConfig->onlyInternalFederation()) {
962
-			return false;
963
-		}
964
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
965
-		return $result === 'yes';
966
-	}
967
-
968
-
969
-	/**
970
-	 * Check if users from other Nextcloud instances are allowed to send federated group shares
971
-	 */
972
-	public function isOutgoingServer2serverGroupShareEnabled(): bool {
973
-		if ($this->gsConfig->onlyInternalFederation()) {
974
-			return false;
975
-		}
976
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
977
-		return $result === 'yes';
978
-	}
979
-
980
-	/**
981
-	 * Check if users are allowed to receive federated group shares
982
-	 */
983
-	public function isIncomingServer2serverGroupShareEnabled(): bool {
984
-		if ($this->gsConfig->onlyInternalFederation()) {
985
-			return false;
986
-		}
987
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
988
-		return $result === 'yes';
989
-	}
990
-
991
-	/**
992
-	 * Check if federated group sharing is supported, therefore the OCM API need to be enabled
993
-	 */
994
-	public function isFederatedGroupSharingSupported(): bool {
995
-		return $this->cloudFederationProviderManager->isReady();
996
-	}
997
-
998
-	/**
999
-	 * Check if querying sharees on the lookup server is enabled
1000
-	 */
1001
-	public function isLookupServerQueriesEnabled(): bool {
1002
-		// in a global scale setup we should always query the lookup server
1003
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1004
-			return true;
1005
-		}
1006
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no') === 'yes';
1007
-		// TODO: Reenable if lookup server is used again
1008
-		// return $result;
1009
-		return false;
1010
-	}
1011
-
1012
-
1013
-	/**
1014
-	 * Check if it is allowed to publish user specific data to the lookup server
1015
-	 */
1016
-	public function isLookupServerUploadEnabled(): bool {
1017
-		// in a global scale setup the admin is responsible to keep the lookup server up-to-date
1018
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1019
-			return false;
1020
-		}
1021
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'no') === 'yes';
1022
-		// TODO: Reenable if lookup server is used again
1023
-		// return $result;
1024
-		return false;
1025
-	}
1026
-
1027
-	/**
1028
-	 * Check if auto accepting incoming shares from trusted servers is enabled
1029
-	 */
1030
-	public function isFederatedTrustedShareAutoAccept(): bool {
1031
-		$result = $this->config->getAppValue('files_sharing', 'federatedTrustedShareAutoAccept', 'yes');
1032
-		return $result === 'yes';
1033
-	}
1034
-
1035
-	public function getAccessList($nodes, $currentAccess) {
1036
-		$ids = [];
1037
-		foreach ($nodes as $node) {
1038
-			$ids[] = $node->getId();
1039
-		}
1040
-
1041
-		$qb = $this->dbConnection->getQueryBuilder();
1042
-		$qb->select('share_with', 'token', 'file_source')
1043
-			->from('share')
1044
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
1045
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1046
-			->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)));
1047
-		$cursor = $qb->executeQuery();
1048
-
1049
-		if ($currentAccess === false) {
1050
-			$remote = $cursor->fetchAssociative() !== false;
1051
-			$cursor->closeCursor();
1052
-
1053
-			return ['remote' => $remote];
1054
-		}
1055
-
1056
-		$remote = [];
1057
-		while ($row = $cursor->fetchAssociative()) {
1058
-			$remote[$row['share_with']] = [
1059
-				'node_id' => $row['file_source'],
1060
-				'token' => $row['token'],
1061
-			];
1062
-		}
1063
-		$cursor->closeCursor();
1064
-
1065
-		return ['remote' => $remote];
1066
-	}
1067
-
1068
-	public function getAllShares(): iterable {
1069
-		$qb = $this->dbConnection->getQueryBuilder();
1070
-
1071
-		$qb->select('*')
1072
-			->from('share')
1073
-			->where($qb->expr()->in('share_type', $qb->createNamedParameter([IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE], IQueryBuilder::PARAM_INT_ARRAY)));
1074
-
1075
-		$cursor = $qb->executeQuery();
1076
-		while ($data = $cursor->fetchAssociative()) {
1077
-			try {
1078
-				$share = $this->createShareObject($data);
1079
-			} catch (InvalidShare $e) {
1080
-				continue;
1081
-			} catch (ShareNotFound $e) {
1082
-				continue;
1083
-			}
1084
-
1085
-			yield $share;
1086
-		}
1087
-		$cursor->closeCursor();
1088
-	}
431
+        return $share;
432
+    }
433
+
434
+    public function getChildren(IShare $parent): array {
435
+        $children = [];
436
+
437
+        $qb = $this->dbConnection->getQueryBuilder();
438
+        $qb->select('*')
439
+            ->from('share')
440
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
441
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
442
+            ->orderBy('id');
443
+
444
+        $cursor = $qb->executeQuery();
445
+        while ($data = $cursor->fetchAssociative()) {
446
+            $children[] = $this->createShareObject($data);
447
+        }
448
+        $cursor->closeCursor();
449
+
450
+        return $children;
451
+    }
452
+
453
+    /**
454
+     * Delete a share (owner unShares the file)
455
+     *
456
+     * @param IShare $share
457
+     * @throws ShareNotFound
458
+     * @throws HintException
459
+     */
460
+    public function delete(IShare $share) {
461
+        [, $remote] = $this->addressHandler->splitUserRemote($share->getSharedWith());
462
+
463
+        // if the local user is the owner we can send the unShare request directly...
464
+        if ($this->userManager->userExists($share->getShareOwner())) {
465
+            $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
466
+            $this->revokeShare($share, true);
467
+        } else { // ... if not we need to correct ID for the unShare request
468
+            $remoteId = $this->getRemoteId($share);
469
+            $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
470
+            $this->revokeShare($share, false);
471
+        }
472
+
473
+        // only remove the share when all messages are send to not lose information
474
+        // about the share to early
475
+        $this->removeShareFromTable($share);
476
+    }
477
+
478
+    /**
479
+     * in case of a re-share we need to send the other use (initiator or owner)
480
+     * a message that the file was unshared
481
+     *
482
+     * @param IShare $share
483
+     * @param bool $isOwner the user can either be the owner or the user who re-sahred it
484
+     * @throws ShareNotFound
485
+     * @throws HintException
486
+     */
487
+    protected function revokeShare($share, $isOwner) {
488
+        if ($this->userManager->userExists($share->getShareOwner()) && $this->userManager->userExists($share->getSharedBy())) {
489
+            // If both the owner and the initiator of the share are local users we don't have to notify anybody else
490
+            return;
491
+        }
492
+
493
+        // also send a unShare request to the initiator, if this is a different user than the owner
494
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
495
+            if ($isOwner) {
496
+                [, $remote] = $this->addressHandler->splitUserRemote($share->getSharedBy());
497
+            } else {
498
+                [, $remote] = $this->addressHandler->splitUserRemote($share->getShareOwner());
499
+            }
500
+            $remoteId = $this->getRemoteId($share);
501
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
502
+        }
503
+    }
504
+
505
+    /**
506
+     * remove share from table
507
+     *
508
+     * @param IShare $share
509
+     */
510
+    public function removeShareFromTable(IShare $share) {
511
+        $this->removeShareFromTableById($share->getId());
512
+    }
513
+
514
+    /**
515
+     * remove share from table
516
+     *
517
+     * @param string $shareId
518
+     */
519
+    private function removeShareFromTableById($shareId) {
520
+        $qb = $this->dbConnection->getQueryBuilder();
521
+        $qb->delete('share')
522
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
523
+            ->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
524
+        $qb->executeStatement();
525
+
526
+        $qb = $this->dbConnection->getQueryBuilder();
527
+        $qb->delete('federated_reshares')
528
+            ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
529
+        $qb->executeStatement();
530
+    }
531
+
532
+    /**
533
+     * @inheritdoc
534
+     */
535
+    public function deleteFromSelf(IShare $share, $recipient) {
536
+        // nothing to do here. Technically deleteFromSelf in the context of federated
537
+        // shares is a umount of an external storage. This is handled here
538
+        // apps/files_sharing/lib/external/manager.php
539
+        // TODO move this code over to this app
540
+    }
541
+
542
+    public function restore(IShare $share, string $recipient): IShare {
543
+        throw new GenericShareException('not implemented');
544
+    }
545
+
546
+
547
+    public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true) {
548
+        if (!$shallow) {
549
+            throw new \Exception('non-shallow getSharesInFolder is no longer supported');
550
+        }
551
+        return $this->getSharesInFolderInternal($userId, $node, $reshares);
552
+    }
553
+
554
+    public function getAllSharesInFolder(Folder $node): array {
555
+        return $this->getSharesInFolderInternal(null, $node, null);
556
+    }
557
+
558
+    /**
559
+     * @return array<int, list<IShare>>
560
+     */
561
+    private function getSharesInFolderInternal(?string $userId, Folder $node, ?bool $reshares): array {
562
+        $qb = $this->dbConnection->getQueryBuilder();
563
+        $qb->select('*')
564
+            ->from('share', 's')
565
+            ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)))
566
+            ->andWhere(
567
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
568
+            );
569
+
570
+        if ($userId !== null) {
571
+            /**
572
+             * Reshares for this user are shares where they are the owner.
573
+             */
574
+            if ($reshares !== true) {
575
+                $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
576
+            } else {
577
+                $qb->andWhere(
578
+                    $qb->expr()->orX(
579
+                        $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
580
+                        $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
581
+                    )
582
+                );
583
+            }
584
+        }
585
+
586
+        $qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
587
+
588
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
589
+
590
+        $qb->orderBy('id');
591
+
592
+        $cursor = $qb->executeQuery();
593
+        $shares = [];
594
+        while ($data = $cursor->fetchAssociative()) {
595
+            $shares[$data['fileid']][] = $this->createShareObject($data);
596
+        }
597
+        $cursor->closeCursor();
598
+
599
+        return $shares;
600
+    }
601
+
602
+    /**
603
+     * @inheritdoc
604
+     */
605
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
606
+        $qb = $this->dbConnection->getQueryBuilder();
607
+        $qb->select('*')
608
+            ->from('share');
609
+
610
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
611
+
612
+        /**
613
+         * Reshares for this user are shares where they are the owner.
614
+         */
615
+        if ($reshares === false) {
616
+            //Special case for old shares created via the web UI
617
+            $or1 = $qb->expr()->andX(
618
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
619
+                $qb->expr()->isNull('uid_initiator')
620
+            );
621
+
622
+            $qb->andWhere(
623
+                $qb->expr()->orX(
624
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
625
+                    $or1
626
+                )
627
+            );
628
+        } else {
629
+            $qb->andWhere(
630
+                $qb->expr()->orX(
631
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
632
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
633
+                )
634
+            );
635
+        }
636
+
637
+        if ($node !== null) {
638
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
639
+        }
640
+
641
+        if ($limit !== -1) {
642
+            $qb->setMaxResults($limit);
643
+        }
644
+
645
+        $qb->setFirstResult($offset);
646
+        $qb->orderBy('id');
647
+
648
+        $cursor = $qb->executeQuery();
649
+        $shares = [];
650
+        while ($data = $cursor->fetchAssociative()) {
651
+            $shares[] = $this->createShareObject($data);
652
+        }
653
+        $cursor->closeCursor();
654
+
655
+        return $shares;
656
+    }
657
+
658
+    /**
659
+     * @inheritdoc
660
+     */
661
+    public function getShareById($id, $recipientId = null) {
662
+        $qb = $this->dbConnection->getQueryBuilder();
663
+
664
+        $qb->select('*')
665
+            ->from('share')
666
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
667
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
668
+
669
+        $cursor = $qb->executeQuery();
670
+        $data = $cursor->fetchAssociative();
671
+        $cursor->closeCursor();
672
+
673
+        if ($data === false) {
674
+            throw new ShareNotFound('Can not find share with ID: ' . $id);
675
+        }
676
+
677
+        try {
678
+            $share = $this->createShareObject($data);
679
+        } catch (InvalidShare $e) {
680
+            throw new ShareNotFound();
681
+        }
682
+
683
+        return $share;
684
+    }
685
+
686
+    /**
687
+     * Get shares for a given path
688
+     *
689
+     * @param Node $path
690
+     * @return IShare[]
691
+     */
692
+    public function getSharesByPath(Node $path) {
693
+        $qb = $this->dbConnection->getQueryBuilder();
694
+
695
+        // get federated user shares
696
+        $cursor = $qb->select('*')
697
+            ->from('share')
698
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
699
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
700
+            ->executeQuery();
701
+
702
+        $shares = [];
703
+        while ($data = $cursor->fetchAssociative()) {
704
+            $shares[] = $this->createShareObject($data);
705
+        }
706
+        $cursor->closeCursor();
707
+
708
+        return $shares;
709
+    }
710
+
711
+    /**
712
+     * @inheritdoc
713
+     */
714
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
715
+        /** @var IShare[] $shares */
716
+        $shares = [];
717
+
718
+        //Get shares directly with this user
719
+        $qb = $this->dbConnection->getQueryBuilder();
720
+        $qb->select('*')
721
+            ->from('share');
722
+
723
+        // Order by id
724
+        $qb->orderBy('id');
725
+
726
+        // Set limit and offset
727
+        if ($limit !== -1) {
728
+            $qb->setMaxResults($limit);
729
+        }
730
+        $qb->setFirstResult($offset);
731
+
732
+        $qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
733
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
734
+
735
+        // Filter by node if provided
736
+        if ($node !== null) {
737
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
738
+        }
739
+
740
+        $cursor = $qb->executeQuery();
741
+
742
+        while ($data = $cursor->fetchAssociative()) {
743
+            $shares[] = $this->createShareObject($data);
744
+        }
745
+        $cursor->closeCursor();
746
+
747
+
748
+        return $shares;
749
+    }
750
+
751
+    /**
752
+     * Get a share by token
753
+     *
754
+     * @param string $token
755
+     * @return IShare
756
+     * @throws ShareNotFound
757
+     */
758
+    public function getShareByToken($token) {
759
+        $qb = $this->dbConnection->getQueryBuilder();
760
+
761
+        $cursor = $qb->select('*')
762
+            ->from('share')
763
+            ->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
764
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
765
+            ->executeQuery();
766
+
767
+        $data = $cursor->fetchAssociative();
768
+
769
+        if ($data === false) {
770
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
771
+        }
772
+
773
+        try {
774
+            $share = $this->createShareObject($data);
775
+        } catch (InvalidShare $e) {
776
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
777
+        }
778
+
779
+        return $share;
780
+    }
781
+
782
+    /**
783
+     * get database row of a give share
784
+     *
785
+     * @param $id
786
+     * @return array
787
+     * @throws ShareNotFound
788
+     */
789
+    private function getRawShare($id) {
790
+        // Now fetch the inserted share and create a complete share object
791
+        $qb = $this->dbConnection->getQueryBuilder();
792
+        $qb->select('*')
793
+            ->from('share')
794
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
795
+
796
+        $cursor = $qb->executeQuery();
797
+        $data = $cursor->fetchAssociative();
798
+        $cursor->closeCursor();
799
+
800
+        if ($data === false) {
801
+            throw new ShareNotFound;
802
+        }
803
+
804
+        return $data;
805
+    }
806
+
807
+    /**
808
+     * Create a share object from an database row
809
+     *
810
+     * @param array $data
811
+     * @return IShare
812
+     * @throws InvalidShare
813
+     * @throws ShareNotFound
814
+     */
815
+    private function createShareObject($data) {
816
+        $share = new Share($this->rootFolder, $this->userManager);
817
+        $share->setId((int)$data['id'])
818
+            ->setShareType((int)$data['share_type'])
819
+            ->setPermissions((int)$data['permissions'])
820
+            ->setTarget($data['file_target'])
821
+            ->setMailSend((bool)$data['mail_send'])
822
+            ->setStatus((int)$data['accepted'])
823
+            ->setToken($data['token']);
824
+
825
+        $shareTime = new \DateTime();
826
+        $shareTime->setTimestamp((int)$data['stime']);
827
+        $share->setShareTime($shareTime);
828
+        $share->setSharedWith($data['share_with']);
829
+
830
+        if ($data['uid_initiator'] !== null) {
831
+            $share->setShareOwner($data['uid_owner']);
832
+            $share->setSharedBy($data['uid_initiator']);
833
+        } else {
834
+            //OLD SHARE
835
+            $share->setSharedBy($data['uid_owner']);
836
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
837
+
838
+            $owner = $path->getOwner();
839
+            $share->setShareOwner($owner->getUID());
840
+        }
841
+
842
+        $share->setNodeId((int)$data['file_source']);
843
+        $share->setNodeType($data['item_type']);
844
+
845
+        $share->setProviderId($this->identifier());
846
+
847
+        if ($data['expiration'] !== null) {
848
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
849
+            $share->setExpirationDate($expiration);
850
+        }
851
+
852
+        return $share;
853
+    }
854
+
855
+    /**
856
+     * Get the node with file $id for $user
857
+     *
858
+     * @param string $userId
859
+     * @param int $id
860
+     * @return Node
861
+     * @throws InvalidShare
862
+     */
863
+    private function getNode($userId, $id) {
864
+        try {
865
+            $userFolder = $this->rootFolder->getUserFolder($userId);
866
+        } catch (NotFoundException $e) {
867
+            throw new InvalidShare();
868
+        }
869
+
870
+        $node = $userFolder->getFirstNodeById($id);
871
+
872
+        if (!$node) {
873
+            throw new InvalidShare();
874
+        }
875
+
876
+        return $node;
877
+    }
878
+
879
+    /**
880
+     * A user is deleted from the system
881
+     * So clean up the relevant shares.
882
+     *
883
+     * @param string $uid
884
+     * @param int $shareType
885
+     */
886
+    public function userDeleted($uid, $shareType) {
887
+        //TODO: probably a good idea to send unshare info to remote servers
888
+
889
+        $qb = $this->dbConnection->getQueryBuilder();
890
+        $qb->delete('share')
891
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
892
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
893
+            ->executeStatement();
894
+
895
+        $qb = $this->dbConnection->getQueryBuilder();
896
+        $qb->delete('share_external')
897
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
898
+            ->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($uid)))
899
+            ->executeStatement();
900
+    }
901
+
902
+    public function groupDeleted($gid) {
903
+        $qb = $this->dbConnection->getQueryBuilder();
904
+        $qb->select('id')
905
+            ->from('share_external')
906
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
907
+            // This is not a typo, the group ID is really stored in the 'user' column
908
+            ->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($gid)));
909
+        $cursor = $qb->executeQuery();
910
+        $parentShareIds = $cursor->fetchFirstColumn();
911
+        $cursor->closeCursor();
912
+        if ($parentShareIds === []) {
913
+            return;
914
+        }
915
+
916
+        $qb = $this->dbConnection->getQueryBuilder();
917
+        $parentShareIdsParam = $qb->createNamedParameter($parentShareIds, IQueryBuilder::PARAM_INT_ARRAY);
918
+        $qb->delete('share_external')
919
+            ->where($qb->expr()->in('id', $parentShareIdsParam))
920
+            ->orWhere($qb->expr()->in('parent', $parentShareIdsParam))
921
+            ->executeStatement();
922
+    }
923
+
924
+    public function userDeletedFromGroup($uid, $gid) {
925
+        $qb = $this->dbConnection->getQueryBuilder();
926
+        $qb->select('id')
927
+            ->from('share_external')
928
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
929
+            // This is not a typo, the group ID is really stored in the 'user' column
930
+            ->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($gid)));
931
+        $cursor = $qb->executeQuery();
932
+        $parentShareIds = $cursor->fetchFirstColumn();
933
+        $cursor->closeCursor();
934
+        if ($parentShareIds === []) {
935
+            return;
936
+        }
937
+
938
+        $qb = $this->dbConnection->getQueryBuilder();
939
+        $parentShareIdsParam = $qb->createNamedParameter($parentShareIds, IQueryBuilder::PARAM_INT_ARRAY);
940
+        $qb->delete('share_external')
941
+            ->where($qb->expr()->in('parent', $parentShareIdsParam))
942
+            ->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($uid)))
943
+            ->executeStatement();
944
+    }
945
+
946
+    /**
947
+     * Check if users from other Nextcloud instances are allowed to mount public links share by this instance
948
+     */
949
+    public function isOutgoingServer2serverShareEnabled(): bool {
950
+        if ($this->gsConfig->onlyInternalFederation()) {
951
+            return false;
952
+        }
953
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
954
+        return $result === 'yes';
955
+    }
956
+
957
+    /**
958
+     * Check if users are allowed to mount public links from other Nextclouds
959
+     */
960
+    public function isIncomingServer2serverShareEnabled(): bool {
961
+        if ($this->gsConfig->onlyInternalFederation()) {
962
+            return false;
963
+        }
964
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
965
+        return $result === 'yes';
966
+    }
967
+
968
+
969
+    /**
970
+     * Check if users from other Nextcloud instances are allowed to send federated group shares
971
+     */
972
+    public function isOutgoingServer2serverGroupShareEnabled(): bool {
973
+        if ($this->gsConfig->onlyInternalFederation()) {
974
+            return false;
975
+        }
976
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
977
+        return $result === 'yes';
978
+    }
979
+
980
+    /**
981
+     * Check if users are allowed to receive federated group shares
982
+     */
983
+    public function isIncomingServer2serverGroupShareEnabled(): bool {
984
+        if ($this->gsConfig->onlyInternalFederation()) {
985
+            return false;
986
+        }
987
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
988
+        return $result === 'yes';
989
+    }
990
+
991
+    /**
992
+     * Check if federated group sharing is supported, therefore the OCM API need to be enabled
993
+     */
994
+    public function isFederatedGroupSharingSupported(): bool {
995
+        return $this->cloudFederationProviderManager->isReady();
996
+    }
997
+
998
+    /**
999
+     * Check if querying sharees on the lookup server is enabled
1000
+     */
1001
+    public function isLookupServerQueriesEnabled(): bool {
1002
+        // in a global scale setup we should always query the lookup server
1003
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1004
+            return true;
1005
+        }
1006
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no') === 'yes';
1007
+        // TODO: Reenable if lookup server is used again
1008
+        // return $result;
1009
+        return false;
1010
+    }
1011
+
1012
+
1013
+    /**
1014
+     * Check if it is allowed to publish user specific data to the lookup server
1015
+     */
1016
+    public function isLookupServerUploadEnabled(): bool {
1017
+        // in a global scale setup the admin is responsible to keep the lookup server up-to-date
1018
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1019
+            return false;
1020
+        }
1021
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'no') === 'yes';
1022
+        // TODO: Reenable if lookup server is used again
1023
+        // return $result;
1024
+        return false;
1025
+    }
1026
+
1027
+    /**
1028
+     * Check if auto accepting incoming shares from trusted servers is enabled
1029
+     */
1030
+    public function isFederatedTrustedShareAutoAccept(): bool {
1031
+        $result = $this->config->getAppValue('files_sharing', 'federatedTrustedShareAutoAccept', 'yes');
1032
+        return $result === 'yes';
1033
+    }
1034
+
1035
+    public function getAccessList($nodes, $currentAccess) {
1036
+        $ids = [];
1037
+        foreach ($nodes as $node) {
1038
+            $ids[] = $node->getId();
1039
+        }
1040
+
1041
+        $qb = $this->dbConnection->getQueryBuilder();
1042
+        $qb->select('share_with', 'token', 'file_source')
1043
+            ->from('share')
1044
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
1045
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1046
+            ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)));
1047
+        $cursor = $qb->executeQuery();
1048
+
1049
+        if ($currentAccess === false) {
1050
+            $remote = $cursor->fetchAssociative() !== false;
1051
+            $cursor->closeCursor();
1052
+
1053
+            return ['remote' => $remote];
1054
+        }
1055
+
1056
+        $remote = [];
1057
+        while ($row = $cursor->fetchAssociative()) {
1058
+            $remote[$row['share_with']] = [
1059
+                'node_id' => $row['file_source'],
1060
+                'token' => $row['token'],
1061
+            ];
1062
+        }
1063
+        $cursor->closeCursor();
1064
+
1065
+        return ['remote' => $remote];
1066
+    }
1067
+
1068
+    public function getAllShares(): iterable {
1069
+        $qb = $this->dbConnection->getQueryBuilder();
1070
+
1071
+        $qb->select('*')
1072
+            ->from('share')
1073
+            ->where($qb->expr()->in('share_type', $qb->createNamedParameter([IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE], IQueryBuilder::PARAM_INT_ARRAY)));
1074
+
1075
+        $cursor = $qb->executeQuery();
1076
+        while ($data = $cursor->fetchAssociative()) {
1077
+            try {
1078
+                $share = $this->createShareObject($data);
1079
+            } catch (InvalidShare $e) {
1080
+                continue;
1081
+            } catch (ShareNotFound $e) {
1082
+                continue;
1083
+            }
1084
+
1085
+            yield $share;
1086
+        }
1087
+        $cursor->closeCursor();
1088
+    }
1089 1089
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -140,7 +140,7 @@  discard block
 block discarded – undo
140 140
 		if ($remoteShare) {
141 141
 			try {
142 142
 				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
143
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType, $expirationDate);
143
+				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_'.time(), $shareType, $expirationDate);
144 144
 				$share->setId($shareId);
145 145
 				[$token, $remoteId] = $this->askOwnerToReShare($shareWith, $share, $shareId);
146 146
 				// remote share was create successfully if we get a valid token as return
@@ -274,7 +274,7 @@  discard block
 block discarded – undo
274 274
 		$result = $qResult->fetchAllAssociative();
275 275
 		$qResult->closeCursor();
276 276
 
277
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
277
+		if (isset($result[0]) && (int) $result[0]['remote_id'] > 0) {
278 278
 			return $result[0];
279 279
 		}
280 280
 
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
 	public function getRemoteId(IShare $share): string {
409 409
 		$query = $this->dbConnection->getQueryBuilder();
410 410
 		$query->select('remote_id')->from('federated_reshares')
411
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
411
+			->where($query->expr()->eq('share_id', $query->createNamedParameter((int) $share->getId())));
412 412
 		$result = $query->executeQuery();
413 413
 		$data = $result->fetchAssociative();
414 414
 		$result->closeCursor();
@@ -417,7 +417,7 @@  discard block
 block discarded – undo
417 417
 			throw new ShareNotFound();
418 418
 		}
419 419
 
420
-		return (string)$data['remote_id'];
420
+		return (string) $data['remote_id'];
421 421
 	}
422 422
 
423 423
 	/**
@@ -671,7 +671,7 @@  discard block
 block discarded – undo
671 671
 		$cursor->closeCursor();
672 672
 
673 673
 		if ($data === false) {
674
-			throw new ShareNotFound('Can not find share with ID: ' . $id);
674
+			throw new ShareNotFound('Can not find share with ID: '.$id);
675 675
 		}
676 676
 
677 677
 		try {
@@ -814,16 +814,16 @@  discard block
 block discarded – undo
814 814
 	 */
815 815
 	private function createShareObject($data) {
816 816
 		$share = new Share($this->rootFolder, $this->userManager);
817
-		$share->setId((int)$data['id'])
818
-			->setShareType((int)$data['share_type'])
819
-			->setPermissions((int)$data['permissions'])
817
+		$share->setId((int) $data['id'])
818
+			->setShareType((int) $data['share_type'])
819
+			->setPermissions((int) $data['permissions'])
820 820
 			->setTarget($data['file_target'])
821
-			->setMailSend((bool)$data['mail_send'])
822
-			->setStatus((int)$data['accepted'])
821
+			->setMailSend((bool) $data['mail_send'])
822
+			->setStatus((int) $data['accepted'])
823 823
 			->setToken($data['token']);
824 824
 
825 825
 		$shareTime = new \DateTime();
826
-		$shareTime->setTimestamp((int)$data['stime']);
826
+		$shareTime->setTimestamp((int) $data['stime']);
827 827
 		$share->setShareTime($shareTime);
828 828
 		$share->setSharedWith($data['share_with']);
829 829
 
@@ -833,13 +833,13 @@  discard block
 block discarded – undo
833 833
 		} else {
834 834
 			//OLD SHARE
835 835
 			$share->setSharedBy($data['uid_owner']);
836
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
836
+			$path = $this->getNode($share->getSharedBy(), (int) $data['file_source']);
837 837
 
838 838
 			$owner = $path->getOwner();
839 839
 			$share->setShareOwner($owner->getUID());
840 840
 		}
841 841
 
842
-		$share->setNodeId((int)$data['file_source']);
842
+		$share->setNodeId((int) $data['file_source']);
843 843
 		$share->setNodeType($data['item_type']);
844 844
 
845 845
 		$share->setProviderId($this->identifier());
Please login to merge, or discard this patch.