diff --git a/app/src/Controller/RolesController.php b/app/src/Controller/RolesController.php new file mode 100644 index 0000000..daa4edd --- /dev/null +++ b/app/src/Controller/RolesController.php @@ -0,0 +1,58 @@ +CRUD->index([ + 'filters' => ['name', 'uuid', 'perm_admin'], + 'quickFilters' => ['name'], + 'contain' => $this->checkPermission('admin') ? ['Users'] : [] + ]); + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + } + + public function add() + { + $this->CRUD->add(); + if ($this->ParamHandler->isRest()) { + return $this->restResponsePayload; + } + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + } + + public function view($id) + { + $this->CRUD->view($id); + if ($this->ParamHandler->isRest()) { + return $this->restResponsePayload; + } + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + } + + public function edit($id) + { + $this->CRUD->edit($id); + if ($this->ParamHandler->isRest()) { + return $this->restResponsePayload; + } + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + $this->render('add'); + } + + public function delete($id) + { + $this->CRUD->delete($id); + if ($this->ParamHandler->isRest()) { + return $this->restResponsePayload; + } + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + } +} diff --git a/app/src/Controller/UsersController.php b/app/src/Controller/UsersController.php new file mode 100644 index 0000000..071e537 --- /dev/null +++ b/app/src/Controller/UsersController.php @@ -0,0 +1,79 @@ +CRUD->index([ + 'contain' => ['Individuals', 'Roles'], + 'filters' => ['Users.email', 'uuid'] + ]); + if ($this->ParamHandler->isRest()) { + return $this->restResponsePayload; + } + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + } + + public function add() + { + $this->CRUD->add(); + if ($this->ParamHandler->isRest()) { + return $this->restResponsePayload; + } + $dropdownData = [ + 'role' => $this->Users->Roles->find('list', [ + 'sort' => ['name' => 'asc'] + ]), + 'individual' => $this->Users->Individuals->find('list', [ + 'sort' => ['email' => 'asc'] + ]) + ]; + $this->set(compact('dropdownData')); + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + } + + public function view($id) + { + $this->CRUD->view($id, [ + 'contain' => ['Individuals' => ['Alignments' => 'Organisations'], 'Roles'] + ]); + if ($this->ParamHandler->isRest()) { + return $this->restResponsePayload; + } + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + } + + public function edit($id) + { + $this->CRUD->edit($id); + if ($this->ParamHandler->isRest()) { + return $this->restResponsePayload; + } + $dropdownData = [ + 'role' => $this->Users->Roles->find('list', [ + 'sort' => ['name' => 'asc'] + ]), + 'individual' => $this->Users->Individuals->find('list', [ + 'sort' => ['email' => 'asc'] + ]) + ]; + $this->set(compact('dropdownData')); + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + $this->render('add'); + } + + public function delete($id) + { + $this->CRUD->delete($id); + if ($this->ParamHandler->isRest()) { + return $this->restResponsePayload; + } + $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); + } +} diff --git a/app/src/Model/Entity/Role.php b/app/src/Model/Entity/Role.php new file mode 100644 index 0000000..602a1d9 --- /dev/null +++ b/app/src/Model/Entity/Role.php @@ -0,0 +1,11 @@ +addBehavior('UUID'); + $this->hasMany( + 'Users', + [ + 'dependent' => false, + 'cascadeCallbacks' => false + ] + ); + $this->setDisplayField('name'); + } + + public function validationDefault(Validator $validator): Validator + { + $validator + ->notEmptyString('name') + ->requirePresence(['name'], 'create'); + return $validator; + } +} diff --git a/app/src/Model/Table/UsersTable.php b/app/src/Model/Table/UsersTable.php new file mode 100644 index 0000000..d012b4b --- /dev/null +++ b/app/src/Model/Table/UsersTable.php @@ -0,0 +1,38 @@ +addBehavior('UUID'); + $this->belongsTo( + 'Individuals', + [ + 'dependent' => false, + 'cascadeCallbacks' => false + ] + ); + $this->belongsTo( + 'Roles', + [ + 'dependent' => false, + 'cascadeCallbacks' => false + ] + ); + $this->setDisplayField('id'); + } + + public function validationDefault(Validator $validator): Validator + { + $validator + ->requirePresence(['password'], 'create'); + return $validator; + } +} diff --git a/app/templates/Roles/add.php b/app/templates/Roles/add.php new file mode 100644 index 0000000..2264573 --- /dev/null +++ b/app/templates/Roles/add.php @@ -0,0 +1,27 @@ +element('genericElements/Form/genericForm', [ + 'data' => [ + 'description' => __('Roles define global rules for a set of users, including first and foremost access controls to certain functionalities.'), + 'model' => 'Roles', + 'fields' => [ + [ + 'field' => 'name' + ], + [ + 'field' => 'perm_admin', + 'type' => 'checkbox', + 'label' => 'Full admin privilege' + ], + [ + 'field' => 'is_default', + 'type' => 'checkbox', + 'label' => 'Default role' + ] + ], + 'submit' => [ + 'action' => $this->request->getParam('action') + ] + ] + ]); +?> + diff --git a/app/templates/Roles/index.php b/app/templates/Roles/index.php new file mode 100644 index 0000000..6de46a5 --- /dev/null +++ b/app/templates/Roles/index.php @@ -0,0 +1,70 @@ +element('genericElements/IndexTable/index_table', [ + 'data' => [ + 'data' => $data, + 'top_bar' => [ + 'pull' => 'right', + 'children' => [ + [ + 'type' => 'search', + 'button' => __('Filter'), + 'placeholder' => __('Enter value to search'), + 'data' => '', + 'searchKey' => 'value' + ] + ] + ], + 'fields' => [ + [ + 'name' => '#', + 'sort' => 'id', + 'data_path' => 'id', + ], + [ + 'name' => __('Name'), + 'sort' => 'name', + 'data_path' => 'name', + ], + [ + 'name' => __('UUID'), + 'sort' => 'uuid', + 'data_path' => 'uuid', + 'placeholder' => __('Leave empty to auto generate') + ], + [ + 'name' => __('Admin'), + 'sort' => 'perm_admin', + 'data_path' => 'perm_admin', + 'element' => 'boolean' + ], + [ + 'name' => 'Default', + 'sort' => 'is_default', + 'data_path' => 'is_default', + 'element' => 'boolean' + ], + ], + 'title' => __('Roles Index'), + 'description' => __('A list of configurable user roles. Create or modify user access roles based on the settings below.'), + 'pull' => 'right', + 'actions' => [ + [ + 'url' => '/roles/view', + 'url_params_data_paths' => ['id'], + 'icon' => 'eye' + ], + [ + 'url' => '/roles/edit', + 'url_params_data_paths' => ['id'], + 'icon' => 'edit' + ], + [ + 'onclick' => 'populateAndLoadModal(\'/roles/delete/[onclick_params_data_path]\');', + 'onclick_params_data_path' => 'id', + 'icon' => 'trash' + ] + ] + ] +]); +echo ''; +?> diff --git a/app/templates/Roles/view.php b/app/templates/Roles/view.php new file mode 100644 index 0000000..917fda9 --- /dev/null +++ b/app/templates/Roles/view.php @@ -0,0 +1,28 @@ +element( + '/genericElements/SingleViews/single_view', + [ + 'data' => $entity, + 'fields' => [ + [ + 'key' => __('ID'), + 'path' => 'id' + ], + [ + 'key' => __('Name'), + 'path' => 'name' + ], + [ + 'key' => __('Admin permission'), + 'path' => 'perm_admin', + 'type' => 'boolean' + ], + [ + 'key' => __('Default role'), + 'path' => 'is_default', + 'type' => 'boolean' + ] + ], + 'children' => [] + ] +); diff --git a/app/templates/Users/add.php b/app/templates/Users/add.php new file mode 100644 index 0000000..d2c0054 --- /dev/null +++ b/app/templates/Users/add.php @@ -0,0 +1,39 @@ +element('genericElements/Form/genericForm', [ + 'data' => [ + 'description' => __('Roles define global rules for a set of users, including first and foremost access controls to certain functionalities.'), + 'model' => 'Roles', + 'fields' => [ + [ + 'field' => 'individual_id', + 'type' => 'dropdown', + 'label' => __('Associated individual'), + 'options' => $dropdownData['individual'] + ], + [ + 'field' => 'role_id', + 'type' => 'dropdown', + 'label' => __('Role'), + 'options' => $dropdownData['role'] + ], + [ + 'field' => 'password', + 'label' => __('Password') + ], + [ + 'field' => 'confirm_password', + 'label' => __('Confirm Password') + ], + [ + 'field' => 'disabled', + 'type' => 'checkbox', + 'label' => 'Disable' + ] + ], + 'submit' => [ + 'action' => $this->request->getParam('action') + ] + ] + ]); +?> + diff --git a/app/templates/Users/index.php b/app/templates/Users/index.php new file mode 100644 index 0000000..00a306b --- /dev/null +++ b/app/templates/Users/index.php @@ -0,0 +1,71 @@ +element('genericElements/IndexTable/index_table', [ + 'data' => [ + 'data' => $data, + 'top_bar' => [ + 'pull' => 'right', + 'children' => [ + [ + 'type' => 'search', + 'button' => __('Filter'), + 'placeholder' => __('Enter value to search'), + 'data' => '', + 'searchKey' => 'value' + ] + ] + ], + 'fields' => [ + [ + 'name' => '#', + 'sort' => 'id', + 'data_path' => 'id', + ], + [ + 'name' => __('Email'), + 'sort' => 'individual.email', + 'data_path' => 'individual.email', + 'url' => '/individuals/view/{{0}}', + 'url_vars' => ['individual.id'] + ], + [ + 'name' => __('First Name'), + 'sort' => 'individual.first_name', + 'data_path' => 'individual.first_name', + ], + [ + 'name' => __('Last Name'), + 'sort' => 'individual.last_name', + 'data_path' => 'individual.last_name' + ], + [ + 'name' => __('Role'), + 'sort' => 'role.name', + 'data_path' => 'role.name', + 'url' => '/roles/view/{{0}}', + 'url_vars' => ['role.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.'), + 'pull' => 'right', + 'actions' => [ + [ + 'url' => '/users/view', + 'url_params_data_paths' => ['id'], + 'icon' => 'eye' + ], + [ + 'url' => '/users/edit', + 'url_params_data_paths' => ['id'], + 'icon' => 'edit' + ], + [ + 'onclick' => 'populateAndLoadModal(\'/users/delete/[onclick_params_data_path]\');', + 'onclick_params_data_path' => 'id', + 'icon' => 'trash' + ] + ] + ] +]); +echo ''; +?> diff --git a/app/templates/Users/view.php b/app/templates/Users/view.php new file mode 100644 index 0000000..cdbc8c3 --- /dev/null +++ b/app/templates/Users/view.php @@ -0,0 +1,42 @@ +element( + '/genericElements/SingleViews/single_view', + [ + 'data' => $entity, + 'fields' => [ + [ + 'key' => __('ID'), + 'path' => 'id' + ], + [ + 'key' => __('UUID'), + 'path' => 'uuid' + ], + [ + 'key' => __('Email'), + 'path' => 'individual.email' + ], + [ + 'key' => __('Role'), + 'path' => 'role.name', + 'url' => '/roles/view/{{0}}', + 'url_vars' => 'role.id' + ], + [ + 'key' => __('First name'), + 'path' => 'individual.first_name' + ], + [ + 'key' => __('Last name'), + 'path' => 'individual.last_name' + ], + [ + 'key' => __('Alignments'), + 'type' => 'alignment', + 'path' => 'individual', + 'scope' => 'individuals' + ] + ], + 'children' => [] + ] +);