new: [user-settings] Added user settings feature
parent
7ab8a93fbd
commit
39fdb8ec0d
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Migrations\AbstractMigration;
|
||||
use Phinx\Db\Adapter\MysqlAdapter;
|
||||
|
||||
|
||||
class UserSettings extends AbstractMigration
|
||||
{
|
||||
|
||||
public $autoId = false; // turn off automatic `id` column create. We want it to be `int(10) unsigned`
|
||||
|
||||
|
||||
public function change()
|
||||
{
|
||||
$table = $this->table('user_settings', [
|
||||
'signed' => false,
|
||||
'collation' => 'utf8mb4_unicode_ci',
|
||||
]);
|
||||
$table
|
||||
->addColumn('id', 'integer', [
|
||||
'autoIncrement' => true,
|
||||
'limit' => 10,
|
||||
'signed' => false,
|
||||
])
|
||||
->addPrimaryKey('id')
|
||||
->addColumn('name', 'string', [
|
||||
'default' => null,
|
||||
'null' => false,
|
||||
'limit' => 255,
|
||||
'comment' => 'The name of the user setting',
|
||||
])
|
||||
->addColumn('value', 'text', [
|
||||
'default' => null,
|
||||
'null' => true,
|
||||
'limit' => MysqlAdapter::TEXT_LONG,
|
||||
'comment' => 'The value of the user setting',
|
||||
])
|
||||
->addColumn('user_id', 'integer', [
|
||||
'default' => null,
|
||||
'null' => true,
|
||||
'signed' => false,
|
||||
'length' => 10,
|
||||
])
|
||||
->addColumn('created', 'datetime', [
|
||||
'default' => null,
|
||||
'null' => false,
|
||||
])
|
||||
->addColumn('modified', 'datetime', [
|
||||
'default' => null,
|
||||
'null' => false,
|
||||
]);
|
||||
|
||||
$table->addForeignKey('user_id', 'users', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE']);
|
||||
|
||||
$table->addIndex('name')
|
||||
->addIndex('user_id')
|
||||
->addIndex('created')
|
||||
->addIndex('modified');
|
||||
|
||||
$table->create();
|
||||
}
|
||||
}
|
|
@ -196,6 +196,7 @@ class CRUDComponent extends Component
|
|||
}
|
||||
}
|
||||
}
|
||||
$this->Controller->entity = $data;
|
||||
$this->Controller->set('entity', $data);
|
||||
}
|
||||
|
||||
|
@ -317,6 +318,7 @@ class CRUDComponent extends Component
|
|||
}
|
||||
}
|
||||
}
|
||||
$this->Controller->entity = $data;
|
||||
$this->Controller->set('entity', $data);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
namespace BreadcrumbNavigation;
|
||||
|
||||
require_once(APP . 'Controller' . DS . 'Component' . DS . 'Navigation' . DS . 'base.php');
|
||||
|
||||
class UserSettingsNavigation extends BaseNavigation
|
||||
{
|
||||
public function addLinks()
|
||||
{
|
||||
$bcf = $this->bcf;
|
||||
$request = $this->request;
|
||||
$this->bcf->addLink('UserSettings', 'index', 'Users', 'view', function ($config) use ($bcf, $request) {
|
||||
if (!empty($request->getQuery('Users_id'))) {
|
||||
$user_id = h($request->getQuery('Users_id'));
|
||||
$linkData = [
|
||||
'label' => __('View user ({0})', h($user_id)),
|
||||
'url' => sprintf('/users/view/%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
$this->bcf->addLink('UserSettings', 'index', 'Users', 'edit', function ($config) use ($bcf, $request) {
|
||||
if (!empty($request->getQuery('Users_id'))) {
|
||||
$user_id = h($request->getQuery('Users_id'));
|
||||
$linkData = [
|
||||
'label' => __('Edit user ({0})', h($user_id)),
|
||||
'url' => sprintf('/users/edit/%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
if (!empty($request->getQuery('Users_id'))) {
|
||||
$this->bcf->addSelfLink('UserSettings', 'index');
|
||||
}
|
||||
if ($this->request->getParam('controller') == 'UserSettings' && $this->request->getParam('action') == 'index') {
|
||||
if (!empty($this->request->getQuery('Users_id'))) {
|
||||
$user_id = $this->request->getQuery('Users_id');
|
||||
$this->bcf->addParent('UserSettings', 'index', 'Users', 'view', [
|
||||
'textGetter' => [
|
||||
'path' => 'username',
|
||||
'varname' => 'settingsForUser',
|
||||
],
|
||||
'url' => "/users/view/{$user_id}"
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
namespace BreadcrumbNavigation;
|
||||
|
||||
require_once(APP . 'Controller' . DS . 'Component' . DS . 'Navigation' . DS . 'base.php');
|
||||
|
||||
class UsersNavigation extends BaseNavigation
|
||||
{
|
||||
public function addLinks()
|
||||
{
|
||||
$bcf = $this->bcf;
|
||||
$request = $this->request;
|
||||
$this->bcf->addLink('Users', 'view', 'UserSettings', 'index', function ($config) use ($bcf, $request) {
|
||||
if (!empty($this->passedData[0])) {
|
||||
$user_id = $this->passedData[0];
|
||||
$linkData = [
|
||||
'label' => __('User Setting ({0})', h($user_id)),
|
||||
'url' => sprintf('/user-settings/index?Users.id=%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
}
|
||||
return [];
|
||||
});
|
||||
$this->bcf->addLink('Users', 'edit', 'UserSettings', 'index', function ($config) use ($bcf, $request) {
|
||||
if (!empty($this->passedData[0])) {
|
||||
$user_id = $this->passedData[0];
|
||||
$linkData = [
|
||||
'label' => __('User Setting ({0})', h($user_id)),
|
||||
'url' => sprintf('/user-settings/index?Users.id=%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
}
|
||||
return [];
|
||||
});
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ class NavigationComponent extends Component
|
|||
'Broods' => 'network-wired',
|
||||
'Roles' => 'id-badge',
|
||||
'Users' => 'users',
|
||||
'UserSettings' => 'user-cog',
|
||||
'Inbox' => 'inbox',
|
||||
'Outbox' => 'inbox',
|
||||
'MetaTemplates' => 'object-group',
|
||||
|
@ -128,6 +129,7 @@ class NavigationComponent extends Component
|
|||
'Users',
|
||||
'Tags',
|
||||
'LocalTools',
|
||||
'UserSettings',
|
||||
];
|
||||
foreach ($CRUDControllers as $controller) {
|
||||
$bcf->setDefaultCRUDForModel($controller);
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Controller\AppController;
|
||||
use Cake\Utility\Hash;
|
||||
use Cake\Utility\Text;
|
||||
use \Cake\Database\Expression\QueryExpression;
|
||||
use Cake\Http\Exception\NotFoundException;
|
||||
use Cake\Http\Exception\MethodNotAllowedException;
|
||||
use Cake\Http\Exception\ForbiddenException;
|
||||
|
||||
class UserSettingsController extends AppController
|
||||
{
|
||||
public $quickFilterFields = [['name' => true], ['value' => true]];
|
||||
public $filterFields = ['name', 'value', 'Users.id'];
|
||||
public $containFields = ['Users'];
|
||||
|
||||
public function index()
|
||||
{
|
||||
$conditions = [];
|
||||
$this->CRUD->index([
|
||||
'conditions' => [],
|
||||
'contain' => $this->containFields,
|
||||
'filters' => $this->filterFields,
|
||||
'quickFilters' => $this->quickFilterFields,
|
||||
]);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
if (!empty($this->request->getQuery('Users_id'))) {
|
||||
$settingsForUser = $this->UserSettings->Users->find()->where([
|
||||
'id' => $this->request->getQuery('Users_id')
|
||||
])->first();
|
||||
$this->set('settingsForUser', $settingsForUser);
|
||||
}
|
||||
}
|
||||
|
||||
public function add($user_id = false)
|
||||
{
|
||||
$this->CRUD->add([
|
||||
'redirect' => ['action' => 'index', $user_id],
|
||||
'beforeSave' => function($data) use ($user_id) {
|
||||
$data['user_id'] = $user_id;
|
||||
return $data;
|
||||
}
|
||||
]);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
$dropdownData = [
|
||||
'user' => $this->UserSettings->Users->find('list', [
|
||||
'sort' => ['username' => 'asc']
|
||||
]),
|
||||
];
|
||||
$this->set(compact('dropdownData'));
|
||||
$this->set('user_id', $user_id);
|
||||
}
|
||||
|
||||
public function edit($id)
|
||||
{
|
||||
$entity = $this->UserSettings->find()->where([
|
||||
'id' => $id
|
||||
])->first();
|
||||
$entity = $this->CRUD->edit($id, [
|
||||
'redirect' => ['action' => 'index', $entity->user_id]
|
||||
]);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
$dropdownData = [
|
||||
'user' => $this->UserSettings->Users->find('list', [
|
||||
'sort' => ['username' => 'asc']
|
||||
]),
|
||||
];
|
||||
$this->set(compact('dropdownData'));
|
||||
$this->set('user_id', $this->entity->user_id);
|
||||
$this->render('add');
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$this->CRUD->delete($id);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -11,7 +11,7 @@ class UsersController extends AppController
|
|||
{
|
||||
public $filterFields = ['Individuals.uuid', 'username', 'Individuals.email', 'Individuals.first_name', 'Individuals.last_name'];
|
||||
public $quickFilterFields = ['Individuals.uuid', ['username' => true], ['Individuals.first_name' => true], ['Individuals.last_name' => true], 'Individuals.email'];
|
||||
public $containFields = ['Individuals', 'Roles'];
|
||||
public $containFields = ['Individuals', 'Roles', 'UserSettings'];
|
||||
|
||||
public function index()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace App\Model\Entity;
|
||||
|
||||
use App\Model\Entity\AppModel;
|
||||
|
||||
class UserSetting extends AppModel
|
||||
{
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use App\Model\Table\AppTable;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
|
||||
class UserSettingsTable extends AppTable
|
||||
{
|
||||
public function initialize(array $config): void
|
||||
{
|
||||
parent::initialize($config);
|
||||
$this->addBehavior('Timestamp');
|
||||
$this->belongsTo(
|
||||
'Users'
|
||||
);
|
||||
$this->setDisplayField('name');
|
||||
}
|
||||
|
||||
public function validationDefault(Validator $validator): Validator
|
||||
{
|
||||
$validator
|
||||
->requirePresence(['name', 'user_id'], 'create')
|
||||
->notEmptyString('name', __('Please fill this field'))
|
||||
->notEmptyString('user_id', __('Please supply the user id to which this setting belongs to'));
|
||||
return $validator;
|
||||
}
|
||||
}
|
|
@ -34,6 +34,13 @@ class UsersTable extends AppTable
|
|||
'cascadeCallbacks' => false
|
||||
]
|
||||
);
|
||||
$this->hasMany(
|
||||
'UserSettings',
|
||||
[
|
||||
'dependent' => true,
|
||||
'cascadeCallbacks' => true
|
||||
]
|
||||
);
|
||||
$this->setDisplayField('username');
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
echo $this->element('genericElements/Form/genericForm', [
|
||||
'data' => [
|
||||
'description' => __('User settings are used to register setting tied to user profile.'),
|
||||
'model' => 'UserSettings',
|
||||
'fields' => [
|
||||
[
|
||||
'field' => 'user_id',
|
||||
'type' => 'dropdown',
|
||||
'label' => __('User'),
|
||||
'options' => $dropdownData['user'],
|
||||
'value' => !empty($user_id) ? $user_id : '',
|
||||
'disabled' => !empty($user_id),
|
||||
],
|
||||
[
|
||||
'field' => 'name',
|
||||
'label' => __('Setting Name'),
|
||||
],
|
||||
[
|
||||
'field' => 'value',
|
||||
'label' => __('Setting Value'),
|
||||
'type' => 'codemirror',
|
||||
'codemirror' => [
|
||||
'height' => '10rem',
|
||||
'mode' => [
|
||||
'name' => 'text',
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
'submit' => [
|
||||
'action' => $this->request->getParam('action')
|
||||
]
|
||||
]
|
||||
]);
|
||||
?>
|
||||
</div>
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
$title = __('User Setting index');
|
||||
if (!empty($settingsForUser)) {
|
||||
$title .= __(' of {0}', $settingsForUser->username);
|
||||
}
|
||||
|
||||
echo $this->element('genericElements/IndexTable/index_table', [
|
||||
'data' => [
|
||||
'data' => $data,
|
||||
'top_bar' => [
|
||||
'children' => [
|
||||
[
|
||||
'type' => 'simple',
|
||||
'children' => [
|
||||
'data' => [
|
||||
'type' => 'simple',
|
||||
'text' => __('Add Setting'),
|
||||
'class' => 'btn btn-primary',
|
||||
'popover_url' => sprintf('/userSettings/add/%s', h($this->request->getQuery('Users_id')))
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'type' => 'search',
|
||||
'button' => __('Filter'),
|
||||
'placeholder' => __('Enter value to search'),
|
||||
'data' => '',
|
||||
'searchKey' => 'value'
|
||||
]
|
||||
]
|
||||
],
|
||||
'fields' => [
|
||||
[
|
||||
'name' => '#',
|
||||
'sort' => 'id',
|
||||
'data_path' => 'id',
|
||||
],
|
||||
[
|
||||
'name' => __('User'),
|
||||
'sort' => 'user.username',
|
||||
'data_path' => 'user.username',
|
||||
'url' => '/users/view/{{0}}',
|
||||
'url_vars' => ['user.id']
|
||||
],
|
||||
[
|
||||
'name' => __('Setting Name'),
|
||||
'sort' => 'name',
|
||||
'data_path' => 'name',
|
||||
],
|
||||
[
|
||||
'name' => __('Setting Value'),
|
||||
'sort' => 'value',
|
||||
'data_path' => 'value',
|
||||
'class' => 'font-monospace'
|
||||
],
|
||||
],
|
||||
'title' => $title,
|
||||
'description' => __('The list of user settings in this Cerebrate instance. All users can have setting tied to their user profile.'),
|
||||
'actions' => [
|
||||
[
|
||||
'open_modal' => '/userSettings/edit/[onclick_params_data_path]',
|
||||
'modal_params_data_path' => 'id',
|
||||
'icon' => 'edit'
|
||||
],
|
||||
[
|
||||
'open_modal' => '/userSettings/delete/[onclick_params_data_path]',
|
||||
'modal_params_data_path' => 'id',
|
||||
'icon' => 'trash'
|
||||
],
|
||||
]
|
||||
]
|
||||
]);
|
||||
echo '</div>';
|
||||
?>
|
|
@ -75,6 +75,13 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
'url' => '/roles/view/{{0}}',
|
||||
'url_vars' => ['role.id']
|
||||
],
|
||||
[
|
||||
'name' => __('# User Settings'),
|
||||
'element' => 'count_summary',
|
||||
'data_path' => 'user_settings',
|
||||
'url' => '/user-settings/index?Users.id={{url_data}}',
|
||||
'url_data_path' => 'id'
|
||||
],
|
||||
],
|
||||
'title' => __('User index'),
|
||||
'description' => __('The list of enrolled users in this Cerebrate instance. All of the users have or at one point had access to the system.'),
|
||||
|
|
|
@ -51,6 +51,11 @@ echo $this->element(
|
|||
'url' => '/EncryptionKeys/index?Users.id={{0}}',
|
||||
'url_params' => ['id'],
|
||||
'title' => __('Encryption keys')
|
||||
],
|
||||
[
|
||||
'url' => '/UserSettings/index?Users.id={{0}}',
|
||||
'url_params' => ['id'],
|
||||
'title' => __('User settings')
|
||||
]
|
||||
]
|
||||
]
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
$controlParams = [
|
||||
'options' => $fieldData['options'],
|
||||
'empty' => $fieldData['empty'] ?? false,
|
||||
'value' => $fieldData['value'] ?? [],
|
||||
'multiple' => $fieldData['multiple'] ?? false,
|
||||
'disabled' => $fieldData['disabled'] ?? false,
|
||||
'class' => ($fieldData['class'] ?? '') . ' formDropdown form-select'
|
||||
];
|
||||
echo $this->FormFieldMassage->prepareFormElement($this->Form, $controlParams, $fieldData);
|
||||
|
|
|
@ -19,7 +19,7 @@ use Cake\Routing\Router;
|
|||
<i class="me-1 <?= $this->FontAwesome->getClass('user-circle') ?>"></i>
|
||||
<?= __('My Account') ?>
|
||||
</a>
|
||||
<a class="dropdown-item" href="<?= Router::url(['controller' => 'users', 'action' => 'userSettings', 'plugin' => null]) ?>">
|
||||
<a class="dropdown-item" href="<?= Router::url(['controller' => 'user-settings', 'action' => 'index', 'plugin' => null, '?' => ['Users.id' => h($this->request->getAttribute('identity')['id'])]]) ?>">
|
||||
<i class="me-1 <?= $this->FontAwesome->getClass('user-cog') ?>"></i>
|
||||
<?= __('Settings') ?>
|
||||
</a>
|
||||
|
|
Loading…
Reference in New Issue