standaloneusers - Allow installer to customize initial user account
authorTim Otten <totten@civicrm.org>
Sat, 24 Jun 2023 06:25:17 +0000 (23:25 -0700)
committerTim Otten <totten@civicrm.org>
Sat, 24 Jun 2023 06:44:20 +0000 (23:44 -0700)
Before: The initial admin account is always "admin" with a random password.

After: The initial admin account has *default* as above, but it can be customized.

* For `cv`, this looks like `cv core:install -m extras.adminUser=alice -m extras.adminPass=SECRET `
* In the future, the same pathway can be used for web-based installer.

ext/standaloneusers/CRM/Standaloneusers/Upgrader.php
setup/plugins/init/StandaloneUsers.civi-setup.php

index 434a304428004bbc89edc5774797d33d914f8da1..d27e801797eb9bfdbae1d4405f303d267c619474 100644 (file)
@@ -50,58 +50,12 @@ class CRM_Standaloneusers_Upgrader extends CRM_Extension_Upgrader_Base {
 
     $users = \Civi\Api4\User::get(FALSE)->selectRowCount()->execute()->countMatched();
     if ($users == 0) {
-
       CRM_Core_DAO::executeQuery('DELETE FROM civicrm_uf_match');
-
-      // Create an admin contact.
-      $contactID = \Civi\Api4\Contact::create(FALSE)
-        ->setValues([
-          'contact_type' => 'Individual',
-          'first_name' => 'Standalone',
-          'last_name' => 'Admin',
-        ])
-        ->execute()->first()['id'];
-      $dummyEmail = 'admin@localhost.localdomain';
-
-      // Create user
-      $password = substr(base64_encode(random_bytes(8)), 0, 12);
-      $params = [
-        'cms_name'   => 'admin',
-        'cms_pass'   => $password,
-        'notify'     => FALSE,
-        $dummyEmail => $dummyEmail,
-        'contactID'  => $contactID,
-      ];
-      $userID = \CRM_Core_BAO_CMSUser::create($params, $dummyEmail);
-
-      // Create Role
-      $roleID = \Civi\Api4\Role::create(FALSE)->setValues(['name' => 'Administrator'])->execute()->first()['id'];
-
-      // Assign role to user
-      \Civi\Api4\UserRole::create(FALSE)->setValues(['role_id' => $roleID, 'user_id' => $userID])->execute();
-
-      // Create permissions for role
-      // @todo I expect there's a better way than this; this doesn't even bring in all the permissions.
-      $records = [['permission' => 'authenticate with password']];
-      foreach (array_keys(\CRM_Core_Permission::getCorePermissions()) as $permission) {
-        $records[] = ['permission' => $permission];
-      }
-      \Civi\Api4\RolePermission::save(FALSE)
-        ->setDefaults(['role_id' => $roleID])
-        ->setRecords($records)
-        ->execute();
-
-      $message = "Created New admin User $userID and contact $contactID with password $password and ALL permissions.";
-      \Civi::log()->notice($message);
-      if (php_sapi_name() === 'cli') {
-        print $message . "\n";
-      }
-      else {
-        $authx = new \Civi\Authx\Standalone();
-        $authx->loginSession($userID);
-        CRM_Core_Session::setStatus($message . " You are logged in!", 'Standalone installed', 'alert');
-      }
     }
+
+    // `standaloneusers` is installed as part of the overall install process for `Standalone`.
+    // A subsequent step will configure some default users (*depending on local options*).
+    // See also: `StandaloneUsers.civi-setup.php`
   }
 
   /**
index 98680b08976f11df7f1b3332677d6ccfc8d7de0a..886e8d9b07aaf4f6e46294e9776acbb86800b6fd 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * @file
  *
- * By default, enable the "standaloneusers" extension on "Standalone" UF. Setup credentials.
+ * On "Standalone" UF, default policy is to enable `standaloneusers` and create user+role.
  */
 
 if (!defined('CIVI_SETUP')) {
@@ -17,23 +17,63 @@ if (!defined('CIVI_SETUP')) {
 
     \Civi\Setup::log()->info(sprintf('[%s] Handle %s', basename(__FILE__), 'init'));
 
+    // Assign defaults. (These may be overridden by the agent performing installation.)
     $e->getModel()->extensions[] = 'standaloneusers';
-    if (empty($e->getModel()->extras['adminPass'])) {
-      $toAlphanum = function ($bits) {
-        return preg_replace(';[^a-zA-Z0-9];', '', base64_encode($bits));
-      };
-      $e->getModel()->extras['adminPass'] = $toAlphanum(random_bytes(8));
-    }
+
+    $toAlphanum = function ($bits) {
+      return preg_replace(';[^a-zA-Z0-9];', '', base64_encode($bits));
+    };
+    $defaults = [
+      'adminUser' => 'admin',
+      'adminPass' => $toAlphanum(random_bytes(8)),
+      'adminEmail' => 'admin@localhost.localdomain',
+    ];
+    $e->getModel()->extras = array_merge($defaults, $e->getModel()->extras);
   });
 
 \Civi\Setup::dispatcher()
   ->addListener('civi.setup.installDatabase', function (\Civi\Setup\Event\InstallDatabaseEvent $e) {
-    if (!in_array('standaloneusers', $e->getModel()->extensions)) {
+    if ($e->getModel()->cms !== 'Standalone' || !in_array('standaloneusers', $e->getModel()->extensions)) {
       return;
     }
 
     \Civi\Setup::log()->info(sprintf('[%s] Handle %s', basename(__FILE__), 'installDatabase'));
 
-    $security = \Civi\Standalone\Security::singleton();
-    // $security->se
+    // Create role with permissions
+    $roleID = \Civi\Api4\Role::create(FALSE)->setValues(['name' => 'Administrator'])->execute()->first()['id'];
+    // @todo I expect there's a better way than this; this doesn't even bring in all the permissions.
+    $records = [['permission' => 'authenticate with password']];
+    foreach (array_keys(\CRM_Core_Permission::getCorePermissions()) as $permission) {
+      $records[] = ['permission' => $permission];
+    }
+    \Civi\Api4\RolePermission::save(FALSE)
+      ->setDefaults(['role_id' => $roleID])
+      ->setRecords($records)
+      ->execute();
+
+    // Create contact+user for admin.
+    $contactID = \Civi\Api4\Contact::create(FALSE)
+      ->setValues([
+        'contact_type' => 'Individual',
+        'first_name' => 'Standalone',
+        'last_name' => 'Admin',
+      ])
+      ->execute()->first()['id'];
+    $adminEmail = $e->getModel()->extras['adminEmail'];
+    $params = [
+      'cms_name'   => $e->getModel()->extras['adminUser'],
+      'cms_pass'   => $e->getModel()->extras['adminPass'],
+      'notify'     => FALSE,
+      $adminEmail => $adminEmail,
+      'contactID'  => $contactID,
+    ];
+    $userID = \CRM_Core_BAO_CMSUser::create($params, $adminEmail);
+
+    // Assign role to user
+    \Civi\Api4\UserRole::create(FALSE)->setValues(['role_id' => $roleID, 'user_id' => $userID])->execute();
+
+    // TODO - If admin specified an explicit password, then we don't really need to log it.
+    $message = "Created new user \"admin\" (user ID #$userID, contact ID #$contactID) with default password \"" . ($e->getModel()->extras['adminPass']) . "\" and ALL permissions.";
+    \Civi::log()->notice($message);
+
   }, \Civi\Setup::PRIORITY_LATE);