Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store roles in database #5134

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
123 changes: 121 additions & 2 deletions application/controllers/ConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@

namespace Icinga\Controllers;

use DateTime;
use Exception;
use Icinga\Application\Version;
use Icinga\Common\Database;
use Icinga\Forms\Security\RoleForm;
use Icinga\Model\Role;
use Icinga\Util\StringHelper;
use InvalidArgumentException;
use Icinga\Application\Config;
use Icinga\Application\Icinga;
Expand All @@ -23,12 +28,18 @@
use Icinga\Web\Notification;
use Icinga\Web\Url;
use Icinga\Web\Widget;
use ipl\Sql\Connection;
use ipl\Sql\Insert;
use ipl\Sql\Select;
use ipl\Sql\Update;

/**
* Application and module configuration
*/
class ConfigController extends Controller
{
use Database;

/**
* Create and return the tabs to display when showing application configuration
*/
Expand Down Expand Up @@ -99,13 +110,21 @@
$form->setOnSuccess(function (GeneralConfigForm $form) {
$config = Config::app();
$useStrictCsp = (bool) $config->get('security', 'use_strict_csp', false);
$storeRolesInDb = (bool) $config->get('global', 'store_roles_in_db', false);
if ($form->onSuccess() === false) {
return false;
}

$appConfigForm = $form->getSubForm('form_config_general_application');
if ($appConfigForm && (bool) $appConfigForm->getValue('security_use_strict_csp') !== $useStrictCsp) {
$this->getResponse()->setReloadWindow(true);

if ($appConfigForm) {
if ((bool) $appConfigForm->getValue('security_use_strict_csp') !== $useStrictCsp) {
$this->getResponse()->setReloadWindow(true);
}

if (! $storeRolesInDb && $appConfigForm->getValue('global_store_roles_in_db')) {
$this->migrateRolesToFreshDb();
}
}
})->handleRequest();

Expand All @@ -114,6 +133,106 @@
$this->createApplicationTabs()->activate('general');
}

/**
* Migrate roles.ini to database if the latter contains no roles
*/
private function migrateRolesToFreshDb(): void
{
$roles = Config::app('roles');
$now = (new DateTime())->getTimestamp() * 1000;

$this->getDb()->transaction(function (Connection $db) use ($roles, $now) {
if (Role::on($db)->columns('id')->first()) {
return;
}

foreach ($roles as $name => $role) {
$db->prepexec(
(new Insert())
->into('icingaweb_role')
->columns(['name', 'unrestricted', 'ctime'])
->values([$name, $role->unrestricted ? 'y' : 'n', $now])
);

$id = $db->lastInsertId();

Check failure on line 157 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Call to an undefined method ipl\Sql\Connection::lastInsertId().

Check failure on line 157 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.4 on ubuntu-latest

Call to an undefined method ipl\Sql\Connection::lastInsertId().

Check failure on line 157 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.3 on ubuntu-latest

Call to an undefined method ipl\Sql\Connection::lastInsertId().

Check failure on line 157 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Call to an undefined method ipl\Sql\Connection::lastInsertId().

Check failure on line 157 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Call to an undefined method ipl\Sql\Connection::lastInsertId().

Check failure on line 157 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.2 on ubuntu-latest

Call to an undefined method ipl\Sql\Connection::lastInsertId().

Check failure on line 157 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Call to an undefined method ipl\Sql\Connection::lastInsertId().
$permissions = StringHelper::trimSplit($role->permissions);

Check failure on line 158 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 158 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.4 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 158 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.3 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 158 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 158 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 158 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.2 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 158 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.
$refusals = StringHelper::trimSplit($role->refusals);

Check failure on line 159 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 159 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.4 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 159 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.3 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 159 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 159 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 159 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.2 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 159 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.
$permissionsAndRefusals = [];

foreach (StringHelper::trimSplit($role->users) as $user) {

Check failure on line 162 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 162 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.4 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 162 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.3 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 162 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 162 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 162 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.2 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 162 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.
$db->prepexec(
(new Insert())
->into('icingaweb_role_user')
->columns(['role_id', 'user_name'])
->values([$id, $user])
);
}

foreach (StringHelper::trimSplit($role->groups) as $group) {

Check failure on line 171 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 171 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.4 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 171 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.3 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 171 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 171 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 171 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.2 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.

Check failure on line 171 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Parameter #1 $value of static method Icinga\Util\StringHelper::trimSplit() expects string, mixed given.
$db->prepexec(
(new Insert())
->into('icingaweb_role_group')
->columns(['role_id', 'group_name'])
->values([$id, $group])
);
}

foreach ([$permissions, $refusals] as $permissionsOrRefusals) {
foreach ($permissionsOrRefusals as $permissionOrRefusal) {
$permissionsAndRefusals[$permissionOrRefusal] = ['allowed' => 'n', 'denied' => 'n'];
}
}

foreach ($permissions as $permission) {
$permissionsAndRefusals[$permission]['allowed'] = 'y';
}

foreach ($refusals as $refusal) {
$permissionsAndRefusals[$refusal]['denied'] = 'y';
}

foreach ($permissionsAndRefusals as $permission => $authz) {
$db->prepexec(
(new Insert())
->into('icingaweb_role_permission')
->columns(['role_id', 'permission', 'allowed', 'denied'])
->values([$id, $permission, $authz['allowed'], $authz['denied']])
);
}

foreach (RoleForm::collectProvidedPrivileges()[1] as $restrictionList) {
foreach ($restrictionList as $restriction => $_) {
if (isset($role->$restriction)) {
$db->prepexec(
(new Insert())
->into('icingaweb_role_restriction')
->columns(['role_id', 'restriction', 'filter'])
->values([$id, $restriction, $role->$restriction])
);
}
}
}
}

foreach ($roles as $name => $role) {
if (isset($role->parent)) {
$db->prepexec(
(new Update())
->table('icingaweb_role')
->set([
'parent_id' => (new Select())
->from('icingaweb_role')
->where(['name = ?' => $role->parent])
->columns(['id'])
,
])
->where(['name = ?' => $name])
);
}
}
});
}

/**
* Display the list of all modules
*/
Expand All @@ -135,7 +254,7 @@
->order('installed', 'asc')
->order('name');
$this->setupLimitControl();
$this->setupPaginationControl($this->view->modules);

Check failure on line 257 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 257 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.4 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 257 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.3 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 257 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 257 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 257 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.2 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 257 in application/controllers/ConfigController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.
$this->view->title = $this->translate('Modules');
}

