88use Illuminate \Support \Facades \Validator ;
99use Illuminate \Support \Str ;
1010use Illuminate \Validation \Rules \Password ;
11- use Illuminate \Validation \Rules \Unique ;
1211
1312class CreateAdminCommand extends Command
1413{
@@ -21,7 +20,9 @@ class CreateAdminCommand extends Command
2120 {--email= : The email address for the new admin user}
2221 {--name= : The name of the new admin user}
2322 {--password= : The password to assign to the new admin user}
24- {--external-auth-id= : The external authentication system id for the new admin user (SAML2/LDAP/OIDC)} ' ;
23+ {--external-auth-id= : The external authentication system id for the new admin user (SAML2/LDAP/OIDC)}
24+ {--generate-password : Generate a random password for the new admin user}
25+ {--initial : Indicate if this should set/update the details of the initial admin user} ' ;
2526
2627 /**
2728 * The console command description.
@@ -35,26 +36,12 @@ class CreateAdminCommand extends Command
3536 */
3637 public function handle (UserRepo $ userRepo ): int
3738 {
38- $ details = $ this ->snakeCaseOptions ();
39-
40- if (empty ($ details ['email ' ])) {
41- $ details ['email ' ] = $ this ->ask ('Please specify an email address for the new admin user ' );
42- }
43-
44- if (empty ($ details ['name ' ])) {
45- $ details ['name ' ] = $ this ->ask ('Please specify a name for the new admin user ' );
46- }
47-
48- if (empty ($ details ['password ' ])) {
49- if (empty ($ details ['external_auth_id ' ])) {
50- $ details ['password ' ] = $ this ->ask ('Please specify a password for the new admin user (8 characters min) ' );
51- } else {
52- $ details ['password ' ] = Str::random (32 );
53- }
54- }
39+ $ initialAdminOnly = $ this ->option ('initial ' );
40+ $ shouldGeneratePassword = $ this ->option ('generate-password ' );
41+ $ details = $ this ->gatherDetails ($ shouldGeneratePassword , $ initialAdminOnly );
5542
5643 $ validator = Validator::make ($ details , [
57- 'email ' => ['required ' , 'email ' , 'min:5 ' , new Unique ( ' users ' , ' email ' ) ],
44+ 'email ' => ['required ' , 'email ' , 'min:5 ' ],
5845 'name ' => ['required ' , 'min:2 ' ],
5946 'password ' => ['required_without:external_auth_id ' , Password::default ()],
6047 'external_auth_id ' => ['required_without:password ' ],
@@ -68,16 +55,101 @@ public function handle(UserRepo $userRepo): int
6855 return 1 ;
6956 }
7057
58+ $ adminRole = Role::getSystemRole ('admin ' );
59+
60+ if ($ initialAdminOnly ) {
61+ $ handled = $ this ->handleInitialAdminIfExists ($ userRepo , $ details , $ shouldGeneratePassword , $ adminRole );
62+ if ($ handled !== null ) {
63+ return $ handled ;
64+ }
65+ }
66+
67+ $ emailUsed = $ userRepo ->getByEmail ($ details ['email ' ]) !== null ;
68+ if ($ emailUsed ) {
69+ $ this ->error ("Could not create admin account. " );
70+ $ this ->error ("An account with the email address \"{$ details ['email ' ]}\" already exists. " );
71+ return 1 ;
72+ }
73+
7174 $ user = $ userRepo ->createWithoutActivity ($ validator ->validated ());
72- $ user ->attachRole (Role:: getSystemRole ( ' admin ' ) );
75+ $ user ->attachRole ($ adminRole );
7376 $ user ->email_confirmed = true ;
7477 $ user ->save ();
7578
76- $ this ->info ("Admin account with email \"{$ user ->email }\" successfully created! " );
79+ if ($ shouldGeneratePassword ) {
80+ $ this ->line ($ details ['password ' ]);
81+ } else {
82+ $ this ->info ("Admin account with email \"{$ user ->email }\" successfully created! " );
83+ }
7784
7885 return 0 ;
7986 }
8087
88+ /**
89+ * Handle updates to the original admin account if it exists.
90+ * Returns an int return status if handled, otherwise returns null if not handled (new user to be created).
91+ */
92+ protected function handleInitialAdminIfExists (UserRepo $ userRepo , array $ data , bool $ generatePassword , Role $ adminRole ): int |null
93+ {
94+ $ defaultAdmin =
$ userRepo->
getByEmail (
'[email protected] ' );
95+ if ($ defaultAdmin && $ defaultAdmin ->hasSystemRole ('admin ' )) {
96+ if ($ defaultAdmin ->email !== $ data ['email ' ] && $ userRepo ->getByEmail ($ data ['email ' ]) !== null ) {
97+ $ this ->error ("Could not create admin account. " );
98+ $ this ->error ("An account with the email address \"{$ data ['email ' ]}\" already exists. " );
99+ return 1 ;
100+ }
101+
102+ $ userRepo ->updateWithoutActivity ($ defaultAdmin , $ data , true );
103+ if ($ generatePassword ) {
104+ $ this ->line ($ data ['password ' ]);
105+ } else {
106+ $ this ->info ("The default admin user has been updated with the provided details! " );
107+ }
108+
109+ return 0 ;
110+ } else if ($ adminRole ->users ()->count () > 0 ) {
111+ $ this ->warn ('Non-default admin user already exists. Skipping creation of new admin user. ' );
112+ return 2 ;
113+ }
114+
115+ return null ;
116+ }
117+
118+ protected function gatherDetails (bool $ generatePassword , bool $ initialAdmin ): array
119+ {
120+ $ details = $ this ->snakeCaseOptions ();
121+
122+ if (empty ($ details ['email ' ])) {
123+ if ($ initialAdmin ) {
124+ $ details[
'email ' ] =
'[email protected] ' ;
125+ } else {
126+ $ details ['email ' ] = $ this ->ask ('Please specify an email address for the new admin user ' );
127+ }
128+ }
129+
130+ if (empty ($ details ['name ' ])) {
131+ if ($ initialAdmin ) {
132+ $ details ['name ' ] = 'Admin ' ;
133+ } else {
134+ $ details ['name ' ] = $ this ->ask ('Please specify a name for the new admin user ' );
135+ }
136+ }
137+
138+ if (empty ($ details ['password ' ])) {
139+ if (empty ($ details ['external_auth_id ' ])) {
140+ if ($ generatePassword ) {
141+ $ details ['password ' ] = Str::random (32 );
142+ } else {
143+ $ details ['password ' ] = $ this ->ask ('Please specify a password for the new admin user (8 characters min) ' );
144+ }
145+ } else {
146+ $ details ['password ' ] = Str::random (32 );
147+ }
148+ }
149+
150+ return $ details ;
151+ }
152+
81153 protected function snakeCaseOptions (): array
82154 {
83155 $ returnOpts = [];
0 commit comments