2020-11-23 17:10:48 -05:00
< ? php
2022-03-23 13:44:16 -04:00
declare ( strict_types = 1 );
2020-11-23 17:10:48 -05:00
/**
* @ copyright Copyright ( c ) 2020 , NextCloud , Inc .
*
2021-06-04 15:52:51 -04:00
* @ author Bjoern Schiessle < bjoern @ schiessle . org >
2020-11-23 17:10:48 -05:00
* @ author Sean Molenaar < sean @ seanmolenaar . eu >
*
2021-06-04 15:52:51 -04:00
* @ license GNU AGPL version 3 or any later version
2020-11-23 17:10:48 -05:00
*
2021-06-04 15:52:51 -04:00
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
2020-11-23 17:10:48 -05:00
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
2021-06-04 15:52:51 -04:00
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < http :// www . gnu . org / licenses />.
2020-11-23 17:10:48 -05:00
*
*/
namespace OC\Core\Command\User ;
2022-03-10 09:25:22 -05:00
use OC\Authentication\Events\AppPasswordCreatedEvent ;
2020-11-23 17:10:48 -05:00
use OC\Authentication\Token\IProvider ;
use OC\Authentication\Token\IToken ;
2022-03-10 09:25:22 -05:00
use OCP\EventDispatcher\IEventDispatcher ;
2020-11-23 17:10:48 -05:00
use OCP\IUserManager ;
use OCP\Security\ISecureRandom ;
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 AddAppPassword extends Command {
2022-04-12 11:55:01 -04:00
protected IUserManager $userManager ;
protected IProvider $tokenProvider ;
private ISecureRandom $random ;
private IEventDispatcher $eventDispatcher ;
2020-11-23 17:10:48 -05:00
public function __construct ( IUserManager $userManager ,
IProvider $tokenProvider ,
ISecureRandom $random ,
2022-03-10 09:25:22 -05:00
IEventDispatcher $eventDispatcher ) {
2020-11-23 17:10:48 -05:00
$this -> tokenProvider = $tokenProvider ;
$this -> userManager = $userManager ;
$this -> random = $random ;
2022-03-10 09:25:22 -05:00
$this -> eventDispatcher = $eventDispatcher ;
2020-11-23 17:10:48 -05:00
parent :: __construct ();
}
protected function configure () {
$this
-> setName ( 'user:add-app-password' )
-> setDescription ( 'Add app password for the named user' )
-> addArgument (
'user' ,
InputArgument :: REQUIRED ,
'Username to add app password for'
)
-> addOption (
'password-from-env' ,
null ,
InputOption :: VALUE_NONE ,
2022-03-23 13:44:16 -04:00
'Read password from environment variable NC_PASS/OC_PASS. Alternatively it will be asked for interactively or an app password without the login password will be created.'
2020-11-23 17:10:48 -05:00
)
;
}
protected function execute ( InputInterface $input , OutputInterface $output ) : int {
$username = $input -> getArgument ( 'user' );
2022-03-23 13:44:16 -04:00
$password = null ;
2020-11-23 17:10:48 -05:00
$user = $this -> userManager -> get ( $username );
if ( is_null ( $user )) {
$output -> writeln ( '<error>User does not exist</error>' );
return 1 ;
}
if ( $input -> getOption ( 'password-from-env' )) {
$password = getenv ( 'NC_PASS' ) ? ? getenv ( 'OC_PASS' );
if ( ! $password ) {
$output -> writeln ( '<error>--password-from-env given, but NC_PASS is empty!</error>' );
return 1 ;
}
} elseif ( $input -> isInteractive ()) {
/** @var QuestionHelper $helper */
$helper = $this -> getHelper ( 'question' );
$question = new Question ( 'Enter the user password: ' );
$question -> setHidden ( true );
2022-03-23 13:44:16 -04:00
/** @var null|string $password */
2020-11-23 17:10:48 -05:00
$password = $helper -> ask ( $input , $output , $question );
}
2022-03-23 13:44:16 -04:00
if ( $password === null ) {
$output -> writeln ( '<info>No password provided. The generated app password will therefore have limited capabilities. Any operation that requires the login password will fail.</info>' );
}
2020-11-23 17:10:48 -05:00
$token = $this -> random -> generate ( 72 , ISecureRandom :: CHAR_UPPER . ISecureRandom :: CHAR_LOWER . ISecureRandom :: CHAR_DIGITS );
2022-03-10 09:25:22 -05:00
$generatedToken = $this -> tokenProvider -> generateToken (
2020-11-23 17:10:48 -05:00
$token ,
$user -> getUID (),
2021-05-11 14:38:54 -04:00
$user -> getUID (),
2020-11-23 17:10:48 -05:00
$password ,
'cli' ,
IToken :: PERMANENT_TOKEN ,
IToken :: DO_NOT_REMEMBER
);
2022-03-10 09:25:22 -05:00
$this -> eventDispatcher -> dispatchTyped (
new AppPasswordCreatedEvent ( $generatedToken )
);
2020-11-23 17:10:48 -05:00
$output -> writeln ( 'app password:' );
$output -> writeln ( $token );
return 0 ;
}
}