Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions Classes/Controller/PermissionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
namespace HOV\MaskPermissions\Controller;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use HOV\MaskPermissions\Permissions\MaskPermissions;
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
Expand Down Expand Up @@ -75,6 +76,67 @@ public function updateAction(): ResponseInterface
} else {
$this->addFlashMessage('Update failed.', '', ContextualFeedbackSeverity::ERROR);
}
return $this->redirect('index');
}

public function selectMasksAction(): ResponseInterface
{
$groupUid = (int)$this->request->getArgument('group');
$group = $this->backendUserGroupRepository->findByUid($groupUid);
if (!$group) {
$this->addFlashMessage('Group not found', '', ContextualFeedbackSeverity::ERROR);
return $this->redirect('index');
}

$maskElements = $this->getAvailableMaskCTypes();
$selectedMaskElements = $this->permissionUpdater->getSelectedMasks($groupUid);

$moduleTemplate = $this->moduleTemplateFactory->create($this->request);

if (method_exists($moduleTemplate, 'assign')) {
$moduleTemplate->assignMultiple([
'group' => $group,
'maskElements' => $maskElements,
'selectedMaskElements' => $selectedMaskElements,
]);
}
return $moduleTemplate->renderResponse('Permission/SelectMasks');
}

public function saveMasksAction(): ResponseInterface
{
$groupUid = (int)$this->request->getArgument('group');
$selected = $this->request->hasArgument('selected') ? $this->request->getArgument('selected') : [];

$success = $this->permissionUpdater->update($groupUid, $selected);
if ($success) {
$this->addFlashMessage('MASK permissions saved.', '', ContextualFeedbackSeverity::OK);
} else {
$this->addFlashMessage('MASK permissions save failed.', '', ContextualFeedbackSeverity::ERROR);
}

return $this->redirect('index');
}

protected function getAvailableMaskCTypes(): array
{
$maskElements = [];
$cTypes = $GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'];
foreach ($cTypes ?? [] as $type) {
$label = $type[0] ?? $type['label'];
$value = $type[1] ?? $type['value'];
if ($value !== '--div--') {
$maskElements[$value] = $this->getLanguageService()->sL($label);
}
}
$maskElements = array_filter($maskElements, function ($key) {
return strpos($key, 'mask_') === 0;
}, ARRAY_FILTER_USE_KEY);
return $maskElements;
}

protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
}
44 changes: 40 additions & 4 deletions Classes/Permissions/MaskPermissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function __construct(TableDefinitionCollection $tableDefinitionCollection
'editlock'
];

public function update(int $groupUid = 0): bool
public function update(int $groupUid = 0, array $selected = []): bool
{
$maskConfig = $this->getMaskConfig();
if ($maskConfig === []) {
Expand Down Expand Up @@ -98,7 +98,7 @@ public function update(int $groupUid = 0): bool
// Update explicit_allowdeny
$explicitAllowDeny = $result['explicit_allowdeny'] ?? '';
$explicitAllowDeny = GeneralUtility::trimExplode(',', $explicitAllowDeny);
$explicitAllowDeny = array_merge($explicitAllowDeny, $this->getMaskExplicitAllow());
$explicitAllowDeny = array_merge($explicitAllowDeny, $this->getMaskExplicitAllow($selected));
$explicitAllowDeny = array_unique($explicitAllowDeny);
$explicitAllowDeny = implode(',', $explicitAllowDeny);

Expand Down Expand Up @@ -230,15 +230,21 @@ protected function getMaskAdditionalTableModify(): array
return $additionalTableModify;
}

protected function getMaskExplicitAllow(): array
protected function getMaskExplicitAllow(array $selected = []): array
{
$explicitAllow = [];
$allow = '';
if ((new Typo3Version())->getMajorVersion() < 12) {
$allow = ':ALLOW';
}
foreach ($this->tableDefinitionCollection->getTable('tt_content')->elements as $elementDefinition) {
$explicitAllow[] = 'tt_content:CType:' . AffixUtility::addMaskCTypePrefix($elementDefinition->key) . $allow;
if ($selected) {
if (in_array(AffixUtility::addMaskCTypePrefix($elementDefinition->key), $selected)) {
$explicitAllow[] = 'tt_content:CType:' . AffixUtility::addMaskCTypePrefix($elementDefinition->key) . $allow;
}
} else {
$explicitAllow[] = 'tt_content:CType:' . AffixUtility::addMaskCTypePrefix($elementDefinition->key) . $allow;
}
}
return $explicitAllow;
}
Expand Down Expand Up @@ -272,4 +278,34 @@ protected function getConditionForDifferentTypo3Version($column, $table, $elemen
}
return $fieldType === FieldType::PALETTE;
}

