CheckGroup.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OCA\User_LDAP\Command;
  8. use OCA\User_LDAP\Group_Proxy;
  9. use OCA\User_LDAP\Helper;
  10. use OCA\User_LDAP\Mapping\GroupMapping;
  11. use OCA\User_LDAP\Service\UpdateGroupsService;
  12. use OCP\EventDispatcher\IEventDispatcher;
  13. use OCP\Group\Events\GroupCreatedEvent;
  14. use OCP\Group\Events\UserAddedEvent;
  15. use OCP\Group\Events\UserRemovedEvent;
  16. use Symfony\Component\Console\Command\Command;
  17. use Symfony\Component\Console\Input\InputArgument;
  18. use Symfony\Component\Console\Input\InputInterface;
  19. use Symfony\Component\Console\Input\InputOption;
  20. use Symfony\Component\Console\Output\OutputInterface;
  21. class CheckGroup extends Command {
  22. public function __construct(
  23. private UpdateGroupsService $service,
  24. protected Group_Proxy $backend,
  25. protected Helper $helper,
  26. protected GroupMapping $mapping,
  27. protected IEventDispatcher $dispatcher,
  28. ) {
  29. parent::__construct();
  30. }
  31. protected function configure(): void {
  32. $this
  33. ->setName('ldap:check-group')
  34. ->setDescription('checks whether a group exists on LDAP.')
  35. ->addArgument(
  36. 'ocName',
  37. InputArgument::REQUIRED,
  38. 'the group name as used in Nextcloud, or the LDAP DN'
  39. )
  40. ->addOption(
  41. 'force',
  42. null,
  43. InputOption::VALUE_NONE,
  44. 'ignores disabled LDAP configuration'
  45. )
  46. ->addOption(
  47. 'update',
  48. null,
  49. InputOption::VALUE_NONE,
  50. 'syncs values from LDAP'
  51. )
  52. ;
  53. }
  54. protected function execute(InputInterface $input, OutputInterface $output): int {
  55. $this->dispatcher->addListener(GroupCreatedEvent::class, fn ($event) => $this->onGroupCreatedEvent($event, $output));
  56. $this->dispatcher->addListener(UserAddedEvent::class, fn ($event) => $this->onUserAddedEvent($event, $output));
  57. $this->dispatcher->addListener(UserRemovedEvent::class, fn ($event) => $this->onUserRemovedEvent($event, $output));
  58. try {
  59. $this->assertAllowed($input->getOption('force'));
  60. $gid = $input->getArgument('ocName');
  61. $wasMapped = $this->groupWasMapped($gid);
  62. if ($this->backend->getLDAPAccess($gid)->stringResemblesDN($gid)) {
  63. $groupname = $this->backend->dn2GroupName($gid);
  64. if ($groupname !== false) {
  65. $gid = $groupname;
  66. }
  67. }
  68. /* Search to trigger mapping for new groups */
  69. $this->backend->getGroups($gid);
  70. $exists = $this->backend->groupExistsOnLDAP($gid, true);
  71. if ($exists === true) {
  72. $output->writeln('The group is still available on LDAP.');
  73. if ($input->getOption('update')) {
  74. $this->backend->getLDAPAccess($gid)->connection->clearCache();
  75. if ($wasMapped) {
  76. $this->service->handleKnownGroups([$gid]);
  77. } else {
  78. $this->service->handleCreatedGroups([$gid]);
  79. }
  80. }
  81. return self::SUCCESS;
  82. }
  83. if ($wasMapped) {
  84. $output->writeln('The group does not exist on LDAP anymore.');
  85. if ($input->getOption('update')) {
  86. $this->backend->getLDAPAccess($gid)->connection->clearCache();
  87. $this->service->handleRemovedGroups([$gid]);
  88. }
  89. return self::SUCCESS;
  90. }
  91. throw new \Exception('The given group is not a recognized LDAP group.');
  92. } catch (\Exception $e) {
  93. $output->writeln('<error>' . $e->getMessage(). '</error>');
  94. return self::FAILURE;
  95. }
  96. }
  97. public function onGroupCreatedEvent(GroupCreatedEvent $event, OutputInterface $output): void {
  98. $output->writeln('<info>The group '.$event->getGroup()->getGID().' was added to Nextcloud with '.$event->getGroup()->count().' users</info>');
  99. }
  100. public function onUserAddedEvent(UserAddedEvent $event, OutputInterface $output): void {
  101. $user = $event->getUser();
  102. $group = $event->getGroup();
  103. $output->writeln('<info>The user '.$user->getUID().' was added to group '.$group->getGID().'</info>');
  104. }
  105. public function onUserRemovedEvent(UserRemovedEvent $event, OutputInterface $output): void {
  106. $user = $event->getUser();
  107. $group = $event->getGroup();
  108. $output->writeln('<info>The user '.$user->getUID().' was removed from group '.$group->getGID().'</info>');
  109. }
  110. /**
  111. * checks whether a group is actually mapped
  112. * @param string $gid the groupname as passed to the command
  113. */
  114. protected function groupWasMapped(string $gid): bool {
  115. $dn = $this->mapping->getDNByName($gid);
  116. if ($dn !== false) {
  117. return true;
  118. }
  119. $name = $this->mapping->getNameByDN($gid);
  120. return $name !== false;
  121. }
  122. /**
  123. * checks whether the setup allows reliable checking of LDAP group existence
  124. * @throws \Exception
  125. */
  126. protected function assertAllowed(bool $force): void {
  127. if ($this->helper->haveDisabledConfigurations() && !$force) {
  128. throw new \Exception('Cannot check group existence, because '
  129. . 'disabled LDAP configurations are present.');
  130. }
  131. // we don't check ldapUserCleanupInterval from config.php because this
  132. // action is triggered manually, while the setting only controls the
  133. // background job.
  134. }
  135. private function updateGroup(string $gid, OutputInterface $output, bool $wasMapped): void {
  136. try {
  137. if ($wasMapped) {
  138. $this->service->handleKnownGroups([$gid]);
  139. } else {
  140. $this->service->handleCreatedGroups([$gid]);
  141. }
  142. } catch (\Exception $e) {
  143. $output->writeln('<error>Error while trying to lookup and update attributes from LDAP</error>');
  144. }
  145. }
  146. }