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 @@
+
+
+
| = $this->Paginator->sort('id') ?> | += $this->Paginator->sort('title') ?> | += __('Actions') ?> | +
|---|---|---|
| = $this->Number->format($role->id) ?> | += h($role->title) ?> | ++ = $this->Html->link(__('View'), ['action' => 'view', $role->id]) ?> + = $this->Html->link(__('Edit'), ['action' => 'edit', $role->id]) ?> + = $this->Form->postLink(__('Delete'), ['action' => 'delete', $role->id], ['confirm' => __('Are you sure you want to delete # {0}?', $role->id)]) ?> + | +
= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?>
+| = __('Title') ?> | += h($role->title) ?> | +
|---|---|
| = __('Id') ?> | += $this->Number->format($role->id) ?> | +
Assign Role
+| = $this->Paginator->sort('id') ?> | + += $this->Paginator->sort('first_name') ?> + | = $this->Paginator->sort('last_name') ?> + | = $this->Paginator->sort('username') ?> + | = $this->Paginator->sort('email') ?> + | = $this->Paginator->sort('disabled') ?> + | = __('Actions') ?> | +
|---|---|---|---|---|---|---|
| = $this->Number->format($stateUser->id) ?> | + += $stateUser->first_name ?> | += $stateUser->last_name ?> | += $stateUser->username ?> | += $stateUser->email ?> | += $stateUser->disabled ?> | ++ = $this->Html->link(__('View'), ['action' => 'view', $stateUser->id]) ?> + = $this->Html->link(__('Edit'), ['action' => 'edit', $stateUser->id]) ?> + = $this->Form->postLink(__('Delete'), ['action' => 'delete', $stateUser->id], ['confirm' => __('Are you sure you want to delete # {0}?', $stateUser->id)]) ?> + | +
= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?>
+Benutzer suchen
+| = $this->Paginator->sort('first_name') ?> | += $this->Paginator->sort('last_name') ?> | += $this->Paginator->sort('email') ?> | += __('Role') ?> | += __('Actions') ?> | +
|---|---|---|---|---|
| = $stateUser['first_name'] ?> | += $stateUser['last_name'] ?> | += $stateUser['email'] ?> | += $stateUser['role_name'] ?> | ++ = $this->Html->link(__('Assign Role'), ['action' => 'assignRole', $stateUser['pubkeyhex']]) ?> + | +