CheckUser.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\User_LDAP\Command;
  8. use OCA\User_LDAP\Helper;
  9. use OCA\User_LDAP\Mapping\UserMapping;
  10. use OCA\User_LDAP\User\DeletedUsersIndex;
  11. use OCA\User_LDAP\User_Proxy;
  12. use Symfony\Component\Console\Command\Command;
  13. use Symfony\Component\Console\Input\InputArgument;
  14. use Symfony\Component\Console\Input\InputInterface;
  15. use Symfony\Component\Console\Input\InputOption;
  16. use Symfony\Component\Console\Output\OutputInterface;
  17. class CheckUser extends Command {
  18. public function __construct(
  19. protected User_Proxy $backend,
  20. protected Helper $helper,
  21. protected DeletedUsersIndex $dui,
  22. protected UserMapping $mapping,
  23. ) {
  24. parent::__construct();
  25. }
  26. protected function configure(): void {
  27. $this
  28. ->setName('ldap:check-user')
  29. ->setDescription('checks whether a user exists on LDAP.')
  30. ->addArgument(
  31. 'ocName',
  32. InputArgument::REQUIRED,
  33. 'the user name as used in Nextcloud, or the LDAP DN'
  34. )
  35. ->addOption(
  36. 'force',
  37. null,
  38. InputOption::VALUE_NONE,
  39. 'ignores disabled LDAP configuration'
  40. )
  41. ->addOption(
  42. 'update',
  43. null,
  44. InputOption::VALUE_NONE,
  45. 'syncs values from LDAP'
  46. )
  47. ;
  48. }
  49. protected function execute(InputInterface $input, OutputInterface $output): int {
  50. try {
  51. $this->assertAllowed($input->getOption('force'));
  52. $uid = $input->getArgument('ocName');
  53. if ($this->backend->getLDAPAccess($uid)->stringResemblesDN($uid)) {
  54. $username = $this->backend->dn2UserName($uid);
  55. if ($username !== false) {
  56. $uid = $username;
  57. }
  58. }
  59. $wasMapped = $this->userWasMapped($uid);
  60. $exists = $this->backend->userExistsOnLDAP($uid, true);
  61. if ($exists === true) {
  62. $output->writeln('The user is still available on LDAP.');
  63. if ($input->getOption('update')) {
  64. $this->updateUser($uid, $output);
  65. }
  66. return self::SUCCESS;
  67. }
  68. if ($wasMapped) {
  69. $this->dui->markUser($uid);
  70. $output->writeln('The user does not exists on LDAP anymore.');
  71. $output->writeln('Clean up the user\'s remnants by: ./occ user:delete "'
  72. . $uid . '"');
  73. return self::SUCCESS;
  74. }
  75. throw new \Exception('The given user is not a recognized LDAP user.');
  76. } catch (\Exception $e) {
  77. $output->writeln('<error>' . $e->getMessage() . '</error>');
  78. return self::FAILURE;
  79. }
  80. }
  81. /**
  82. * checks whether a user is actually mapped
  83. * @param string $ocName the username as used in Nextcloud
  84. */
  85. protected function userWasMapped(string $ocName): bool {
  86. $dn = $this->mapping->getDNByName($ocName);
  87. return $dn !== false;
  88. }
  89. /**
  90. * checks whether the setup allows reliable checking of LDAP user existence
  91. * @throws \Exception
  92. */
  93. protected function assertAllowed(bool $force): void {
  94. if ($this->helper->haveDisabledConfigurations() && !$force) {
  95. throw new \Exception('Cannot check user existence, because '
  96. . 'disabled LDAP configurations are present.');
  97. }
  98. // we don't check ldapUserCleanupInterval from config.php because this
  99. // action is triggered manually, while the setting only controls the
  100. // background job.
  101. }
  102. private function updateUser(string $uid, OutputInterface $output): void {
  103. try {
  104. $access = $this->backend->getLDAPAccess($uid);
  105. $attrs = $access->userManager->getAttributes();
  106. $user = $access->userManager->get($uid);
  107. $avatarAttributes = $access->getConnection()->resolveRule('avatar');
  108. $baseDn = $this->helper->DNasBaseParameter($user->getDN());
  109. $result = $access->search('objectclass=*', $baseDn, $attrs, 1, 0);
  110. foreach ($result[0] as $attribute => $valueSet) {
  111. $output->writeln(' ' . $attribute . ': ');
  112. foreach ($valueSet as $value) {
  113. if (in_array($attribute, $avatarAttributes)) {
  114. $value = '{ImageData}';
  115. }
  116. $output->writeln(' ' . $value);
  117. }
  118. }
  119. $access->batchApplyUserAttributes($result);
  120. } catch (\Exception $e) {
  121. $output->writeln('<error>Error while trying to lookup and update attributes from LDAP</error>');
  122. }
  123. }
  124. }