Skip to content

Commit 2779940

Browse files
authored
Merge pull request #26191 from nextcloud/backport/25331/stable19
[stable19] Fix valid storages removed when cleaning remote storages
2 parents 0e30c82 + 05cbddd commit 2779940

File tree

5 files changed

+107
-5
lines changed

5 files changed

+107
-5
lines changed

.drone.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ steps:
833833
- bash tests/drone-run-integration-tests.sh || exit 0
834834
- ./occ maintenance:install --admin-pass=admin
835835
- cd build/integration
836-
- ./run.sh federation_features/federated.feature
836+
- ./run.sh federation_features/
837837

838838
trigger:
839839
branch:

apps/files_sharing/lib/Command/CleanupRemoteStorages.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
namespace OCA\Files_Sharing\Command;
2626

2727
use OCP\DB\QueryBuilder\IQueryBuilder;
28+
use OCP\Federation\ICloudIdManager;
2829
use OCP\IDBConnection;
2930
use Symfony\Component\Console\Command\Command;
3031
use Symfony\Component\Console\Input\InputInterface;
@@ -42,8 +43,14 @@ class CleanupRemoteStorages extends Command {
4243
*/
4344
protected $connection;
4445

45-
public function __construct(IDBConnection $connection) {
46+
/**
47+
* @var ICloudIdManager
48+
*/
49+
private $cloudIdManager;
50+
51+
public function __construct(IDBConnection $connection, ICloudIdManager $cloudIdManager) {
4652
$this->connection = $connection;
53+
$this->cloudIdManager = $cloudIdManager;
4754
parent::__construct();
4855
}
4956

@@ -165,14 +172,17 @@ public function getRemoteStorages() {
165172

166173
public function getRemoteShareIds() {
167174
$queryBuilder = $this->connection->getQueryBuilder();
168-
$queryBuilder->select(['id', 'share_token', 'remote'])
175+
$queryBuilder->select(['id', 'share_token', 'owner', 'remote'])
169176
->from('share_external');
170177
$query = $queryBuilder->execute();
171178

172179
$remoteShareIds = [];
173180

174181
while ($row = $query->fetch()) {
175-
$remoteShareIds[$row['id']] = 'shared::' . md5($row['share_token'] . '@' . $row['remote']);
182+
$cloudId = $this->cloudIdManager->getCloudId($row['owner'], $row['remote']);
183+
$remote = $cloudId->getRemote();
184+
185+
$remoteShareIds[$row['id']] = 'shared::' . md5($row['share_token'] . '@' . $remote);
176186
}
177187

178188
return $remoteShareIds;

apps/files_sharing/tests/Command/CleanupRemoteStoragesTest.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
namespace OCA\Files_Sharing\Tests\Command;
2626

2727
use OCA\Files_Sharing\Command\CleanupRemoteStorages;
28+
use OCP\Federation\ICloudId;
29+
use OCP\Federation\ICloudIdManager;
2830
use Symfony\Component\Console\Input\InputInterface;
2931
use Symfony\Component\Console\Output\OutputInterface;
3032
use Test\TestCase;
@@ -48,6 +50,11 @@ class CleanupRemoteStoragesTest extends TestCase {
4850
*/
4951
private $connection;
5052

53+
/**
54+
* @var ICloudIdManager|\PHPUnit\Framework\MockObject\MockObject
55+
*/
56+
private $cloudIdManager;
57+
5158
private $storages = [
5259
['id' => 'shared::7b4a322b22f9d0047c38d77d471ce3cf', 'share_token' => 'f2c69dad1dc0649f26976fd210fc62e1', 'remote' => 'https://hostname.tld/owncloud1', 'user' => 'user1'],
5360
['id' => 'shared::efe3b456112c3780da6155d3a9b9141c', 'share_token' => 'f2c69dad1dc0649f26976fd210fc62e2', 'remote' => 'https://hostname.tld/owncloud2', 'user' => 'user2'],
@@ -108,7 +115,9 @@ protected function setUp(): void {
108115
}
109116
}
110117

111-
$this->command = new CleanupRemoteStorages($this->connection);
118+
$this->cloudIdManager = $this->createMock(ICloudIdManager::class);
119+
120+
$this->command = new CleanupRemoteStorages($this->connection, $this->cloudIdManager);
112121
}
113122

114123
protected function tearDown(): void {
@@ -184,6 +193,22 @@ public function testCleanup() {
184193
->method('writeln')
185194
->with('5 remote share(s) exist');
186195

196+
$this->cloudIdManager
197+
->expects($this->any())
198+
->method('getCloudId')
199+
->will($this->returnCallback(function (string $user, string $remote) {
200+
$cloudIdMock = $this->createMock(ICloudId::class);
201+
202+
// The remotes are already sanitized in the original data, so
203+
// they can be directly returned.
204+
$cloudIdMock
205+
->expects($this->any())
206+
->method('getRemote')
207+
->willReturn($remote);
208+
209+
return $cloudIdMock;
210+
}));
211+
187212
$this->command->execute($input, $output);
188213

189214
$this->assertTrue($this->doesStorageExist($this->storages[0]['numeric_id']));

build/integration/features/bootstrap/FederationContext.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@
3636
class FederationContext implements Context, SnippetAcceptingContext {
3737
use WebDav;
3838
use AppConfiguration;
39+
use CommandLine;
40+
41+
/**
42+
* @BeforeScenario
43+
*/
44+
public function cleanupRemoteStorages() {
45+
// Ensure that dangling remote storages from previous tests will not
46+
// interfere with the current scenario.
47+
// The storages must be cleaned before each scenario; they can not be
48+
// cleaned after each scenario, as this hook is executed before the hook
49+
// that removes the users, so the shares would be still valid and thus
50+
// the storages would not be dangling yet.
51+
$this->runOcc(['sharing:cleanup-remote-storages']);
52+
}
3953

4054
/**
4155
* @Given /^User "([^"]*)" from server "(LOCAL|REMOTE)" shares "([^"]*)" with user "([^"]*)" from server "(LOCAL|REMOTE)"$/
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
Feature: cleanup-remote-storage
2+
Background:
3+
Given using api version "1"
4+
5+
Scenario: cleanup remote storage with active storages
6+
Given Using server "LOCAL"
7+
And user "user0" exists
8+
Given Using server "REMOTE"
9+
And user "user1" exists
10+
# Rename file so it has a unique name in the target server (as the target
11+
# server may have its own /textfile0.txt" file)
12+
And User "user1" copies file "/textfile0.txt" to "/remote-share.txt"
13+
And User "user1" from server "REMOTE" shares "/remote-share.txt" with user "user0" from server "LOCAL"
14+
And Using server "LOCAL"
15+
# Accept and download the file to ensure that a storage is created for the
16+
# federated share
17+
And User "user0" from server "LOCAL" accepts last pending share
18+
And As an "user0"
19+
And Downloading file "/remote-share.txt"
20+
And the HTTP status code should be "200"
21+
When invoking occ with "sharing:cleanup-remote-storage"
22+
Then the command was successful
23+
And the command output contains the text "1 remote storage(s) need(s) to be checked"
24+
And the command output contains the text "1 remote share(s) exist"
25+
And the command output contains the text "no storages deleted"
26+
27+
Scenario: cleanup remote storage with inactive storages
28+
Given Using server "LOCAL"
29+
And user "user0" exists
30+
Given Using server "REMOTE"
31+
And user "user1" exists
32+
# Rename file so it has a unique name in the target server (as the target
33+
# server may have its own /textfile0.txt" file)
34+
And User "user1" copies file "/textfile0.txt" to "/remote-share.txt"
35+
And User "user1" from server "REMOTE" shares "/remote-share.txt" with user "user0" from server "LOCAL"
36+
And Using server "LOCAL"
37+
# Accept and download the file to ensure that a storage is created for the
38+
# federated share
39+
And User "user0" from server "LOCAL" accepts last pending share
40+
And As an "user0"
41+
And Downloading file "/remote-share.txt"
42+
And the HTTP status code should be "200"
43+
And Using server "REMOTE"
44+
And As an "user1"
45+
And Deleting last share
46+
And the OCS status code should be "100"
47+
And the HTTP status code should be "200"
48+
When Using server "LOCAL"
49+
And invoking occ with "sharing:cleanup-remote-storage"
50+
Then the command was successful
51+
And the command output contains the text "1 remote storage(s) need(s) to be checked"
52+
And the command output contains the text "0 remote share(s) exist"
53+
And the command output contains the text "deleted 1 storage"

0 commit comments

Comments
 (0)