diff --git a/CHANGELOG.md b/CHANGELOG.md index c517197fd89..9a6af5db6fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Release Notes for Craft CMS 4 +## Unreleased + +- The `entrify/categories` and `entrify/global-set` commands now update user permissions for the new sections. ([#12849](https://github.com/craftcms/cms/discussions/12849)) + ## 4.4.1 - 2023-03-09 - Fixed a bug where it wasn’t possible to select subfolders on the Assets index page. ([#12802](https://github.com/craftcms/cms/issues/12802)) diff --git a/src/console/controllers/EntrifyController.php b/src/console/controllers/EntrifyController.php index 473eb237970..672c9111095 100644 --- a/src/console/controllers/EntrifyController.php +++ b/src/console/controllers/EntrifyController.php @@ -10,6 +10,7 @@ use Craft; use craft\base\Event; use craft\console\Controller; +use craft\db\Query; use craft\db\Table; use craft\elements\Category; use craft\elements\Entry; @@ -106,6 +107,7 @@ public function actionCategories(string $categoryGroup): int $projectConfigService = Craft::$app->getProjectConfig(); $projectConfigChanged = false; + $sectionCreated = false; if ( !isset($this->section) && @@ -120,6 +122,7 @@ public function actionCategories(string $categoryGroup): int 'fromCategoryGroup' => $categoryGroup->handle, ]); $projectConfigChanged = true; + $sectionCreated = true; } try { @@ -221,6 +224,25 @@ public function actionCategories(string $categoryGroup): int $this->success('Categories converted.'); + $this->_updateUserPermissions([ + "viewCategories:$categoryGroup->uid" => [ + "viewEntries:$section->uid", + "viewPeerEntries:$section->uid", + ], + "saveCategories:$categoryGroup->uid" => [ + "createEntries:$section->uid", + "saveEntries:$section->uid", + "savePeerEntries:$section->uid", + ], + "deleteCategories:$categoryGroup->uid" => [ + "deleteEntries:$section->uid", + "deletePeerEntries:$section->uid", + ], + "viewPeerCategoryDrafts:$categoryGroup->uid" => "viewPeerEntryDrafts:$section->uid", + "savePeerCategoryDrafts:$categoryGroup->uid" => "savePeerEntryDrafts:$section->uid", + "deletePeerCategoryDrafts:$categoryGroup->uid" => "deletePeerEntryDrafts:$section->uid", + ], $sectionCreated); + if (!$projectConfigService->readOnly) { if (!$categoryGroup->dateDeleted && $this->confirm("Delete the “{$categoryGroup}” category group?", true)) { $this->do('Deleting category group', function() use ($categoryGroup) { @@ -421,6 +443,7 @@ public function actionGlobalSet(string $globalSet): int } $projectConfigChanged = false; + $sectionCreated = false; if ( !isset($this->section) && @@ -435,6 +458,7 @@ public function actionGlobalSet(string $globalSet): int 'fromGlobalSet' => $globalSet->handle, ]); $projectConfigChanged = true; + $sectionCreated = true; } try { @@ -499,6 +523,16 @@ public function actionGlobalSet(string $globalSet): int $this->success('Global set converted.'); + $this->_updateUserPermissions([ + "editGlobalSet:$globalSet->uid" => [ + "viewEntries:$section->uid", + "saveEntries:$section->uid", + "viewPeerEntryDrafts:$section->uid", + "savePeerEntryDrafts:$section->uid", + "deletePeerEntryDrafts:$section->uid", + ], + ], $sectionCreated); + if ($projectConfigChanged) { $this->_deployTip('global-set', $globalSet->handle); } @@ -601,6 +635,77 @@ private function _author(): User return $this->_author; } + private function _updateUserPermissions(array $map, $updateUserGroups): void + { + // Normalize the permission map + $map = array_combine( + array_map('strtolower', array_keys($map)), + array_map(fn($newPermissions) => array_map('strtolower', (array)$newPermissions), $map) + ); + + $this->do('Updating user permissions', function() use ($map, $updateUserGroups) { + foreach ($map as $oldPermission => $newPermissions) { + $userIds = (new Query()) + ->select(['upu.userId']) + ->from(['upu' => Table::USERPERMISSIONS_USERS]) + ->innerJoin(['up' => Table::USERPERMISSIONS], '[[up.id]] = [[upu.permissionId]]') + ->where(['up.name' => $oldPermission]) + ->column(); + + $userIds = array_unique($userIds); + + if (!empty($userIds)) { + $insert = []; + + foreach ($newPermissions as $newPermission) { + $newPermissionId = (new Query()) + ->select('id') + ->from(Table::USERPERMISSIONS) + ->where(['name' => $newPermission]) + ->scalar(); + + if (!$newPermissionId) { + Db::insert(Table::USERPERMISSIONS, [ + 'name' => $newPermission, + ]); + $newPermissionId = Craft::$app->getDb()->getLastInsertID(Table::USERPERMISSIONS); + } + + foreach ($userIds as $userId) { + $insert[] = [$newPermissionId, $userId]; + } + } + + Db::batchInsert(Table::USERPERMISSIONS_USERS, ['permissionId', 'userId'], $insert); + } + } + + if ($updateUserGroups) { + $projectConfig = Craft::$app->getProjectConfig(); + + foreach ($projectConfig->get('users.groups') ?? [] as $uid => $group) { + $groupPermissions = array_flip($group['permissions'] ?? []); + $changed = false; + + foreach ($map as $oldPermission => $newPermissions) { + if (isset($groupPermissions[$oldPermission])) { + foreach ($newPermissions as $newPermission) { + $groupPermissions[$newPermission] = true; + } + $changed = true; + } + } + + if ($changed) { + $projectConfig->set("users.groups.$uid.permissions", array_keys($groupPermissions)); + } + } + } + }); + + $this->stdout(PHP_EOL); + } + private function _findInProjectConfig(ProjectConfig $projectConfigService, callable $check): array { $results = [];