99 * file that was distributed with this source code.
1010 */
1111
12- namespace App \Command \Users ;
12+ namespace App \Command \User ;
1313
14+ use App \Entity \Tenant ;
1415use App \Entity \User ;
1516use App \Entity \UserRoleTenant ;
1617use App \Repository \TenantRepository ;
2223use Symfony \Component \Console \Exception \RuntimeException ;
2324use Symfony \Component \Console \Input \InputArgument ;
2425use Symfony \Component \Console \Input \InputInterface ;
25- use Symfony \Component \Console \Input \InputOption ;
2626use Symfony \Component \Console \Output \OutputInterface ;
27+ use Symfony \Component \Console \Question \ChoiceQuestion ;
2728use Symfony \Component \Console \Style \SymfonyStyle ;
2829use Symfony \Component \PasswordHasher \Hasher \UserPasswordHasherInterface ;
2930use Symfony \Component \Stopwatch \Stopwatch ;
@@ -63,7 +64,7 @@ public function __construct(
6364 private UserPasswordHasherInterface $ passwordHasher ,
6465 private CommandInputValidator $ validator ,
6566 private UserRepository $ users ,
66- private TenantRepository $ tenants
67+ private TenantRepository $ tenantRepository
6768 ) {
6869 parent ::__construct ();
6970 }
@@ -80,7 +81,8 @@ protected function configure(): void
8081 ->addArgument ('email ' , InputArgument::OPTIONAL , 'The email of the new user ' )
8182 ->addArgument ('password ' , InputArgument::OPTIONAL , 'The plain password of the new user ' )
8283 ->addArgument ('full-name ' , InputArgument::OPTIONAL , 'The full name of the new user ' )
83- ->addOption ('admin ' , null , InputOption::VALUE_NONE , 'If set, the user is created as an administrator ' )
84+ ->addArgument ('role ' , InputArgument::OPTIONAL , 'The role of the user [editor|admin] ' )
85+ ->addArgument ('tenant-keys ' , InputArgument::IS_ARRAY | InputArgument::OPTIONAL , 'The keys of the tenants the user should belong to (separate multiple keys with a space) ' )
8486 ;
8587 }
8688
@@ -109,7 +111,12 @@ protected function initialize(InputInterface $input, OutputInterface $output): v
109111 */
110112 protected function interact (InputInterface $ input , OutputInterface $ output ): void
111113 {
112- if (null !== $ input ->getArgument ('email ' ) && null !== $ input ->getArgument ('password ' ) && null !== $ input ->getArgument ('full-name ' )) {
114+ if (null !== $ input ->getArgument ('email ' ) &&
115+ null !== $ input ->getArgument ('password ' ) &&
116+ null !== $ input ->getArgument ('full-name ' ) &&
117+ null !== $ input ->getArgument ('role ' ) &&
118+ null !== $ input ->getArgument ('tenant-keys ' )
119+ ) {
113120 return ;
114121 }
115122
@@ -149,6 +156,39 @@ protected function interact(InputInterface $input, OutputInterface $output): voi
149156 $ fullName = $ this ->io ->ask ('Full Name ' , null , [$ this ->validator , 'validateFullName ' ]);
150157 $ input ->setArgument ('full-name ' , $ fullName );
151158 }
159+
160+ $ helper = $ this ->getHelper ('question ' );
161+
162+ // Ask for the role if it's not defined
163+ $ role = $ input ->getArgument ('role ' );
164+ if (null !== $ role ) {
165+ $ this ->io ->text (' > <info>Role</info>: ' .$ role );
166+ } else {
167+ $ question = new ChoiceQuestion (
168+ 'Please select the user \'s role (defaults to editor) ' ,
169+ CommandInputValidator::ALLOWED_USER_ROLES ,
170+ 0
171+ );
172+ $ question ->setErrorMessage ('Role %s is invalid. ' );
173+
174+ $ role = $ helper ->ask ($ input , $ output , $ question );
175+ $ output ->writeln ('You have just selected: ' .$ role );
176+ }
177+
178+ // Ask for the tenant keys if it's not defined
179+ $ tenantKeys = $ input ->getArgument ('tenant-keys ' );
180+ if (0 < \count ($ tenantKeys )) {
181+ $ this ->io ->text (' > <info>Tenant Keys</info>: ' .$ tenantKeys );
182+ } else {
183+ $ question = new ChoiceQuestion (
184+ 'Please select the tenant(s) the user should belong to (to select multiple answer with a list. E.g: "key1, key3") ' ,
185+ $ this ->getTenantsChoiceList (),
186+ );
187+ $ question ->setMultiselect (true );
188+
189+ $ tenantKeys = $ helper ->ask ($ input , $ output , $ question );
190+ $ output ->writeln ('You have just selected: ' .implode (', ' , $ tenantKeys ));
191+ }
152192 }
153193
154194 /**
@@ -163,10 +203,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
163203 $ email = $ input ->getArgument ('email ' );
164204 $ plainPassword = $ input ->getArgument ('password ' );
165205 $ fullName = $ input ->getArgument ('full-name ' );
166- $ isAdmin = $ input ->getOption ('admin ' );
206+ $ role = $ input ->getArgument ('role ' );
207+ $ tenantKeys = $ input ->getArgument ('tenant-keys ' );
167208
168209 // make sure to validate the user data is correct
169- $ this ->validateUserData ($ email , $ plainPassword , $ fullName );
210+ $ this ->validateUserData ($ email , $ plainPassword , $ fullName, $ role , $ tenantKeys );
170211
171212 // create the user and hash its password
172213 $ user = new User ();
@@ -179,19 +220,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int
179220 $ hashedPassword = $ this ->passwordHasher ->hashPassword ($ user , $ plainPassword );
180221 $ user ->setPassword ($ hashedPassword );
181222
182- // @TODO Make it possible to only select specific Tenants
183- $ tenants = $ this ->tenants ->findAll ();
184- foreach ($ tenants as $ tenant ) {
223+ foreach ($ tenantKeys as $ tenantKey ) {
224+ $ tenant = $ this ->tenantRepository ->findOneBy (['tenantKey ' => $ tenantKey ]);
185225 $ userRoleTenant = new UserRoleTenant ();
186226 $ userRoleTenant ->setTenant ($ tenant );
187- $ userRoleTenant ->setRoles ([$ isAdmin ? ' ROLE_ADMIN ' : ' ROLE_EDITOR ' ]);
227+ $ userRoleTenant ->setRoles ([' ROLE_ ' . strtoupper ( $ role ) ]);
188228 $ user ->addUserRoleTenant ($ userRoleTenant );
189229 }
190230
191231 $ this ->entityManager ->persist ($ user );
192232 $ this ->entityManager ->flush ();
193233
194- $ this ->io ->success (sprintf ('%s was successfully created: %s ' , $ isAdmin ? ' Administrator user ' : ' User ' , $ user ->getUserIdentifier ()));
234+ $ this ->io ->success (sprintf ('%s was successfully created: %s ' , ucfirst ( $ role ) , $ user ->getUserIdentifier ()));
195235
196236 $ event = $ stopwatch ->stop ('add-user-command ' );
197237 if ($ output ->isVerbose ()) {
@@ -201,7 +241,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
201241 return Command::SUCCESS ;
202242 }
203243
204- private function validateUserData ($ email , $ plainPassword , $ fullName ): void
244+ private function validateUserData ($ email , $ plainPassword , $ fullName, $ role , $ tenantKeys ): void
205245 {
206246 // first check if a user with the same username already exists.
207247 $ existingUser = $ this ->users ->findOneBy (['email ' => $ email ]);
@@ -214,6 +254,19 @@ private function validateUserData($email, $plainPassword, $fullName): void
214254 $ this ->validator ->validatePassword ($ plainPassword );
215255 $ this ->validator ->validateEmail ($ email );
216256 $ this ->validator ->validateFullName ($ fullName );
257+ $ this ->validator ->validateRole ($ role );
258+ $ this ->validator ->validateTenantKeys ($ tenantKeys );
259+ }
260+
261+ private function getTenantsChoiceList (): array
262+ {
263+ $ tenants = [];
264+ /** @var Tenant $tenant */
265+ foreach ($ this ->tenantRepository ->findBy ([], ['tenantKey ' => 'ASC ' ]) as $ tenant ) {
266+ $ tenants [$ tenant ->getTenantKey ()] = $ tenant ->getDescription ();
267+ }
268+
269+ return $ tenants ;
217270 }
218271
219272 /**
@@ -226,17 +279,12 @@ private function getCommandHelp(): string
226279 return <<<'HELP'
227280The <info>%command.name%</info> command creates new users and saves them in the database:
228281
229- <info>php %command.full_name%</info> <comment>email password</comment>
230-
231- By default the command creates regular users. To create administrator users,
232- add the <comment>--admin</comment> option:
233-
234- <info>php %command.full_name%</info> email password <comment>--admin</comment>
282+ <info>php %command.full_name%</info> <comment>email password fullname role tenants</comment>
235283
236- If you omit any of the two required arguments, the command will ask you to
284+ If you omit any of the required arguments, the command will ask you to
237285provide the missing values:
238286
239- # command will ask you for the password
287+ # command will ask you for the password etc.
240288 <info>php %command.full_name%</info> <comment>email</comment>
241289
242290 # command will ask you for all arguments
0 commit comments