configID === null) { return; } $this->disableLDAPConfiguration(); # via occ in case of big config issues $this->asAn('admin'); $this->sendingTo('DELETE', $this->apiUrl . '/' . $this->configID); } /** * @Given /^the response should contain a tag "([^"]*)"$/ */ public function theResponseShouldContainATag($arg1) { $configID = simplexml_load_string($this->response->getBody())->data[0]->$arg1; Assert::assertInstanceOf(SimpleXMLElement::class, $configID[0]); } /** * @Given /^creating an LDAP configuration at "([^"]*)"$/ */ public function creatingAnLDAPConfigurationAt($apiUrl) { $this->apiUrl = $apiUrl; $this->sendingToWith('POST', $this->apiUrl, null); $configElements = simplexml_load_string($this->response->getBody())->data[0]->configID; $this->configID = $configElements[0]; } /** * @When /^deleting the LDAP configuration$/ */ public function deletingTheLDAPConfiguration() { $this->sendingToWith('DELETE', $this->apiUrl . '/' . $this->configID, null); } /** * @Given /^the response should contain a tag "([^"]*)" with value "([^"]*)"$/ */ public function theResponseShouldContainATagWithValue($tagName, $expectedValue) { $data = simplexml_load_string($this->response->getBody())->data[0]->$tagName; Assert::assertEquals($expectedValue, $data[0]); } /** * @When /^getting the LDAP configuration with showPassword "([^"]*)"$/ */ public function gettingTheLDAPConfigurationWithShowPassword($showPassword) { $this->sendingToWith( 'GET', $this->apiUrl . '/' . $this->configID . '?showPassword=' . $showPassword, null ); } /** * @Given /^setting the LDAP configuration to$/ */ public function settingTheLDAPConfigurationTo(TableNode $configData) { $this->sendingToWith('PUT', $this->apiUrl . '/' . $this->configID, $configData); } /** * @Given /^having a valid LDAP configuration$/ */ public function havingAValidLDAPConfiguration() { $this->asAn('admin'); $this->creatingAnLDAPConfigurationAt('/apps/user_ldap/api/v1/config'); $data = new TableNode([ ['configData[ldapHost]', getenv('LDAP_HOST') ?: 'openldap'], ['configData[ldapPort]', '389'], ['configData[ldapBase]', 'dc=nextcloud,dc=ci'], ['configData[ldapAgentName]', 'cn=admin,dc=nextcloud,dc=ci'], ['configData[ldapAgentPassword]', 'admin'], ['configData[ldapUserFilter]', '(&(objectclass=inetorgperson))'], ['configData[ldapLoginFilter]', '(&(objectclass=inetorgperson)(uid=%uid))'], ['configData[ldapUserDisplayName]', 'displayname'], ['configData[ldapGroupDisplayName]', 'cn'], ['configData[ldapEmailAttribute]', 'mail'], ['configData[ldapConfigurationActive]', '1'], ]); $this->settingTheLDAPConfigurationTo($data); $this->asAn(''); } /** * @Given /^looking up details for the first result matches expectations$/ * @param TableNode $expectations */ public function lookingUpDetailsForTheFirstResult(TableNode $expectations) { $userResultElements = simplexml_load_string($this->response->getBody())->data[0]->users[0]->element; $userResults = json_decode(json_encode($userResultElements), 1); $userId = array_shift($userResults); $this->sendingTo('GET', '/cloud/users/' . $userId); $this->theRecordFieldsShouldMatch($expectations); } /** * @Given /^modify LDAP configuration$/ */ public function modifyLDAPConfiguration(TableNode $table) { $originalAsAn = $this->currentUser; $this->asAn('admin'); $configData = $table->getRows(); foreach ($configData as &$row) { if (str_contains($row[0], 'Host') && getenv('LDAP_HOST')) { $row[1] = str_replace('openldap', getenv('LDAP_HOST'), $row[1]); } $row[0] = 'configData[' . $row[0] . ']'; } $this->settingTheLDAPConfigurationTo(new TableNode($configData)); $this->asAn($originalAsAn); } /** * @Given /^the "([^"]*)" result should match$/ */ public function theGroupResultShouldMatch(string $type, TableNode $expectations) { $listReturnedElements = simplexml_load_string($this->response->getBody())->data[0]->$type[0]->element; $extractedIDsArray = json_decode(json_encode($listReturnedElements), 1); foreach ($expectations->getRows() as $expectation) { if ((int)$expectation[1] === 1) { Assert::assertContains($expectation[0], $extractedIDsArray); } else { Assert::assertNotContains($expectation[0], $extractedIDsArray); } } } /** * @Given /^Expect ServerException on failed web login as "([^"]*)"$/ */ public function expectServerExceptionOnFailedWebLoginAs($login) { try { $this->loggingInUsingWebAs($login); } catch (\GuzzleHttp\Exception\ServerException $e) { Assert::assertEquals(500, $e->getResponse()->getStatusCode()); return; } Assert::assertTrue(false, 'expected Exception not received'); } /** * @Given /^the "([^"]*)" result should contain "([^"]*)" of$/ */ public function theResultShouldContainOf($type, $expectedCount, TableNode $expectations) { $listReturnedElements = simplexml_load_string($this->response->getBody())->data[0]->$type[0]->element; $extractedIDsArray = json_decode(json_encode($listReturnedElements), 1); $uidsFound = 0; foreach ($expectations->getRows() as $expectation) { if (in_array($expectation[0], $extractedIDsArray)) { $uidsFound++; } } Assert::assertSame((int)$expectedCount, $uidsFound); } /** * @Given /^the record's fields should match$/ */ public function theRecordFieldsShouldMatch(TableNode $expectations) { foreach ($expectations->getRowsHash() as $k => $v) { $value = (string)simplexml_load_string($this->response->getBody())->data[0]->$k; Assert::assertEquals($v, $value, "got $value"); } $backend = (string)simplexml_load_string($this->response->getBody())->data[0]->backend; Assert::assertEquals('LDAP', $backend); } public function disableLDAPConfiguration() { $configKey = $this->configID . 'ldap_configuration_active'; $this->invokingTheCommand('config:app:set user_ldap ' . $configKey . ' --value="0"'); } protected function resetAppConfigs() { // not implemented } } _close Nextcloud server, a safe home for all your data: https://github.com/nextcloud/serverwww-data
aboutsummaryrefslogtreecommitdiffstats
path: root/apps/user_ldap/lib/Command/PromoteGroup.php
blob: b203a910b1498e165c0d13b4de917b799228bd67 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?php

