aboutsummaryrefslogtreecommitdiffstats
path: root/apps/user_ldap/lib/Command/ShowRemnants.php
blob: d255aac13689693e2c7c44a3fd635ba95475919e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<?php

/**
 * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
 * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
 * SPDX-License-Identifier: AGPL-3.0-only
 */
namespace OCA\User_LDAP\Command;

use OCA\User_LDAP\User\DeletedUsersIndex;
use OCP\IDateTimeFormatter;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;

use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class ShowRemnants extends Command {
	public function __construct(
		protected DeletedUsersIndex $dui,
		protected IDateTimeFormatter $dateFormatter,
	) {
		parent::__construct();
	}

	protected function configure(): void {
		$this
			->setName('ldap:show-remnants')
			->setDescription('shows which users are not available on LDAP anymore, but have remnants in Nextcloud.')
			->addOption('json', null, InputOption::VALUE_NONE, 'return JSON array instead of pretty table.')
			->addOption('short-date', null, InputOption::VALUE_NONE, 'show dates in Y-m-d format');
	}

	protected function formatDate(int $timestamp, string $default, bool $showShortDate): string {
		if (!($timestamp > 0)) {
			return $default;
		}
		if ($showShortDate) {
			return date('Y-m-d', $timestamp);
		}
		return $this->dateFormatter->formatDate($timestamp);
	}

	/**
	 * executes the command, i.e. creates and outputs a table of LDAP users marked as deleted
	 *
	 * {@inheritdoc}
	 */
	protected function execute(InputInterface $input, OutputInterface $output): int {
		/** @var \Symfony\Component\Console\Helper\Table $table */
		$table = new Table($output);
		$table->setHeaders([
			'Nextcloud name', 'Display Name', 'LDAP UID', 'LDAP DN', 'Last Login',
			'Detected on', 'Dir', 'Sharer'
		]);
		$rows = [];
		$resultSet = $this->dui->getUsers();
		foreach ($resultSet as $user) {
			$rows[] = [
				'ocName' => $user->getOCName(),
				'displayName' => $user->getDisplayName(),
				'uid' => $user->getUID(),
				'dn' => $user->getDN(),
				'lastLogin' => $this->formatDate($user->getLastLogin(), '-', (bool)$input->getOption('short-date')),
				'detectedOn' => $this->formatDate($user->getDetectedOn(), 'unknown', (bool)$input->getOption('short-date')),
				'homePath' => $user->getHomePath(),
				'sharer' => $user->getHasActiveShares() ? 'Y' : 'N',
			];
		}

		if ($input->getOption('json')) {
			$output->writeln(json_encode($rows));
		} else {
			$table->setRows($rows);
			$table->render();
		}
		return self::SUCCESS;
	}
}
span class="na">appName = $container['AppName']; } /** * The routes and resource will be registered to the \OCP\Route\IRouter */ public function register() { // parse simple $this->processSimpleRoutes($this->routes); // parse resources $this->processResources($this->routes); /* * OCS routes go into a different collection */ $oldCollection = $this->router->getCurrentCollection(); $this->router->useCollection($oldCollection.'.ocs'); // parse ocs simple routes $this->processOCS($this->routes); $this->router->useCollection($oldCollection); } private function processOCS(array $routes) { $ocsRoutes = isset($routes['ocs']) ? $routes['ocs'] : []; foreach ($ocsRoutes as $ocsRoute) { $name = $ocsRoute['name']; $postfix = ''; if (isset($ocsRoute['postfix'])) { $postfix = $ocsRoute['postfix']; } if (isset($ocsRoute['root'])) { $root = $ocsRoute['root']; } else { $root = '/apps/'.$this->appName; } $url = $root . $ocsRoute['url']; $verb = isset($ocsRoute['verb']) ? strtoupper($ocsRoute['verb']) : 'GET'; $split = explode('#', $name, 2); if (count($split) != 2) { throw new \UnexpectedValueException('Invalid route name'); } $controller = $split[0]; $action = $split[1]; $controllerName = $this->buildControllerName($controller); $actionName = $this->buildActionName($action); // register the route $handler = new RouteActionHandler($this->container, $controllerName, $actionName); $router = $this->router->create('ocs.'.$this->appName.'.'.$controller.'.'.$action . $postfix, $url) ->method($verb) ->action($handler); // optionally register requirements for route. This is used to // tell the route parser how url parameters should be matched if(array_key_exists('requirements', $ocsRoute)) { $router->requirements($ocsRoute['requirements']); } // optionally register defaults for route. This is used to // tell the route parser how url parameters should be default valued if(array_key_exists('defaults', $ocsRoute)) { $router->defaults($ocsRoute['defaults']); } } } /** * Creates one route base on the give configuration * @param array $routes * @throws \UnexpectedValueException */ private function processSimpleRoutes($routes) { $simpleRoutes = isset($routes['routes']) ? $routes['routes'] : array(); foreach ($simpleRoutes as $simpleRoute) { $name = $simpleRoute['name']; $postfix = ''; if (isset($simpleRoute['postfix'])) { $postfix = $simpleRoute['postfix']; } $url = $simpleRoute['url']; $verb = isset($simpleRoute['verb']) ? strtoupper($simpleRoute['verb']) : 'GET'; $split = explode('#', $name, 2); if (count($split) != 2) { throw new \UnexpectedValueException('Invalid route name'); } $controller = $split[0]; $action = $split[1]; $controllerName = $this->buildControllerName($controller); $actionName = $this->buildActionName($action); // register the route $handler = new RouteActionHandler($this->container, $controllerName, $actionName); $router = $this->router->create($this->appName.'.'.$controller.'.'.$action . $postfix, $url) ->method($verb) ->action($handler); // optionally register requirements for route. This is used to // tell the route parser how url parameters should be matched if(array_key_exists('requirements', $simpleRoute)) { $router->requirements($simpleRoute['requirements']); } // optionally register defaults for route. This is used to // tell the route parser how url parameters should be default valued if(array_key_exists('defaults', $simpleRoute)) { $router->defaults($simpleRoute['defaults']); } } } /** * For a given name and url restful routes are created: * - index * - show * - new * - create * - update * - destroy * * @param array $routes */ private function processResources($routes) { // declaration of all restful actions $actions = array( array('name' => 'index', 'verb' => 'GET', 'on-collection' => true), array('name' => 'show', 'verb' => 'GET'), array('name' => 'create', 'verb' => 'POST', 'on-collection' => true), array('name' => 'update', 'verb' => 'PUT'), array('name' => 'destroy', 'verb' => 'DELETE'), ); $resources = isset($routes['resources']) ? $routes['resources'] : array(); foreach ($resources as $resource => $config) { // the url parameter used as id to the resource foreach($actions as $action) { $url = $config['url']; $method = $action['name']; $verb = isset($action['verb']) ? strtoupper($action['verb']) : 'GET'; $collectionAction = isset($action['on-collection']) ? $action['on-collection'] : false; if (!$collectionAction) { $url = $url . '/{id}'; } if (isset($action['url-postfix'])) { $url = $url . '/' . $action['url-postfix']; } $controller = $resource; $controllerName = $this->buildControllerName($controller); $actionName = $this->buildActionName($method); $routeName = $this->appName . '.' . strtolower($resource) . '.' . strtolower($method); $this->router->create($routeName, $url)->method($verb)->action( new RouteActionHandler($this->container, $controllerName, $actionName) ); } } } /** * Based on a given route name the controller name is generated * @param string $controller * @return string */ private function buildControllerName($controller) { if (!isset($this->controllerNameCache[$controller])) { $this->controllerNameCache[$controller] = $this->underScoreToCamelCase(ucfirst($controller)) . 'Controller'; } return $this->controllerNameCache[$controller]; } /** * Based on the action part of the route name the controller method name is generated * @param string $action * @return string */ private function buildActionName($action) { return $this->underScoreToCamelCase($action); } /** * Underscored strings are converted to camel case strings * @param string $str * @return string */ private function underScoreToCamelCase($str) { $pattern = "/_[a-z]?/"; return preg_replace_callback( $pattern, function ($matches) { return strtoupper(ltrim($matches[0], "_")); }, $str); } }