From 0eab750a3aa8cfc0a905d9f3cc9d9481bb623d56 Mon Sep 17 00:00:00 2001 From: Rich Lott / Artful Robot Date: Mon, 3 Jul 2023 10:57:06 +0100 Subject: [PATCH] standalone: change schema for RBAC; update tests --- CRM/Core/SelectValues.php | 19 ++ .../CRM/Standaloneusers/BAO/Role.php | 30 ++++ .../DAO/{RolePermission.php => Role.php} | 162 +++++++++++++----- .../CRM/Standaloneusers/DAO/User.php | 12 +- .../Api4/{RolePermission.php => Role.php} | 4 +- .../Civi/Standalone/Security.php | 34 ++-- .../managed/OptionGroup_role.mgd.php | 64 ------- ext/standaloneusers/sql/auto_install.sql | 18 +- ext/standaloneusers/sql/auto_uninstall.sql | 2 +- .../phpunit/Civi/Standalone/SecurityTest.php | 35 ++-- ...ion.entityType.php => Role.entityType.php} | 6 +- .../xml/schema/CRM/Standaloneusers/Role.xml | 65 +++++++ .../CRM/Standaloneusers/RolePermission.xml | 41 ----- .../xml/schema/CRM/Standaloneusers/User.xml | 7 +- .../init/StandaloneUsers.civi-setup.php | 33 ++-- 15 files changed, 311 insertions(+), 221 deletions(-) create mode 100644 ext/standaloneusers/CRM/Standaloneusers/BAO/Role.php rename ext/standaloneusers/CRM/Standaloneusers/DAO/{RolePermission.php => Role.php} (54%) rename ext/standaloneusers/Civi/Api4/{RolePermission.php => Role.php} (60%) delete mode 100644 ext/standaloneusers/managed/OptionGroup_role.mgd.php rename ext/standaloneusers/xml/schema/CRM/Standaloneusers/{RolePermission.entityType.php => Role.entityType.php} (59%) create mode 100644 ext/standaloneusers/xml/schema/CRM/Standaloneusers/Role.xml delete mode 100644 ext/standaloneusers/xml/schema/CRM/Standaloneusers/RolePermission.xml diff --git a/CRM/Core/SelectValues.php b/CRM/Core/SelectValues.php index 3b7c242781..bcbff0c96d 100644 --- a/CRM/Core/SelectValues.php +++ b/CRM/Core/SelectValues.php @@ -1210,4 +1210,23 @@ class CRM_Core_SelectValues { ]; } + /** + * Callback for Role.permissions pseudoconstant values. + * + * Permissions for Civi Standalone, not used by CMS-based systems. + * + * @return array + */ + public static function permissions() { + $perms = $options = []; + \CRM_Utils_Hook::permissionList($perms); + + foreach ($perms as $machineName => $details) { + if ($details['is_active']) { + $options[$machineName] = $details['title']; + } + } + return $options; + } + } diff --git a/ext/standaloneusers/CRM/Standaloneusers/BAO/Role.php b/ext/standaloneusers/CRM/Standaloneusers/BAO/Role.php new file mode 100644 index 0000000000..5517aa72f5 --- /dev/null +++ b/ext/standaloneusers/CRM/Standaloneusers/BAO/Role.php @@ -0,0 +1,30 @@ +copyValues($params); + $instance->save(); + CRM_Utils_Hook::post($hook, $entityName, $instance->id, $instance); + + return $instance; + } + */ + +} diff --git a/ext/standaloneusers/CRM/Standaloneusers/DAO/RolePermission.php b/ext/standaloneusers/CRM/Standaloneusers/DAO/Role.php similarity index 54% rename from ext/standaloneusers/CRM/Standaloneusers/DAO/RolePermission.php rename to ext/standaloneusers/CRM/Standaloneusers/DAO/Role.php index fc800fb637..f673ef5494 100644 --- a/ext/standaloneusers/CRM/Standaloneusers/DAO/RolePermission.php +++ b/ext/standaloneusers/CRM/Standaloneusers/DAO/Role.php @@ -4,16 +4,16 @@ * @package CRM * @copyright CiviCRM LLC https://civicrm.org/licensing * - * Generated from standaloneusers/xml/schema/CRM/Standaloneusers/RolePermission.xml + * Generated from standaloneusers/xml/schema/CRM/Standaloneusers/Role.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:9bd09dba43f645696426e1ef15f776d9) + * (GenCodeChecksum:d28fa09f872be30740de728c9e344a6d) */ use CRM_Standaloneusers_ExtensionUtil as E; /** - * Database access object for the RolePermission entity. + * Database access object for the Role entity. */ -class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { +class CRM_Standaloneusers_DAO_Role extends CRM_Core_DAO { const EXT = E::LONG_NAME; const TABLE_ADDED = ''; @@ -22,7 +22,14 @@ class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { * * @var string */ - public static $_tableName = 'civicrm_role_permission'; + public static $_tableName = 'civicrm_role'; + + /** + * Field to show when displaying a record. + * + * @var string + */ + public static $_labelField = 'label'; /** * Should CiviCRM log any modifications to this table in the civicrm_log table. @@ -32,7 +39,7 @@ class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { public static $_log = TRUE; /** - * Unique RolePermission ID + * Unique Role ID * * @var int|string|null * (SQL type: int unsigned) @@ -41,28 +48,46 @@ class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { public $id; /** - * FK to a role option value + * Machine name for this role * - * @var int|string|null - * (SQL type: int unsigned) + * @var string + * (SQL type: varchar(60)) * Note that values will be retrieved from the database as a string. */ - public $role_id; + public $name; /** - * A single permission granted to this role + * Human friendly name for this role * * @var string - * (SQL type: varchar(60)) + * (SQL type: varchar(128)) + * Note that values will be retrieved from the database as a string. + */ + public $label; + + /** + * List of permissions granted by this role + * + * @var string + * (SQL type: text) + * Note that values will be retrieved from the database as a string. + */ + public $permissions; + + /** + * Only active roles grant permissions + * + * @var bool|string|null + * (SQL type: tinyint) * Note that values will be retrieved from the database as a string. */ - public $permission; + public $is_active; /** * Class constructor. */ public function __construct() { - $this->__table = 'civicrm_role_permission'; + $this->__table = 'civicrm_role'; parent::__construct(); } @@ -73,7 +98,7 @@ class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { * Whether to return the plural version of the title. */ public static function getEntityTitle($plural = FALSE) { - return $plural ? E::ts('Role Permissions') : E::ts('Role Permission'); + return $plural ? E::ts('Roles') : E::ts('Role'); } /** @@ -88,7 +113,7 @@ class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { 'name' => 'id', 'type' => CRM_Utils_Type::T_INT, 'title' => E::ts('ID'), - 'description' => E::ts('Unique RolePermission ID'), + 'description' => E::ts('Unique Role ID'), 'required' => TRUE, 'usage' => [ 'import' => FALSE, @@ -96,10 +121,10 @@ class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { 'duplicate_matching' => FALSE, 'token' => FALSE, ], - 'where' => 'civicrm_role_permission.id', - 'table_name' => 'civicrm_role_permission', - 'entity' => 'RolePermission', - 'bao' => 'CRM_Standaloneusers_DAO_RolePermission', + 'where' => 'civicrm_role.id', + 'table_name' => 'civicrm_role', + 'entity' => 'Role', + 'bao' => 'CRM_Standaloneusers_DAO_Role', 'localizable' => 0, 'html' => [ 'type' => 'Number', @@ -107,47 +132,94 @@ class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { 'readonly' => TRUE, 'add' => NULL, ], - 'role_id' => [ - 'name' => 'role_id', - 'type' => CRM_Utils_Type::T_INT, - 'title' => E::ts('Role ID'), - 'description' => E::ts('FK to a role option value'), + 'name' => [ + 'name' => 'name', + 'type' => CRM_Utils_Type::T_STRING, + 'title' => E::ts('Name'), + 'description' => E::ts('Machine name for this role'), + 'required' => TRUE, + 'maxlength' => 60, + 'size' => CRM_Utils_Type::BIG, 'usage' => [ 'import' => FALSE, 'export' => FALSE, 'duplicate_matching' => FALSE, 'token' => FALSE, ], - 'where' => 'civicrm_role_permission.role_id', - 'table_name' => 'civicrm_role_permission', - 'entity' => 'RolePermission', - 'bao' => 'CRM_Standaloneusers_DAO_RolePermission', + 'where' => 'civicrm_role.name', + 'table_name' => 'civicrm_role', + 'entity' => 'Role', + 'bao' => 'CRM_Standaloneusers_DAO_Role', 'localizable' => 0, - 'pseudoconstant' => [ - 'optionGroupName' => 'role', - 'optionEditPath' => 'civicrm/admin/options/role', - ], 'add' => NULL, ], - 'permission' => [ - 'name' => 'permission', + 'label' => [ + 'name' => 'label', 'type' => CRM_Utils_Type::T_STRING, - 'title' => E::ts('Permission'), - 'description' => E::ts('A single permission granted to this role'), + 'title' => E::ts('Label'), + 'description' => E::ts('Human friendly name for this role'), + 'required' => TRUE, + 'maxlength' => 128, + 'size' => CRM_Utils_Type::HUGE, + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], + 'where' => 'civicrm_role.label', + 'table_name' => 'civicrm_role', + 'entity' => 'Role', + 'bao' => 'CRM_Standaloneusers_DAO_Role', + 'localizable' => 0, + 'add' => NULL, + ], + 'permissions' => [ + 'name' => 'permissions', + 'type' => CRM_Utils_Type::T_TEXT, + 'title' => E::ts('Permissions'), + 'description' => E::ts('List of permissions granted by this role'), 'required' => TRUE, - 'maxlength' => 60, - 'size' => CRM_Utils_Type::BIG, 'usage' => [ 'import' => FALSE, 'export' => FALSE, 'duplicate_matching' => FALSE, 'token' => FALSE, ], - 'where' => 'civicrm_role_permission.permission', - 'table_name' => 'civicrm_role_permission', - 'entity' => 'RolePermission', - 'bao' => 'CRM_Standaloneusers_DAO_RolePermission', + 'where' => 'civicrm_role.permissions', + 'table_name' => 'civicrm_role', + 'entity' => 'Role', + 'bao' => 'CRM_Standaloneusers_DAO_Role', 'localizable' => 0, + 'serialize' => self::SERIALIZE_SEPARATOR_BOOKEND, + 'html' => [ + 'type' => 'Select', + ], + 'pseudoconstant' => [ + 'callback' => 'CRM_Core_SelectValues::permissions', + ], + 'add' => NULL, + ], + 'is_active' => [ + 'name' => 'is_active', + 'type' => CRM_Utils_Type::T_BOOLEAN, + 'title' => E::ts('Role is active'), + 'description' => E::ts('Only active roles grant permissions'), + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], + 'where' => 'civicrm_role.is_active', + 'default' => '1', + 'table_name' => 'civicrm_role', + 'entity' => 'Role', + 'bao' => 'CRM_Standaloneusers_DAO_Role', + 'localizable' => 0, + 'html' => [ + 'type' => 'CheckBox', + ], 'add' => NULL, ], ]; @@ -195,7 +267,7 @@ class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { * @return array */ public static function &import($prefix = FALSE) { - $r = CRM_Core_DAO_AllCoreTables::getImports(__CLASS__, 'role_permission', $prefix, []); + $r = CRM_Core_DAO_AllCoreTables::getImports(__CLASS__, 'role', $prefix, []); return $r; } @@ -207,7 +279,7 @@ class CRM_Standaloneusers_DAO_RolePermission extends CRM_Core_DAO { * @return array */ public static function &export($prefix = FALSE) { - $r = CRM_Core_DAO_AllCoreTables::getExports(__CLASS__, 'role_permission', $prefix, []); + $r = CRM_Core_DAO_AllCoreTables::getExports(__CLASS__, 'role', $prefix, []); return $r; } diff --git a/ext/standaloneusers/CRM/Standaloneusers/DAO/User.php b/ext/standaloneusers/CRM/Standaloneusers/DAO/User.php index eaf0b65fee..d41f9d64c7 100644 --- a/ext/standaloneusers/CRM/Standaloneusers/DAO/User.php +++ b/ext/standaloneusers/CRM/Standaloneusers/DAO/User.php @@ -6,7 +6,7 @@ * * Generated from standaloneusers/xml/schema/CRM/Standaloneusers/User.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:7f2d1d449d263061c7db7a6c5d57c27d) + * (GenCodeChecksum:8b4f87b26bd48490757533b57378e33d) */ use CRM_Standaloneusers_ExtensionUtil as E; @@ -92,7 +92,7 @@ class CRM_Standaloneusers_DAO_User extends CRM_Core_DAO { public $email; /** - * FK to values from OptionGroup role + * FK to Role * * @var string|null * (SQL type: varchar(128)) @@ -301,7 +301,7 @@ class CRM_Standaloneusers_DAO_User extends CRM_Core_DAO { 'name' => 'roles', 'type' => CRM_Utils_Type::T_STRING, 'title' => E::ts('Roles'), - 'description' => E::ts('FK to values from OptionGroup role'), + 'description' => E::ts('FK to Role'), 'maxlength' => 128, 'size' => CRM_Utils_Type::HUGE, 'usage' => [ @@ -320,8 +320,10 @@ class CRM_Standaloneusers_DAO_User extends CRM_Core_DAO { 'type' => 'Select', ], 'pseudoconstant' => [ - 'optionGroupName' => 'role', - 'optionEditPath' => 'civicrm/admin/options/role', + 'table' => 'civicrm_role', + 'keyColumn' => 'id', + 'labelColumn' => 'label', + 'nameColumn' => 'name', ], 'add' => NULL, ], diff --git a/ext/standaloneusers/Civi/Api4/RolePermission.php b/ext/standaloneusers/Civi/Api4/Role.php similarity index 60% rename from ext/standaloneusers/Civi/Api4/RolePermission.php rename to ext/standaloneusers/Civi/Api4/Role.php index df22311640..678779fa3a 100644 --- a/ext/standaloneusers/Civi/Api4/RolePermission.php +++ b/ext/standaloneusers/Civi/Api4/Role.php @@ -2,12 +2,12 @@ namespace Civi\Api4; /** - * RolePermission entity. + * Role entity. * * Provided by the Standalone Users extension. * * @package Civi\Api4 */ -class RolePermission extends Generic\DAOEntity { +class Role extends Generic\DAOEntity { } diff --git a/ext/standaloneusers/Civi/Standalone/Security.php b/ext/standaloneusers/Civi/Standalone/Security.php index c2f4e2cead..3014805bcd 100644 --- a/ext/standaloneusers/Civi/Standalone/Security.php +++ b/ext/standaloneusers/Civi/Standalone/Security.php @@ -64,6 +64,7 @@ class Security { public function checkPermission(\CRM_Core_Permission_Standalone $permissionObject, string $permissionName, $userID) { // I think null means the current logged-in user + xdebug_break(); $userID = $userID ?? $this->getLoggedInUfID(); if (!$userID) { @@ -71,19 +72,28 @@ class Security { return FALSE; } - // @todo handle anonymous permissions! + if (!isset(\Civi::$statics[__METHOD__][$userID])) { + if ($userID) { + $roleIDs = \Civi\Api4\User::get(FALSE)->addWhere('id', '=', $userID) + ->addSelect('roles')->execute()->first()['roles']; + // Grant the 'Everyone' role, too. + $roleIDs[] = 1; + } + else { + // Everyone + $roleIDs = [1]; + } - $roleIDs = \Civi\Api4\User::get(FALSE)->addWhere('id', '=', $userID) - ->addSelect('roles')->execute()->first()['roles']; + $permissionsPerRole = \Civi\Api4\Role::get(FALSE) + ->addSelect('permissions') + ->addWhere('id', 'IN', $roleIDs) + // ->addWhere('is_active', '=', TRUE) @todo + ->execute()->column('permissions'); + $permissions = array_unique(array_merge(...$permissionsPerRole)); + \Civi::$statics[__METHOD__][$userID] = $permissions; + } - // artfulrobot: I think we should cache these per request, e.g. Civi::$statics? - // except in testing permissions shouldn't change during a request. @todo - $found = \Civi\Api4\RolePermission::get(FALSE) - ->selectRowCount() - ->addWhere('role_id', 'IN', $roleIDs) - ->addWhere('permission', '=', $permissionName) - ->execute()->countMatched(); - return (bool) $found; + return in_array($permissionName, \Civi::$statics[__METHOD__][$userID]); } /** @@ -143,7 +153,7 @@ class Security { * - 'cms_pass' plaintext password * - 'notify' boolean * @param string $mail - * Email id for cms user. + * Email address for cms user. * * @return int|bool * uid if user was created, false otherwise diff --git a/ext/standaloneusers/managed/OptionGroup_role.mgd.php b/ext/standaloneusers/managed/OptionGroup_role.mgd.php deleted file mode 100644 index 6cde7cb77b..0000000000 --- a/ext/standaloneusers/managed/OptionGroup_role.mgd.php +++ /dev/null @@ -1,64 +0,0 @@ - 'OptionGroup_role', - 'entity' => 'OptionGroup', - 'cleanup' => 'unused', - 'update' => 'unmodified', - 'params' => [ - 'version' => 4, - 'values' => [ - 'name' => 'role', - 'title' => E::ts('Role'), - 'description' => E::ts('A role is grants permissions to users in CiviCRM Standalone.'), - 'data_type' => 'Integer', - 'is_reserved' => TRUE, - 'is_active' => TRUE, - 'is_locked' => FALSE, - 'option_value_fields' => [ - 'label', - 'description', - 'icon', - 'color', - 'name', - ], - ], - 'match' => [ - 'name', - ], - ], - ], - [ - 'name' => 'OptionGroup_role_OptionValue_admin', - 'entity' => 'OptionValue', - 'cleanup' => 'unused', - 'update' => 'unmodified', - 'params' => [ - 'version' => 4, - 'values' => [ - 'option_group_id.name' => 'role', - 'label' => E::ts('Administrator'), - 'value' => '1', - 'name' => 'admin', - 'grouping' => NULL, - 'filter' => 0, - 'is_default' => FALSE, - 'description' => NULL, - 'is_optgroup' => FALSE, - 'is_reserved' => TRUE, - 'is_active' => TRUE, - 'component_id' => NULL, - 'domain_id' => NULL, - 'visibility_id' => NULL, - 'icon' => NULL, - 'color' => NULL, - ], - 'match' => [ - 'name', - 'option_group_id', - ], - ], - ], -]; diff --git a/ext/standaloneusers/sql/auto_install.sql b/ext/standaloneusers/sql/auto_install.sql index c03740accf..6bec096b99 100644 --- a/ext/standaloneusers/sql/auto_install.sql +++ b/ext/standaloneusers/sql/auto_install.sql @@ -18,7 +18,7 @@ SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS `civicrm_user`; -DROP TABLE IF EXISTS `civicrm_role_permission`; +DROP TABLE IF EXISTS `civicrm_role`; SET FOREIGN_KEY_CHECKS=1; -- /******************************************************* @@ -29,15 +29,17 @@ SET FOREIGN_KEY_CHECKS=1; -- /******************************************************* -- * --- * civicrm_role_permission +-- * civicrm_role -- * --- * Assigns permissions to roles +-- * A Role holds a set of permissions. Roles may be granted to Users. -- * -- *******************************************************/ -CREATE TABLE `civicrm_role_permission` ( - `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'Unique RolePermission ID', - `role_id` int unsigned COMMENT 'FK to a role option value', - `permission` varchar(60) NOT NULL COMMENT 'A single permission granted to this role', +CREATE TABLE `civicrm_role` ( + `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'Unique Role ID', + `name` varchar(60) NOT NULL COMMENT 'Machine name for this role', + `label` varchar(128) NOT NULL COMMENT 'Human friendly name for this role', + `permissions` text NOT NULL COMMENT 'List of permissions granted by this role', + `is_active` tinyint DEFAULT 1 COMMENT 'Only active roles grant permissions', PRIMARY KEY (`id`) ) ENGINE=InnoDB; @@ -55,7 +57,7 @@ CREATE TABLE `civicrm_user` ( `username` varchar(60) NOT NULL, `password` varchar(128) NOT NULL COMMENT 'Hashed password', `email` varchar(255) NOT NULL COMMENT 'Email (e.g. for password resets)', - `roles` varchar(128) COMMENT 'FK to values from OptionGroup role', + `roles` varchar(128) COMMENT 'FK to Role', `when_created` timestamp DEFAULT CURRENT_TIMESTAMP, `when_last_accessed` timestamp NULL, `when_updated` timestamp NULL, diff --git a/ext/standaloneusers/sql/auto_uninstall.sql b/ext/standaloneusers/sql/auto_uninstall.sql index 6485a0f1ef..f754abde63 100644 --- a/ext/standaloneusers/sql/auto_uninstall.sql +++ b/ext/standaloneusers/sql/auto_uninstall.sql @@ -16,6 +16,6 @@ SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS `civicrm_user`; -DROP TABLE IF EXISTS `civicrm_role_permission`; +DROP TABLE IF EXISTS `civicrm_role`; SET FOREIGN_KEY_CHECKS=1; \ No newline at end of file diff --git a/ext/standaloneusers/tests/phpunit/Civi/Standalone/SecurityTest.php b/ext/standaloneusers/tests/phpunit/Civi/Standalone/SecurityTest.php index 97db8a5f90..9336b7ae23 100644 --- a/ext/standaloneusers/tests/phpunit/Civi/Standalone/SecurityTest.php +++ b/ext/standaloneusers/tests/phpunit/Civi/Standalone/SecurityTest.php @@ -74,39 +74,26 @@ class SecurityTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf [$contactID, $userID, $security] = $this->createFixtureContactAndUser(); // Create a custom role - $roleID = \Civi\Api4\OptionValue::create(FALSE) + $roleID = \Civi\Api4\Role::create(FALSE) ->setValues([ - 'option_group_id.name' => 'role', 'name' => 'demo_role', 'label' => 'demo_role', - ])->execute()->first()['value']; + 'permissions' => [ + // Main control for access to the main CiviCRM backend and API. Give to trusted roles only. + 'access CiviCRM', + 'view all contacts', + 'add contacts', + 'edit all contacts', + // 'administer CiviCRM' // Perform all tasks in the Administer CiviCRM control panel and Import Contacts + ], + ])->execute()->first()['id']; // Give our user this role only. \Civi\Api4\User::update(FALSE) - ->addValue('roles', [$roleID]) + ->addValue('roles:name', ['demo_role']) ->addWhere('id', '=', $userID) ->execute(); - $existingPermissions = \Civi\Api4\RolePermission::get(FALSE) - ->selectRowCount() - ->addWhere('role_id', '=', $demoRoleID) - ->execute()->count(); - $this->assertEquals(0, $existingPermissions); - - // Assign some permissions to the role. - \Civi\Api4\RolePermission::save(FALSE) - ->setDefaults(['role_id' => $roleID]) - ->setRecords([ - // Master control for access to the main CiviCRM backend and API. Give to trusted roles only. - ['permission' => 'access CiviCRM'], - // Perform all tasks in the Administer CiviCRM control panel and Import Contacts - // ['permission' => 'administer CiviCRM'], - ['permission' => 'view all contacts'], - ['permission' => 'add contacts'], - ['permission' => 'edit all contacts'], - ]) - ->execute(); - $this->switchToOurUFClasses(); foreach (['access CiviCRM', 'view all contacts', 'add contacts', 'edit all contacts'] as $allowed) { $this->assertTrue(\CRM_Core_Permission::check([$allowed], $contactID), "Should have '$allowed' permission but don't"); diff --git a/ext/standaloneusers/xml/schema/CRM/Standaloneusers/RolePermission.entityType.php b/ext/standaloneusers/xml/schema/CRM/Standaloneusers/Role.entityType.php similarity index 59% rename from ext/standaloneusers/xml/schema/CRM/Standaloneusers/RolePermission.entityType.php rename to ext/standaloneusers/xml/schema/CRM/Standaloneusers/Role.entityType.php index 922e73b92d..881922985e 100644 --- a/ext/standaloneusers/xml/schema/CRM/Standaloneusers/RolePermission.entityType.php +++ b/ext/standaloneusers/xml/schema/CRM/Standaloneusers/Role.entityType.php @@ -3,8 +3,8 @@ // https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_entityTypes return [ [ - 'name' => 'RolePermission', - 'class' => 'CRM_Standaloneusers_DAO_RolePermission', - 'table' => 'civicrm_role_permission', + 'name' => 'Role', + 'class' => 'CRM_Standaloneusers_DAO_Role', + 'table' => 'civicrm_role', ], ]; diff --git a/ext/standaloneusers/xml/schema/CRM/Standaloneusers/Role.xml b/ext/standaloneusers/xml/schema/CRM/Standaloneusers/Role.xml new file mode 100644 index 0000000000..35a3b2c994 --- /dev/null +++ b/ext/standaloneusers/xml/schema/CRM/Standaloneusers/Role.xml @@ -0,0 +1,65 @@ + + + + CRM/Standaloneusers + Role + civicrm_role + A Role holds a set of permissions. Roles may be granted to Users. + true + + + id + int unsigned + true + Unique Role ID + + Number + + + + id + true + + + + name + Machine name for this role + varchar + 60 + true + + + + label + Human friendly name for this role + varchar + 128 + true + + + + permissions + List of permissions granted by this role + text + true + + CRM_Core_SelectValues::permissions + + + Select + + SEPARATOR_BOOKEND + + + + is_active + Role is active + Only active roles grant permissions + boolean + 1 + + CheckBox + + + +
diff --git a/ext/standaloneusers/xml/schema/CRM/Standaloneusers/RolePermission.xml b/ext/standaloneusers/xml/schema/CRM/Standaloneusers/RolePermission.xml deleted file mode 100644 index 7d6abf6487..0000000000 --- a/ext/standaloneusers/xml/schema/CRM/Standaloneusers/RolePermission.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - CRM/Standaloneusers - RolePermission - civicrm_role_permission - Assigns permissions to roles - true - - - id - int unsigned - true - Unique RolePermission ID - - Number - - - - id - true - - - - role_id - int unsigned - FK to a role option value - - role - - - - - permission - varchar - 60 - true - A single permission granted to this role - - -
diff --git a/ext/standaloneusers/xml/schema/CRM/Standaloneusers/User.xml b/ext/standaloneusers/xml/schema/CRM/Standaloneusers/User.xml index db7b91cde0..8c199292aa 100644 --- a/ext/standaloneusers/xml/schema/CRM/Standaloneusers/User.xml +++ b/ext/standaloneusers/xml/schema/CRM/Standaloneusers/User.xml @@ -80,9 +80,12 @@ varchar Roles 128 - FK to values from OptionGroup role + FK to Role - role + civicrm_role
+ id + label + name
Select diff --git a/setup/plugins/init/StandaloneUsers.civi-setup.php b/setup/plugins/init/StandaloneUsers.civi-setup.php index 692dc1b1b1..b8a3b0bfed 100644 --- a/setup/plugins/init/StandaloneUsers.civi-setup.php +++ b/setup/plugins/init/StandaloneUsers.civi-setup.php @@ -40,18 +40,24 @@ if (!defined('CIVI_SETUP')) { \Civi\Setup::log()->info(sprintf('[%s] Handle %s', basename(__FILE__), 'installDatabase')); - // admin should always be role 1 on install. - $roleID = 1; - - // @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(); + $roles = \Civi\Api4\Role::save(FALSE) + ->setDefaults([ + 'is_active' => TRUE, + ]) + ->setRecords([ + [ + 'name' => 'everyone', + 'label' => 'Everyone, including anonymous users', + // @todo some standard ones, e.g. view civimail. + 'permissions' => [], + ], + [ + 'name' => 'admin', + 'label' => 'Administrator', + 'permissions' => array_keys(\CRM_Core_SelectValues::permissions()), + ], + ]) + ->execute()->indexBy('name'); // Create contact+user for admin. $contactID = \Civi\Api4\Contact::create(FALSE) @@ -66,7 +72,6 @@ if (!defined('CIVI_SETUP')) { '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); @@ -74,7 +79,7 @@ if (!defined('CIVI_SETUP')) { // Assign 'admin' role to user \Civi\Api4\User::update(FALSE) ->addWhere('id', '=', $userID) - ->addValue('roles', [$roleID]) + ->addValue('roles:name', ['admin']) ->execute(); $message = "Created new user \"{$e->getModel()->extras['adminUser']}\" (user ID #$userID, contact ID #$contactID) with 'admin' role and "; -- 2.25.1