AddAppPassword.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2020, NextCloud, Inc.
  4. *
  5. * @author Bjoern Schiessle <bjoern@schiessle.org>
  6. * @author Sean Molenaar <sean@seanmolenaar.eu>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. */
  24. namespace OC\Core\Command\User;
  25. use OC\Authentication\Token\IProvider;
  26. use OC\Authentication\Token\IToken;
  27. use OCP\IUserManager;
  28. use OCP\Security\ICrypto;
  29. use OCP\Security\ISecureRandom;
  30. use Symfony\Component\Console\Command\Command;
  31. use Symfony\Component\Console\Helper\QuestionHelper;
  32. use Symfony\Component\Console\Input\InputArgument;
  33. use Symfony\Component\Console\Input\InputInterface;
  34. use Symfony\Component\Console\Input\InputOption;
  35. use Symfony\Component\Console\Output\OutputInterface;
  36. use Symfony\Component\Console\Question\Question;
  37. class AddAppPassword extends Command {
  38. /** @var IUserManager */
  39. protected $userManager;
  40. /** @var IProvider */
  41. protected $tokenProvider;
  42. /** @var ISecureRandom */
  43. private $random;
  44. /** @var ICrypto */
  45. private $crypto;
  46. public function __construct(IUserManager $userManager,
  47. IProvider $tokenProvider,
  48. ISecureRandom $random,
  49. ICrypto $crypto) {
  50. $this->tokenProvider = $tokenProvider;
  51. $this->userManager = $userManager;
  52. $this->random = $random;
  53. $this->crypto = $crypto;
  54. parent::__construct();
  55. }
  56. protected function configure() {
  57. $this
  58. ->setName('user:add-app-password')
  59. ->setDescription('Add app password for the named user')
  60. ->addArgument(
  61. 'user',
  62. InputArgument::REQUIRED,
  63. 'Username to add app password for'
  64. )
  65. ->addOption(
  66. 'password-from-env',
  67. null,
  68. InputOption::VALUE_NONE,
  69. 'read password from environment variable NC_PASS/OC_PASS'
  70. )
  71. ;
  72. }
  73. protected function execute(InputInterface $input, OutputInterface $output): int {
  74. $username = $input->getArgument('user');
  75. $user = $this->userManager->get($username);
  76. if (is_null($user)) {
  77. $output->writeln('<error>User does not exist</error>');
  78. return 1;
  79. }
  80. if ($input->getOption('password-from-env')) {
  81. $password = getenv('NC_PASS') ?? getenv('OC_PASS');
  82. if (!$password) {
  83. $output->writeln('<error>--password-from-env given, but NC_PASS is empty!</error>');
  84. return 1;
  85. }
  86. } elseif ($input->isInteractive()) {
  87. /** @var QuestionHelper $helper */
  88. $helper = $this->getHelper('question');
  89. $question = new Question('Enter the user password: ');
  90. $question->setHidden(true);
  91. $password = $helper->ask($input, $output, $question);
  92. if ($password === null) {
  93. $output->writeln("<error>Password cannot be empty!</error>");
  94. return 1;
  95. }
  96. } else {
  97. $output->writeln("<error>Interactive input or --password-from-env is needed for entering a new password!</error>");
  98. return 1;
  99. }
  100. $output->writeln('<info>The password is not validated so what you provide is what gets recorded in the token</info>');
  101. $token = $this->random->generate(72, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS);
  102. $this->tokenProvider->generateToken(
  103. $token,
  104. $user->getUID(),
  105. $user->getUID(),
  106. $password,
  107. 'cli',
  108. IToken::PERMANENT_TOKEN,
  109. IToken::DO_NOT_REMEMBER
  110. );
  111. $output->writeln('app password:');
  112. $output->writeln($token);
  113. return 0;
  114. }
  115. }