/**
* Get selected masks for a specific backend user group.
*
* @param int $groupId The UID of the backend user group.
* @return array An associative array of selected masks.
*/
public function getSelectedMasks($groupId): array
{
$queryBuilder = $this->getQueryBuilder('be_groups');
$result = $queryBuilder
->select('explicit_allowdeny')
->from('be_groups')
->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($groupId, Connection::PARAM_INT)))
->executeQuery()
->fetchOne();

if ($result) {
$masks = GeneralUtility::trimExplode(',', $result);
$filteredMasks = array_filter(array_map(function ($item) {
if (strpos($item, 'mask_') !== false) {
return substr($item, strpos($item, 'mask_'));
}
return null;
}, $masks), fn($item) => !is_null($item));

return array_combine($filteredMasks, $filteredMasks);
}
return [];
}
}
2 changes: 2 additions & 0 deletions Configuration/Backend/Modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
\HOV\MaskPermissions\Controller\PermissionController::class => [
'index',
'update',
'selectMasks',
'saveMasks',
],
],
],
Expand Down
3 changes: 3 additions & 0 deletions Resources/Private/Partials/Form.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ <h1>Mask Permissions</h1>
<f:be.infobox message="Everything up to date."/>
</f:else>
</f:if>

<ul class="list-group">
<f:for each="{groups}" as="group">
<li class="list-group-item">
<span>[{group.uid}] {group.title}</span>
<f:if condition="{updatesNeeded.{group.uid}}">
<f:then>
<f:link.action action="update" arguments="{group: group}" class="btn btn-sm btn-xs btn-primary mp-button">Grant permissions</f:link.action>
<f:link.action action="selectMasks" arguments="{group: group}" class="btn btn-sm btn-xs btn-secondary mp-button">Assign MASK Permissions</f:link.action>

<span class="badge badge-warning pull-right">Missing permissions</span>
</f:then>
<f:else>
Expand Down
40 changes: 40 additions & 0 deletions Resources/Private/Templates/Permission/SelectMasks.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<f:layout name="Module" />

<f:section name="Content">
<div class="container my-5">
<h1 class="mb-4 fw-semibold text-primary-emphasis">
Assign MASK Permissions to <span class="text-decoration-underline">{group.title}</span>
</h1>

<f:form action="saveMasks" controller="Permission">
<f:form.hidden name="group" value="{group.uid}" />

<div class="row row-cols-1 row-cols-md-2 g-4">
<f:for each="{maskElements}" as="element" key="key">
<div class="col">
<div class="card p-2 h-100 d-flex align-items-center justify-content-center">
<div class="form-check w-100">
<f:form.checkbox
class="form-check-input me-2"
name="selected[]"
id="checkbox-{key}"
value="{key}"
checked="{f:if(condition: '{key} === {selectedMaskElements.{key}}', then: 'checked')}" />
<label
class="form-check-label fw-bold text-break"
for="checkbox-{key}"
title="{element}">
{element}
</label>
</div>
</div>
</div>
</f:for>
</div>

<div class="mt-5 text-center">
<f:form.submit value="Save Permissions" class="btn btn-primary btn-lg px-5" />
</div>
</f:form>
</div>
</f:section>