Expand Down
109 changes: 89 additions & 20 deletions application/controllers/RoleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,28 @@

use Exception;
use GuzzleHttp\Psr7\ServerRequest;
use Icinga\Application\Config;
use Icinga\Authentication\AdmissionLoader;
use Icinga\Authentication\Auth;
use Icinga\Authentication\RolesConfig;
use Icinga\Authentication\User\DomainAwareInterface;
use Icinga\Common\Database;
use Icinga\Data\Selectable;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\Security\RoleDbForm;
use Icinga\Forms\Security\RoleForm;
use Icinga\Model\Role;
use Icinga\Repository\Repository;
use Icinga\Security\SecurityException;
use Icinga\User;
use Icinga\Web\Controller\AuthBackendController;
use Icinga\Web\View\PrivilegeAudit;
use Icinga\Web\Widget\RolesTable;
use Icinga\Web\Widget\SingleValueSearchControl;
use ipl\Html\Html;
use ipl\Html\HtmlString;
use ipl\Web\Compat\SearchControls;
use ipl\Web\Filter\QueryString;
use ipl\Web\Url;
use ipl\Web\Widget\Link;

Expand All @@ -30,6 +37,9 @@
*/
class RoleController extends AuthBackendController
{
use Database;
use SearchControls;

public function init()
{
$this->assertPermission('config/access-control/roles');
Expand Down Expand Up @@ -59,20 +69,70 @@
public function listAction()
{
$this->createListTabs()->activate('role/list');
$this->view->roles = (new RolesConfig())
->select();

$sortAndFilterColumns = [
'name' => $this->translate('Name'),
'users' => $this->translate('Users'),
'groups' => $this->translate('Groups'),
'permissions' => $this->translate('Permissions')
];

$this->setupFilterControl($this->view->roles, $sortAndFilterColumns, ['name']);
$this->setupLimitControl();
$this->setupPaginationControl($this->view->roles);
$this->setupSortControl($sortAndFilterColumns, $this->view->roles, ['name']);

if (Config::app()->get('global', 'store_roles_in_db')) {
$db = $this->getDb();
$query = Role::on($db)->with('parent');

$limitControl = $this->createLimitControl();
$sortControl = $this->createSortControl($query, ['name' => $this->translate('Name')]);
$paginationControl = $this->createPaginationControl($query);
$searchBar = $this->createSearchBar($query, [$limitControl->getLimitParam(), $sortControl->getSortParam()]);

if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) {
if ($searchBar->hasBeenSubmitted()) {
$filter = QueryString::parse((string) $this->params);
} else {
$this->addControl($searchBar);
$this->sendMultipartUpdate();

return;
}
} else {
$filter = $searchBar->getFilter();
}

$query->filter($filter);

$this->addControl($paginationControl);
$this->addControl($limitControl);
$this->addControl($sortControl);
$this->addControl($searchBar);

$this->addControl(Html::tag(
'a',
[
'href' => Url::fromPath('role/add'),
'data-base-target' => '_next',
'class' => 'button-link icon-plus'
],
$this->translate('Create a New Role')
));

if ($query->count()) {
$this->addContent((new RolesTable())->setRoles($query));
} else {
$this->addContent(Html::tag('p', $this->translate('No roles found.')));
}

if (! $searchBar->hasBeenSubmitted() && $searchBar->hasBeenSent()) {
$this->sendMultipartUpdate();
}
} else {
$this->view->roles = (new RolesConfig())->select();

$sortAndFilterColumns = [
'name' => $this->translate('Name'),
'users' => $this->translate('Users'),
'groups' => $this->translate('Groups'),
'permissions' => $this->translate('Permissions')
];

$this->setupFilterControl($this->view->roles, $sortAndFilterColumns, ['name']);
$this->setupLimitControl();
$this->setupPaginationControl($this->view->roles);

Check failure on line 133 in application/controllers/RoleController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 133 in application/controllers/RoleController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.4 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 133 in application/controllers/RoleController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.3 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 133 in application/controllers/RoleController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 133 in application/controllers/RoleController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 133 in application/controllers/RoleController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 7.2 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.

Check failure on line 133 in application/controllers/RoleController.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Parameter #1 $query of method Icinga\Web\Controller::setupPaginationControl() expects Icinga\Data\QueryInterface, null given.
$this->setupSortControl($sortAndFilterColumns, $this->view->roles, ['name']);
}
}

/**
Expand All @@ -82,9 +142,8 @@
*/
public function addAction()
{
$role = new RoleForm();
$role = $this->prepareForm();
$role->setRedirectUrl('__CLOSE__');
$role->setRepository(new RolesConfig());
$role->setSubmitLabel($this->translate('Create Role'));
$role->add()->handleRequest();

Expand All @@ -99,9 +158,8 @@
public function editAction()
{
$name = $this->params->getRequired('role');
$role = new RoleForm();
$role = $this->prepareForm();
$role->setRedirectUrl('__CLOSE__');
$role->setRepository(new RolesConfig());
$role->setSubmitLabel($this->translate('Update Role'));
$role->edit($name);

Expand All @@ -120,9 +178,8 @@
public function removeAction()
{
$name = $this->params->getRequired('role');
$role = new RoleForm();
$role = $this->prepareForm();
$role->setRedirectUrl('__CLOSE__');
$role->setRepository(new RolesConfig());
$role->setSubmitLabel($this->translate('Remove Role'));
$role->remove($name);

Expand Down Expand Up @@ -389,4 +446,16 @@

return $tabs;
}

/**
* Create a form for role addition/modification/deletion and set the storage
*
* @return RoleForm
*/
private function prepareForm(): RoleForm
{
return Config::app()->get('global', 'store_roles_in_db')
? (new RoleDbForm())->setDb($this->getDb())
: (new RoleForm())->setRepository(new RolesConfig());
}
}
11 changes: 11 additions & 0 deletions application/forms/Config/General/ApplicationConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,17 @@ public function createElements(array $formData)
)
);

$this->addElement(
'checkbox',
'global_store_roles_in_db',
[
'label' => $this->translate('Store Roles in Database'),
'description' => $this->translate(
'Set whether to store roles used for access control in the database selected above.'
)
]
);

return $this;
}
}
Loading
Loading