Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 117 additions & 34 deletions core/Command/User/SyncBackend.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php
/**
* @author Jörn Friedrich Dreyer <[email protected]>
* @author Thomas Müller <[email protected]>
*
* @copyright Copyright (c) 2017, ownCloud GmbH
Expand All @@ -22,15 +23,17 @@
namespace OC\Core\Command\User;


use OC\Migration\ConsoleOutput;
use OC\User\AccountMapper;
use OC\User\SyncService;
use OC\User\SyncServiceCallback;
use OCP\IConfig;
use OCP\ILogger;
use OCP\IUser;
use OCP\IUserManager;
use OCP\UserInterface;
use OCP\Util;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand All @@ -48,6 +51,13 @@ class SyncBackend extends Command {
/** @var ILogger */
private $logger;

private $verbosityLevelMap = array(
OutputInterface::VERBOSITY_QUIET => Util::ERROR,
OutputInterface::VERBOSITY_NORMAL => Util::WARN,
OutputInterface::VERBOSITY_VERBOSE => Util::INFO,
OutputInterface::VERBOSITY_VERY_VERBOSE => Util::DEBUG,
OutputInterface::VERBOSITY_DEBUG => Util::DEBUG,
);
/**
* @param AccountMapper $accountMapper
* @param IConfig $config
Expand Down Expand Up @@ -75,6 +85,7 @@ protected function configure() {
'The php class name - e.g. "OCA\User_LDAP\User_Proxy". Please wrap the class name into double quotes. You can use the option --list to list all known backend classes'
)
->addOption('list', 'l', InputOption::VALUE_NONE, 'list all known backend classes')
->addOption('userid', 'u', InputOption::VALUE_REQUIRED, 'sync only the user with the given id')
->addOption('missing-account-action', 'm', InputOption::VALUE_REQUIRED, 'action to do if the account isn\'t connected to a backend any longer. Options are "disable" and "remove". Use quotes. Note that removing the account will also remove the stored data and files for that account');
}

Expand Down Expand Up @@ -103,8 +114,8 @@ protected function execute(InputInterface $input, OutputInterface $output) {

$validActions = ['disable', 'remove'];

if ($input->getOption('missing-account-action') !== null) {
$missingAccountsAction = $input->getOption('missing-account-action');
$missingAccountsAction = $input->getOption('missing-account-action');
if ($missingAccountsAction !== null) {
if (!in_array($missingAccountsAction, $validActions, true)) {
$output->writeln("<error>Unknown action. Choose between \"disable\" or \"remove\"</error>");
return 1;
Expand All @@ -122,27 +133,108 @@ protected function execute(InputInterface $input, OutputInterface $output) {

$syncService = new SyncService($this->accountMapper, $backend, $this->config, $this->logger);

// analyse unknown users
$this->handleUnknownUsers($input, $output, $syncService, $missingAccountsAction, $validActions);

// insert/update known users
$output->writeln("Insert new and update existing users ...");
$p = new ProgressBar($output);
$max = null;
if ($backend->implementsActions(\OC_User_Backend::COUNT_USERS)) {
$max = $backend->countUsers();
$userid = $input->getOption('userid');
$consoleOutput = new ConsoleOutput($output);

if ($userid) {
$this->syncSingleUser($userid, $input, $output, $consoleOutput, $syncService, $backend, $missingAccountsAction, $validActions);
} else {
$this->syncMultipleUsers($input, $output, $consoleOutput, $syncService, $backend, $missingAccountsAction, $validActions);
}
$p->start($max);
$syncService->run(function () use ($p) {
$p->advance();
});
$p->finish();

$output->writeln('');
$output->writeln('');

return 0;
}

/**
* @param InputInterface $input
* @param OutputInterface $output
* @param ConsoleOutput $consoleOutput
* @param SyncService $syncService
* @param UserInterface $backend
* @param string $missingAccountsAction
* @param array $validActions
*/
private function syncMultipleUsers (
InputInterface $input,
OutputInterface $output,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather get the OutputInterface from the ConsoleOutput instead of sending it raw here.

Ideally, we shouldn't need to get the OutputInterface, so we should use one or another, but if we need the ConsoleOutput, it should be possible to get the OutputInterface from it.

ConsoleOutput $consoleOutput,
SyncService $syncService,
UserInterface $backend,
$missingAccountsAction,
array $validActions
) {

$output->writeln("Analyzing synced users ...");
$consoleOutput->startProgress($this->accountMapper->getUserCount(false));
$unknownUsers = $syncService->getNoLongerExistingUsers(function () use ($consoleOutput) {
$consoleOutput->advance();
});
$consoleOutput->finishProgress();
$output->writeln('');
$output->writeln('');

$this->handleUnknownUsers($unknownUsers, $input, $output, $missingAccountsAction, $validActions);

// insert/update known users
if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only if the verbosity is normal, or if it's normal or greater?

if ($backend->implementsActions(\OC_User_Backend::COUNT_USERS)) {
$consoleOutput->startProgress($backend->countUsers());
} else {
$consoleOutput->startProgress();
}
}

