diff --git a/src/Controller/RolesController.php b/src/Controller/RolesController.php new file mode 100644 index 000000000..80aa493d3 --- /dev/null +++ b/src/Controller/RolesController.php @@ -0,0 +1,108 @@ +paginate($this->Roles); + + $this->set(compact('roles')); + } + + /** + * View method + * + * @param string|null $id Role id. + * @return \Cake\Http\Response|null + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function view($id = null) + { + $role = $this->Roles->get($id, [ + 'contain' => [], + ]); + + $this->set('role', $role); + } + + /** + * Add method + * + * @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise. + */ + public function add() + { + $role = $this->Roles->newEntity(); + if ($this->request->is('post')) { + $role = $this->Roles->patchEntity($role, $this->request->getData()); + if ($this->Roles->save($role)) { + $this->Flash->success(__('The role has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The role could not be saved. Please, try again.')); + } + $this->set(compact('role')); + } + + /** + * Edit method + * + * @param string|null $id Role id. + * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function edit($id = null) + { + $role = $this->Roles->get($id, [ + 'contain' => [], + ]); + if ($this->request->is(['patch', 'post', 'put'])) { + $role = $this->Roles->patchEntity($role, $this->request->getData()); + if ($this->Roles->save($role)) { + $this->Flash->success(__('The role has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The role could not be saved. Please, try again.')); + } + $this->set(compact('role')); + } + + /** + * Delete method + * + * @param string|null $id Role id. + * @return \Cake\Http\Response|null Redirects to index. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function delete($id = null) + { + $this->request->allowMethod(['post', 'delete']); + $role = $this->Roles->get($id); + if ($this->Roles->delete($role)) { + $this->Flash->success(__('The role has been deleted.')); + } else { + $this->Flash->error(__('The role could not be deleted. Please, try again.')); + } + + return $this->redirect(['action' => 'index']); + } +} diff --git a/src/Controller/StateUserRolesController.php b/src/Controller/StateUserRolesController.php new file mode 100644 index 000000000..b61d6b82b --- /dev/null +++ b/src/Controller/StateUserRolesController.php @@ -0,0 +1,307 @@ +loadComponent('JsonRequestClient'); + $this->Auth->allow([ + 'search' + ]); + $this->set( + 'naviHierarchy', + (new NaviHierarchy())-> + add(new NaviHierarchyEntry(__('Startseite'), 'Dashboard', 'index', false))->add(new NaviHierarchyEntry(__('Benutzer suchen'), 'StateUsers', 'search', true)) + ); + } + + public function search() + { + $this->loadModel('StateUsers'); + $startTime = microtime(true); + I18n::setLocale('de_DE'); + $this->viewBuilder()->setLayout('frontend'); + $session = $this->getRequest()->getSession(); + $result = $this->requestLogin(); + if ($result !== true) { + return $result; + } + $user = $session->read('StateUser'); + if ($user['role'] != 'admin') { + return $this->redirect(['controller' => 'dashboard', 'action' => 'index']); + } + + $searchForm = new UserSearchForm(); + + $timeUsed = microtime(true) - $startTime; + //$this->set('timeUsed', $timeUsed); + $csfr_token = $this->request->getParam('_csrfToken'); + $this->set(compact('timeUsed', 'searchForm', 'csfr_token')); + + if ($this->request->is('post')) { + $requestData = $this->request->getData(); + + if ($searchForm->validate($requestData)) { + //var_dump($requestData); + $searchString = $requestData['search']; + $searchType = 'unknown'; + if (GenericValidation::email($searchString, [])) { + $searchType = 'email'; + } + // find users on login server + $resultJson = $this->JsonRequestClient->getUsers($session->read('session_id'), $searchString); + $loginServerUser = []; + if ($resultJson['state'] == 'success') { + $dataJson = $resultJson['data']; + if ($dataJson['state'] != 'success') { + if ($dataJson['msg'] == 'session not found') { + $session->destroy(); + return $this->redirect(Router::url('/', true) . 'account', 303); + } + } + //var_dump($dataJson); + if (isset($dataJson['users'])) { + $loginServerUser = $dataJson['users']; + } + } + $pubkeySorted = []; + $emptyPubkeys = []; + foreach ($loginServerUser as $u) { + if (!isset($u['public_hex']) || $u['public_hex'] == '') { + array_push($emptyPubkeys, $u); + } else { + if (!isset($pubkeySorted[$u['public_hex']])) { + $pubkeySorted[$u['public_hex']] = ['login' => [], 'community' => []]; + } + array_push($pubkeySorted[$u['public_hex']]['login'], $u); + } + } + // find user on community server db + $globalSearch = '%' . $searchString . '%'; + $communityUsers = $this->StateUsers + ->find('all') + ->contain(['StateBalances' => ['fields' => ['amount', 'state_user_id']]]); + + $communityUsers->where(['OR' => [ + 'first_name LIKE' => $globalSearch, + 'last_name LIKE' => $globalSearch, + //'username LIKE' => $globalSearch, + 'email LIKE' => $globalSearch + ]]); + + //var_dump($communityUsers->toArray()); + foreach ($communityUsers as $u) { + $pubkey_hex = bin2hex(stream_get_contents($u->public_key)); + $u->public_hex = $pubkey_hex; + if (!isset($pubkeySorted[$pubkey_hex])) { + $pubkeySorted[$pubkey_hex] = ['login' => [], 'community' => []]; + } + array_push($pubkeySorted[$pubkey_hex]['community'], $u); + } + $finalUserEntrys = []; + // detect states + foreach ($pubkeySorted as $pubhex => $user) { + $finalUser = []; + $state = 'account created'; + $color = 'secondary'; + $finalUser['balance'] = 0; + $finalUser['pubkeyhex'] = $pubhex; + $finalUser['created'] = null; + + if (count($user['community']) == 1) { + if (isset($user['community'][0]->state_balances) && + isset($user['community'][0]->state_balances[0]['amount'])) { + $finalUser['balance'] = $user['community'][0]->state_balances[0]->amount; + } + } + + if (count($user['login']) == 0) { + $state = 'account not on login-server'; + $color = 'danger'; + if (count($user['community']) == 1) { + $c_user = $user['community'][0]; + $finalUser['name'] = $c_user->first_name . ' ' . $c_user->last_name; + $finalUser['first_name'] = $c_user->first_name; + $finalUser['last_name'] = $c_user->last_name; + //$finalUser['username'] = $c_user->username; + $finalUser['email'] = $c_user->email; + } + } elseif (count($user['login']) == 1) { + if ($user['login'][0]['email_checked'] == true) { + $state = 'email activated'; + $color = 'primary'; + + if (count($user['community']) == 1) { + $state = 'account copied to community'; + $color = 'success'; + //var_dump($user['community'][0]->state_balances[0]['amount']); + } + } else { + $state = 'email not activated'; + $color = 'warning'; + } + + $l_user = $user['login'][0]; + $finalUser['name'] = $l_user['first_name'] . ' ' . $l_user['last_name']; + $finalUser['first_name'] = $l_user['first_name']; + $finalUser['last_name'] = $l_user['last_name']; + //$finalUser['username'] = $l_user['username']; + $finalUser['email'] = $l_user['email']; + $finalUser['created'] = new FrozenTime($l_user['created']); + } else { + $state = 'account multiple times on login-server'; + $color = 'danger'; + } + + $this->loadModel('Roles'); + $state_user_id = $user['community'][0]->id; + $stateUserRole = $this->StateUserRoles->find('all')->where(['state_user_id' => $state_user_id])->all(); + + $role_ids = ""; + foreach ($stateUserRole as $userRole) { + if($role_ids != "") + $role_ids .= ",".$userRole->role_id; + else + $role_ids = $userRole->role_id; + } + + $roles = $this->Roles->find('all')->where(['id IN' => explode(",",$role_ids)])->all(); + + $role_names = ""; + foreach($roles as $role) + { + if($role_names != "") + $role_names .= "
".$role->title; + else + $role_names = $role->title; + } + + $finalUser['role_name'] = $role_names; + + $finalUser['indicator'] = ['name' => $state, 'color' => $color]; + array_push($finalUserEntrys, $finalUser); + } + + foreach ($emptyPubkeys as $user) { + $finalUser = []; + $state = 'account not on community server'; + $color = 'secondary'; + if ($user['email_checked'] == false) { + $state = 'email not activated'; + $color = 'warning'; + } else { + $state = 'no keys'; + $color = 'warning'; + } + $finalUser['balance'] = 0; + $finalUser['pubkeyhex'] = ''; + $finalUser['name'] = $user['first_name'] . ' ' . $user['last_name']; + $finalUser['first_name'] = $user['first_name']; + $finalUser['last_name'] = $user['last_name']; + //$finalUser['username'] = $user['username']; + $finalUser['email'] = $user['email']; + + + $finalUser['created'] = new FrozenTime($user['created']); + $finalUser['indicator'] = ['name' => $state, 'color' => $color]; + array_push($finalUserEntrys, $finalUser); + } + //var_dump($pubkeySorted); + } else { + $this->Flash->error(__('Something was invalid, please try again!')); + } + $this->set('finalUserEntrys', $finalUserEntrys); + } + $timeUsed = microtime(true) - $startTime; + $this->set('timeUsed', $timeUsed); + } + + public function assignRole() + { + $this->loadModel('Roles'); + $this->loadModel('StateUsers'); + + if ($this->request->is('post')) { + $requestData = $this->request->getData(); + + $public_hex = hex2bin($requestData['public_hex']); + + $stateUser = $this->StateUsers->find('all')->where(['public_key' => $public_hex])->first(); + + foreach($requestData['role_id'] as $role_id) + { + $newStateUserRole = $this->StateUserRoles->newEntity(); + + $post_data = []; + $post_data['state_user_id'] = $stateUser->id; + $post_data['role_id'] = $role_id; + $this->StateUserRoles->patchEntity($newStateUserRole, $post_data); + $this->StateUserRoles->save($newStateUserRole); + + } + + $this->Flash->success(__('Role has been assigned to User.')); + + return $this->redirect(['controller' => 'state-user-roles', 'action' => 'search']); + + } + + $assignRoleForm = new AssignRoleForm(); + + $public_hex = $this->request->getParam('pass')[0]; + + $publichex = hex2bin($public_hex); + + $stateUser = $this->StateUsers->find('all')->where(['public_key' => $publichex])->first(); + + $stateUserRoles = $this->StateUserRoles->find('all')->where(['state_user_id' => $stateUser->id])->all(); + + $role_ids = ""; + foreach ($stateUserRoles as $userRole) { + if($role_ids != "") + $role_ids .= ",".$userRole->role_id; + else + $role_ids = $userRole->role_id; + } + + $role_ids = explode(",", $role_ids); + + $roles = $this->Roles->find('list', array('fields' => array('id', 'title'))); + + + $this->set('roles', $roles); + $this->set('stateUser', $stateUser); + $this->set('role_ids', $role_ids); + $this->set('assignRoleForm', $assignRoleForm); + $this->set('public_hex', $public_hex); + } + +} diff --git a/src/Model/Entity/Role.php b/src/Model/Entity/Role.php new file mode 100644 index 000000000..ae0ddd0ba --- /dev/null +++ b/src/Model/Entity/Role.php @@ -0,0 +1,26 @@ + true, + ]; +} diff --git a/src/Model/Entity/StateUserRole.php b/src/Model/Entity/StateUserRole.php new file mode 100644 index 000000000..d510bb025 --- /dev/null +++ b/src/Model/Entity/StateUserRole.php @@ -0,0 +1,30 @@ + true, + 'role_id' => true + ]; +} diff --git a/src/Model/Table/RolesTable.php b/src/Model/Table/RolesTable.php new file mode 100644 index 000000000..940b7f246 --- /dev/null +++ b/src/Model/Table/RolesTable.php @@ -0,0 +1,72 @@ +setTable('roles'); + $this->setDisplayField('title'); + $this->setPrimaryKey('id'); + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->integer('id') + ->allowEmptyString('id', null, 'create') + ->add('id', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']); + + $validator + ->scalar('title') + ->maxLength('title', 255) + ->allowEmptyString('title'); + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. + * @return \Cake\ORM\RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + $rules->add($rules->isUnique(['id'])); + + return $rules; + } +} diff --git a/src/Model/Table/StateUserRolesTable.php b/src/Model/Table/StateUserRolesTable.php new file mode 100644 index 000000000..895e788b2 --- /dev/null +++ b/src/Model/Table/StateUserRolesTable.php @@ -0,0 +1,86 @@ +setTable('state_user_roles'); + $this->setPrimaryKey('id'); + + + $this->belongsTo('StateUser', [ + 'foreignKey' => 'state_user_id', + 'joinType' => 'INNER' + ]); + + $this->belongsTo('Role', [ + 'foreignKey' => 'role_id', + 'joinType' => 'INNER' + ]); + + + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->integer('id') + ->allowEmptyString('id', null, 'create'); + + + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. + * @return \Cake\ORM\RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + // $rules->add($rules->existsIn(['index_id'], 'Indices')); + //$rules->add($rules->existsIn(['state_group_id'], 'StateGroups')); + + return $rules; + } + + +} diff --git a/src/Template/Roles/add.ctp b/src/Template/Roles/add.ctp new file mode 100644 index 000000000..c671ed011 --- /dev/null +++ b/src/Template/Roles/add.ctp @@ -0,0 +1,23 @@ + + +
+ Form->create($role) ?> +
+ + Form->control('title'); + ?> +
+ Form->button(__('Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Roles/edit.ctp b/src/Template/Roles/edit.ctp new file mode 100644 index 000000000..8a7cd385f --- /dev/null +++ b/src/Template/Roles/edit.ctp @@ -0,0 +1,29 @@ + + +
+ Form->create($role) ?> +
+ + Form->control('title'); + ?> +
+ Form->button(__('Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Roles/index.ctp b/src/Template/Roles/index.ctp new file mode 100644 index 000000000..2637ef958 --- /dev/null +++ b/src/Template/Roles/index.ctp @@ -0,0 +1,47 @@ + + +
+

+ + + + + + + + + + + + + + + + + +
Paginator->sort('id') ?>Paginator->sort('title') ?>
Number->format($role->id) ?>title) ?> + Html->link(__('View'), ['action' => 'view', $role->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $role->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $role->id], ['confirm' => __('Are you sure you want to delete # {0}?', $role->id)]) ?> +
+
+ +

Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?>

+
+
diff --git a/src/Template/Roles/view.ctp b/src/Template/Roles/view.ctp new file mode 100644 index 000000000..04e1dcec5 --- /dev/null +++ b/src/Template/Roles/view.ctp @@ -0,0 +1,28 @@ + + +
+

title) ?>

+ + + + + + + + + +
title) ?>
Number->format($role->id) ?>
+
diff --git a/src/Template/StateUserRoles/assign_role.ctp b/src/Template/StateUserRoles/assign_role.ctp new file mode 100644 index 000000000..64d3a1f8b --- /dev/null +++ b/src/Template/StateUserRoles/assign_role.ctp @@ -0,0 +1,49 @@ +assign('title', __('Assign Role')); +// In a View class +$this->loadHelper('Form', [ + 'templates' => 'horizontal_form', +]); +?> +Html->css([ + 'loginServer/style.css', + 'rippleUI/style.css', + 'materialdesignicons.min.css' +]) ?> + +
+

Assign Role

+
+ Form->create($assignRoleForm, []) ?> +
User:  first_name." ".$stateUser->last_name ?>
+
Select Role:
Form->select('role_id', $roles, ['label' => __('Role'), 'class' => 'form-control', 'id' => 'inlineFormInputGroup', 'placeholder' => __('Role'), "multiple" => "multiple", "value" => $role_ids]) ?>
+ Form->button(' ' . __('Assign Role'), ['class' => 'form-button']) ?> + Form->hidden('public_hex', ['id' => 'input-order-row', 'value' => $public_hex]) ?> +
+
diff --git a/src/Template/StateUserRoles/index.ctp b/src/Template/StateUserRoles/index.ctp new file mode 100644 index 000000000..4e6ea8cb1 --- /dev/null +++ b/src/Template/StateUserRoles/index.ctp @@ -0,0 +1,69 @@ + + +
+

+ + + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('id') ?>Paginator->sort('first_name') ?> + Paginator->sort('last_name') ?> + Paginator->sort('username') ?> + Paginator->sort('email') ?> + Paginator->sort('disabled') ?> +
Number->format($stateUser->id) ?>first_name ?>last_name ?>username ?>email ?>disabled ?> + Html->link(__('View'), ['action' => 'view', $stateUser->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $stateUser->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $stateUser->id], ['confirm' => __('Are you sure you want to delete # {0}?', $stateUser->id)]) ?> +
+
+ +

Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?>

+
+
diff --git a/src/Template/StateUserRoles/search.ctp b/src/Template/StateUserRoles/search.ctp new file mode 100644 index 000000000..c1234d245 --- /dev/null +++ b/src/Template/StateUserRoles/search.ctp @@ -0,0 +1,80 @@ +assign('title', __('Benutzer suchen')); +// In a View class +$this->loadHelper('Form', [ + 'templates' => 'horizontal_form', +]); +?> +Html->css([ + 'loginServer/style.css', + 'rippleUI/style.css', + 'materialdesignicons.min.css' +]) ?> + +
+

Benutzer suchen

+
+ Form->create($searchForm, []) ?> + Form->control('search', ['label' => __('Suchbegriff'), 'class' => 'form-control', 'id' => 'inlineFormInputGroup', 'placeholder' => __('Vorname/Nachname/E-Mail')]) ?> + Form->button('search ' . __('Suchen'), ['class' => 'form-button']) ?> + Form->hidden('order_row', ['id' => 'input-order-row']) ?> +
+
+
+

+ + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('first_name') ?>Paginator->sort('last_name') ?>Paginator->sort('email') ?>
+ Html->link(__('Assign Role'), ['action' => 'assignRole', $stateUser['pubkeyhex']]) ?> +
+
+ + diff --git a/tests/Fixture/RolesFixture.php b/tests/Fixture/RolesFixture.php new file mode 100644 index 000000000..db2c7640f --- /dev/null +++ b/tests/Fixture/RolesFixture.php @@ -0,0 +1,45 @@ + ['type' => 'integer', 'length' => 11, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'autoIncrement' => true, 'precision' => null], + 'title' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'collate' => 'utf8mb4_unicode_ci', 'comment' => '', 'precision' => null, 'fixed' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + 'roles_id_IDX' => ['type' => 'unique', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8mb4_unicode_ci' + ], + ]; + // @codingStandardsIgnoreEnd + /** + * Init method + * + * @return void + */ + public function init() + { + $this->records = [ + [ + 'id' => 1, + 'title' => 'Lorem ipsum dolor sit amet', + ], + ]; + parent::init(); + } +} diff --git a/tests/TestCase/Controller/RolesControllerTest.php b/tests/TestCase/Controller/RolesControllerTest.php new file mode 100644 index 000000000..12b2868a2 --- /dev/null +++ b/tests/TestCase/Controller/RolesControllerTest.php @@ -0,0 +1,75 @@ +markTestIncomplete('Not implemented yet.'); + } + + /** + * Test view method + * + * @return void + */ + public function testView() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test add method + * + * @return void + */ + public function testAdd() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test edit method + * + * @return void + */ + public function testEdit() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test delete method + * + * @return void + */ + public function testDelete() + { + $this->markTestIncomplete('Not implemented yet.'); + } +} diff --git a/tests/TestCase/Model/Table/RolesTableTest.php b/tests/TestCase/Model/Table/RolesTableTest.php new file mode 100644 index 000000000..b40a0ca9b --- /dev/null +++ b/tests/TestCase/Model/Table/RolesTableTest.php @@ -0,0 +1,82 @@ +exists('Roles') ? [] : ['className' => RolesTable::class]; + $this->Roles = TableRegistry::getTableLocator()->get('Roles', $config); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->Roles); + + parent::tearDown(); + } + + /** + * Test initialize method + * + * @return void + */ + public function testInitialize() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test validationDefault method + * + * @return void + */ + public function testValidationDefault() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test buildRules method + * + * @return void + */ + public function testBuildRules() + { + $this->markTestIncomplete('Not implemented yet.'); + } +}