Skip to content

Commit

Permalink
FRW-9170 Changed ACL role form fields in Back Office to select type. …
Browse files Browse the repository at this point in the history
…(#11136)

FRW-9170 Changed ACL role form fields in Back Office to select type.
  • Loading branch information
annakotiuk authored Oct 11, 2024
1 parent c5036b8 commit 1c309a1
Show file tree
Hide file tree
Showing 17 changed files with 463 additions and 20 deletions.
21 changes: 21 additions & 0 deletions architecture-baseline.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
[
{
"fileName": "src/Spryker/Zed/Acl/Dependency/Facade/AclToRouterFacadeBridge.php",
"description": "Bridges: Method `getRouterBundleCollection()` must have `public function get<DomainEntity>Collection(<DomainEntity>CriteriaTransfer): <DomainEntity>CollectionTransfer` signature.",
"rule": "BridgeFacadeMethodsRule",
"ruleset": "Spryker",
"priority": "2"
},
{
"fileName": "src/Spryker/Zed/Acl/Dependency/Facade/AclToRouterFacadeBridge.php",
"description": "Bridges: Method `getRouterControllerCollection()` must have `public function get<DomainEntity>Collection(<DomainEntity>CriteriaTransfer): <DomainEntity>CollectionTransfer` signature.",
"rule": "BridgeFacadeMethodsRule",
"ruleset": "Spryker",
"priority": "2"
},
{
"fileName": "src/Spryker/Zed/Acl/Dependency/Facade/AclToRouterFacadeBridge.php",
"description": "Bridges: Method `getRouterActionCollection()` must have `public function get<DomainEntity>Collection(<DomainEntity>CriteriaTransfer): <DomainEntity>CollectionTransfer` signature.",
"rule": "BridgeFacadeMethodsRule",
"ruleset": "Spryker",
"priority": "2"
},
{
"fileName": "src/Spryker/Zed/Acl/Dependency/Facade/AclToUserBridge.php",
"description": "Bridges: Method `getCurrentUser()` must have `public function get<DomainEntity>Collection(<DomainEntity>CriteriaTransfer): <DomainEntity>CollectionTransfer` signature.",
Expand Down
96 changes: 96 additions & 0 deletions assets/Zed/js/spryker-zed-acl-role.entry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
$(document).ready(function () {
initializeDropdowns();

$('.js-select-dependable.js-select-dependable--bundle').on('change', function (event) {
handleBundleChange(event);
});

$('.js-select-dependable.js-select-dependable--controller').on('change', function (event) {
handleControllerChange(event);
});
});

function initializeDropdowns() {
const dropdowns = getDropdowns();
resetDropdowns([dropdowns.controller, dropdowns.action]);
disablePlaceholders(dropdowns.all);
}

function getDropdowns() {
const bundle = $('.js-select-dependable.js-select-dependable--bundle');
const controller = $('.js-select-dependable.js-select-dependable--controller');
const action = $('.js-select-dependable.js-select-dependable--action');
return {
bundle,
controller,
action,
all: [bundle, controller, action],
};
}

function handleBundleChange(event) {
const dropdowns = getDropdowns();
handleDropdownChange(event, `/acl/rules/controller-choices?bundle=`, dropdowns.controller);
resetDropdowns([dropdowns.action]);
}

function handleControllerChange(event) {
const dropdowns = getDropdowns();
const bundle = $('.js-select-dependable.js-select-dependable--bundle').val();
handleDropdownChange(event, `/acl/rules/action-choices?bundle=${bundle}&controller=`, dropdowns.action);
}

function resetDropdowns(dropdownsArray) {
dropdownsArray.forEach((dropdown) => {
const emptyOption = getEmptyOption(dropdown);
dropdown.empty().append(emptyOption);
});
}

function disablePlaceholders(dropdownsArray) {
dropdownsArray.forEach((dropdown) => {
const emptyOption = getEmptyOption(dropdown);
});
}

function getEmptyOption(dropdown) {
const firstDropdown = dropdown[0];
const emptyOption = firstDropdown ? firstDropdown.querySelector('option[value=""]') : null;

if (emptyOption) {
emptyOption.disabled = true;
}
const option = new Option(emptyOption ? emptyOption.text : 'Select option', '', true, true);
option.disabled = true;
return option;
}

function handleDropdownAvailability(isDisabled) {
const dropdowns = getDropdowns().all;
dropdowns.forEach((dropdown) => dropdown.prop('disabled', isDisabled));
}

function handleDropdownChange(event, queryUrl, dropdown) {
const value = event.target.value;
sendRequest(queryUrl + value, dropdown);
}

function sendRequest(queryUrl, dropdown) {
handleDropdownAvailability(true);

$.ajax({
url: queryUrl,
}).done(function (data) {
updateDropdownData(dropdown, data);
handleDropdownAvailability(false);
});
}

function updateDropdownData(dropdown, data) {
const emptyOption = getEmptyOption(dropdown);
dropdown.empty().append(emptyOption);
for (const [key, value] of Object.entries(data)) {
dropdown.append(new Option(key, value, false, false));
}
dropdown.prop('disabled', false);
}
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"spryker/gui": "^3.33.0",
"spryker/kernel": "^3.52.0",
"spryker/propel-orm": "^1.0.0",
"spryker/router": "^1.21.0",
"spryker/symfony": "^3.5.0",
"spryker/transfer": "^3.27.0",
"spryker/user": "^3.17.0",
Expand All @@ -27,7 +28,6 @@
"spryker/form": "*",
"spryker/installer": "*",
"spryker/propel": "*",
"spryker/router": "*",
"spryker/silex": "*",
"spryker/store": "*",
"spryker/testify": "*",
Expand Down
10 changes: 10 additions & 0 deletions src/Spryker/Shared/Acl/Transfer/acl.transfer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,14 @@
<property name="groupNames" type="string[]" singular="groupName"/>
</transfer>

<transfer name="RouterBundleCollection">
<property name="bundles" type="string[]" singular="bundle"/>
</transfer>
<transfer name="RouterControllerCollection">
<property name="controllers" type="string[]" singular="controller"/>
</transfer>
<transfer name="RouterActionCollection">
<property name="actions" type="string[]" singular="action"/>
</transfer>

</transfers>
22 changes: 22 additions & 0 deletions src/Spryker/Zed/Acl/AclDependencyProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

namespace Spryker\Zed\Acl;

use Spryker\Zed\Acl\Dependency\Facade\AclToRouterFacadeBridge;
use Spryker\Zed\Acl\Dependency\Facade\AclToRouterFacadeInterface;
use Spryker\Zed\Acl\Dependency\Facade\AclToUserBridge;
use Spryker\Zed\Kernel\AbstractBundleDependencyProvider;
use Spryker\Zed\Kernel\Container;
Expand Down Expand Up @@ -61,6 +63,11 @@ class AclDependencyProvider extends AbstractBundleDependencyProvider
*/
public const PLUGINS_ACL_ACCESS_CHECKER_STRATEGY = 'PLUGINS_ACL_ACCESS_CHECKER_STRATEGY';

/**
* @var string
*/
public const FACADE_ROUTER = 'FACADE_ROUTER';

/**
* @param \Spryker\Zed\Kernel\Container $container
*
Expand All @@ -70,6 +77,7 @@ public function provideCommunicationLayerDependencies(Container $container)
{
$container = $this->addFacadeUser($container);
$container = $this->addAclQueryContainer($container);
$container = $this->addRouterFacade($container);

$container->set(static::SERVICE_DATE_FORMATTER, function (Container $container) {
return $container->getLocator()->utilDateTime()->service();
Expand Down Expand Up @@ -108,6 +116,20 @@ public function providePersistenceLayerDependencies(Container $container)
return $container;
}

/**
* @param \Spryker\Zed\Kernel\Container $container
*
* @return \Spryker\Zed\Kernel\Container
*/
protected function addRouterFacade(Container $container): Container
{
$container->set(static::FACADE_ROUTER, function (Container $container): AclToRouterFacadeInterface {
return new AclToRouterFacadeBridge($container->getLocator()->router()->facade());
});

return $container;
}

/**
* @param \Spryker\Zed\Kernel\Container $container
*
Expand Down
11 changes: 10 additions & 1 deletion src/Spryker/Zed/Acl/Communication/AclCommunicationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Spryker\Zed\Acl\Communication\Table\GroupUsersTable;
use Spryker\Zed\Acl\Communication\Table\RoleTable;
use Spryker\Zed\Acl\Communication\Table\RulesetTable;
use Spryker\Zed\Acl\Dependency\Facade\AclToRouterFacadeInterface;
use Spryker\Zed\Kernel\Communication\AbstractCommunicationFactory;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Response;
Expand Down Expand Up @@ -153,7 +154,7 @@ public function createAclRuleFormDataProvider()
/** @var \Spryker\Zed\Acl\Business\AclFacade $facade */
$facade = $this->getFacade();

return new AclRuleFormDataProvider($facade);
return new AclRuleFormDataProvider($facade, $this->getRouterFacade());
}

/**
Expand All @@ -175,4 +176,12 @@ public function createDeleteRoleForm(): FormInterface
'fields' => [],
]);
}

/**
* @return \Spryker\Zed\Acl\Dependency\Facade\AclToRouterFacadeInterface
*/
public function getRouterFacade(): AclToRouterFacadeInterface
{
return $this->getProvidedDependency(AclDependencyProvider::FACADE_ROUTER);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,13 @@ protected function createAndHandleRuleSetForm(Request $request, $idAclRole)
$ruleSetForm = $this->getFactory()
->createRuleForm(
$dataProvider->getData($idAclRole),
$dataProvider->getOptions(),
array_merge(
$dataProvider->getOptions(),
$dataProvider->getRouterOptions(
$request->get('ruleset')['bundle'] ?? null,
$request->get('ruleset')['controller'] ?? null,
),
),
)
->handleRequest($request);

Expand Down
83 changes: 83 additions & 0 deletions src/Spryker/Zed/Acl/Communication/Controller/RulesController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

/**
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
*/

namespace Spryker\Zed\Acl\Communication\Controller;

use Spryker\Zed\Kernel\Communication\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

/**
* @method \Spryker\Zed\Acl\Communication\AclCommunicationFactory getFactory()
* @method \Spryker\Zed\Acl\Business\AclFacadeInterface getFacade()
* @method \Spryker\Zed\Acl\Persistence\AclQueryContainerInterface getQueryContainer()
* @method \Spryker\Zed\Acl\Persistence\AclRepositoryInterface getRepository()
*/
class RulesController extends AbstractController
{
/**
* @var string
*/
protected const BUNDLE_FIELD = 'bundle';

/**
* @var string
*/
protected const CONTROLLER_FIELD = 'controller';

/**
* @var string
*/
protected const ROOT_ACCESS = '*';

/**
* @param \Symfony\Component\HttpFoundation\Request $request
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
public function controllerChoicesAction(Request $request): JsonResponse
{
$bundle = (string)$request->query->get(static::BUNDLE_FIELD);
if ($bundle === static::ROOT_ACCESS) {
return $this->jsonResponse([static::ROOT_ACCESS => static::ROOT_ACCESS]);
}

$choices = $this->getFactory()->getRouterFacade()->getRouterControllerCollection($bundle)->getControllers();

array_unshift($choices, static::ROOT_ACCESS);

return $this->jsonResponse(array_combine($choices, $choices));
}

/**
* @param \Symfony\Component\HttpFoundation\Request $request
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
public function actionChoicesAction(Request $request): JsonResponse
{
$bundle = (string)$request->query->get(static::BUNDLE_FIELD);
if ($bundle === static::ROOT_ACCESS) {
return $this->jsonResponse(['error' => 'Please select a bundle first.'], 400);
}

$controller = (string)$request->query->get(static::CONTROLLER_FIELD);

if ($controller === static::ROOT_ACCESS) {
return $this->jsonResponse([static::ROOT_ACCESS => static::ROOT_ACCESS]);
}

$choices = $this->getFactory()
->getRouterFacade()
->getRouterActionCollection($bundle, $controller)
->getActions();

array_unshift($choices, static::ROOT_ACCESS);

return $this->jsonResponse(array_combine($choices, $choices));
}
}
Loading

0 comments on commit 1c309a1

Please sign in to comment.