Passed
Push — master ( aded13...d42d8b )
by Christoph
25:54 queued 10:56
created
core/Command/Maintenance/RepairShareOwnership.php 2 patches
Indentation   +155 added lines, -155 removed lines patch added patch discarded remove patch
@@ -38,159 +38,159 @@
 block discarded – undo
38 38
 use Symfony\Component\Console\Question\ConfirmationQuestion;
39 39
 
40 40
 class RepairShareOwnership extends Command {
41
-	private IDBConnection $dbConnection;
42
-	private IUserManager $userManager;
43
-
44
-	public function __construct(
45
-		IDBConnection $dbConnection,
46
-		IUserManager $userManager
47
-	) {
48
-		$this->dbConnection = $dbConnection;
49
-		$this->userManager = $userManager;
50
-		parent::__construct();
51
-	}
52
-
53
-	protected function configure() {
54
-		$this
55
-			->setName('maintenance:repair-share-owner')
56
-			->setDescription('repair invalid share-owner entries in the database')
57
-			->addOption('no-confirm', 'y', InputOption::VALUE_NONE, "Don't ask for confirmation before repairing the shares")
58
-			->addArgument('user', InputArgument::OPTIONAL, "User to fix incoming shares for, if omitted all users will be fixed");
59
-	}
60
-
61
-	protected function execute(InputInterface $input, OutputInterface $output): int {
62
-		$noConfirm = $input->getOption('no-confirm');
63
-		$userId = $input->getArgument('user');
64
-		if ($userId) {
65
-			$user = $this->userManager->get($userId);
66
-			if (!$user) {
67
-				$output->writeln("<error>user $userId not found</error>");
68
-				return 1;
69
-			}
70
-			$shares = $this->getWrongShareOwnershipForUser($user);
71
-		} else {
72
-			$shares = $this->getWrongShareOwnership();
73
-		}
74
-
75
-		if ($shares) {
76
-			$output->writeln("");
77
-			$output->writeln("Found " . count($shares) . " shares with invalid share owner");
78
-			foreach ($shares as $share) {
79
-				/** @var array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string} $share */
80
-				$output->writeln(" - share {$share['shareId']} from \"{$share['initiator']}\" to \"{$share['receiver']}\" at \"{$share['fileTarget']}\", owned by \"{$share['owner']}\", that should be owned by \"{$share['mountOwner']}\"");
81
-			}
82
-			$output->writeln("");
83
-
84
-			if (!$noConfirm) {
85
-				$helper = $this->getHelper('question');
86
-				$question = new ConfirmationQuestion('Repair these shares? [y/N]', false);
87
-
88
-				if (!$helper->ask($input, $output, $question)) {
89
-					return 0;
90
-				}
91
-			}
92
-			$output->writeln("Repairing " . count($shares) . " shares");
93
-			$this->repairShares($shares);
94
-		} else {
95
-			$output->writeln("Found no shares with invalid share owner");
96
-		}
97
-
98
-		return 0;
99
-	}
100
-
101
-	/**
102
-	 * @return array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[]
103
-	 * @throws \OCP\DB\Exception
104
-	 */
105
-	protected function getWrongShareOwnership(): array {
106
-		$qb = $this->dbConnection->getQueryBuilder();
107
-		$brokenShares = $qb
108
-			->select('s.id', 'm.user_id', 's.uid_owner', 's.uid_initiator', 's.share_with', 's.file_target')
109
-			->from('share', 's')
110
-			->join('s', 'filecache', 'f', $qb->expr()->eq('s.item_source', $qb->expr()->castColumn('f.fileid', IQueryBuilder::PARAM_STR)))
111
-			->join('s', 'mounts', 'm', $qb->expr()->eq('f.storage', 'm.storage_id'))
112
-			->where($qb->expr()->neq('m.user_id', 's.uid_owner'))
113
-			->andWhere($qb->expr()->eq($qb->func()->concat($qb->expr()->literal('/'), 'm.user_id', $qb->expr()->literal('/')), 'm.mount_point'))
114
-			->executeQuery()
115
-			->fetchAll();
116
-
117
-		$found = [];
118
-
119
-		foreach ($brokenShares as $share) {
120
-			$found[] = [
121
-				'shareId' => (int) $share['id'],
122
-				'fileTarget' => $share['file_target'],
123
-				'initiator' => $share['uid_initiator'],
124
-				'receiver' => $share['share_with'],
125
-				'owner' => $share['uid_owner'],
126
-				'mountOwner' => $share['user_id'],
127
-			];
128
-		}
129
-
130
-		return $found;
131
-	}
132
-
133
-	/**
134
-	 * @param IUser $user
135
-	 * @return array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[]
136
-	 * @throws \OCP\DB\Exception
137
-	 */
138
-	protected function getWrongShareOwnershipForUser(IUser $user): array {
139
-		$qb = $this->dbConnection->getQueryBuilder();
140
-		$brokenShares = $qb
141
-			->select('s.id', 'm.user_id', 's.uid_owner', 's.uid_initiator', 's.share_with', 's.file_target')
142
-			->from('share', 's')
143
-			->join('s', 'filecache', 'f', $qb->expr()->eq('s.item_source', $qb->expr()->castColumn('f.fileid', IQueryBuilder::PARAM_STR)))
144
-			->join('s', 'mounts', 'm', $qb->expr()->eq('f.storage', 'm.storage_id'))
145
-			->where($qb->expr()->neq('m.user_id', 's.uid_owner'))
146
-			->andWhere($qb->expr()->eq($qb->func()->concat($qb->expr()->literal('/'), 'm.user_id', $qb->expr()->literal('/')), 'm.mount_point'))
147
-			->andWhere($qb->expr()->eq('s.share_with', $qb->createNamedParameter($user->getUID())))
148
-			->executeQuery()
149
-			->fetchAll();
150
-
151
-		$found = [];
152
-
153
-		foreach ($brokenShares as $share) {
154
-			$found[] = [
155
-				'shareId' => (int) $share['id'],
156
-				'fileTarget' => $share['file_target'],
157
-				'initiator' => $share['uid_initiator'],
158
-				'receiver' => $share['share_with'],
159
-				'owner' => $share['uid_owner'],
160
-				'mountOwner' => $share['user_id'],
161
-			];
162
-		}
163
-
164
-		return $found;
165
-	}
166
-
167
-	/**
168
-	 * @param array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[] $shares
169
-	 * @return void
170
-	 */
171
-	protected function repairShares(array $shares) {
172
-		$this->dbConnection->beginTransaction();
173
-
174
-		$update = $this->dbConnection->getQueryBuilder();
175
-		$update->update('share')
176
-			->set('uid_owner', $update->createParameter('share_owner'))
177
-			->set('uid_initiator', $update->createParameter('share_initiator'))
178
-			->where($update->expr()->eq('id', $update->createParameter('share_id')));
179
-
180
-		foreach ($shares as $share) {
181
-			/** @var array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string} $share */
182
-			$update->setParameter('share_id', $share['shareId'], IQueryBuilder::PARAM_INT);
183
-			$update->setParameter('share_owner', $share['mountOwner']);
184
-
185
-			// if the broken owner is also the initiator it's safe to update them both, otherwise we don't touch the initiator
186
-			if ($share['initiator'] === $share['owner']) {
187
-				$update->setParameter('share_initiator', $share['mountOwner']);
188
-			} else {
189
-				$update->setParameter('share_initiator', $share['initiator']);
190
-			}
191
-			$update->executeStatement();
192
-		}
193
-
194
-		$this->dbConnection->commit();
195
-	}
41
+    private IDBConnection $dbConnection;
42
+    private IUserManager $userManager;
43
+
44
+    public function __construct(
45
+        IDBConnection $dbConnection,
46
+        IUserManager $userManager
47
+    ) {
48
+        $this->dbConnection = $dbConnection;
49
+        $this->userManager = $userManager;
50
+        parent::__construct();
51
+    }
52
+
53
+    protected function configure() {
54
+        $this
55
+            ->setName('maintenance:repair-share-owner')
56
+            ->setDescription('repair invalid share-owner entries in the database')
57
+            ->addOption('no-confirm', 'y', InputOption::VALUE_NONE, "Don't ask for confirmation before repairing the shares")
58
+            ->addArgument('user', InputArgument::OPTIONAL, "User to fix incoming shares for, if omitted all users will be fixed");
59
+    }
60
+
61
+    protected function execute(InputInterface $input, OutputInterface $output): int {
62
+        $noConfirm = $input->getOption('no-confirm');
63
+        $userId = $input->getArgument('user');
64
+        if ($userId) {
65
+            $user = $this->userManager->get($userId);
66
+            if (!$user) {
67
+                $output->writeln("<error>user $userId not found</error>");
68
+                return 1;
69
+            }
70
+            $shares = $this->getWrongShareOwnershipForUser($user);
71
+        } else {
72
+            $shares = $this->getWrongShareOwnership();
73
+        }
74
+
75
+        if ($shares) {
76
+            $output->writeln("");
77
+            $output->writeln("Found " . count($shares) . " shares with invalid share owner");
78
+            foreach ($shares as $share) {
79
+                /** @var array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string} $share */
80
+                $output->writeln(" - share {$share['shareId']} from \"{$share['initiator']}\" to \"{$share['receiver']}\" at \"{$share['fileTarget']}\", owned by \"{$share['owner']}\", that should be owned by \"{$share['mountOwner']}\"");
81
+            }
82
+            $output->writeln("");
83
+
84
+            if (!$noConfirm) {
85
+                $helper = $this->getHelper('question');
86
+                $question = new ConfirmationQuestion('Repair these shares? [y/N]', false);
87
+
88
+                if (!$helper->ask($input, $output, $question)) {
89
+                    return 0;
90
+                }
91
+            }
92
+            $output->writeln("Repairing " . count($shares) . " shares");
93
+            $this->repairShares($shares);
94
+        } else {
95
+            $output->writeln("Found no shares with invalid share owner");
96
+        }
97
+
98
+        return 0;
99
+    }
100
+
101
+    /**
102
+     * @return array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[]
103
+     * @throws \OCP\DB\Exception
104
+     */
105
+    protected function getWrongShareOwnership(): array {
106
+        $qb = $this->dbConnection->getQueryBuilder();
107
+        $brokenShares = $qb
108
+            ->select('s.id', 'm.user_id', 's.uid_owner', 's.uid_initiator', 's.share_with', 's.file_target')
109
+            ->from('share', 's')
110
+            ->join('s', 'filecache', 'f', $qb->expr()->eq('s.item_source', $qb->expr()->castColumn('f.fileid', IQueryBuilder::PARAM_STR)))
111
+            ->join('s', 'mounts', 'm', $qb->expr()->eq('f.storage', 'm.storage_id'))
112
+            ->where($qb->expr()->neq('m.user_id', 's.uid_owner'))
113
+            ->andWhere($qb->expr()->eq($qb->func()->concat($qb->expr()->literal('/'), 'm.user_id', $qb->expr()->literal('/')), 'm.mount_point'))
114
+            ->executeQuery()
115
+            ->fetchAll();
116
+
117
+        $found = [];
118
+
119
+        foreach ($brokenShares as $share) {
120
+            $found[] = [
121
+                'shareId' => (int) $share['id'],
122
+                'fileTarget' => $share['file_target'],
123
+                'initiator' => $share['uid_initiator'],
124
+                'receiver' => $share['share_with'],
125
+                'owner' => $share['uid_owner'],
126
+                'mountOwner' => $share['user_id'],
127
+            ];
128
+        }
129
+
130
+        return $found;
131
+    }
132
+
133
+    /**
134
+     * @param IUser $user
135
+     * @return array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[]
136
+     * @throws \OCP\DB\Exception
137
+     */
138
+    protected function getWrongShareOwnershipForUser(IUser $user): array {
139
+        $qb = $this->dbConnection->getQueryBuilder();
140
+        $brokenShares = $qb
141
+            ->select('s.id', 'm.user_id', 's.uid_owner', 's.uid_initiator', 's.share_with', 's.file_target')
142
+            ->from('share', 's')
143
+            ->join('s', 'filecache', 'f', $qb->expr()->eq('s.item_source', $qb->expr()->castColumn('f.fileid', IQueryBuilder::PARAM_STR)))
144
+            ->join('s', 'mounts', 'm', $qb->expr()->eq('f.storage', 'm.storage_id'))
145
+            ->where($qb->expr()->neq('m.user_id', 's.uid_owner'))
146
+            ->andWhere($qb->expr()->eq($qb->func()->concat($qb->expr()->literal('/'), 'm.user_id', $qb->expr()->literal('/')), 'm.mount_point'))
147
+            ->andWhere($qb->expr()->eq('s.share_with', $qb->createNamedParameter($user->getUID())))
148
+            ->executeQuery()
149
+            ->fetchAll();
150
+
151
+        $found = [];
152
+
153
+        foreach ($brokenShares as $share) {
154
+            $found[] = [
155
+                'shareId' => (int) $share['id'],
156
+                'fileTarget' => $share['file_target'],
157
+                'initiator' => $share['uid_initiator'],
158
+                'receiver' => $share['share_with'],
159
+                'owner' => $share['uid_owner'],
160
+                'mountOwner' => $share['user_id'],
161
+            ];
162
+        }
163
+
164
+        return $found;
165
+    }
166
+
167
+    /**
168
+     * @param array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[] $shares
169
+     * @return void
170
+     */
171
+    protected function repairShares(array $shares) {
172
+        $this->dbConnection->beginTransaction();
173
+
174
+        $update = $this->dbConnection->getQueryBuilder();
175
+        $update->update('share')
176
+            ->set('uid_owner', $update->createParameter('share_owner'))
177
+            ->set('uid_initiator', $update->createParameter('share_initiator'))
178
+            ->where($update->expr()->eq('id', $update->createParameter('share_id')));
179
+
180
+        foreach ($shares as $share) {
181
+            /** @var array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string} $share */
182
+            $update->setParameter('share_id', $share['shareId'], IQueryBuilder::PARAM_INT);
183
+            $update->setParameter('share_owner', $share['mountOwner']);
184
+
185
+            // if the broken owner is also the initiator it's safe to update them both, otherwise we don't touch the initiator
186
+            if ($share['initiator'] === $share['owner']) {
187
+                $update->setParameter('share_initiator', $share['mountOwner']);
188
+            } else {
189
+                $update->setParameter('share_initiator', $share['initiator']);
190
+            }
191
+            $update->executeStatement();
192
+        }
193
+
194
+        $this->dbConnection->commit();
195
+    }
196 196
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
 
75 75
 		if ($shares) {
76 76
 			$output->writeln("");
77
-			$output->writeln("Found " . count($shares) . " shares with invalid share owner");
77
+			$output->writeln("Found ".count($shares)." shares with invalid share owner");
78 78
 			foreach ($shares as $share) {
79 79
 				/** @var array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string} $share */
80 80
 				$output->writeln(" - share {$share['shareId']} from \"{$share['initiator']}\" to \"{$share['receiver']}\" at \"{$share['fileTarget']}\", owned by \"{$share['owner']}\", that should be owned by \"{$share['mountOwner']}\"");
@@ -89,7 +89,7 @@  discard block
 block discarded – undo
89 89
 					return 0;
90 90
 				}
91 91
 			}
92
-			$output->writeln("Repairing " . count($shares) . " shares");
92
+			$output->writeln("Repairing ".count($shares)." shares");
93 93
 			$this->repairShares($shares);
94 94
 		} else {
95 95
 			$output->writeln("Found no shares with invalid share owner");
Please login to merge, or discard this patch.