declare(strict_types=1);
/**
 * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */
namespace OCA\User_LDAP\Command;

use OCA\User_LDAP\Group_Proxy;
use OCP\IGroup;
use OCP\IGroupManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\QuestionHelper;
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\Question;

class PromoteGroup extends Command {

	public function __construct(
		private IGroupManager $groupManager,
		private Group_Proxy $backend,
	) {
		parent::__construct();
	}

	protected function configure(): void {
		$this
			->setName('ldap:promote-group')
			->setDescription('declares the specified group as admin group (only one is possible per LDAP configuration)')
			->addArgument(
				'group',
				InputArgument::REQUIRED,
				'the group ID in Nextcloud or a group name'
			)
			->addOption(
				'yes',
				'y',
				InputOption::VALUE_NONE,
				'do not ask for confirmation'
			);
	}

	protected function formatGroupName(IGroup $group): string {
		$idLabel = '';
		if ($group->getGID() !== $group->getDisplayName()) {
			$idLabel = sprintf(' (Group ID: %s)', $group->getGID());
		}
		return sprintf('%s%s', $group->getDisplayName(), $idLabel);
	}

	protected function promoteGroup(IGroup $group, InputInterface $input, OutputInterface $output): void {
		$access = $this->backend->getLDAPAccess($group->getGID());
		$currentlyPromotedGroupId = $access->connection->ldapAdminGroup;
		if ($currentlyPromotedGroupId === $group->getGID()) {
			$output->writeln('<info>The specified group is already promoted</info>');
			return;
		}

		if ($input->getOption('yes') === false) {
			$currentlyPromotedGroup = $this->groupManager->get($currentlyPromotedGroupId);
			$demoteLabel = '';
			if ($currentlyPromotedGroup instanceof IGroup && $this->backend->groupExists($currentlyPromotedGroup->getGID())) {
				$groupNameLabel = $this->formatGroupName($currentlyPromotedGroup);
				$demoteLabel = sprintf('and demote %s ', $groupNameLabel);
			}

			/** @var QuestionHelper $helper */
			$helper = $this->getHelper('question');
			$q = new Question(sprintf('Promote %s to the admin group %s(y|N)? ', $this->formatGroupName($group), $demoteLabel));
			$input->setOption('yes', $helper->ask($input, $output, $q) === 'y');
		}
		if ($input->getOption('yes') === true) {
			$access->connection->setConfiguration(['ldapAdminGroup' => $group->getGID()]);
			$access->connection->saveConfiguration();
			$output->writeln(sprintf('<info>Group %s was promoted</info>', $group->getDisplayName()));
		} else {
			$output->writeln('<comment>Group promotion cancelled</comment>');
		}
	}

	protected function execute(InputInterface $input, OutputInterface $output): int {
		$groupInput = (string)$input->getArgument('group');
		$group = $this->groupManager->get($groupInput);

		if ($group instanceof IGroup && $this->backend->groupExists($group->getGID())) {
			$this->promoteGroup($group, $input, $output);
			return 0;
		}

		$groupCandidates = $this->backend->getGroups($groupInput, 20);
		foreach ($groupCandidates as $gidCandidate) {
			$group = $this->groupManager->get($gidCandidate);
			if ($group !== null
				&& $this->backend->groupExists($group->getGID()) // ensure it is an LDAP group
				&& ($group->getGID() === $groupInput
					|| $group->getDisplayName() === $groupInput)
			) {
				$this->promoteGroup($group, $input, $output);
				return 0;
			}
		}

		$output->writeln('<error>No matching group found</error>');
		return 1;
	}

}