aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2018-10-08 16:21:31 +0200
committerChristoph Wurst <christoph@winzerhof-wurst.at>2018-10-08 16:21:31 +0200
commitd9783af7bdca7069d76a8e58c0d78d840a02715e (patch)
tree68d16a39e9880274bc8bd68287414b0c4f98a357
parentd5b53d0ede3c1dc40c9e347c4b33f2a68ff35dde (diff)
downloadnextcloud-server-d9783af7bdca7069d76a8e58c0d78d840a02715e.tar.gz
nextcloud-server-d9783af7bdca7069d76a8e58c0d78d840a02715e.zip
Remove outdated comment
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
-rw-r--r--core/js/js.js8
1 files changed, 0 insertions, 8 deletions
diff --git a/core/js/js.js b/core/js/js.js
index 197f375fe12..5c12031c5e4 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -1,11 +1,3 @@
-/**
- * Disable console output unless DEBUG mode is enabled.
- * Add
- * 'debug' => true,
- * To the definition of $CONFIG in config/config.php to enable debug mode.
- * The undefined checks fix the broken ie8 console
- */
-
/* global oc_isadmin */
var oc_debug;
='n140' href='#n140'>140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
<?php

declare(strict_types=1);

/**
 * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

namespace OC\Core\Command\Maintenance;

use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;

class RepairShareOwnership extends Command {
	public function __construct(
		private IDBConnection $dbConnection,
		private IUserManager $userManager,
	) {
		parent::__construct();
	}

	protected function configure() {
		$this
			->setName('maintenance:repair-share-owner')
			->setDescription('repair invalid share-owner entries in the database')
			->addOption('no-confirm', 'y', InputOption::VALUE_NONE, "Don't ask for confirmation before repairing the shares")
			->addArgument('user', InputArgument::OPTIONAL, "User to fix incoming shares for, if omitted all users will be fixed");
	}

	protected function execute(InputInterface $input, OutputInterface $output): int {
		$noConfirm = $input->getOption('no-confirm');
		$userId = $input->getArgument('user');
		if ($userId) {
			$user = $this->userManager->get($userId);
			if (!$user) {
				$output->writeln("<error>user $userId not found</error>");
				return 1;
			}
			$shares = $this->getWrongShareOwnershipForUser($user);
		} else {
			$shares = $this->getWrongShareOwnership();
		}

		if ($shares) {
			$output->writeln("");
			$output->writeln("Found " . count($shares) . " shares with invalid share owner");
			foreach ($shares as $share) {
				/** @var array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string} $share */
				$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']}\"");
			}
			$output->writeln("");

			if (!$noConfirm) {
				$helper = $this->getHelper('question');
				$question = new ConfirmationQuestion('Repair these shares? [y/N]', false);

				if (!$helper->ask($input, $output, $question)) {
					return 0;
				}
			}
			$output->writeln("Repairing " . count($shares) . " shares");
			$this->repairShares($shares);
		} else {
			$output->writeln("Found no shares with invalid share owner");
		}

		return 0;
	}

	/**
	 * @return array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[]
	 * @throws \OCP\DB\Exception
	 */
	protected function getWrongShareOwnership(): array {
		$qb = $this->dbConnection->getQueryBuilder();
		$brokenShares = $qb
			->select('s.id', 'm.user_id', 's.uid_owner', 's.uid_initiator', 's.share_with', 's.file_target')
			->from('share', 's')
			->join('s', 'filecache', 'f', $qb->expr()->eq('s.item_source', $qb->expr()->castColumn('f.fileid', IQueryBuilder::PARAM_STR)))
			->join('s', 'mounts', 'm', $qb->expr()->eq('f.storage', 'm.storage_id'))
			->where($qb->expr()->neq('m.user_id', 's.uid_owner'))
			->andWhere($qb->expr()->eq($qb->func()->concat($qb->expr()->literal('/'), 'm.user_id', $qb->expr()->literal('/')), 'm.mount_point'))
			->executeQuery()
			->fetchAll();

		$found = [];

		foreach ($brokenShares as $share) {
			$found[] = [
				'shareId' => (int) $share['id'],
				'fileTarget' => $share['file_target'],
				'initiator' => $share['uid_initiator'],
				'receiver' => $share['share_with'],
				'owner' => $share['uid_owner'],
				'mountOwner' => $share['user_id'],
			];
		}

		return $found;
	}

	/**
	 * @param IUser $user
	 * @return array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[]
	 * @throws \OCP\DB\Exception
	 */
	protected function getWrongShareOwnershipForUser(IUser $user): array {
		$qb = $this->dbConnection->getQueryBuilder();
		$brokenShares = $qb
			->select('s.id', 'm.user_id', 's.uid_owner', 's.uid_initiator', 's.share_with', 's.file_target')
			->from('share', 's')
			->join('s', 'filecache', 'f', $qb->expr()->eq('s.item_source', $qb->expr()->castColumn('f.fileid', IQueryBuilder::PARAM_STR)))
			->join('s', 'mounts', 'm', $qb->expr()->eq('f.storage', 'm.storage_id'))
			->where($qb->expr()->neq('m.user_id', 's.uid_owner'))
			->andWhere($qb->expr()->eq($qb->func()->concat($qb->expr()->literal('/'), 'm.user_id', $qb->expr()->literal('/')), 'm.mount_point'))
			->andWhere($qb->expr()->eq('s.share_with', $qb->createNamedParameter($user->getUID())))
			->executeQuery()
			->fetchAll();

		$found = [];

		foreach ($brokenShares as $share) {
			$found[] = [
				'shareId' => (int) $share['id'],
				'fileTarget' => $share['file_target'],
				'initiator' => $share['uid_initiator'],
				'receiver' => $share['share_with'],
				'owner' => $share['uid_owner'],
				'mountOwner' => $share['user_id'],
			];
		}

		return $found;
	}

	/**
	 * @param array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[] $shares
	 * @return void
	 */
	protected function repairShares(array $shares) {
		$this->dbConnection->beginTransaction();

		$update = $this->dbConnection->getQueryBuilder();
		$update->update('share')
			->set('uid_owner', $update->createParameter('share_owner'))
			->set('uid_initiator', $update->createParameter('share_initiator'))
			->where($update->expr()->eq('id', $update->createParameter('share_id')));

		foreach ($shares as $share) {
			/** @var array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string} $share */
			$update->setParameter('share_id', $share['shareId'], IQueryBuilder::PARAM_INT);
			$update->setParameter('share_owner', $share['mountOwner']);

			// if the broken owner is also the initiator it's safe to update them both, otherwise we don't touch the initiator
			if ($share['initiator'] === $share['owner']) {
				$update->setParameter('share_initiator', $share['mountOwner']);
			} else {
				$update->setParameter('share_initiator', $share['initiator']);
			}
			$update->executeStatement();
		}

		$this->dbConnection->commit();
	}
}