diff --git a/.gitattributes b/.gitattributes index 79ede15..1f4997c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,5 @@ /.gitattributes export-ignore /Tests/ export-ignore +/Build/ export-ignore +/.gitignore export-ignore +/.github export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6e586fc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,57 @@ +name: CI + +on: [push, pull_request] + +jobs: + testsuite: + + runs-on: ubuntu-latest + strategy: + matrix: + TYPO3: ['12', '13'] + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up PHP Version + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + tools: composer:v2 + + - name: Start MySQL + run: sudo /etc/init.d/mysql start + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Cache dependencies + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: dependencies-composer-${{ hashFiles('composer.json') }} + + - name: Install composer dependencies TYPO3 13 + if: matrix.TYPO3 == '13' + run: | + composer install --no-progress --no-interaction + + - name: Install composer dependencies TYPO3 12 + if: matrix.TYPO3 == '12' + run: | + composer require typo3/cms-core:^12.4 --no-progress --no-interaction --dev -W + + - name: Phpstan + run: .Build/bin/phpstan analyze -c Build/phpstan.neon + + - name: Phpcsfix + run: .Build/bin/php-cs-fixer fix --config=Build/php-cs-fixer.php --dry-run --stop-on-violation --using-cache=no + + - name: Functional Tests + run: | + export typo3DatabaseName="typo3"; + export typo3DatabaseHost="127.0.0.1"; + export typo3DatabaseUsername="root"; + export typo3DatabasePassword="root"; + .Build/bin/phpunit -c Build/phpunit/FunctionalTests.xml Tests/Functional diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8c34ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.Build/ +/composer.lock \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/all-mfa-providers.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/all-mfa-providers.yaml new file mode 100644 index 0000000..2a6d5a0 --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/all-mfa-providers.yaml @@ -0,0 +1,2 @@ +label: Allow all MFA Providers +mfa_providers: ['*'] \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/all-web-modules.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/all-web-modules.yaml new file mode 100644 index 0000000..1219aa9 --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/all-web-modules.yaml @@ -0,0 +1,3 @@ +label: Allow all web modules +modules: + web: "*" \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/all-widgets.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/all-widgets.yaml new file mode 100644 index 0000000..a1605b6 --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/all-widgets.yaml @@ -0,0 +1,2 @@ +label: Allow all widgets +widgets: ['*'] \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/clear-all-cache-settings.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/clear-all-cache-settings.yaml new file mode 100644 index 0000000..2871852 --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/clear-all-cache-settings.yaml @@ -0,0 +1,4 @@ +label: clear all cache +settings: + TCEMAIN: + clearCache: all \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/doktype-sysfolder-page.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/doktype-sysfolder-page.yaml new file mode 100644 index 0000000..b2716af --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/doktype-sysfolder-page.yaml @@ -0,0 +1,5 @@ +label: Allow doktype sysfilder +resources: + pages: + types: + - 254 diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/existing-site-mount.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/existing-site-mount.yaml new file mode 100644 index 0000000..9109944 --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/existing-site-mount.yaml @@ -0,0 +1,3 @@ +label: Allow to site +sites: + - main \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/language-de.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/language-de.yaml new file mode 100644 index 0000000..d00a181 --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/language-de.yaml @@ -0,0 +1,2 @@ +label: Allow language de +languages: ["de-DE"] diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/non-existing-site-mount.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/non-existing-site-mount.yaml new file mode 100644 index 0000000..2d8491a --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/non-existing-site-mount.yaml @@ -0,0 +1,3 @@ +label: Allow to non existing site +sites: + - foo \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/page-mount.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/page-mount.yaml new file mode 100644 index 0000000..57934bd --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/page-mount.yaml @@ -0,0 +1,3 @@ +label: Allow to site +sites: + - 2 \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/read-file.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/read-file.yaml new file mode 100644 index 0000000..6b6cba3 --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/read-file.yaml @@ -0,0 +1,3 @@ +label: Allow reading files- +files: + - readFile diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/read-page-title.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/read-page-title.yaml new file mode 100644 index 0000000..208415c --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/read-page-title.yaml @@ -0,0 +1,6 @@ +label: Allow reading of page title +resources: + pages: + permissions: ['read'] + fields: + - title diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/t3news-widget.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/t3news-widget.yaml new file mode 100644 index 0000000..9e63a34 --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/t3news-widget.yaml @@ -0,0 +1,3 @@ +label: Allow all widgets +widgets: + - t3news \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/totp-mfa-provider.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/totp-mfa-provider.yaml new file mode 100644 index 0000000..8925921 --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/totp-mfa-provider.yaml @@ -0,0 +1,3 @@ +label: Allow totp MFA Providers +mfa_providers: + - totp \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/web-list-module.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/web-list-module.yaml new file mode 100644 index 0000000..240658c --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/web-list-module.yaml @@ -0,0 +1,3 @@ +label: Allow web_info modules +modules: + web_list: true \ No newline at end of file diff --git a/Build/Packages/permission-sets-examples/Configuration/PermissionSets/write-page-title.yaml b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/write-page-title.yaml new file mode 100644 index 0000000..0fb4cae --- /dev/null +++ b/Build/Packages/permission-sets-examples/Configuration/PermissionSets/write-page-title.yaml @@ -0,0 +1,6 @@ +label: Allow writing of page title +resources: + pages: + permissions: ['write'] + fields: + - title diff --git a/Build/Packages/permission-sets-examples/composer.json b/Build/Packages/permission-sets-examples/composer.json new file mode 100644 index 0000000..f391b88 --- /dev/null +++ b/Build/Packages/permission-sets-examples/composer.json @@ -0,0 +1,12 @@ +{ + "name": "b13/permission-sets-examples", + "type": "typo3-cms-extension", + "description": "Examples for testing", + "license": "GPL-2.0-or-later", + "version": "1.0.0", + "extra": { + "typo3/cms": { + "extension-key": "permission_sets_examples" + } + } +} diff --git a/Build/README.md b/Build/README.md new file mode 100644 index 0000000..2494622 --- /dev/null +++ b/Build/README.md @@ -0,0 +1,4 @@ + +- run ``php -d memory_limit=2G .Build/bin/phpstan analyse -c Build/phpstan.neon`` +- run ``php -d memory_limit=2G .Build/bin/php-cs-fixer fix --config=Build/php-cs-fixer.php --dry-run --stop-on-violation --using-cache=no`` +- run ``php -d memory_limit=2G .Build/bin/phpunit -c Build/phpunit/FunctionalTests.xml Tests/Functional`` \ No newline at end of file diff --git a/Build/php-cs-fixer.php b/Build/php-cs-fixer.php new file mode 100644 index 0000000..151f8f9 --- /dev/null +++ b/Build/php-cs-fixer.php @@ -0,0 +1,18 @@ +in(__DIR__ . '/../Classes') + ->in(__DIR__ . '/../Tests') + ->in(__DIR__ . '/../Configuration'); + +return \TYPO3\CodingStandards\CsFixerConfig::create() + ->setFinder($finder) + ->addRules([ + 'nullable_type_declaration' => [ + 'syntax' => 'question_mark', + ], + 'nullable_type_declaration_for_default_null_value' => true, + 'declare_strict_types' => true, + ]) + ->setUsingCache(false); + diff --git a/Build/phpstan.neon b/Build/phpstan.neon new file mode 100644 index 0000000..95dc589 --- /dev/null +++ b/Build/phpstan.neon @@ -0,0 +1,5 @@ +parameters: + level: 5 + + paths: + - %currentWorkingDirectory%/Classes diff --git a/Build/phpunit/FunctionalTests.xml b/Build/phpunit/FunctionalTests.xml new file mode 100644 index 0000000..0c697bf --- /dev/null +++ b/Build/phpunit/FunctionalTests.xml @@ -0,0 +1,30 @@ + + + + + + ../../Tests/Functional/ + + + + + + + diff --git a/Build/phpunit/FunctionalTestsBootstrap.php b/Build/phpunit/FunctionalTestsBootstrap.php new file mode 100644 index 0000000..3eb6c05 --- /dev/null +++ b/Build/phpunit/FunctionalTestsBootstrap.php @@ -0,0 +1,21 @@ +defineOriginalRootPath(); + $testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/tests'); + $testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/transient'); +})(); diff --git a/Build/sites/main/config.yaml b/Build/sites/main/config.yaml new file mode 100644 index 0000000..6c70488 --- /dev/null +++ b/Build/sites/main/config.yaml @@ -0,0 +1,23 @@ +base: '/' +baseVariants: { } +errorHandling: { } +languages: + - + title: english + enabled: true + base: / + locale: en_US.UTF-8 + flag: global + languageId: '0' + websiteTitle: '' + - + title: german + enabled: true + base: /de/ + locale: de_DE.UTF-8 + flag: de + languageId: '1' + +rootPageId: 1 +routes: { } +websiteTitle: 'Testing' diff --git a/Classes/AttachPermissionsToGroups.php b/Classes/AttachPermissionsToGroups.php index 971b58b..fdfc758 100644 --- a/Classes/AttachPermissionsToGroups.php +++ b/Classes/AttachPermissionsToGroups.php @@ -14,7 +14,7 @@ use TYPO3\CMS\Core\Authentication\Event\AfterGroupsResolvedEvent; use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderRegistry; -use TYPO3\CMS\Core\Information\Typo3Version; +use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\TypoScript\TypoScriptService; use TYPO3\CMS\Core\Utility\ArrayUtility; @@ -84,7 +84,11 @@ private function expandGroupPermissionsWithPermissionSet(array $group, Permissio if (MathUtility::canBeInterpretedAsInteger($siteOrPage)) { $finalSitesAndPages[] = $siteOrPage; } else { - $finalSitesAndPages[] = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByIdentifier($siteOrPage)->getRootPageId(); + try { + $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByIdentifier($siteOrPage); + $finalSitesAndPages[] = $site->getRootPageId(); + } catch (SiteNotFoundException $e) { + } } } $group['db_mountpoints'] .= ',' . implode(',', $finalSitesAndPages); @@ -141,58 +145,57 @@ private function expandGroupPermissionsWithPermissionSet(array $group, Permissio $allowedContentTypes = $contentTypeLimitation['types']; } foreach ($allowedContentTypes as $allowedContentType) { - if ((new Typo3Version())->getMajorVersion() > 11) { - // needs to be like tt_content:CType:db_content_keyvisual - // @todo: add support for list_type - $finishedData[] = 'tt_content:CType:' . $allowedContentType; - } else { - // needs to be like tt_content:CType:db_content_keyvisual:ALLOW - // @todo: add support for list_type - $finishedData[] = 'tt_content:CType:' . $allowedContentType . ':ALLOW'; - } + // needs to be like tt_content:CType:db_content_keyvisual + // @todo: add support for list_type + $finishedData[] = 'tt_content:CType:' . $allowedContentType; } $group['explicit_allowdeny'] .= ',' . implode(',', $finishedData); } - - // @todo: $group['allowed_languages'] .= ',' . $languages; + $languages = $permissionSet->getAllowedLanguages(); + if ($languages) { + $group['allowed_languages'] .= ',' . implode(',', $this->expandLanguageInstruction($languages)); + } // @todo: add userTsConfig $settings = $permissionSet->getSettings(); if ($settings !== null) { $settings = (new TypoScriptService())->convertPlainArrayToTypoScriptArray($settings); $settings = ArrayUtility::flatten($settings, '', true); - $group['TSconfig'] .= "\n\r" . implode("\n\r", $settings); + foreach ($settings as $key => $value) { + $group['TSconfig'] .= "\n\r" . $key . ' = ' . $value; + } } return $group; } + private function expandLanguageInstruction(array $languages): array + { + $languageIds = []; + $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); + $sites = $siteFinder->getAllSites(); + foreach ($sites as $site) { + $siteLanguages = $site->getLanguages(); + foreach ($siteLanguages as $siteLanguage) { + if (in_array((string)$siteLanguage->getLocale(), $languages, true)) { + $languageIds[] = $siteLanguage->getLanguageId(); + } + } + } + return $languageIds; + } + private function expandModuleInstruction(array $allowedModules): array { $finalModules = []; foreach ($allowedModules as $moduleName => $allowedModule) { if ($allowedModule === '*' || $allowedModule === ['*']) { // Fetch all submodules of a module - if ((new Typo3Version())->getMajorVersion() > 11) { - $subModuleList = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleProvider::class)->getModule($moduleName)->getSubmodules(); - foreach ($subModuleList as $subModuleName) { - $finalModules[] = $subModuleName->getIdentifier(); - } - } else { - $subModuleList = $GLOBALS['TBE_MODULES'][$moduleName] ?? ''; - $subModuleList = explode(',', $subModuleList); - foreach ($subModuleList as $subModuleName) { - $finalModules[] = $moduleName . '_' . $subModuleName; - } + $subModuleList = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleProvider::class)->getModule($moduleName)->getSubmodules(); + foreach ($subModuleList as $subModuleName) { + $finalModules[] = $subModuleName->getIdentifier(); } - } else if ((bool)$allowedModule === true) { - if ((new Typo3Version())->getMajorVersion() > 11) { - if (GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleProvider::class)->isModuleRegistered($moduleName)) { - $finalModules[] = $moduleName; - } - } else { - [$module, $subModule] = GeneralUtility::trimExplode('_', $moduleName, true); - if (array_key_exists($module, $GLOBALS['TBE_MODULES']) && str_contains($GLOBALS['TBE_MODULES'][$module], $subModule)) { - $finalModules[] = $moduleName; - } + } elseif ((bool)$allowedModule === true) { + if (GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleProvider::class)->isModuleRegistered($moduleName)) { + $finalModules[] = $moduleName; } } } @@ -201,7 +204,11 @@ private function expandModuleInstruction(array $allowedModules): array private function expandWidgetInstruction(array $allowedDashboardWidgets): array { - if ($allowedDashboardWidgets === '*' || $allowedDashboardWidgets === ['*']) { + $packageManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\PackageManager::class); + if ($packageManager->isPackageActive('dashboard') === false) { + return []; + } + if ($allowedDashboardWidgets === ['*']) { $finalDashboardWidgets = []; $dashboardWidgets = GeneralUtility::makeInstance(WidgetRegistry::class)->getAllWidgets(); foreach ($dashboardWidgets as $dashboardWidget) { diff --git a/Classes/AvailablePermissionSets.php b/Classes/AvailablePermissionSets.php index 257949e..b18fc32 100644 --- a/Classes/AvailablePermissionSets.php +++ b/Classes/AvailablePermissionSets.php @@ -23,14 +23,13 @@ class AvailablePermissionSets public function __construct( PermissionSetRegistry $registry - ) - { + ) { $this->registry = $registry; } public function backendGroupSelector(array &$params, TcaSelectItems $parentObject) { foreach ($this->registry->all() as $identifier => $permissionSet) { - $params['items'][] = [$permissionSet->label, $identifier]; + $params['items'][] = ['label' => $permissionSet->label, 'value' => $identifier]; } } } diff --git a/Classes/Discovery/PermissionSetLocator.php b/Classes/Discovery/PermissionSetLocator.php index 0e03741..69acf3e 100644 --- a/Classes/Discovery/PermissionSetLocator.php +++ b/Classes/Discovery/PermissionSetLocator.php @@ -55,6 +55,5 @@ public function locate(PermissionSetRegistry $registry) $registry->add($file->getBasename('.yaml'), $permissionSet); } } - } } diff --git a/Classes/PermissionSet.php b/Classes/PermissionSet.php index 46fe4bc..ddf16a6 100644 --- a/Classes/PermissionSet.php +++ b/Classes/PermissionSet.php @@ -58,6 +58,9 @@ public function getAllowedResources(string $permission): ?array } $tables = []; foreach ($this->instructions['resources'] as $tableName => $details) { + if (!isset($details['permissions'])) { + continue; + } if ($details['permissions'] === '*' || in_array($permission, $details['permissions'], true)) { $tables[] = $tableName; } @@ -98,4 +101,9 @@ public function getAllowedMfaProviders(): ?array { return $this->instructions['mfa_providers'] ?? null; } + + public function getAllowedLanguages(): ?array + { + return $this->instructions['languages'] ?? null; + } } diff --git a/Configuration/TCA/Overrides/groups.php b/Configuration/TCA/Overrides/groups.php index d99b3cf..f1e8957 100644 --- a/Configuration/TCA/Overrides/groups.php +++ b/Configuration/TCA/Overrides/groups.php @@ -1,13 +1,15 @@ 'Permission Sets', 'config' => [ 'type' => 'select', 'renderType' => 'selectMultipleSideBySide', 'itemsProcFunc' => \B13\PermissionSets\AvailablePermissionSets::class . '->backendGroupSelector', - 'items' => [] - ] + 'items' => [], + ], ]; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('be_groups', 'permission_sets', '', 'after:subgroup'); diff --git a/README.md b/README.md index 65ab699..f1fdca7 100644 --- a/README.md +++ b/README.md @@ -67,11 +67,9 @@ Special options: ### Languages ``` -# Allow any language -languages: "*" # Allow any locale (used from site configuration) -languages: ["de_DE", "en_UK"] +languages: ["de-DE", "en-UK"] ``` ### Dashboard Widgets diff --git a/Tests/Functional/AttachPermissionsToGroupsTest.php b/Tests/Functional/AttachPermissionsToGroupsTest.php new file mode 100644 index 0000000..1547cbd --- /dev/null +++ b/Tests/Functional/AttachPermissionsToGroupsTest.php @@ -0,0 +1,254 @@ + 1, + 'pid' => 0, + 'category_perms' => '', + 'workspace_perms' => '', + 'db_mountpoints' => '', + 'TSconfig' => '', + 'file_mountpoints' => '', + 'file_permissions' => '', + 'pagetypes_select' => '', + 'tables_modify' => '', + 'tables_select' => '', + 'non_exclude_fields' => '', + 'explicit_allowdeny' => '', + 'allowed_languages' => '', + 'custom_options' => '', + 'groupMods' => '', + 'mfa_providers' => '', + 'subgroup' => '', + 'availableWidgets' => '', + 'permission_sets' => '', + ]; + + protected array $testExtensionsToLoad = [ + 'permission_sets', + 'permission_sets_examples', + 'dashboard', + ]; + + protected array $pathsToLinkInTestInstance = [ + 'typo3conf/ext/permission_sets/Build/sites' => 'typo3conf/sites', + ]; + + #[Test] + public function noModificationIfNoPermissionSetIsAttached(): void + { + $event = new AfterGroupsResolvedEvent('be_groups', [$this->emptyGroup], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertSame($this->emptyGroup, $modGroup); + } + + #[Test] + public function readPageTitle(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/read-page-title'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('pages:title', $modGroup['non_exclude_fields']); + self::assertStringContainsString('pages', $modGroup['tables_select']); + self::assertStringNotContainsString('pages', $modGroup['tables_modify']); + } + + #[Test] + public function writePageTitle(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/write-page-title'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('pages:title', $modGroup['non_exclude_fields']); + self::assertStringContainsString('pages', $modGroup['tables_modify']); + } + + #[Test] + public function doktypeSysFolder(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/doktype-sysfolder-page'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('254', $modGroup['pagetypes_select']); + } + + #[Test] + public function allWebModules(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/all-web-modules'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('web_layout', $modGroup['groupMods']); + self::assertStringContainsString('web_list', $modGroup['groupMods']); + } + + #[Test] + public function webInfoModule(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/web-list-module'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringNotContainsString('web_layout', $modGroup['groupMods']); + self::assertStringContainsString('web_list', $modGroup['groupMods']); + } + + #[Test] + public function languages(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/language-de'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('1', $modGroup['allowed_languages']); + } + + #[Test] + public function allWidgets(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/all-widgets'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('sysLogErrors', $modGroup['availableWidgets']); + self::assertStringContainsString('t3news', $modGroup['availableWidgets']); + } + + #[Test] + public function t3NewsWidgets(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/t3news-widget'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringNotContainsString('sysLogErrors', $modGroup['availableWidgets']); + self::assertStringContainsString('t3news', $modGroup['availableWidgets']); + } + + #[Test] + public function allMfaProviders(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/all-mfa-providers'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('totp', $modGroup['mfa_providers']); + self::assertStringContainsString('recovery-codes', $modGroup['mfa_providers']); + } + + #[Test] + public function totpMfaProvider(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/totp-mfa-provider'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('totp', $modGroup['mfa_providers']); + self::assertStringNotContainsString('recovery-codes', $modGroup['mfa_providers']); + } + + #[Test] + public function readFile(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/read-file'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('readFile', $modGroup['file_permissions']); + } + + #[Test] + public function nonExistingSiteMount(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/non-existing-site-mount'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertSame(',', $modGroup['db_mountpoints']); + } + + #[Test] + public function existingSiteMount(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/existing-site-mount'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('1', $modGroup['db_mountpoints']); + } + + #[Test] + public function pageMount(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/page-mount'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('2', $modGroup['db_mountpoints']); + } + + #[Test] + public function clearAllCacheSettings(): void + { + $group = $this->emptyGroup; + $group['permission_sets'] = 'b13/permission-sets-examples/clear-all-cache-settings'; + $event = new AfterGroupsResolvedEvent('be_groups', [$group], [1], []); + $attachPermissionsToGroups = GeneralUtility::makeInstance(AttachPermissionsToGroups::class); + $attachPermissionsToGroups($event); + $modGroup = $event->getGroups()[0]; + self::assertStringContainsString('TCEMAIN.clearCache = all', $modGroup['TSconfig']); + } +} diff --git a/Tests/Functional/AvailablePermissionSetsTest.php b/Tests/Functional/AvailablePermissionSetsTest.php new file mode 100644 index 0000000..781d581 --- /dev/null +++ b/Tests/Functional/AvailablePermissionSetsTest.php @@ -0,0 +1,36 @@ +getMockBuilder(TcaSelectItems::class)->disableOriginalConstructor()->getMock(); + $availablePermissionSets = GeneralUtility::makeInstance(AvailablePermissionSets::class); + $params = ['items' => []]; + $availablePermissionSets->backendGroupSelector($params, $tcaSelectItms); + self::assertCount(2, $params['items']); + } +} diff --git a/Tests/Functional/PermissionSetRegistryTest.php b/Tests/Functional/PermissionSetRegistryTest.php new file mode 100644 index 0000000..95cfdb3 --- /dev/null +++ b/Tests/Functional/PermissionSetRegistryTest.php @@ -0,0 +1,33 @@ +has('b13/permission-sets-examples/read-page-title')); + } +} diff --git a/composer.json b/composer.json index c4f5b12..7cd8143 100644 --- a/composer.json +++ b/composer.json @@ -5,16 +5,46 @@ "keywords": ["typo3", "permissions", "acl", "deployment"], "license": "GPL-2.0-or-later", "require": { - "typo3/cms-core": "^11.5 || ^12.0" + "typo3/cms-core": "^12.4 || ^13.4" }, "extra": { "typo3/cms": { - "extension-key": "permission_sets" + "extension-key": "permission_sets", + "cms-package-dir": "{$vendor-dir}/typo3/cms", + "app-dir": ".Build", + "web-dir": ".Build/Web" } }, "autoload": { "psr-4": { "B13\\PermissionSets\\": "Classes/" } - } + }, + "require-dev": { + "typo3/cms-dashboard": "^12.4 || ^13.4", + "saschaegerer/phpstan-typo3": "^1.8", + "typo3/coding-standards": "^0.5.5", + "typo3/testing-framework": "^8.0", + "b13/permission-sets-examples": "1.0.0" + }, + "config": { + "vendor-dir": ".Build/vendor", + "bin-dir": ".Build/bin", + "allow-plugins": { + "typo3/class-alias-loader": true, + "typo3/cms-composer-installers": true + }, + "sort-packages": true + }, + "autoload-dev": { + "psr-4": { + "B13\\PermissionSets\\Tests\\": "Tests/" + } + }, + "repositories": [ + { + "type": "path", + "url": "Build/Packages/*" + } + ] } diff --git a/ext_emconf.php b/ext_emconf.php index 8f080ea..860fd3a 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -12,7 +12,7 @@ 'version' => '0.1.0', 'constraints' => [ 'depends' => [ - 'typo3' => '11.5.0-12.9.99', + 'typo3' => '12.4.0-13.99.99', ], 'conflicts' => [], 'suggests' => [],