$syncService->run(new SyncServiceCallback(
$consoleOutput,
$this->verbosityLevelMap[$output->getVerbosity()]
));

if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

$consoleOutput->finishProgress();
}
}

/**
* @param InputInterface $input
* @param OutputInterface $output
* @param ConsoleOutput $consoleOutput
* @param SyncService $syncService
* @param UserInterface $backend
* @param string $missingAccountsAction
* @param array $validActions
*/
private function syncSingleUser(
$uid,
InputInterface $input,
OutputInterface $output,
ConsoleOutput $consoleOutput,
SyncService $syncService,
UserInterface $backend,
$missingAccountsAction,
array $validActions
) {

$output->writeln("Analyzing {$uid} ...");
if (!$backend->userExists($uid)) {
$this->handleUnknownUsers([$uid], $input, $output, $missingAccountsAction, $validActions);
} else {
// sync
// use at least Verbose output
if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
$logLevel = $this->verbosityLevelMap[OutputInterface::VERBOSITY_VERBOSE];
} else {
$logLevel = $this->verbosityLevelMap[$output->getVerbosity()];
}
$syncService->syncUser($uid, new SyncServiceCallback(
$consoleOutput, $logLevel
));
}
}
/**
* @param $backend
* @return null|UserInterface
Expand Down Expand Up @@ -177,30 +269,21 @@ private function doActionForAccountUids(array $uids, callable $callbackExists, c
}

/**
* @param string[] $userIds
* @param InputInterface $input
* @param OutputInterface $output
* @param $syncService
* @param $missingAccountsAction
* @param $validActions
* @param string $missingAccountsAction
* @param array $validActions
*/
private function handleUnknownUsers(InputInterface $input, OutputInterface $output, $syncService, $missingAccountsAction, $validActions) {
$output->writeln("Analyse unknown users ...");
$p = new ProgressBar($output);
$toBeDeleted = $syncService->getNoLongerExistingUsers(function () use ($p) {
$p->advance();
});
$p->finish();
$output->writeln('');
$output->writeln('');

if (empty($toBeDeleted)) {
private function handleUnknownUsers(array $userIds, InputInterface $input, OutputInterface $output, $missingAccountsAction, $validActions) {
if (empty($userIds)) {
$output->writeln("No unknown users have been detected.");
} else {
$output->writeln("Following users are no longer known with the connected backend.");
switch ($missingAccountsAction) {
case 'disable':
$output->writeln("Proceeding to disable the accounts");
$this->doActionForAccountUids($toBeDeleted,
$this->doActionForAccountUids($userIds,
function ($uid, IUser $ac) use ($output) {
$ac->setEnabled(false);
$output->writeln($uid);
Expand All @@ -211,7 +294,7 @@ function ($uid) use ($output) {
break;
case 'remove':
$output->writeln("Proceeding to remove the accounts");
$this->doActionForAccountUids($toBeDeleted,
$this->doActionForAccountUids($userIds,
function ($uid, IUser $ac) use ($output) {
$ac->delete();
$output->writeln($uid);
Expand All @@ -222,7 +305,7 @@ function ($uid) use ($output) {
break;
case 'ask later':
$output->writeln("listing the unknown accounts");
$this->doActionForAccountUids($toBeDeleted,
$this->doActionForAccountUids($userIds,
function ($uid) use ($output) {
$output->writeln($uid);
},
Expand All @@ -241,7 +324,7 @@ function ($uid) use ($output) {
// if "nothing" is selected, just ignore and finish
case 'disable':
$output->writeln("Proceeding to disable the accounts");
$this->doActionForAccountUids($toBeDeleted,
$this->doActionForAccountUids($userIds,
function ($uid, IUser $ac) {
$ac->setEnabled(false);
},
Expand All @@ -251,7 +334,7 @@ function ($uid) use ($output) {
break;
case 'remove':
$output->writeln("Proceeding to remove the accounts");
$this->doActionForAccountUids($toBeDeleted,
$this->doActionForAccountUids($userIds,
function ($uid, IUser $ac) {
$ac->delete();
},
Expand Down
13 changes: 8 additions & 5 deletions core/Migrations/Version20170221114437.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
<?php
namespace OC\Migrations;

use OC\User\Account;
use OC\Migration\OutputAdapter;
use OC\Migration\SimpleOutput;
use OC\User\AccountMapper;
use OC\User\AccountTermMapper;
use OC\User\Database;
use OC\User\SyncService;
use OCP\IConfig;
use OC\User\SyncServiceCallback;
use OCP\Migration\ISimpleMigration;
use OCP\Migration\IOutput;
use OCP\Util;

class Version20170221114437 implements ISimpleMigration {

Expand All @@ -26,9 +28,10 @@ public function run(IOutput $out) {
// insert/update known users
$out->info("Insert new users ...");
$out->startProgress($backend->countUsers());
$syncService->run(function () use ($out) {
$out->advance();
});
$syncService->run(new SyncServiceCallback(
$out,
(int)$config->getSystemValue('loglevel', Util::WARN)
));
$out->finishProgress();
}
}
16 changes: 11 additions & 5 deletions lib/private/Migration/ConsoleOutput.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php
/**
* @author Jörn Friedrich Dreyer <[email protected]>
* @author Thomas Müller <[email protected]>
*
* @copyright Copyright (c) 2017, ownCloud GmbH
Expand Down Expand Up @@ -49,16 +50,18 @@ public function __construct(OutputInterface $output) {

/**
* @param string $message
* @param bool $newline
*/
public function info($message) {
$this->output->writeln("<info>$message</info>");
public function info($message, $newline = true) {
$this->output->write("<info>$message</info>", $newline);
}

/**
* @param string $message
* @param bool $newline
*/
public function warning($message) {
$this->output->writeln("<comment>$message</comment>");
public function warning($message, $newline = true) {
$this->output->write("<comment>$message</comment>", $newline);
}

/**
Expand All @@ -77,13 +80,16 @@ public function startProgress($max = 0) {
* @param string $description
*/
public function advance($step = 1, $description = '') {
if (!is_null($this->progressBar)) {
if (is_null($this->progressBar)) {
$this->progressBar = new ProgressBar($this->output);
$this->progressBar->start();
}
$this->progressBar->advance($step);
}

/**
* @since 9.1.0
*/
public function finishProgress() {
if (is_null($this->progressBar)) {
return;
Expand Down
7 changes: 5 additions & 2 deletions lib/private/Migration/SimpleOutput.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php
/**
* @author Jörn Friedrich Dreyer <[email protected]>
* @author Thomas Müller <[email protected]>
*
* @copyright Copyright (c) 2017, ownCloud GmbH
Expand Down Expand Up @@ -47,17 +48,19 @@ public function __construct(ILogger $logger, $appName) {

/**
* @param string $message
* @param bool $newline always true because ILogger always uses newlines
* @since 9.1.0
*/
public function info($message) {
public function info($message, $newline = true) {
$this->logger->info($message, ['app' => $this->appName]);
}

/**
* @param string $message
* @param bool $newline always true because ILogger always uses newlines
* @since 9.1.0
*/
public function warning($message) {
public function warning($message, $newline = true) {
$this->logger->warning($message, ['app' => $this->appName]);
}

Expand Down
Loading