From adb948d1a52963ae3588fe845c6cc6051cb876e2 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 21 Aug 2020 13:05:31 +0000 Subject: [PATCH 01/57] adding error transaction api endpoint, only empty function --- src/Controller/JsonRequestHandlerController.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index 89d07a93f..d97f27373 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,11 +58,20 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); + case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionSha256, $jsonData->error, $jsonData->errorMessage); } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } return $this->returnJson(['state' => 'error', 'msg' => 'no post or get']); } + + //! \param $transactionCreated creation of transaction in timestamp in seconds + //! \param $transactionBodyBase64Sha256 sha256 hash from transaction body serialized and converted to base64 + //! \param $error short error name in user language + //! \param $errorDetails more detailed error message in user language + private function errorInTransaction($transactionCreated, $transactionBodyBase64Sha256, $error, $errorDetails) { + + } private function putTransaction($transactionBase64) { $transaction = new Transaction($transactionBase64); From 28ab6f3810da9823a1d36d6be2a901561cda10c6 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 21 Aug 2020 13:16:58 +0000 Subject: [PATCH 02/57] change to blake2 --- src/Controller/JsonRequestHandlerController.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index d97f27373..af93d2190 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,7 +58,7 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); - case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionSha256, $jsonData->error, $jsonData->errorMessage); + case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionGenericHash, $jsonData->error, $jsonData->errorMessage); } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } @@ -66,10 +66,11 @@ class JsonRequestHandlerController extends AppController { } //! \param $transactionCreated creation of transaction in timestamp in seconds - //! \param $transactionBodyBase64Sha256 sha256 hash from transaction body serialized and converted to base64 + //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 + //! using sodium_crypto_generichash to calculate //! \param $error short error name in user language //! \param $errorDetails more detailed error message in user language - private function errorInTransaction($transactionCreated, $transactionBodyBase64Sha256, $error, $errorDetails) { + private function errorInTransaction($transactionCreated, $transactionBodyBase64GenericHash, $error, $errorDetails) { } From e143a5c72954967d06738890c4b0035a68e19db7 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 4 Sep 2020 14:40:44 +0000 Subject: [PATCH 03/57] js for login server --- .../JsonRequestHandlerController.php | 2 + .../TransactionSendCoinsController.php | 2 +- webroot/js/time_calculations.js | 68 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 webroot/js/time_calculations.js diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index af93d2190..cced85daa 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -66,8 +66,10 @@ class JsonRequestHandlerController extends AppController { } //! \param $transactionCreated creation of transaction in timestamp in seconds + //! -1 if transaction couldn't decode //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 //! using sodium_crypto_generichash to calculate + // hash also in base64 format //! \param $error short error name in user language //! \param $errorDetails more detailed error message in user language private function errorInTransaction($transactionCreated, $transactionBodyBase64GenericHash, $error, $errorDetails) { diff --git a/src/Controller/TransactionSendCoinsController.php b/src/Controller/TransactionSendCoinsController.php index 40cccb90e..d49038148 100644 --- a/src/Controller/TransactionSendCoinsController.php +++ b/src/Controller/TransactionSendCoinsController.php @@ -187,7 +187,7 @@ class TransactionSendCoinsController extends AppController $this->set('timeUsed', microtime(true) - $startTime); return; } - if($requestAnswear['data']['userData']['disabled']) { + if(isset($requestAnswear['data']['userData']['disabled']) && $requestAnswear['data']['userData']['disabled']) { $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); $this->set('timeUsed', microtime(true) - $startTime); return; diff --git a/webroot/js/time_calculations.js b/webroot/js/time_calculations.js new file mode 100644 index 000000000..7ca61c492 --- /dev/null +++ b/webroot/js/time_calculations.js @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + + + +var SECONDS_TO_YEAR = 31536000; +var SECONDS_TO_DAY = 86400; +var SECONDS_TO_HOUR = 3600; +var SECONDS_TO_MINUTE = 60; +SECONDS_TO = { + YEAR: SECONDS_TO_YEAR, + DAY: SECONDS_TO_DAY, + HOUR: SECONDS_TO_HOUR, + MINUTE: SECONDS_TO_MINUTE +}; + + + +function getReadableAge(timestamp) { + if(timestamp === undefined) { + return "no timestamp" + } + var ageSeconds = ((new Date()).getTime()/1000) - timestamp; + if(ageSeconds < SECONDS_TO_MINUTE) { + return Math.round(ageSeconds) + " seconds"; + } else if(ageSeconds < SECONDS_TO_HOUR) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_MINUTE) + " minutes"; + } else if(ageSeconds < SECONDS_TO_DAY) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_HOUR) + " hours"; + } else if(ageSeconds < SECONDS_TO_YEAR) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_DAY) + " days"; + } else { + return "~ " + Math.round(ageSeconds / SECONDS_TO_YEAR) + " years"; + } +} + +function getExactTimeDuration(durationSeconds) { + var parts = { + seconds: durationSeconds, + minutes: 0, + hours: 0, + days: 0, + years: 0 + }; + var durationString = ''; + for(var i in SECONDS_TO) { + if(parts.seconds > SECONDS_TO[i]) { + var partIndexName = i.toLowerCase() + 's'; + parts[partIndexName] = Math.floor(parts.seconds / SECONDS_TO[i]); + parts.seconds -= parts[partIndexName] * SECONDS_TO[i]; + if(durationString.length > 0) { + durationString += ', '; + } + var unitName = partIndexName; + if(parts[partIndexName] === 1) { + unitName = partIndexName.substring(0, partIndexName.length-1); + } + durationString += parts[partIndexName] + ' ' + unitName; + break; + } + + } + return durationString; + +} \ No newline at end of file From a7ecfa45d9aad0b91129bd67f7043317a950b172 Mon Sep 17 00:00:00 2001 From: team-devstage Date: Mon, 7 Sep 2020 16:34:33 +0200 Subject: [PATCH 04/57] update grd styles --- mithril_client | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mithril_client b/mithril_client index 21d4a0a5e..a04d47699 160000 --- a/mithril_client +++ b/mithril_client @@ -1 +1 @@ -Subproject commit 21d4a0a5e9a19f251e26c0ae07ce74be2fa99bbf +Subproject commit a04d4769974b9d93ba72e490ed7dca3fbaed768c From 69e7897fddb9451f73e6c653a4d91c03f0ec9662 Mon Sep 17 00:00:00 2001 From: team-devstage Date: Tue, 15 Sep 2020 14:57:29 +0200 Subject: [PATCH 05/57] git checkout work of samir --- src/Controller/AppController.php | 1 - src/Controller/ServerUsersController.php | 2 +- src/Template/Dashboard/index.ctp | 21 +++++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 94b99da73..97da257b3 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -129,7 +129,6 @@ class AppController extends Controller if ($this->Auth->user('id')) { $GLOBALS['ServerUser'] = $this->Auth->user(); } - // login server url $loginServer = Configure::read('LoginServer'); if ($loginServer && isset($loginServer['url'])) { diff --git a/src/Controller/ServerUsersController.php b/src/Controller/ServerUsersController.php index 52165bb3b..236e35b7f 100644 --- a/src/Controller/ServerUsersController.php +++ b/src/Controller/ServerUsersController.php @@ -15,7 +15,7 @@ class ServerUsersController extends AppController public function initialize() { parent::initialize(); - //$this->Auth->allow(['add', 'edit']); + $this->Auth->allow(['add', 'edit']); $this->Auth->deny('index'); } diff --git a/src/Template/Dashboard/index.ctp b/src/Template/Dashboard/index.ctp index 3e93e968a..095234222 100644 --- a/src/Template/Dashboard/index.ctp +++ b/src/Template/Dashboard/index.ctp @@ -111,4 +111,25 @@ $this->assign( +
+

Roles ...

+
+
+ roles + Html->link( + __('View'), + ['controller' => 'Roles', 'action' => 'index'], + ['class' => 'info-item-link'] + ); ?> +
+
+ assign_roles + Html->link( + __('Assign Roles'), + ['controller' => 'StateUserRoles', 'action' => 'search'], + ['class' => 'info-item-link'] + ); ?> +
+
+
From 99a68091ae0bae659c1dffbc7ed874aa671c653c Mon Sep 17 00:00:00 2001 From: team-devstage Date: Fri, 18 Sep 2020 18:08:17 +0200 Subject: [PATCH 06/57] add files created from samir --- src/Form/AssignRoleForm.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/Form/AssignRoleForm.php diff --git a/src/Form/AssignRoleForm.php b/src/Form/AssignRoleForm.php new file mode 100644 index 000000000..158fa2296 --- /dev/null +++ b/src/Form/AssignRoleForm.php @@ -0,0 +1,30 @@ +addField('role_id', ['type' => 'string']); + } + + function validationDefault(Validator $validator) + { + $validator->setProvider('custom', 'App\Model\Validation\GenericValidation'); + + return $validator; + } + + + protected function _execute(array $data) + { + // Send an email. + return true; + } +} \ No newline at end of file From 0e5edbcd658642be5f1944d75216f66477ff560e Mon Sep 17 00:00:00 2001 From: team-devstage Date: Thu, 24 Sep 2020 08:01:11 +0200 Subject: [PATCH 07/57] add new created files from samir --- src/Controller/RolesController.php | 108 ++++++ src/Controller/StateUserRolesController.php | 307 ++++++++++++++++++ src/Model/Entity/Role.php | 26 ++ src/Model/Entity/StateUserRole.php | 30 ++ src/Model/Table/RolesTable.php | 72 ++++ src/Model/Table/StateUserRolesTable.php | 86 +++++ src/Template/Roles/add.ctp | 23 ++ src/Template/Roles/edit.ctp | 29 ++ src/Template/Roles/index.ctp | 47 +++ src/Template/Roles/view.ctp | 28 ++ src/Template/StateUserRoles/assign_role.ctp | 49 +++ src/Template/StateUserRoles/index.ctp | 69 ++++ src/Template/StateUserRoles/search.ctp | 80 +++++ tests/Fixture/RolesFixture.php | 45 +++ .../Controller/RolesControllerTest.php | 75 +++++ tests/TestCase/Model/Table/RolesTableTest.php | 82 +++++ 16 files changed, 1156 insertions(+) create mode 100644 src/Controller/RolesController.php create mode 100644 src/Controller/StateUserRolesController.php create mode 100644 src/Model/Entity/Role.php create mode 100644 src/Model/Entity/StateUserRole.php create mode 100644 src/Model/Table/RolesTable.php create mode 100644 src/Model/Table/StateUserRolesTable.php create mode 100644 src/Template/Roles/add.ctp create mode 100644 src/Template/Roles/edit.ctp create mode 100644 src/Template/Roles/index.ctp create mode 100644 src/Template/Roles/view.ctp create mode 100644 src/Template/StateUserRoles/assign_role.ctp create mode 100644 src/Template/StateUserRoles/index.ctp create mode 100644 src/Template/StateUserRoles/search.ctp create mode 100644 tests/Fixture/RolesFixture.php create mode 100644 tests/TestCase/Controller/RolesControllerTest.php create mode 100644 tests/TestCase/Model/Table/RolesTableTest.php 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.'); + } +} From 35b14d7480c66f54c40392fd01a68f1335503d41 Mon Sep 17 00:00:00 2001 From: team-devstage Date: Fri, 25 Sep 2020 15:01:33 +0200 Subject: [PATCH 08/57] cleanup samirs code, remove not needed stuff from my old code -Dario --- src/Controller/StateUserRolesController.php | 142 ++------------------ src/Template/StateUserRoles/search.ctp | 27 ---- 2 files changed, 10 insertions(+), 159 deletions(-) diff --git a/src/Controller/StateUserRolesController.php b/src/Controller/StateUserRolesController.php index b61d6b82b..9f83dc0bc 100644 --- a/src/Controller/StateUserRolesController.php +++ b/src/Controller/StateUserRolesController.php @@ -34,7 +34,7 @@ class StateUserRolesController extends AppController parent::initialize(); $this->loadComponent('JsonRequestClient'); $this->Auth->allow([ - 'search' +// 'search' ]); $this->set( 'naviHierarchy', @@ -49,22 +49,12 @@ class StateUserRolesController extends AppController $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')); + $this->set(compact('timeUsed', 'searchForm')); if ($this->request->is('post')) { $requestData = $this->request->getData(); @@ -72,43 +62,12 @@ class StateUserRolesController extends AppController 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']]]); + ->contain([]); $communityUsers->where(['OR' => [ 'first_name LIKE' => $globalSearch, @@ -118,71 +77,15 @@ class StateUserRolesController extends AppController ]]); //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'); +// foreach ($pubkeySorted as $pubhex => $user) { + foreach($communityUsers as $communityUser) { + $finalUser = $communityUser; + $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); - $this->loadModel('Roles'); - $state_user_id = $user['community'][0]->id; + $state_user_id = $communityUser->id; $stateUserRole = $this->StateUserRoles->find('all')->where(['state_user_id' => $state_user_id])->all(); $role_ids = ""; @@ -206,34 +109,9 @@ class StateUserRolesController extends AppController $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!')); diff --git a/src/Template/StateUserRoles/search.ctp b/src/Template/StateUserRoles/search.ctp index c1234d245..aff7fbbcb 100644 --- a/src/Template/StateUserRoles/search.ctp +++ b/src/Template/StateUserRoles/search.ctp @@ -12,31 +12,6 @@ $this->loadHelper('Form', [ 'templates' => 'horizontal_form', ]); ?> -Html->css([ - 'loginServer/style.css', - 'rippleUI/style.css', - 'materialdesignicons.min.css' -]) ?> -

Benutzer suchen

@@ -76,5 +51,3 @@ $this->loadHelper('Form', [
- - From 9353d35a6fe871266fd84da6217a33d88ce2ee73 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 25 Sep 2020 13:56:16 +0000 Subject: [PATCH 09/57] add new gradido proto files and update parse proto script --- mithril_client | 2 +- parse_proto.php | 2 +- src/Controller/StateUserRolesController.php | 4 +- .../Proto/Gradido/CrossGroupTransfer.php | 146 +++++++++++++ .../Proto/Gradido/GradidoCreation.php | 102 +++++++++ .../Proto/Gradido/GradidoTransaction.php | 116 +++++++++++ .../Proto/Gradido/GradidoTransfer.php | 109 ++++++++++ .../Proto/Gradido/GroupFriendsUpdate.php | 92 +++++++++ .../Gradido/GroupFriendsUpdate/Action.php | 51 +++++ .../Gradido/GroupFriendsUpdate_Action.php | 16 ++ .../Proto/Gradido/GroupMemberUpdate.php | 146 +++++++++++++ .../GroupMemberUpdate/MemberUpdateType.php | 56 +++++ .../GroupMemberUpdate_MemberUpdateType.php | 16 ++ src/Model/Messages/Proto/Gradido/Key.php | 96 +++++++++ .../Messages/Proto/Gradido/LocalTransfer.php | 85 ++++++++ .../Messages/Proto/Gradido/SignatureMap.php | 65 ++++++ .../Messages/Proto/Gradido/SignaturePair.php | 123 +++++++++++ .../Messages/Proto/Gradido/Timestamp.php | 101 +++++++++ .../Proto/Gradido/TimestampSeconds.php | 67 ++++++ .../Proto/Gradido/TransactionBody.php | 193 ++++++++++++++++++ .../Messages/Proto/Gradido/TransferAmount.php | 85 ++++++++ src/protobuf | 2 +- 22 files changed, 1670 insertions(+), 5 deletions(-) create mode 100644 src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php create mode 100644 src/Model/Messages/Proto/Gradido/GradidoCreation.php create mode 100644 src/Model/Messages/Proto/Gradido/GradidoTransaction.php create mode 100644 src/Model/Messages/Proto/Gradido/GradidoTransfer.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupMemberUpdate.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php create mode 100644 src/Model/Messages/Proto/Gradido/Key.php create mode 100644 src/Model/Messages/Proto/Gradido/LocalTransfer.php create mode 100644 src/Model/Messages/Proto/Gradido/SignatureMap.php create mode 100644 src/Model/Messages/Proto/Gradido/SignaturePair.php create mode 100644 src/Model/Messages/Proto/Gradido/Timestamp.php create mode 100644 src/Model/Messages/Proto/Gradido/TimestampSeconds.php create mode 100644 src/Model/Messages/Proto/Gradido/TransactionBody.php create mode 100644 src/Model/Messages/Proto/Gradido/TransferAmount.php diff --git a/mithril_client b/mithril_client index a04d47699..21d4a0a5e 160000 --- a/mithril_client +++ b/mithril_client @@ -1 +1 @@ -Subproject commit a04d4769974b9d93ba72e490ed7dca3fbaed768c +Subproject commit 21d4a0a5e9a19f251e26c0ae07ce74be2fa99bbf diff --git a/parse_proto.php b/parse_proto.php index 576b99691..e6ccb451f 100755 --- a/parse_proto.php +++ b/parse_proto.php @@ -16,5 +16,5 @@ #PHP_PLUGIN="$(which grpc_php_plugin)" #protoc --proto_path=./src/protobuf/gradido --php_out=./src/ --grpc_out=./src/ --plugin=protoc-gen-grpc=$PHP_PLUGIN ./src/protobuf/gradido/*.proto -protoc --proto_path=./src/protobuf/gradido --php_out=./src/ ./src/protobuf/gradido/*.proto +protoc --proto_path=./src/protobuf --php_out=./src/Model/Messages ./src/protobuf/gradido/*.proto diff --git a/src/Controller/StateUserRolesController.php b/src/Controller/StateUserRolesController.php index 9f83dc0bc..9238c7ad6 100644 --- a/src/Controller/StateUserRolesController.php +++ b/src/Controller/StateUserRolesController.php @@ -81,9 +81,9 @@ class StateUserRolesController extends AppController // detect states $this->loadModel('Roles'); // foreach ($pubkeySorted as $pubhex => $user) { - foreach($communityUsers as $communityUser) { + foreach($communityUsers as $communityUser) { $finalUser = $communityUser; - $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); + $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); $state_user_id = $communityUser->id; $stateUserRole = $this->StateUserRoles->find('all')->where(['state_user_id' => $state_user_id])->all(); diff --git a/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php b/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php new file mode 100644 index 000000000..781ac8f25 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php @@ -0,0 +1,146 @@ +proto.gradido.CrossGroupTransfer + */ +class CrossGroupTransfer extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + */ + private $sender = null; + /** + * Generated from protobuf field bytes receiver = 2; + */ + private $receiver = ''; + /** + * Generated from protobuf field string other_group = 3; + */ + private $other_group = ''; + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + */ + private $paired_transaction_id = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $sender + * @type string $receiver + * @type string $other_group + * @type \Proto\Gradido\Timestamp $paired_transaction_id + * this matches related OutboundTransfer.paired_transaction_id + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getSender() + { + return $this->sender; + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setSender($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->sender = $var; + + return $this; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @return string + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @param string $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkString($var, False); + $this->receiver = $var; + + return $this; + } + + /** + * Generated from protobuf field string other_group = 3; + * @return string + */ + public function getOtherGroup() + { + return $this->other_group; + } + + /** + * Generated from protobuf field string other_group = 3; + * @param string $var + * @return $this + */ + public function setOtherGroup($var) + { + GPBUtil::checkString($var, True); + $this->other_group = $var; + + return $this; + } + + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + * @return \Proto\Gradido\Timestamp + */ + public function getPairedTransactionId() + { + return $this->paired_transaction_id; + } + + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + * @param \Proto\Gradido\Timestamp $var + * @return $this + */ + public function setPairedTransactionId($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\Timestamp::class); + $this->paired_transaction_id = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GradidoCreation.php b/src/Model/Messages/Proto/Gradido/GradidoCreation.php new file mode 100644 index 000000000..9b4c3208d --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GradidoCreation.php @@ -0,0 +1,102 @@ +proto.gradido.GradidoCreation + */ +class GradidoCreation extends \Google\Protobuf\Internal\Message +{ + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + */ + private $receiver = null; + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + */ + private $target_date = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $receiver + * 40 Byte + * @type \Proto\Gradido\TimestampSeconds $target_date + * 8 Byte + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoCreation::initOnce(); + parent::__construct($data); + } + + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->receiver = $var; + + return $this; + } + + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + * @return \Proto\Gradido\TimestampSeconds + */ + public function getTargetDate() + { + return $this->target_date; + } + + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + * @param \Proto\Gradido\TimestampSeconds $var + * @return $this + */ + public function setTargetDate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TimestampSeconds::class); + $this->target_date = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GradidoTransaction.php b/src/Model/Messages/Proto/Gradido/GradidoTransaction.php new file mode 100644 index 000000000..b4b34c77e --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GradidoTransaction.php @@ -0,0 +1,116 @@ +proto.gradido.GradidoTransaction + */ +class GradidoTransaction extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + */ + private $sig_map = null; + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + */ + private $body_bytes = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\SignatureMap $sig_map + * @type string $body_bytes + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransaction::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + * @return \Proto\Gradido\SignatureMap + */ + public function getSigMap() + { + return $this->sig_map; + } + + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + * @param \Proto\Gradido\SignatureMap $var + * @return $this + */ + public function setSigMap($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\SignatureMap::class); + $this->sig_map = $var; + + return $this; + } + + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + * @return string + */ + public function getBodyBytes() + { + return $this->body_bytes; + } + + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + * @param string $var + * @return $this + */ + public function setBodyBytes($var) + { + GPBUtil::checkString($var, False); + $this->body_bytes = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GradidoTransfer.php b/src/Model/Messages/Proto/Gradido/GradidoTransfer.php new file mode 100644 index 000000000..a76954c2e --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GradidoTransfer.php @@ -0,0 +1,109 @@ +proto.gradido.GradidoTransfer + */ +class GradidoTransfer extends \Google\Protobuf\Internal\Message +{ + protected $data; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\LocalTransfer $local + * @type \Proto\Gradido\CrossGroupTransfer $inbound + * @type \Proto\Gradido\CrossGroupTransfer $outbound + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.LocalTransfer local = 1; + * @return \Proto\Gradido\LocalTransfer + */ + public function getLocal() + { + return $this->readOneof(1); + } + + /** + * Generated from protobuf field .proto.gradido.LocalTransfer local = 1; + * @param \Proto\Gradido\LocalTransfer $var + * @return $this + */ + public function setLocal($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\LocalTransfer::class); + $this->writeOneof(1, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer inbound = 2; + * @return \Proto\Gradido\CrossGroupTransfer + */ + public function getInbound() + { + return $this->readOneof(2); + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer inbound = 2; + * @param \Proto\Gradido\CrossGroupTransfer $var + * @return $this + */ + public function setInbound($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\CrossGroupTransfer::class); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer outbound = 3; + * @return \Proto\Gradido\CrossGroupTransfer + */ + public function getOutbound() + { + return $this->readOneof(3); + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer outbound = 3; + * @param \Proto\Gradido\CrossGroupTransfer $var + * @return $this + */ + public function setOutbound($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\CrossGroupTransfer::class); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getData() + { + return $this->whichOneof("data"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php new file mode 100644 index 000000000..22e86d3e1 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php @@ -0,0 +1,92 @@ +proto.gradido.GroupFriendsUpdate + */ +class GroupFriendsUpdate extends \Google\Protobuf\Internal\Message +{ + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + */ + private $group = ''; + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + */ + private $action = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $group + * char[16], alias + * @type int $action + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GroupFriendsUpdate::initOnce(); + parent::__construct($data); + } + + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + * @return string + */ + public function getGroup() + { + return $this->group; + } + + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + * @param string $var + * @return $this + */ + public function setGroup($var) + { + GPBUtil::checkString($var, True); + $this->group = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + * @return int + */ + public function getAction() + { + return $this->action; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + * @param int $var + * @return $this + */ + public function setAction($var) + { + GPBUtil::checkEnum($var, \Proto\Gradido\GroupFriendsUpdate_Action::class); + $this->action = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php new file mode 100644 index 000000000..2a3396c55 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php @@ -0,0 +1,51 @@ +proto.gradido.GroupFriendsUpdate.Action + */ +class Action +{ + /** + * Generated from protobuf enum ADD_FRIEND = 0; + */ + const ADD_FRIEND = 0; + /** + * Generated from protobuf enum REMOVE_FRIEND = 1; + */ + const REMOVE_FRIEND = 1; + + private static $valueToName = [ + self::ADD_FRIEND => 'ADD_FRIEND', + self::REMOVE_FRIEND => 'REMOVE_FRIEND', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Action::class, \Proto\Gradido\GroupFriendsUpdate_Action::class); + diff --git a/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php new file mode 100644 index 000000000..24f8cef70 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php @@ -0,0 +1,16 @@ +proto.gradido.GroupMemberUpdate + */ +class GroupMemberUpdate extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes user_pubkey = 1; + */ + private $user_pubkey = ''; + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + */ + private $member_update_type = 0; + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + */ + private $paired_transaction_id = null; + /** + * Generated from protobuf field string target_group = 4; + */ + private $target_group = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $user_pubkey + * @type int $member_update_type + * @type \Proto\Gradido\Timestamp $paired_transaction_id + * this only makes sense for user move, TODO: probably restructure + * @type string $target_group + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GroupMemberUpdate::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes user_pubkey = 1; + * @return string + */ + public function getUserPubkey() + { + return $this->user_pubkey; + } + + /** + * Generated from protobuf field bytes user_pubkey = 1; + * @param string $var + * @return $this + */ + public function setUserPubkey($var) + { + GPBUtil::checkString($var, False); + $this->user_pubkey = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + * @return int + */ + public function getMemberUpdateType() + { + return $this->member_update_type; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + * @param int $var + * @return $this + */ + public function setMemberUpdateType($var) + { + GPBUtil::checkEnum($var, \Proto\Gradido\GroupMemberUpdate_MemberUpdateType::class); + $this->member_update_type = $var; + + return $this; + } + + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + * @return \Proto\Gradido\Timestamp + */ + public function getPairedTransactionId() + { + return $this->paired_transaction_id; + } + + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + * @param \Proto\Gradido\Timestamp $var + * @return $this + */ + public function setPairedTransactionId($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\Timestamp::class); + $this->paired_transaction_id = $var; + + return $this; + } + + /** + * Generated from protobuf field string target_group = 4; + * @return string + */ + public function getTargetGroup() + { + return $this->target_group; + } + + /** + * Generated from protobuf field string target_group = 4; + * @param string $var + * @return $this + */ + public function setTargetGroup($var) + { + GPBUtil::checkString($var, True); + $this->target_group = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php new file mode 100644 index 000000000..57580cd75 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php @@ -0,0 +1,56 @@ +proto.gradido.GroupMemberUpdate.MemberUpdateType + */ +class MemberUpdateType +{ + /** + * Generated from protobuf enum ADD_USER = 0; + */ + const ADD_USER = 0; + /** + * Generated from protobuf enum MOVE_USER_INBOUND = 1; + */ + const MOVE_USER_INBOUND = 1; + /** + * Generated from protobuf enum MOVE_USER_OUTBOUND = 2; + */ + const MOVE_USER_OUTBOUND = 2; + + private static $valueToName = [ + self::ADD_USER => 'ADD_USER', + self::MOVE_USER_INBOUND => 'MOVE_USER_INBOUND', + self::MOVE_USER_OUTBOUND => 'MOVE_USER_OUTBOUND', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(MemberUpdateType::class, \Proto\Gradido\GroupMemberUpdate_MemberUpdateType::class); + diff --git a/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php new file mode 100644 index 000000000..b7080cf75 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php @@ -0,0 +1,16 @@ +proto.gradido.Key + */ +class Key extends \Google\Protobuf\Internal\Message +{ + protected $key; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $ed25519 + * ed25519 signature (libsodium default) + * @type string $ed25519_ref10 + * ed25519 ref10 signature + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @return string + */ + public function getEd25519() + { + return $this->readOneof(2); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @param string $var + * @return $this + */ + public function setEd25519($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @return string + */ + public function getEd25519Ref10() + { + return $this->readOneof(3); + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @param string $var + * @return $this + */ + public function setEd25519Ref10($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getKey() + { + return $this->whichOneof("key"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/LocalTransfer.php b/src/Model/Messages/Proto/Gradido/LocalTransfer.php new file mode 100644 index 000000000..58f5e23ae --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/LocalTransfer.php @@ -0,0 +1,85 @@ +proto.gradido.LocalTransfer + */ +class LocalTransfer extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + */ + private $sender = null; + /** + * Generated from protobuf field bytes receiver = 2; + */ + private $receiver = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $sender + * @type string $receiver + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getSender() + { + return $this->sender; + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setSender($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->sender = $var; + + return $this; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @return string + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @param string $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkString($var, False); + $this->receiver = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/SignatureMap.php b/src/Model/Messages/Proto/Gradido/SignatureMap.php new file mode 100644 index 000000000..0977169d7 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/SignatureMap.php @@ -0,0 +1,65 @@ +proto.gradido.SignatureMap + */ +class SignatureMap extends \Google\Protobuf\Internal\Message +{ + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + */ + private $sigPair; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $sigPair + * Each signature pair corresponds to a unique Key required to sign the transaction. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getSigPair() + { + return $this->sigPair; + } + + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + * @param \Proto\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setSigPair($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Proto\Gradido\SignaturePair::class); + $this->sigPair = $arr; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/SignaturePair.php b/src/Model/Messages/Proto/Gradido/SignaturePair.php new file mode 100644 index 000000000..2ef0e81c5 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/SignaturePair.php @@ -0,0 +1,123 @@ +proto.gradido.SignaturePair + */ +class SignaturePair extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes pubKey = 1; + */ + private $pubKey = ''; + protected $signature; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $pubKey + * @type string $ed25519 + * ed25519 signature (libsodium default) + * @type string $ed25519_ref10 + * ed25519 ref10 signature + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes pubKey = 1; + * @return string + */ + public function getPubKey() + { + return $this->pubKey; + } + + /** + * Generated from protobuf field bytes pubKey = 1; + * @param string $var + * @return $this + */ + public function setPubKey($var) + { + GPBUtil::checkString($var, False); + $this->pubKey = $var; + + return $this; + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @return string + */ + public function getEd25519() + { + return $this->readOneof(2); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @param string $var + * @return $this + */ + public function setEd25519($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @return string + */ + public function getEd25519Ref10() + { + return $this->readOneof(3); + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @param string $var + * @return $this + */ + public function setEd25519Ref10($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getSignature() + { + return $this->whichOneof("signature"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/Timestamp.php b/src/Model/Messages/Proto/Gradido/Timestamp.php new file mode 100644 index 000000000..ae3ecea0e --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/Timestamp.php @@ -0,0 +1,101 @@ +proto.gradido.Timestamp + */ +class Timestamp extends \Google\Protobuf\Internal\Message +{ + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + */ + private $seconds = 0; + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + */ + private $nanos = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Number of complete seconds since the start of the epoch + * @type int $nanos + * Number of nanoseconds since the start of the last second + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + * @return int + */ + public function getNanos() + { + return $this->nanos; + } + + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + * @param int $var + * @return $this + */ + public function setNanos($var) + { + GPBUtil::checkInt32($var); + $this->nanos = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/TimestampSeconds.php b/src/Model/Messages/Proto/Gradido/TimestampSeconds.php new file mode 100644 index 000000000..d31aa40d2 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/TimestampSeconds.php @@ -0,0 +1,67 @@ +proto.gradido.TimestampSeconds + */ +class TimestampSeconds extends \Google\Protobuf\Internal\Message +{ + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + */ + private $seconds = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Number of complete seconds since the start of the epoch + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/TransactionBody.php b/src/Model/Messages/Proto/Gradido/TransactionBody.php new file mode 100644 index 000000000..0484ecc92 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/TransactionBody.php @@ -0,0 +1,193 @@ +proto.gradido.TransactionBody + */ +class TransactionBody extends \Google\Protobuf\Internal\Message +{ + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + */ + private $memo = ''; + /** + * Generated from protobuf field uint64 version_number = 6; + */ + private $version_number = 0; + protected $data; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $memo + * max 150 chars + * @type \Proto\Gradido\GradidoTransfer $transfer + * @type \Proto\Gradido\GradidoCreation $creation + * @type \Proto\Gradido\GroupFriendsUpdate $group_friends_update + * @type \Proto\Gradido\GroupMemberUpdate $group_member_update + * @type int|string $version_number + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\TransactionBody::initOnce(); + parent::__construct($data); + } + + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + * @return string + */ + public function getMemo() + { + return $this->memo; + } + + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + * @param string $var + * @return $this + */ + public function setMemo($var) + { + GPBUtil::checkString($var, True); + $this->memo = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 2; + * @return \Proto\Gradido\GradidoTransfer + */ + public function getTransfer() + { + return $this->readOneof(2); + } + + /** + * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 2; + * @param \Proto\Gradido\GradidoTransfer $var + * @return $this + */ + public function setTransfer($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GradidoTransfer::class); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GradidoCreation creation = 3; + * @return \Proto\Gradido\GradidoCreation + */ + public function getCreation() + { + return $this->readOneof(3); + } + + /** + * Generated from protobuf field .proto.gradido.GradidoCreation creation = 3; + * @param \Proto\Gradido\GradidoCreation $var + * @return $this + */ + public function setCreation($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GradidoCreation::class); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 4; + * @return \Proto\Gradido\GroupFriendsUpdate + */ + public function getGroupFriendsUpdate() + { + return $this->readOneof(4); + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 4; + * @param \Proto\Gradido\GroupFriendsUpdate $var + * @return $this + */ + public function setGroupFriendsUpdate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GroupFriendsUpdate::class); + $this->writeOneof(4, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 5; + * @return \Proto\Gradido\GroupMemberUpdate + */ + public function getGroupMemberUpdate() + { + return $this->readOneof(5); + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 5; + * @param \Proto\Gradido\GroupMemberUpdate $var + * @return $this + */ + public function setGroupMemberUpdate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GroupMemberUpdate::class); + $this->writeOneof(5, $var); + + return $this; + } + + /** + * Generated from protobuf field uint64 version_number = 6; + * @return int|string + */ + public function getVersionNumber() + { + return $this->version_number; + } + + /** + * Generated from protobuf field uint64 version_number = 6; + * @param int|string $var + * @return $this + */ + public function setVersionNumber($var) + { + GPBUtil::checkUint64($var); + $this->version_number = $var; + + return $this; + } + + /** + * @return string + */ + public function getData() + { + return $this->whichOneof("data"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/TransferAmount.php b/src/Model/Messages/Proto/Gradido/TransferAmount.php new file mode 100644 index 000000000..7673582fa --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/TransferAmount.php @@ -0,0 +1,85 @@ +proto.gradido.TransferAmount + */ +class TransferAmount extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes pubkey = 1; + */ + private $pubkey = ''; + /** + * Generated from protobuf field sint64 amount = 2; + */ + private $amount = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $pubkey + * @type int|string $amount + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes pubkey = 1; + * @return string + */ + public function getPubkey() + { + return $this->pubkey; + } + + /** + * Generated from protobuf field bytes pubkey = 1; + * @param string $var + * @return $this + */ + public function setPubkey($var) + { + GPBUtil::checkString($var, False); + $this->pubkey = $var; + + return $this; + } + + /** + * Generated from protobuf field sint64 amount = 2; + * @return int|string + */ + public function getAmount() + { + return $this->amount; + } + + /** + * Generated from protobuf field sint64 amount = 2; + * @param int|string $var + * @return $this + */ + public function setAmount($var) + { + GPBUtil::checkInt64($var); + $this->amount = $var; + + return $this; + } + +} + diff --git a/src/protobuf b/src/protobuf index 9004e6978..81a461566 160000 --- a/src/protobuf +++ b/src/protobuf @@ -1 +1 @@ -Subproject commit 9004e6978ac3dafcc635b2ffcf8bc6a156451cca +Subproject commit 81a461566e46d71533dc3e284fa075d7d68fd020 From 7af29888ee7621434b9096b18dd21f8215c31d12 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 21 Aug 2020 13:05:31 +0000 Subject: [PATCH 10/57] adding error transaction api endpoint, only empty function --- src/Controller/JsonRequestHandlerController.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index e5823397e..9395e1239 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,7 +58,11 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); + case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionGenericHash, $jsonData->error, $jsonData->errorMessage); + + case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionSha256, $jsonData->error, $jsonData->errorMessage); + } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } @@ -66,6 +70,7 @@ class JsonRequestHandlerController extends AppController { } //! \param $transactionCreated creation of transaction in timestamp in seconds + //! -1 if transaction couldn't decode //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 //! using sodium_crypto_generichash to calculate @@ -80,6 +85,7 @@ class JsonRequestHandlerController extends AppController { * payload.set("error", error); * payload.set("errorMessage", errorDetails); */ + } private function putTransaction($transactionBase64) { From 8f62ad61154d46fa8c3eb5faa6ed7e88f6e6a6c8 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 21 Aug 2020 13:16:58 +0000 Subject: [PATCH 11/57] change to blake2 --- src/Controller/JsonRequestHandlerController.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index 9395e1239..54b6af782 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,11 +58,8 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); - case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionGenericHash, $jsonData->error, $jsonData->errorMessage); - case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionSha256, $jsonData->error, $jsonData->errorMessage); - } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } @@ -70,7 +67,6 @@ class JsonRequestHandlerController extends AppController { } //! \param $transactionCreated creation of transaction in timestamp in seconds - //! -1 if transaction couldn't decode //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 //! using sodium_crypto_generichash to calculate From 2f2af7e96fa68cefd2e71e6e8451750ea75fc5b1 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 4 Sep 2020 14:40:44 +0000 Subject: [PATCH 12/57] js for login server --- .../TransactionSendCoinsController.php | 2 +- webroot/js/time_calculations.js | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 webroot/js/time_calculations.js diff --git a/src/Controller/TransactionSendCoinsController.php b/src/Controller/TransactionSendCoinsController.php index 2f48de063..c5a738736 100644 --- a/src/Controller/TransactionSendCoinsController.php +++ b/src/Controller/TransactionSendCoinsController.php @@ -188,7 +188,7 @@ class TransactionSendCoinsController extends AppController $this->set('timeUsed', microtime(true) - $startTime); return; } - if($requestAnswear['data']['userData']['disabled']) { + if(isset($requestAnswear['data']['userData']['disabled']) && $requestAnswear['data']['userData']['disabled']) { $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); $this->set('timeUsed', microtime(true) - $startTime); return; diff --git a/webroot/js/time_calculations.js b/webroot/js/time_calculations.js new file mode 100644 index 000000000..7ca61c492 --- /dev/null +++ b/webroot/js/time_calculations.js @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + + + +var SECONDS_TO_YEAR = 31536000; +var SECONDS_TO_DAY = 86400; +var SECONDS_TO_HOUR = 3600; +var SECONDS_TO_MINUTE = 60; +SECONDS_TO = { + YEAR: SECONDS_TO_YEAR, + DAY: SECONDS_TO_DAY, + HOUR: SECONDS_TO_HOUR, + MINUTE: SECONDS_TO_MINUTE +}; + + + +function getReadableAge(timestamp) { + if(timestamp === undefined) { + return "no timestamp" + } + var ageSeconds = ((new Date()).getTime()/1000) - timestamp; + if(ageSeconds < SECONDS_TO_MINUTE) { + return Math.round(ageSeconds) + " seconds"; + } else if(ageSeconds < SECONDS_TO_HOUR) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_MINUTE) + " minutes"; + } else if(ageSeconds < SECONDS_TO_DAY) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_HOUR) + " hours"; + } else if(ageSeconds < SECONDS_TO_YEAR) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_DAY) + " days"; + } else { + return "~ " + Math.round(ageSeconds / SECONDS_TO_YEAR) + " years"; + } +} + +function getExactTimeDuration(durationSeconds) { + var parts = { + seconds: durationSeconds, + minutes: 0, + hours: 0, + days: 0, + years: 0 + }; + var durationString = ''; + for(var i in SECONDS_TO) { + if(parts.seconds > SECONDS_TO[i]) { + var partIndexName = i.toLowerCase() + 's'; + parts[partIndexName] = Math.floor(parts.seconds / SECONDS_TO[i]); + parts.seconds -= parts[partIndexName] * SECONDS_TO[i]; + if(durationString.length > 0) { + durationString += ', '; + } + var unitName = partIndexName; + if(parts[partIndexName] === 1) { + unitName = partIndexName.substring(0, partIndexName.length-1); + } + durationString += parts[partIndexName] + ' ' + unitName; + break; + } + + } + return durationString; + +} \ No newline at end of file From 9d8eee819f385ed67d1c8527c4a8be3413f37628 Mon Sep 17 00:00:00 2001 From: team-devstage Date: Tue, 15 Sep 2020 14:57:29 +0200 Subject: [PATCH 13/57] git checkout work of samir --- src/Controller/AppController.php | 1 - src/Template/Dashboard/index.ctp | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index fb0577034..87ec7afb3 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -129,7 +129,6 @@ class AppController extends Controller if ($this->Auth->user('id')) { $GLOBALS['ServerUser'] = $this->Auth->user(); } - // login server url $loginServer = Configure::read('LoginServer'); if ($loginServer && isset($loginServer['url'])) { diff --git a/src/Template/Dashboard/index.ctp b/src/Template/Dashboard/index.ctp index 3e93e968a..095234222 100644 --- a/src/Template/Dashboard/index.ctp +++ b/src/Template/Dashboard/index.ctp @@ -111,4 +111,25 @@ $this->assign(
+
+

Roles ...

+
+
+ roles + Html->link( + __('View'), + ['controller' => 'Roles', 'action' => 'index'], + ['class' => 'info-item-link'] + ); ?> +
+
+ assign_roles + Html->link( + __('Assign Roles'), + ['controller' => 'StateUserRoles', 'action' => 'search'], + ['class' => 'info-item-link'] + ); ?> +
+
+
From 2d6950bc80f1ea74e2f06af67f555bb4ba062185 Mon Sep 17 00:00:00 2001 From: team-devstage Date: Fri, 18 Sep 2020 18:08:17 +0200 Subject: [PATCH 14/57] add files created from samir --- src/Form/AssignRoleForm.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/Form/AssignRoleForm.php diff --git a/src/Form/AssignRoleForm.php b/src/Form/AssignRoleForm.php new file mode 100644 index 000000000..158fa2296 --- /dev/null +++ b/src/Form/AssignRoleForm.php @@ -0,0 +1,30 @@ +addField('role_id', ['type' => 'string']); + } + + function validationDefault(Validator $validator) + { + $validator->setProvider('custom', 'App\Model\Validation\GenericValidation'); + + return $validator; + } + + + protected function _execute(array $data) + { + // Send an email. + return true; + } +} \ No newline at end of file From 46492a1778a55585dce51f4bbcf81e36dd80c6ae Mon Sep 17 00:00:00 2001 From: team-devstage Date: Thu, 24 Sep 2020 08:01:11 +0200 Subject: [PATCH 15/57] add new created files from samir --- src/Controller/RolesController.php | 108 ++++++ src/Controller/StateUserRolesController.php | 307 ++++++++++++++++++ src/Model/Entity/Role.php | 26 ++ src/Model/Entity/StateUserRole.php | 30 ++ src/Model/Table/RolesTable.php | 72 ++++ src/Model/Table/StateUserRolesTable.php | 86 +++++ src/Template/Roles/add.ctp | 23 ++ src/Template/Roles/edit.ctp | 29 ++ src/Template/Roles/index.ctp | 47 +++ src/Template/Roles/view.ctp | 28 ++ src/Template/StateUserRoles/assign_role.ctp | 49 +++ src/Template/StateUserRoles/index.ctp | 69 ++++ src/Template/StateUserRoles/search.ctp | 80 +++++ tests/Fixture/RolesFixture.php | 45 +++ .../Controller/RolesControllerTest.php | 75 +++++ tests/TestCase/Model/Table/RolesTableTest.php | 82 +++++ 16 files changed, 1156 insertions(+) create mode 100644 src/Controller/RolesController.php create mode 100644 src/Controller/StateUserRolesController.php create mode 100644 src/Model/Entity/Role.php create mode 100644 src/Model/Entity/StateUserRole.php create mode 100644 src/Model/Table/RolesTable.php create mode 100644 src/Model/Table/StateUserRolesTable.php create mode 100644 src/Template/Roles/add.ctp create mode 100644 src/Template/Roles/edit.ctp create mode 100644 src/Template/Roles/index.ctp create mode 100644 src/Template/Roles/view.ctp create mode 100644 src/Template/StateUserRoles/assign_role.ctp create mode 100644 src/Template/StateUserRoles/index.ctp create mode 100644 src/Template/StateUserRoles/search.ctp create mode 100644 tests/Fixture/RolesFixture.php create mode 100644 tests/TestCase/Controller/RolesControllerTest.php create mode 100644 tests/TestCase/Model/Table/RolesTableTest.php 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.'); + } +} From b9b724ad07aac2dd0194346651ca68c28d37d07c Mon Sep 17 00:00:00 2001 From: team-devstage Date: Fri, 25 Sep 2020 15:01:33 +0200 Subject: [PATCH 16/57] cleanup samirs code, remove not needed stuff from my old code -Dario --- src/Controller/StateUserRolesController.php | 142 ++------------------ src/Template/StateUserRoles/search.ctp | 27 ---- 2 files changed, 10 insertions(+), 159 deletions(-) diff --git a/src/Controller/StateUserRolesController.php b/src/Controller/StateUserRolesController.php index b61d6b82b..9f83dc0bc 100644 --- a/src/Controller/StateUserRolesController.php +++ b/src/Controller/StateUserRolesController.php @@ -34,7 +34,7 @@ class StateUserRolesController extends AppController parent::initialize(); $this->loadComponent('JsonRequestClient'); $this->Auth->allow([ - 'search' +// 'search' ]); $this->set( 'naviHierarchy', @@ -49,22 +49,12 @@ class StateUserRolesController extends AppController $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')); + $this->set(compact('timeUsed', 'searchForm')); if ($this->request->is('post')) { $requestData = $this->request->getData(); @@ -72,43 +62,12 @@ class StateUserRolesController extends AppController 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']]]); + ->contain([]); $communityUsers->where(['OR' => [ 'first_name LIKE' => $globalSearch, @@ -118,71 +77,15 @@ class StateUserRolesController extends AppController ]]); //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'); +// foreach ($pubkeySorted as $pubhex => $user) { + foreach($communityUsers as $communityUser) { + $finalUser = $communityUser; + $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); - $this->loadModel('Roles'); - $state_user_id = $user['community'][0]->id; + $state_user_id = $communityUser->id; $stateUserRole = $this->StateUserRoles->find('all')->where(['state_user_id' => $state_user_id])->all(); $role_ids = ""; @@ -206,34 +109,9 @@ class StateUserRolesController extends AppController $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!')); diff --git a/src/Template/StateUserRoles/search.ctp b/src/Template/StateUserRoles/search.ctp index c1234d245..aff7fbbcb 100644 --- a/src/Template/StateUserRoles/search.ctp +++ b/src/Template/StateUserRoles/search.ctp @@ -12,31 +12,6 @@ $this->loadHelper('Form', [ 'templates' => 'horizontal_form', ]); ?> -Html->css([ - 'loginServer/style.css', - 'rippleUI/style.css', - 'materialdesignicons.min.css' -]) ?> -

Benutzer suchen

@@ -76,5 +51,3 @@ $this->loadHelper('Form', [
- - From 7e23b36cbc6959289161ae733723db644206cefe Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 25 Sep 2020 13:56:16 +0000 Subject: [PATCH 17/57] add new gradido proto files and update parse proto script --- parse_proto.sh | 2 +- src/Controller/StateUserRolesController.php | 4 +- .../Proto/Gradido/CrossGroupTransfer.php | 146 +++++++++++++ .../Proto/Gradido/GradidoCreation.php | 102 +++++++++ .../Proto/Gradido/GradidoTransaction.php | 116 +++++++++++ .../Proto/Gradido/GradidoTransfer.php | 109 ++++++++++ .../Proto/Gradido/GroupFriendsUpdate.php | 92 +++++++++ .../Gradido/GroupFriendsUpdate/Action.php | 51 +++++ .../Gradido/GroupFriendsUpdate_Action.php | 16 ++ .../Proto/Gradido/GroupMemberUpdate.php | 146 +++++++++++++ .../GroupMemberUpdate/MemberUpdateType.php | 56 +++++ .../GroupMemberUpdate_MemberUpdateType.php | 16 ++ src/Model/Messages/Proto/Gradido/Key.php | 96 +++++++++ .../Messages/Proto/Gradido/LocalTransfer.php | 85 ++++++++ .../Messages/Proto/Gradido/SignatureMap.php | 65 ++++++ .../Messages/Proto/Gradido/SignaturePair.php | 123 +++++++++++ .../Messages/Proto/Gradido/Timestamp.php | 101 +++++++++ .../Proto/Gradido/TimestampSeconds.php | 67 ++++++ .../Proto/Gradido/TransactionBody.php | 193 ++++++++++++++++++ .../Messages/Proto/Gradido/TransferAmount.php | 85 ++++++++ 20 files changed, 1668 insertions(+), 3 deletions(-) create mode 100644 src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php create mode 100644 src/Model/Messages/Proto/Gradido/GradidoCreation.php create mode 100644 src/Model/Messages/Proto/Gradido/GradidoTransaction.php create mode 100644 src/Model/Messages/Proto/Gradido/GradidoTransfer.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupMemberUpdate.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php create mode 100644 src/Model/Messages/Proto/Gradido/Key.php create mode 100644 src/Model/Messages/Proto/Gradido/LocalTransfer.php create mode 100644 src/Model/Messages/Proto/Gradido/SignatureMap.php create mode 100644 src/Model/Messages/Proto/Gradido/SignaturePair.php create mode 100644 src/Model/Messages/Proto/Gradido/Timestamp.php create mode 100644 src/Model/Messages/Proto/Gradido/TimestampSeconds.php create mode 100644 src/Model/Messages/Proto/Gradido/TransactionBody.php create mode 100644 src/Model/Messages/Proto/Gradido/TransferAmount.php diff --git a/parse_proto.sh b/parse_proto.sh index 576b99691..e6ccb451f 100755 --- a/parse_proto.sh +++ b/parse_proto.sh @@ -16,5 +16,5 @@ #PHP_PLUGIN="$(which grpc_php_plugin)" #protoc --proto_path=./src/protobuf/gradido --php_out=./src/ --grpc_out=./src/ --plugin=protoc-gen-grpc=$PHP_PLUGIN ./src/protobuf/gradido/*.proto -protoc --proto_path=./src/protobuf/gradido --php_out=./src/ ./src/protobuf/gradido/*.proto +protoc --proto_path=./src/protobuf --php_out=./src/Model/Messages ./src/protobuf/gradido/*.proto diff --git a/src/Controller/StateUserRolesController.php b/src/Controller/StateUserRolesController.php index 9f83dc0bc..9238c7ad6 100644 --- a/src/Controller/StateUserRolesController.php +++ b/src/Controller/StateUserRolesController.php @@ -81,9 +81,9 @@ class StateUserRolesController extends AppController // detect states $this->loadModel('Roles'); // foreach ($pubkeySorted as $pubhex => $user) { - foreach($communityUsers as $communityUser) { + foreach($communityUsers as $communityUser) { $finalUser = $communityUser; - $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); + $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); $state_user_id = $communityUser->id; $stateUserRole = $this->StateUserRoles->find('all')->where(['state_user_id' => $state_user_id])->all(); diff --git a/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php b/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php new file mode 100644 index 000000000..781ac8f25 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php @@ -0,0 +1,146 @@ +proto.gradido.CrossGroupTransfer + */ +class CrossGroupTransfer extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + */ + private $sender = null; + /** + * Generated from protobuf field bytes receiver = 2; + */ + private $receiver = ''; + /** + * Generated from protobuf field string other_group = 3; + */ + private $other_group = ''; + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + */ + private $paired_transaction_id = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $sender + * @type string $receiver + * @type string $other_group + * @type \Proto\Gradido\Timestamp $paired_transaction_id + * this matches related OutboundTransfer.paired_transaction_id + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getSender() + { + return $this->sender; + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setSender($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->sender = $var; + + return $this; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @return string + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @param string $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkString($var, False); + $this->receiver = $var; + + return $this; + } + + /** + * Generated from protobuf field string other_group = 3; + * @return string + */ + public function getOtherGroup() + { + return $this->other_group; + } + + /** + * Generated from protobuf field string other_group = 3; + * @param string $var + * @return $this + */ + public function setOtherGroup($var) + { + GPBUtil::checkString($var, True); + $this->other_group = $var; + + return $this; + } + + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + * @return \Proto\Gradido\Timestamp + */ + public function getPairedTransactionId() + { + return $this->paired_transaction_id; + } + + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + * @param \Proto\Gradido\Timestamp $var + * @return $this + */ + public function setPairedTransactionId($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\Timestamp::class); + $this->paired_transaction_id = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GradidoCreation.php b/src/Model/Messages/Proto/Gradido/GradidoCreation.php new file mode 100644 index 000000000..9b4c3208d --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GradidoCreation.php @@ -0,0 +1,102 @@ +proto.gradido.GradidoCreation + */ +class GradidoCreation extends \Google\Protobuf\Internal\Message +{ + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + */ + private $receiver = null; + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + */ + private $target_date = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $receiver + * 40 Byte + * @type \Proto\Gradido\TimestampSeconds $target_date + * 8 Byte + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoCreation::initOnce(); + parent::__construct($data); + } + + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->receiver = $var; + + return $this; + } + + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + * @return \Proto\Gradido\TimestampSeconds + */ + public function getTargetDate() + { + return $this->target_date; + } + + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + * @param \Proto\Gradido\TimestampSeconds $var + * @return $this + */ + public function setTargetDate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TimestampSeconds::class); + $this->target_date = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GradidoTransaction.php b/src/Model/Messages/Proto/Gradido/GradidoTransaction.php new file mode 100644 index 000000000..b4b34c77e --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GradidoTransaction.php @@ -0,0 +1,116 @@ +proto.gradido.GradidoTransaction + */ +class GradidoTransaction extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + */ + private $sig_map = null; + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + */ + private $body_bytes = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\SignatureMap $sig_map + * @type string $body_bytes + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransaction::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + * @return \Proto\Gradido\SignatureMap + */ + public function getSigMap() + { + return $this->sig_map; + } + + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + * @param \Proto\Gradido\SignatureMap $var + * @return $this + */ + public function setSigMap($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\SignatureMap::class); + $this->sig_map = $var; + + return $this; + } + + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + * @return string + */ + public function getBodyBytes() + { + return $this->body_bytes; + } + + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + * @param string $var + * @return $this + */ + public function setBodyBytes($var) + { + GPBUtil::checkString($var, False); + $this->body_bytes = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GradidoTransfer.php b/src/Model/Messages/Proto/Gradido/GradidoTransfer.php new file mode 100644 index 000000000..a76954c2e --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GradidoTransfer.php @@ -0,0 +1,109 @@ +proto.gradido.GradidoTransfer + */ +class GradidoTransfer extends \Google\Protobuf\Internal\Message +{ + protected $data; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\LocalTransfer $local + * @type \Proto\Gradido\CrossGroupTransfer $inbound + * @type \Proto\Gradido\CrossGroupTransfer $outbound + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.LocalTransfer local = 1; + * @return \Proto\Gradido\LocalTransfer + */ + public function getLocal() + { + return $this->readOneof(1); + } + + /** + * Generated from protobuf field .proto.gradido.LocalTransfer local = 1; + * @param \Proto\Gradido\LocalTransfer $var + * @return $this + */ + public function setLocal($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\LocalTransfer::class); + $this->writeOneof(1, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer inbound = 2; + * @return \Proto\Gradido\CrossGroupTransfer + */ + public function getInbound() + { + return $this->readOneof(2); + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer inbound = 2; + * @param \Proto\Gradido\CrossGroupTransfer $var + * @return $this + */ + public function setInbound($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\CrossGroupTransfer::class); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer outbound = 3; + * @return \Proto\Gradido\CrossGroupTransfer + */ + public function getOutbound() + { + return $this->readOneof(3); + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer outbound = 3; + * @param \Proto\Gradido\CrossGroupTransfer $var + * @return $this + */ + public function setOutbound($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\CrossGroupTransfer::class); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getData() + { + return $this->whichOneof("data"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php new file mode 100644 index 000000000..22e86d3e1 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php @@ -0,0 +1,92 @@ +proto.gradido.GroupFriendsUpdate + */ +class GroupFriendsUpdate extends \Google\Protobuf\Internal\Message +{ + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + */ + private $group = ''; + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + */ + private $action = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $group + * char[16], alias + * @type int $action + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GroupFriendsUpdate::initOnce(); + parent::__construct($data); + } + + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + * @return string + */ + public function getGroup() + { + return $this->group; + } + + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + * @param string $var + * @return $this + */ + public function setGroup($var) + { + GPBUtil::checkString($var, True); + $this->group = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + * @return int + */ + public function getAction() + { + return $this->action; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + * @param int $var + * @return $this + */ + public function setAction($var) + { + GPBUtil::checkEnum($var, \Proto\Gradido\GroupFriendsUpdate_Action::class); + $this->action = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php new file mode 100644 index 000000000..2a3396c55 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php @@ -0,0 +1,51 @@ +proto.gradido.GroupFriendsUpdate.Action + */ +class Action +{ + /** + * Generated from protobuf enum ADD_FRIEND = 0; + */ + const ADD_FRIEND = 0; + /** + * Generated from protobuf enum REMOVE_FRIEND = 1; + */ + const REMOVE_FRIEND = 1; + + private static $valueToName = [ + self::ADD_FRIEND => 'ADD_FRIEND', + self::REMOVE_FRIEND => 'REMOVE_FRIEND', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Action::class, \Proto\Gradido\GroupFriendsUpdate_Action::class); + diff --git a/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php new file mode 100644 index 000000000..24f8cef70 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php @@ -0,0 +1,16 @@ +proto.gradido.GroupMemberUpdate + */ +class GroupMemberUpdate extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes user_pubkey = 1; + */ + private $user_pubkey = ''; + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + */ + private $member_update_type = 0; + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + */ + private $paired_transaction_id = null; + /** + * Generated from protobuf field string target_group = 4; + */ + private $target_group = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $user_pubkey + * @type int $member_update_type + * @type \Proto\Gradido\Timestamp $paired_transaction_id + * this only makes sense for user move, TODO: probably restructure + * @type string $target_group + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GroupMemberUpdate::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes user_pubkey = 1; + * @return string + */ + public function getUserPubkey() + { + return $this->user_pubkey; + } + + /** + * Generated from protobuf field bytes user_pubkey = 1; + * @param string $var + * @return $this + */ + public function setUserPubkey($var) + { + GPBUtil::checkString($var, False); + $this->user_pubkey = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + * @return int + */ + public function getMemberUpdateType() + { + return $this->member_update_type; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + * @param int $var + * @return $this + */ + public function setMemberUpdateType($var) + { + GPBUtil::checkEnum($var, \Proto\Gradido\GroupMemberUpdate_MemberUpdateType::class); + $this->member_update_type = $var; + + return $this; + } + + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + * @return \Proto\Gradido\Timestamp + */ + public function getPairedTransactionId() + { + return $this->paired_transaction_id; + } + + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + * @param \Proto\Gradido\Timestamp $var + * @return $this + */ + public function setPairedTransactionId($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\Timestamp::class); + $this->paired_transaction_id = $var; + + return $this; + } + + /** + * Generated from protobuf field string target_group = 4; + * @return string + */ + public function getTargetGroup() + { + return $this->target_group; + } + + /** + * Generated from protobuf field string target_group = 4; + * @param string $var + * @return $this + */ + public function setTargetGroup($var) + { + GPBUtil::checkString($var, True); + $this->target_group = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php new file mode 100644 index 000000000..57580cd75 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php @@ -0,0 +1,56 @@ +proto.gradido.GroupMemberUpdate.MemberUpdateType + */ +class MemberUpdateType +{ + /** + * Generated from protobuf enum ADD_USER = 0; + */ + const ADD_USER = 0; + /** + * Generated from protobuf enum MOVE_USER_INBOUND = 1; + */ + const MOVE_USER_INBOUND = 1; + /** + * Generated from protobuf enum MOVE_USER_OUTBOUND = 2; + */ + const MOVE_USER_OUTBOUND = 2; + + private static $valueToName = [ + self::ADD_USER => 'ADD_USER', + self::MOVE_USER_INBOUND => 'MOVE_USER_INBOUND', + self::MOVE_USER_OUTBOUND => 'MOVE_USER_OUTBOUND', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(MemberUpdateType::class, \Proto\Gradido\GroupMemberUpdate_MemberUpdateType::class); + diff --git a/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php new file mode 100644 index 000000000..b7080cf75 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php @@ -0,0 +1,16 @@ +proto.gradido.Key + */ +class Key extends \Google\Protobuf\Internal\Message +{ + protected $key; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $ed25519 + * ed25519 signature (libsodium default) + * @type string $ed25519_ref10 + * ed25519 ref10 signature + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @return string + */ + public function getEd25519() + { + return $this->readOneof(2); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @param string $var + * @return $this + */ + public function setEd25519($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @return string + */ + public function getEd25519Ref10() + { + return $this->readOneof(3); + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @param string $var + * @return $this + */ + public function setEd25519Ref10($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getKey() + { + return $this->whichOneof("key"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/LocalTransfer.php b/src/Model/Messages/Proto/Gradido/LocalTransfer.php new file mode 100644 index 000000000..58f5e23ae --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/LocalTransfer.php @@ -0,0 +1,85 @@ +proto.gradido.LocalTransfer + */ +class LocalTransfer extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + */ + private $sender = null; + /** + * Generated from protobuf field bytes receiver = 2; + */ + private $receiver = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $sender + * @type string $receiver + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getSender() + { + return $this->sender; + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setSender($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->sender = $var; + + return $this; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @return string + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @param string $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkString($var, False); + $this->receiver = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/SignatureMap.php b/src/Model/Messages/Proto/Gradido/SignatureMap.php new file mode 100644 index 000000000..0977169d7 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/SignatureMap.php @@ -0,0 +1,65 @@ +proto.gradido.SignatureMap + */ +class SignatureMap extends \Google\Protobuf\Internal\Message +{ + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + */ + private $sigPair; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $sigPair + * Each signature pair corresponds to a unique Key required to sign the transaction. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getSigPair() + { + return $this->sigPair; + } + + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + * @param \Proto\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setSigPair($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Proto\Gradido\SignaturePair::class); + $this->sigPair = $arr; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/SignaturePair.php b/src/Model/Messages/Proto/Gradido/SignaturePair.php new file mode 100644 index 000000000..2ef0e81c5 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/SignaturePair.php @@ -0,0 +1,123 @@ +proto.gradido.SignaturePair + */ +class SignaturePair extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes pubKey = 1; + */ + private $pubKey = ''; + protected $signature; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $pubKey + * @type string $ed25519 + * ed25519 signature (libsodium default) + * @type string $ed25519_ref10 + * ed25519 ref10 signature + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes pubKey = 1; + * @return string + */ + public function getPubKey() + { + return $this->pubKey; + } + + /** + * Generated from protobuf field bytes pubKey = 1; + * @param string $var + * @return $this + */ + public function setPubKey($var) + { + GPBUtil::checkString($var, False); + $this->pubKey = $var; + + return $this; + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @return string + */ + public function getEd25519() + { + return $this->readOneof(2); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @param string $var + * @return $this + */ + public function setEd25519($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @return string + */ + public function getEd25519Ref10() + { + return $this->readOneof(3); + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @param string $var + * @return $this + */ + public function setEd25519Ref10($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getSignature() + { + return $this->whichOneof("signature"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/Timestamp.php b/src/Model/Messages/Proto/Gradido/Timestamp.php new file mode 100644 index 000000000..ae3ecea0e --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/Timestamp.php @@ -0,0 +1,101 @@ +proto.gradido.Timestamp + */ +class Timestamp extends \Google\Protobuf\Internal\Message +{ + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + */ + private $seconds = 0; + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + */ + private $nanos = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Number of complete seconds since the start of the epoch + * @type int $nanos + * Number of nanoseconds since the start of the last second + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + * @return int + */ + public function getNanos() + { + return $this->nanos; + } + + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + * @param int $var + * @return $this + */ + public function setNanos($var) + { + GPBUtil::checkInt32($var); + $this->nanos = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/TimestampSeconds.php b/src/Model/Messages/Proto/Gradido/TimestampSeconds.php new file mode 100644 index 000000000..d31aa40d2 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/TimestampSeconds.php @@ -0,0 +1,67 @@ +proto.gradido.TimestampSeconds + */ +class TimestampSeconds extends \Google\Protobuf\Internal\Message +{ + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + */ + private $seconds = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Number of complete seconds since the start of the epoch + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/TransactionBody.php b/src/Model/Messages/Proto/Gradido/TransactionBody.php new file mode 100644 index 000000000..0484ecc92 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/TransactionBody.php @@ -0,0 +1,193 @@ +proto.gradido.TransactionBody + */ +class TransactionBody extends \Google\Protobuf\Internal\Message +{ + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + */ + private $memo = ''; + /** + * Generated from protobuf field uint64 version_number = 6; + */ + private $version_number = 0; + protected $data; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $memo + * max 150 chars + * @type \Proto\Gradido\GradidoTransfer $transfer + * @type \Proto\Gradido\GradidoCreation $creation + * @type \Proto\Gradido\GroupFriendsUpdate $group_friends_update + * @type \Proto\Gradido\GroupMemberUpdate $group_member_update + * @type int|string $version_number + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\TransactionBody::initOnce(); + parent::__construct($data); + } + + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + * @return string + */ + public function getMemo() + { + return $this->memo; + } + + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + * @param string $var + * @return $this + */ + public function setMemo($var) + { + GPBUtil::checkString($var, True); + $this->memo = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 2; + * @return \Proto\Gradido\GradidoTransfer + */ + public function getTransfer() + { + return $this->readOneof(2); + } + + /** + * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 2; + * @param \Proto\Gradido\GradidoTransfer $var + * @return $this + */ + public function setTransfer($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GradidoTransfer::class); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GradidoCreation creation = 3; + * @return \Proto\Gradido\GradidoCreation + */ + public function getCreation() + { + return $this->readOneof(3); + } + + /** + * Generated from protobuf field .proto.gradido.GradidoCreation creation = 3; + * @param \Proto\Gradido\GradidoCreation $var + * @return $this + */ + public function setCreation($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GradidoCreation::class); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 4; + * @return \Proto\Gradido\GroupFriendsUpdate + */ + public function getGroupFriendsUpdate() + { + return $this->readOneof(4); + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 4; + * @param \Proto\Gradido\GroupFriendsUpdate $var + * @return $this + */ + public function setGroupFriendsUpdate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GroupFriendsUpdate::class); + $this->writeOneof(4, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 5; + * @return \Proto\Gradido\GroupMemberUpdate + */ + public function getGroupMemberUpdate() + { + return $this->readOneof(5); + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 5; + * @param \Proto\Gradido\GroupMemberUpdate $var + * @return $this + */ + public function setGroupMemberUpdate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GroupMemberUpdate::class); + $this->writeOneof(5, $var); + + return $this; + } + + /** + * Generated from protobuf field uint64 version_number = 6; + * @return int|string + */ + public function getVersionNumber() + { + return $this->version_number; + } + + /** + * Generated from protobuf field uint64 version_number = 6; + * @param int|string $var + * @return $this + */ + public function setVersionNumber($var) + { + GPBUtil::checkUint64($var); + $this->version_number = $var; + + return $this; + } + + /** + * @return string + */ + public function getData() + { + return $this->whichOneof("data"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/TransferAmount.php b/src/Model/Messages/Proto/Gradido/TransferAmount.php new file mode 100644 index 000000000..7673582fa --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/TransferAmount.php @@ -0,0 +1,85 @@ +proto.gradido.TransferAmount + */ +class TransferAmount extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes pubkey = 1; + */ + private $pubkey = ''; + /** + * Generated from protobuf field sint64 amount = 2; + */ + private $amount = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $pubkey + * @type int|string $amount + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes pubkey = 1; + * @return string + */ + public function getPubkey() + { + return $this->pubkey; + } + + /** + * Generated from protobuf field bytes pubkey = 1; + * @param string $var + * @return $this + */ + public function setPubkey($var) + { + GPBUtil::checkString($var, False); + $this->pubkey = $var; + + return $this; + } + + /** + * Generated from protobuf field sint64 amount = 2; + * @return int|string + */ + public function getAmount() + { + return $this->amount; + } + + /** + * Generated from protobuf field sint64 amount = 2; + * @param int|string $var + * @return $this + */ + public function setAmount($var) + { + GPBUtil::checkInt64($var); + $this->amount = $var; + + return $this; + } + +} + From e6fe7556df9e40ea846689ab966c28b39d0b3478 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Wed, 30 Sep 2020 11:08:02 +0000 Subject: [PATCH 18/57] update logo --- .../Component/JsonRequestClientComponent.php | 38 ++++++++++++++++++ webroot/img/logo_schrift_half.png | Bin 29213 -> 0 bytes webroot/img/logo_schrift_half.webp | Bin 12190 -> 0 bytes 3 files changed, 38 insertions(+) delete mode 100644 webroot/img/logo_schrift_half.png delete mode 100644 webroot/img/logo_schrift_half.webp diff --git a/src/Controller/Component/JsonRequestClientComponent.php b/src/Controller/Component/JsonRequestClientComponent.php index 8a071b70b..4132894eb 100644 --- a/src/Controller/Component/JsonRequestClientComponent.php +++ b/src/Controller/Component/JsonRequestClientComponent.php @@ -41,6 +41,11 @@ class JsonRequestClientComponent extends Component } + public function findePublicKeyForEmailHash($emailHash) { + //'ask' = ['account_publickey' => ''] + $results = $this->sendRequestLoginServerNeighbors(json_encode(['ask' => ['account_publickey' => $emailHash]]), 'search'); + } + public function getRunningUserTasks($email) { if($email == "") { @@ -121,6 +126,39 @@ class JsonRequestClientComponent extends Component return ['state' => 'success', 'data' => $json]; } + public function sendRequestLoginServerNeighbors($transactionBody, $url) { + + $http = new Client(); + if(!Configure::check('NeighborLoginServers')) { + return ['state' => 'warning', 'msg' => 'no neighbor server configured']; + } + $nServers = Configure::read('NeighborLoginServers'); + $results = ['errors' => [], 'data' => []]; + foreach($nServers as $nServer) { + $full_url = $nServer['host'] . ':' . $nServer['port'] . '/' . $url; + $response = $http->post($full_url, $transactionBody, ['type' => 'json']); + $responseStatus = $response->getStatusCode(); + if($responseStatus != 200) { + $results['errors'][] = [ + 'state' => 'error', + 'type' => 'request error', + 'msg' => 'server response status code isn\'t 200', + 'details' => $responseStatus, + 'fullUrl' => $full_url + ]; + continue; + } + $json = $response->getJson(); + if($json == null) { + //$responseType = $response->getType(); + $results['errors'][] = ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t valid json']; + continue; + } + $results['data'][] = $json; + } + return $results; + } + static public function getLoginServerUrl() { $loginServer = Configure::read('LoginServer'); diff --git a/webroot/img/logo_schrift_half.png b/webroot/img/logo_schrift_half.png deleted file mode 100644 index 5dfb1b3ac7d2177302625e3b6e9712a3b822d91f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29213 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 diff --git a/webroot/img/logo_schrift_half.webp b/webroot/img/logo_schrift_half.webp deleted file mode 100644 index fa7d49642b12e5f2cab00716bccd2e6b7dfa2486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12190 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 mw^%0_#DOEU|5@4D@|gUDnkB Date: Mon, 26 Oct 2020 15:01:20 +0000 Subject: [PATCH 19/57] add new logo for desktop --- src/Template/Layout/frontend.ctp | 4 ++-- webroot/img/gradido_logo_web.png | Bin 0 -> 22236 bytes webroot/img/gradido_logo_web.webp | Bin 0 -> 13480 bytes 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 webroot/img/gradido_logo_web.png create mode 100644 webroot/img/gradido_logo_web.webp diff --git a/src/Template/Layout/frontend.ctp b/src/Template/Layout/frontend.ctp index 425073374..cb01fea30 100644 --- a/src/Template/Layout/frontend.ctp +++ b/src/Template/Layout/frontend.ctp @@ -55,8 +55,8 @@ $GLOBALS["self"] = $this; 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 Date: Thu, 29 Oct 2020 11:34:15 +0000 Subject: [PATCH 20/57] update transfer with new protocoL --- .../TransactionSendCoinsController.php | 175 +++++++----------- src/Form/TransferForm.php | 17 +- src/Template/TransactionSendCoins/create.ctp | 1 + 3 files changed, 81 insertions(+), 112 deletions(-) diff --git a/src/Controller/TransactionSendCoinsController.php b/src/Controller/TransactionSendCoinsController.php index c5a738736..90c6dc670 100644 --- a/src/Controller/TransactionSendCoinsController.php +++ b/src/Controller/TransactionSendCoinsController.php @@ -146,10 +146,17 @@ class TransactionSendCoinsController extends AppController } $user = $session->read('StateUser'); } + + $known_groups = $this->JsonRequestClient->sendRequest(json_encode([ + 'ask' => ['groups'] + ]), '/networkInfos'); + $transferForm = new TransferForm(); $this->set('transferForm', $transferForm); $this->set('timeUsed', microtime(true) - $startTime); + $this->set('groups', $known_groups['data']['data']['groups']); + $this->set('user', $user); if ($this->request->is('post')) { //$this->Flash->error(__('Wird zurzeit noch entwickelt!')); @@ -159,134 +166,88 @@ class TransactionSendCoinsController extends AppController if(isset($requestData['add'])) {$mode = 'add'; } if($transferForm->validate($requestData)) { - $receiverPubKeyHex = ''; - $senderPubKeyHex = $user['public_hex']; $amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']); if(!isset($user['balance']) || $amountCent > $user['balance']) { $this->Flash->error(__('Du hast nicht genug Geld!')); return; } - + $receiverEmail = $requestData['email']; if($receiverEmail === $user['email']) { $this->Flash->error(__('Du kannst dir leider nicht selbst Geld schicken!')); return; } - $receiverPubkeyHex =''; $requestAnswear = $this->JsonRequestClient->sendRequest(json_encode([ 'session_id' => $session->read('session_id'), - 'email' => $receiverEmail, - 'ask' => ['user.pubkeyhex', 'user.disabled'] - ]), '/getUserInfos'); + 'transaction_type' => 'transfer', + 'memo' => $requestData['memo'], + 'amount' => $amountCent, + 'target_group' => $known_groups['data']['data']['groups'][$requestData['group']], + 'target_email' => $receiverEmail + ]), '/createTransaction'); + if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) { - // will be allways 64 byte long, even if it is empty - $receiverPubKeyHex = $requestAnswear['data']['userData']['pubkeyhex']; - } else { - $this->addAdminError('TransactionSendCoins', 'create', $requestAnswear, $user['id']); - $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); - $this->set('timeUsed', microtime(true) - $startTime); - return; - } - if(isset($requestAnswear['data']['userData']['disabled']) && $requestAnswear['data']['userData']['disabled']) { - $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); - $this->set('timeUsed', microtime(true) - $startTime); - return; - } - - - if(0 == ord($receiverPubKeyHex)) { - $stateUserTable = TableRegistry::getTableLocator()->get('StateUsers'); - $receiverUser = $stateUserTable - ->find('all') - ->select(['public_key']) - ->contain(false) - ->where(['email' => $receiverEmail]); - - - if(!$receiverUser) { - $this->Flash->error(__('Diese E-Mail ist mir nicht bekannt, hat dein Empfänger denn schon ein Gradido-Konto?')); - $this->set('timeUsed', microtime(true) - $startTime); - return; - } - - if(isset($receiverUser->public_key)) { - $receiverPubKeyHex = bin2hex(stream_get_contents($receiverUser->public_key)); + $pendingTransactionCount = $session->read('Transactions.pending'); + if($pendingTransactionCount == null) { + $pendingTransactionCount = 1; } else { - $this->Flash->error(__('Das Konto mit der E-Mail: ' . $receiverEmail . ' wurde noch nicht aktiviert und kann noch keine GDD empfangen!')); + $pendingTransactionCount++; + } + $session->write('Transactions.pending', $pendingTransactionCount); + //echo "pending: " . $pendingTransactionCount; + if($mode === 'next') { + return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); + } else { + $this->Flash->success(__('Transaction submitted for review.')); + } + } else { + + /* + * if request contain unknown parameter format, shouldn't happen't at all + * {"state": "error", "msg": "parameter format unknown"} + * if json parsing failed + * {"state": "error", "msg": "json exception", "details":"exception text"} + * if session_id is zero or not set + * {"state": "error", "msg": "session_id invalid"} + * if session id wasn't found on login server, if server was restartet or user logged out (also per timeout, default: 15 minutes) + * {"state": "error", "msg": "session not found"} + * if session hasn't active user, shouldn't happen't at all, login-server should be checked if happen + * {"state": "code error", "msg":"user is zero"} + * if transaction type not known + * {"state": "error", "msg":"transaction_type unknown"} + * if receiver wasn't known to Login-Server + * {"state": "not found", "msg":"receiver not found"} + * if receiver account disabled, and therefor cannto receive any coins + * {"state": "disabled", "msg":"receiver is disabled"} + * if transaction was okay and will be further proccessed + * {"state":"success"} + */ + $answear_data = $requestAnswear['data']; + if($answear_data['state'] === 'error') { + if($answear_data['msg'] === 'session_id invalid' || $answear_data['msg'] === 'session not found') { + $this->Flash->error(__('Fehler mit der Session, bitte logge dich erneut ein!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + } else if($answear_data['state'] === 'not found' && $answear_data['msg'] === 'receiver not found') { + $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); $this->set('timeUsed', microtime(true) - $startTime); return; - } + } else if($answear_data['state'] === 'disabled') { + $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else { + $this->Flash->error(__('Unbehandelter Fehler: ') . json_encode($answear_data)); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } } - //var_dump($sessionStateUser); - - $builderResult = TransactionTransfer::build( - $amountCent, - $requestData['memo'], - $receiverPubKeyHex, - $senderPubKeyHex - ); - if($builderResult['state'] === 'success') { - - $http = new Client(); - try { - $loginServer = Configure::read('LoginServer'); - $url = $loginServer['host'] . ':' . $loginServer['port']; - $session_id = $session->read('session_id'); - /* - * - * $response = $http->post( - * 'http://example.com/tasks', - * json_encode($data), - * ['type' => 'json'] - * ); - */ - $response = $http->post($url . '/checkTransaction', json_encode([ - 'session_id' => $session_id, - 'transaction_base64' => base64_encode($builderResult['transactionBody']->serializeToString()), - 'balance' => $user['balance'] - ]), ['type' => 'json']); - $json = $response->getJson(); - if($json['state'] != 'success') { - if($json['msg'] == 'session not found') { - $session->destroy(); - return $this->redirect($this->loginServerUrl . 'account', 303); - //$this->Flash->error(__('session not found, please login again')); - } else { - $this->Flash->error(__('login server return error: ' . json_encode($json))); - } - } else { - $pendingTransactionCount = $session->read('Transactions.pending'); - if($pendingTransactionCount == null) { - $pendingTransactionCount = 1; - } else { - $pendingTransactionCount++; - } - $session->write('Transactions.pending', $pendingTransactionCount); - //echo "pending: " . $pendingTransactionCount; - if($mode === 'next') { - return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); - } else { - $this->Flash->success(__('Transaction submitted for review.')); - } - } - - } catch(\Exception $e) { - $msg = $e->getMessage(); - $this->Flash->error(__('error http request: ') . $msg); - } - - } else { - $this->Flash->error(__('No Valid Receiver Public given: ' . $receiverPubKeyHex)); - } - -// */ - } else { - $this->Flash->error(__('Something was invalid, please try again!')); } } - + $this->set('timeUsed', microtime(true) - $startTime); } diff --git a/src/Form/TransferForm.php b/src/Form/TransferForm.php index 5572ddaf9..cb135ab9e 100644 --- a/src/Form/TransferForm.php +++ b/src/Form/TransferForm.php @@ -1,5 +1,5 @@ -addField('email', ['type' => 'string']) + ->addField('group', ['type' => 'string']) ->addField('amount', ['type' => 'decimal', 'precision' => 2]) ->addField('memo', ['type' =>'text', 'default' => '', 'rows' => 3, 'maxlength' => 150]); } function validationDefault(Validator $validator) { - $validator->setProvider('custom', 'App\Model\Validation\TransactionValidation'); + $validator->setProvider('custom', 'App\Model\Validation\TransactionValidation'); /* $validator->add('receiver_pubkey_hex', 'length', [ 'rule' => ['length', 64], @@ -34,6 +35,12 @@ class TransferForm extends Form 'rule' => 'email', 'message' => __('A valid email address is required') ]) + ->add('group', 'custom', [ + 'rule' => 'alphaNumeric', + 'provider' => 'custom', + //'message' => __('Only Alpha Numeric Character allowed') + 'message' => __('No HTML Tags like > or < please.') + ]) ->add('memo', 'length', [ 'rule' => ['maxLength', 150], 'message' => __('The memo should contain max 150 character') @@ -54,7 +61,7 @@ class TransferForm extends Form ->allowEmptyString('receiver_pubkey_hex', null, 'create')*/ ->add('amount', 'custom', [ 'rule' => 'amount', - 'provider' => 'custom', + 'provider' => 'custom', 'message' => __('Please give a valid positive number with maximal 2 decimal places') ]); return $validator; @@ -72,4 +79,4 @@ class TransferForm extends Form // Send an email. return true; } -} +} \ No newline at end of file diff --git a/src/Template/TransactionSendCoins/create.ctp b/src/Template/TransactionSendCoins/create.ctp index 9b578d0c9..91e7678e0 100644 --- a/src/Template/TransactionSendCoins/create.ctp +++ b/src/Template/TransactionSendCoins/create.ctp @@ -17,6 +17,7 @@ $this->loadHelper('Form', [
Form->create($transferForm) ?> Form->control('email', ['label' => __('Empfänger'), 'placeholder' => 'E-Mail']) ?> + Form->control('group', ['label' => __('Community Alias'), 'options' => $groups, 'default' => $user['group_alias']]) ?> Form->control('memo', ['label' => __('Verwendungszweck'), 'rows' => 3]) ?> Form->control('amount', ['label' => __('Betrag in GDD')]) ?> Form->button(__('Transaktion abschließen'), ['name' => 'next', 'class' => 'form-button']) ?> From 23492e97bb7f21a186959f2f72bae308093c8dbb Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Mon, 2 Nov 2020 15:51:37 +0000 Subject: [PATCH 21/57] update pending tasks, creation and transfer --- .../insert/insert_transaction_types.sql | 10 +- .../gradido_community/transaction_types.sql | 2 +- src/Controller/AppController.php | 11 +- .../JsonRequestHandlerController.php | 37 ++++- .../TransactionCreationsController.php | 154 +++++++++++------- .../TransactionSendCoinsController.php | 5 + src/Template/Element/navi_notify.ctp | 21 ++- 7 files changed, 160 insertions(+), 80 deletions(-) diff --git a/skeema/gradido_community/insert/insert_transaction_types.sql b/skeema/gradido_community/insert/insert_transaction_types.sql index 9dbf5b93f..7cc2ebfdd 100644 --- a/skeema/gradido_community/insert/insert_transaction_types.sql +++ b/skeema/gradido_community/insert/insert_transaction_types.sql @@ -1,5 +1,9 @@ - INSERT INTO `transaction_types` (`id`, `name`, `text`) VALUES -(1, 'creation', 'Aktives oder Bedingungsloses Grundeinkommen.'), -(2, 'transfer', 'Einfache Überweisung'); +(1, 'group create', 'create a new group, trigger creation of new hedera topic and new blockchain on node server'), +(2, 'group add member', 'add user to a group or move if he was already in a group'), +(3, 'creation', 'create new gradidos for member and also for group (in development)'), +(4, 'transfer', 'send gradidos from one member to another, also cross group transfer'), +(5, 'hedera topic create', 'create new topic on hedera'), +(6, 'hedera topic send message', 'send consensus message over hedera topic'), +(7, 'hedera account create', 'create new account on hedera for holding some founds with unencrypted keys'); diff --git a/skeema/gradido_community/transaction_types.sql b/skeema/gradido_community/transaction_types.sql index 87492e1fe..a3e6779d9 100644 --- a/skeema/gradido_community/transaction_types.sql +++ b/skeema/gradido_community/transaction_types.sql @@ -1,6 +1,6 @@ CREATE TABLE `transaction_types` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(24) COLLATE utf8mb4_unicode_ci NOT NULL, + `name` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL, `text` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 87ec7afb3..258ee565d 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -129,6 +129,7 @@ class AppController extends Controller if ($this->Auth->user('id')) { $GLOBALS['ServerUser'] = $this->Auth->user(); } + // login server url $loginServer = Configure::read('LoginServer'); if ($loginServer && isset($loginServer['url'])) { @@ -159,12 +160,14 @@ class AppController extends Controller $userStored = $session->read('StateUser'); $transactionPendings = $session->read('Transaction.pending'); - $transactionExecutings = $session->read('Transaction.executing'); + $transactionExecutings = $session->read('Transaction.executing'); + $transaction_can_signed = $session->read('Transaction.can_signed'); if ($session->read('session_id') != $session_id || ( $userStored && (!isset($userStored['id']) || !$userStored['email_checked'])) || intval($transactionPendings) > 0 || - intval($transactionExecutings) > 0) { + intval($transactionExecutings) > 0 || + intval($transaction_can_signed > 0)) { $http = new Client(); try { @@ -188,9 +191,11 @@ class AppController extends Controller //var_dump($json); $transactionPendings = $json['Transaction.pending']; $transactionExecuting = $json['Transaction.executing']; + $transaction_can_signed = $json['Transaction.can_signed']; //echo "read transaction pending: $transactionPendings
"; $session->write('Transaction.pending', $transactionPendings); $session->write('Transaction.executing', $transactionExecuting); + $session->write('Transaction.can_signed', $transaction_can_signed); $session->write('session_id', $session_id); $stateUserTable = TableRegistry::getTableLocator()->get('StateUsers'); @@ -204,7 +209,7 @@ class AppController extends Controller $stateUser = $stateUserQuery->first(); if ($stateUser->first_name != $json['user']['first_name'] || $stateUser->last_name != $json['user']['last_name'] || - $stateUser->disabled != intval($json['user']['disabled']) || + $stateUser->disabled != $json['user']['disabled'] || //$stateUser->username != $json['user']['username'] || // -> throws error $stateUser->email != $json['user']['email'] diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index 76bff2324..a0a0748c5 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,7 +58,7 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); - case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionGenericHash, $jsonData->error, $jsonData->errorMessage); + case 'errorInTransaction': return $this->errorInTransaction($jsonData); } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } @@ -71,16 +71,45 @@ class JsonRequestHandlerController extends AppController { //! using sodium_crypto_generichash to calculate // hash also in base64 format //! \param $error short error name in user language - //! \param $errorDetails more detailed error message in user language - private function errorInTransaction($transactionCreated, $transactionBodyBase64GenericHash, $error, $errorDetails) { + //! \param $errorDetails more detailed error message in user language + private function errorInTransaction($jsonData) { /* * payload.set("created", created); * payload.set("id", task_model->getID()); + * payload.set("type", task_model->getTaskTypeString()); * payload.set("public_key", user_model->getPublicKeyHex()); * payload.set("error", error); * payload.set("errorMessage", errorDetails); */ - + $stateErrorTable = TableRegistry::getTableLocator()->get('StateErrors'); + $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); + $transactionTypesTable = TableRegistry::getTableLocator()->get('TransactionTypes'); + $stateError = $stateErrorTable->newEntity(); + // + $pubkey = hex2bin($jsonData->public_key); + $user_query = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $pubkey]); + if($user_query->count() != 1) { + return $this->returnJson(['state' => 'error', 'msg' => 'user not found', 'details' => 'user pubkey hex:' . $jsonData->public_key]); + } + $stateError->state_user_id = $user_query->first()->id; + //$stateError->transaction_type_id + // TODO: + // - show state errors in navi_notify.ctp + $transaction_type_query = $transactionTypesTable->find('all')->select(['id'])->where(['name' => $jsonData->type]); + if($transaction_type_query->count() != 1) { + return $this->returnJson(['state' => 'error', 'msg' => 'transaction type not found', 'details' => 'transaction type name: ' . $jsonData->type]); + } + $stateError->transaction_type_id = $transaction_type_query->first()->id; + $stateError->created = $jsonData->created; + $stateError->message_json = json_encode(['task_id' => $jsonData->id, 'error' => $jsonData->error, 'errorMessage' => $jsonData->errorMessage]); + if(!$stateErrorTable->save($stateError)) { + $this->returnJsonSaveError($stateError, [ + 'state' => 'error', + 'msg' => 'error saving state_error in db', + 'details' => json_encode($stateError->getErrors()) + ]); + } + return $this->returnJson(['state' => 'success']); } private function putTransaction($transactionBase64) { diff --git a/src/Controller/TransactionCreationsController.php b/src/Controller/TransactionCreationsController.php index 5e29a7997..5acfce2d7 100644 --- a/src/Controller/TransactionCreationsController.php +++ b/src/Controller/TransactionCreationsController.php @@ -335,6 +335,7 @@ class TransactionCreationsController extends AppController if (isset($requestData['add'])) { $mode = 'add'; } + //echo "mode: $mode
"; $memo = $requestData['memo']; $amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']); //$targetDate = $requestData['target_date']; @@ -342,17 +343,20 @@ class TransactionCreationsController extends AppController $this->Flash->error(__('No user selected')); } else { $users = $requestData['user']; + $pendingTransactionCount = $session->read('Transactions.pending'); + if ($pendingTransactionCount == null) { + $pendingTransactionCount = 0; + } if (isset($requestData['user_pending'])) { $pendings = $requestData['user_pending']; } else { $pendings = []; } - $receiverUsers = $stateUserTable - ->find('all') - ->where(['id IN' => array_keys($users)]) - ->select(['public_key', 'email', 'id']) - ->contain(false); - $transactions = []; + $receiverUsers = $stateUserTable->find('all') + ->where(['id IN' => array_keys($users)]) + ->select(['public_key', 'email', 'id']) + ->contain(false); + foreach ($receiverUsers as $receiverUser) { $localAmountCent = $amountCent; //$localTargetDate = $targetDate; @@ -369,25 +373,87 @@ class TransactionCreationsController extends AppController $pendings[$id] = $localAmountCent; } $pubKeyHex = bin2hex(stream_get_contents($receiverUser->public_key)); - $identHash = TransactionCreation::DRMakeStringHash($receiverUser->email); + $localTargetDateFrozen = FrozenDate::now(); $localTargetDateFrozen = $localTargetDateFrozen - ->year($localTargetDate['year']) - ->month($localTargetDate['month']) - ->day($localTargetDate['day']); - //echo "input: "; var_dump($localTargetDate);echo "
"; - //echo "output: "; var_dump($localTargetDateFrozen); - //die('a'); - $builderResult = TransactionCreation::build( - $localAmountCent, - $memo, - $pubKeyHex, - $identHash, - $localTargetDateFrozen - ); - if ($builderResult['state'] == 'success') { - array_push($transactions, base64_encode($builderResult['transactionBody']->serializeToString())); + ->year($localTargetDate['year']) + ->month($localTargetDate['month']) + ->day($localTargetDate['day']); + + $requestAnswear = $this->JsonRequestClient->sendRequest(json_encode([ + 'session_id' => $session->read('session_id'), + 'transaction_type' => 'creation', + 'memo' => $memo, + 'amount' => $localAmountCent, + 'target_pubkey' => $pubKeyHex, + 'target_date' => $localTargetDateFrozen + ]), '/createTransaction'); + + if('success' != $requestAnswear['state']) { + $this->addAdminError('TransactionCreations', 'createMulti', $requestAnswear, $user['id']); + if ($requestResult['type'] == 'request error') { + $this->Flash->error(__('Error by requesting LoginServer, please try again')); + } else { + $this->Flash->error(__('Error, please wait for the admin to fix it')); + } } + if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) { + $pendingTransactionCount++; + //echo "pending transaction count: $pendingTransactionCount
"; + } else { + /* + * if request contain unknown parameter format, shouldn't happen't at all + * {"state": "error", "msg": "parameter format unknown"} + * if json parsing failed + * {"state": "error", "msg": "json exception", "details":"exception text"} + * if session_id is zero or not set + * {"state": "error", "msg": "session_id invalid"} + * if session id wasn't found on login server, if server was restartet or user logged out (also per timeout, default: 15 minutes) + * {"state": "error", "msg": "session not found"} + * if session hasn't active user, shouldn't happen't at all, login-server should be checked if happen + * {"state": "code error", "msg":"user is zero"} + * if transaction type not known + * {"state": "error", "msg":"transaction_type unknown"} + * if receiver wasn't known to Login-Server + * {"state": "not found", "msg":"receiver not found"} + * if receiver account disabled, and therefor cannto receive any coins + * {"state": "disabled", "msg":"receiver is disabled"} + * if amount is invalid in creation + * {"state": "invalid parameter", "msg":"invalid amount", "details":"GDD amount in GDD cent ]0,10000000]"} + * if transaction was okay and will be further proccessed + * {"state":"success"} + */ + $answear_data = $requestAnswear['data']; + if($answear_data['state'] === 'error') { + if($answear_data['msg'] === 'session_id invalid' || $answear_data['msg'] === 'session not found') { + $this->Flash->error(__('Fehler mit der Session, bitte logge dich erneut ein!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + if($answear_data['msg'] === 'user not in group') { + $this->Flash->error(__('Fehler, Benutzer gehört zu einer anderen Gruppe!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + } else if($answear_data['state'] === 'not found' && $answear_data['msg'] === 'receiver not found') { + $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else if($answear_data['state'] === 'disabled') { + $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else if($answear_data['msg'] === 'invalid amount') { + $this->Flash->error(__('Der Betrag ist ungültig, er muss größer als 0 und <= 1000 sein.')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else { + $this->Flash->error(__('Unbehandelter Fehler: ') . json_encode($answear_data)); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + } + } /*echo "pendings: "; var_dump($pendings); @@ -399,49 +465,17 @@ class TransactionCreationsController extends AppController } } $this->set('possibleReceivers', $possibleReceivers); - $creationTransactionCount = count($transactions); - if ($creationTransactionCount > 0) { + if ($pendingTransactionCount > 0) { $user_balance = 0; if (isset($user['balance'])) { $user_balance = $user['balance']; } - // $session_id, $base64Message, $user_balance = 0 - $requestResult = $this->JsonRequestClient->sendTransaction( - $session->read('session_id'), - $transactions, - $user_balance - ); - if ($requestResult['state'] != 'success') { - $this->addAdminError('TransactionCreations', 'createMulti', $requestResult, $user['id']); - if ($requestResult['type'] == 'request error') { - $this->Flash->error(__('Error by requesting LoginServer, please try again')); - } else { - $this->Flash->error(__('Error, please wait for the admin to fix it')); - } + $session->write('Transactions.pending', $pendingTransactionCount); + + if ($mode === 'next') { + return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); } else { - $json = $requestResult['data']; - if ($json['state'] != 'success') { - if ($json['msg'] == 'session not found') { - $session->destroy(); - return $this->redirect($this->loginServerUrl . 'account', 303); - } else { - $this->addAdminError('TransactionCreations', 'createMulti', $json, $user['id']); - $this->Flash->error(__('Login Server Error, please wait for the admin to fix it')); - } - } else { - $pendingTransactionCount = $session->read('Transactions.pending'); - if ($pendingTransactionCount == null) { - $pendingTransactionCount = $creationTransactionCount; - } else { - $pendingTransactionCount += $creationTransactionCount; - } - $session->write('Transactions.pending', $pendingTransactionCount); - if ($mode === 'next') { - return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); - } else { - $this->Flash->success(__('Transaction submitted for review.')); - } - } + $this->Flash->success(__('Transaction submitted for review.')); } } } diff --git a/src/Controller/TransactionSendCoinsController.php b/src/Controller/TransactionSendCoinsController.php index 90c6dc670..39d1eea1b 100644 --- a/src/Controller/TransactionSendCoinsController.php +++ b/src/Controller/TransactionSendCoinsController.php @@ -230,6 +230,11 @@ class TransactionSendCoinsController extends AppController $this->set('timeUsed', microtime(true) - $startTime); return; } + if($answear_data['msg'] === 'user not in group') { + $this->Flash->error(__('Empfänger befindet sich nicht in Zielgruppe!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } } else if($answear_data['state'] === 'not found' && $answear_data['msg'] === 'receiver not found') { $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); $this->set('timeUsed', microtime(true) - $startTime); diff --git a/src/Template/Element/navi_notify.ctp b/src/Template/Element/navi_notify.ctp index 35687687d..61e6cdd5b 100644 --- a/src/Template/Element/navi_notify.ctp +++ b/src/Template/Element/navi_notify.ctp @@ -11,6 +11,7 @@ use Cake\Routing\Router; $session = $this->getRequest()->getSession(); $errorCount = intval($session->read('StateUser.errorCount')); $transactionPendings = $session->read('Transactions.pending'); +$transactionPendings += $session->read('Transaction.can_signed'); /* class NavHeaderEntry @@ -23,19 +24,21 @@ class NavHeaderEntry } */ ?> + 0) : ?> + Html->link( + 'announcement' + . 'ss', + ['controller' => 'StateErrors', 'action' => 'ShowForUser'], + ['class' => 'nav-link', 'escape' => false, 'title' => "$errorCount " . __('Fehler')]) ?> + 0) : ?> -
" href="account/checkTransactions"> - verified_user + " href="account/checkTransactions"> + verified_user - + () + - 0) : ?> - Html->link( - 'announcement', - ['controller' => 'StateErrors', 'action' => 'ShowForUser'], - ['class' => 'notify-link', 'escape' => false, 'title' => "$errorCount " . __('Fehler')]) ?> - From 01f0bd5323a3131790cbab2211ff7b68b4b621f2 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Thu, 5 Nov 2020 16:06:39 +0000 Subject: [PATCH 22/57] add login server manage links to dashboard --- .../JsonRequestHandlerController.php | 25 +++++++---- src/Template/Dashboard/index.ctp | 42 +++++++++++-------- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index a0a0748c5..84a9c4b92 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -59,12 +59,27 @@ class JsonRequestHandlerController extends AppController { case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); case 'errorInTransaction': return $this->errorInTransaction($jsonData); + case 'updateReadNode': return $this->updateReadNode(); } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } return $this->returnJson(['state' => 'error', 'msg' => 'no post or get']); } - + + // Called from login server like a cron job every 10 minutes or after sending transaction to hedera + private function updateReadNode() + { + return $this->returnJson(['state' => 'success']); + } + + /* + * payload.set("created", created); + * payload.set("id", task_model->getID()); + * payload.set("type", task_model->getTaskTypeString()); + * payload.set("public_key", user_model->getPublicKeyHex()); + * payload.set("error", error); + * payload.set("errorMessage", errorDetails); + */ //! \param $transactionCreated creation of transaction in timestamp in seconds //! -1 if transaction couldn't decode //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 @@ -73,14 +88,6 @@ class JsonRequestHandlerController extends AppController { //! \param $error short error name in user language //! \param $errorDetails more detailed error message in user language private function errorInTransaction($jsonData) { - /* - * payload.set("created", created); - * payload.set("id", task_model->getID()); - * payload.set("type", task_model->getTaskTypeString()); - * payload.set("public_key", user_model->getPublicKeyHex()); - * payload.set("error", error); - * payload.set("errorMessage", errorDetails); - */ $stateErrorTable = TableRegistry::getTableLocator()->get('StateErrors'); $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); $transactionTypesTable = TableRegistry::getTableLocator()->get('TransactionTypes'); diff --git a/src/Template/Dashboard/index.ctp b/src/Template/Dashboard/index.ctp index 095234222..fdfe5b072 100644 --- a/src/Template/Dashboard/index.ctp +++ b/src/Template/Dashboard/index.ctp @@ -53,9 +53,8 @@ $this->assign(
redeem - Html->link( - __('schöpfen'), + __('viele schöpfen'), ['controller' => 'TransactionCreations', 'action' => 'createMulti'], ['class' => 'action-button-link'] );?> @@ -63,7 +62,7 @@ $this->assign(
-

Statistik

+ Statistik
cached @@ -112,24 +111,33 @@ $this->assign(
-

Roles ...

+

Login Server ...

- roles - Html->link( - __('View'), - ['controller' => 'Roles', 'action' => 'index'], - ['class' => 'info-item-link'] - ); ?> + groups + + +
- assign_roles - Html->link( - __('Assign Roles'), - ['controller' => 'StateUserRoles', 'action' => 'search'], - ['class' => 'info-item-link'] - ); ?> + servers + + + +
+
+ topics + + + +
+
+
+
+ hedera_accounts + + +
-
From bd6640388d623baa1d1d57e1b9867e5331b83119 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 6 Nov 2020 14:10:38 +0000 Subject: [PATCH 23/57] finish parsing transactions from gradido node --- skeema/gradido_community/address_types.sql | 7 + .../insert/address_types.sql | 2 + .../insert/insert_transaction_types.sql | 15 +- .../state_group_addresses.sql | 3 +- .../transaction_group_addaddress.sql | 1 + .../transaction_send_coins.sql | 5 +- src/Controller/AddressTypesController.php | 5 +- .../JsonRpcRequestClientComponent.php | 13 +- src/Controller/ErrorController.php | 2 +- .../JsonRequestHandlerController.php | 41 ++ src/Controller/StateBalancesController.php | 8 +- src/Model/Entity/AddressType.php | 4 +- .../Entity/TransactionGroupAddaddres.php | 1 + src/Model/Table/AddressTypesTable.php | 11 +- src/Model/Transactions/Record.php | 471 ++++++++++++++++++ src/Template/AddressTypes/add.ctp | 4 +- src/Template/AddressTypes/edit.ctp | 4 +- src/Template/AddressTypes/index.ctp | 8 +- src/Template/AddressTypes/view.ctp | 10 +- src/Template/StateBalances/overview.ctp | 4 +- tests/Fixture/AddressTypesFixture.php | 12 +- 21 files changed, 586 insertions(+), 45 deletions(-) create mode 100644 skeema/gradido_community/address_types.sql create mode 100644 skeema/gradido_community/insert/address_types.sql create mode 100644 src/Model/Transactions/Record.php diff --git a/skeema/gradido_community/address_types.sql b/skeema/gradido_community/address_types.sql new file mode 100644 index 000000000..cb5b1b943 --- /dev/null +++ b/skeema/gradido_community/address_types.sql @@ -0,0 +1,7 @@ +CREATE TABLE `address_types` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL, + `text` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + diff --git a/skeema/gradido_community/insert/address_types.sql b/skeema/gradido_community/insert/address_types.sql new file mode 100644 index 000000000..2a6dc00a5 --- /dev/null +++ b/skeema/gradido_community/insert/address_types.sql @@ -0,0 +1,2 @@ +INSERT INTO `address_types` (`id`, `name`, `text`) VALUES +(1, 'user main', 'user main address'); diff --git a/skeema/gradido_community/insert/insert_transaction_types.sql b/skeema/gradido_community/insert/insert_transaction_types.sql index 7cc2ebfdd..02ef8374a 100644 --- a/skeema/gradido_community/insert/insert_transaction_types.sql +++ b/skeema/gradido_community/insert/insert_transaction_types.sql @@ -1,9 +1,10 @@ INSERT INTO `transaction_types` (`id`, `name`, `text`) VALUES -(1, 'group create', 'create a new group, trigger creation of new hedera topic and new blockchain on node server'), -(2, 'group add member', 'add user to a group or move if he was already in a group'), -(3, 'creation', 'create new gradidos for member and also for group (in development)'), -(4, 'transfer', 'send gradidos from one member to another, also cross group transfer'), -(5, 'hedera topic create', 'create new topic on hedera'), -(6, 'hedera topic send message', 'send consensus message over hedera topic'), -(7, 'hedera account create', 'create new account on hedera for holding some founds with unencrypted keys'); +(1, 'creation', 'create new gradidos for member and also for group (in development)'), +(2, 'transfer', 'send gradidos from one member to another, also cross group transfer'), +(3, 'group create', 'create a new group, trigger creation of new hedera topic and new blockchain on node server'), +(4, 'group add member', 'add user to a group or move if he was already in a group'), +(5, 'group remove member', 'remove user from group, maybe he was moved elsewhere'), +(6, 'hedera topic create', 'create new topic on hedera'), +(7, 'hedera topic send message', 'send consensus message over hedera topic'), +(8, 'hedera account create', 'create new account on hedera for holding some founds with unencrypted keys'); diff --git a/skeema/gradido_community/state_group_addresses.sql b/skeema/gradido_community/state_group_addresses.sql index 1d256f3e0..698a79b98 100644 --- a/skeema/gradido_community/state_group_addresses.sql +++ b/skeema/gradido_community/state_group_addresses.sql @@ -3,5 +3,6 @@ CREATE TABLE `state_group_addresses` ( `group_id` int(10) unsigned NOT NULL, `public_key` binary(32) NOT NULL, `address_type_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + UNIQUE(`public_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/skeema/gradido_community/transaction_group_addaddress.sql b/skeema/gradido_community/transaction_group_addaddress.sql index dceac273c..b9ca95651 100644 --- a/skeema/gradido_community/transaction_group_addaddress.sql +++ b/skeema/gradido_community/transaction_group_addaddress.sql @@ -2,6 +2,7 @@ CREATE TABLE `transaction_group_addaddress` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `transaction_id` int(10) unsigned NOT NULL, `address_type_id` int(10) unsigned NOT NULL, + `remove_from_group` BOOLEAN DEFAULT FALSE, `public_key` binary(32) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/skeema/gradido_community/transaction_send_coins.sql b/skeema/gradido_community/transaction_send_coins.sql index f57a2175e..49423fdbc 100644 --- a/skeema/gradido_community/transaction_send_coins.sql +++ b/skeema/gradido_community/transaction_send_coins.sql @@ -1,9 +1,10 @@ CREATE TABLE `transaction_send_coins` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `transaction_id` int(10) unsigned NOT NULL, - `state_user_id` int(10) unsigned NOT NULL, + `sender_public_key` binary(32) NOT NULL, + `state_user_id` int(10) unsigned DEFAULT 0, `receiver_public_key` binary(32) NOT NULL, - `receiver_user_id` int(10) unsigned NOT NULL, + `receiver_user_id` int(10) unsigned DEFAULT 0, `amount` bigint(20) NOT NULL, `sender_final_balance` bigint(20) NOT NULL, PRIMARY KEY (`id`) diff --git a/src/Controller/AddressTypesController.php b/src/Controller/AddressTypesController.php index 348a8e9e6..9b13a7720 100644 --- a/src/Controller/AddressTypesController.php +++ b/src/Controller/AddressTypesController.php @@ -2,7 +2,6 @@ namespace App\Controller; use App\Controller\AppController; -use Cake\I18n\Number; /** * AddressTypes Controller @@ -35,7 +34,7 @@ class AddressTypesController extends AppController public function view($id = null) { $addressType = $this->AddressTypes->get($id, [ - 'contain' => ['StateGroupAddresses', 'TransactionGroupAddaddress'] + 'contain' => ['StateGroupAddresses', 'TransactionGroupAddaddress'], ]); $this->set('addressType', $addressType); @@ -71,7 +70,7 @@ class AddressTypesController extends AppController public function edit($id = null) { $addressType = $this->AddressTypes->get($id, [ - 'contain' => [] + 'contain' => [], ]); if ($this->request->is(['patch', 'post', 'put'])) { $addressType = $this->AddressTypes->patchEntity($addressType, $this->request->getData()); diff --git a/src/Controller/Component/JsonRpcRequestClientComponent.php b/src/Controller/Component/JsonRpcRequestClientComponent.php index d5ca72808..980a64e8d 100644 --- a/src/Controller/Component/JsonRpcRequestClientComponent.php +++ b/src/Controller/Component/JsonRpcRequestClientComponent.php @@ -41,7 +41,11 @@ class JsonRpcRequestClientComponent extends Component public function sendRequest($message) { $http = new Client(); - $response = $http->post($this->getGradidoNodeUrl(), $message, ['type' => 'json']); + try { + $response = $http->post($this->pickGradidoNodeUrl(), $message, ['type' => 'json']); + } catch(Exception $e) { + return ['state' => 'error', 'type' => 'http exception', 'details' => $e->getMessage()]; + } $responseStatus = $response->getStatusCode(); if($responseStatus != 200) { return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response status code isn\'t 200', 'details' => $responseStatus]; @@ -59,10 +63,11 @@ class JsonRpcRequestClientComponent extends Component //return ['state' => 'success', 'data' => $json]; } - static public function getGradidoNodeUrl() + static public function pickGradidoNodeUrl() { - $gradidoNode = Configure::read('GradidoNode'); - return $gradidoNode['host'] . ':' . $gradidoNode['port']; + $gradidoNodes = Configure::read('GradidoNode'); + $i = rand(0, count($gradidoNodes)-1); + return $gradidoNodes[$i]['host'] . ':' . $gradidoNodes[$i]['port']; } diff --git a/src/Controller/ErrorController.php b/src/Controller/ErrorController.php index 43bd2fb52..c5421a24d 100644 --- a/src/Controller/ErrorController.php +++ b/src/Controller/ErrorController.php @@ -54,7 +54,7 @@ class ErrorController extends AppController public function beforeRender(Event $event) { parent::beforeRender($event); - + $this->RequestHandler->renderAs($this, 'json'); $this->viewBuilder()->setTemplatePath('Error'); } diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index 84a9c4b92..928559d7b 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -10,6 +10,7 @@ use Cake\Core\Configure; use Model\Transactions\TransactionTransfer; use Model\Transactions\Transaction; +use Model\Transactions\Record; /*! * @author: Dario Rekowski# * @@ -24,6 +25,7 @@ class JsonRequestHandlerController extends AppController { { parent::initialize(); $this->loadComponent('JsonRequestClient'); + $this->loadComponent('JsonRpcRequestClient'); //$this->Auth->allow(['add', 'edit']); $this->Auth->allow('index'); } @@ -69,6 +71,45 @@ class JsonRequestHandlerController extends AppController { // Called from login server like a cron job every 10 minutes or after sending transaction to hedera private function updateReadNode() { + $this->autoRender = false; + $response = $this->response->withType('application/json'); + + $transactionsTable = TableRegistry::getTableLocator()->get('Transactions'); + $last_transaction = $transactionsTable->find('all')->order(['id' => 'DESC'])->first(); + $group_alias = Configure::read('GroupAlias'); + $result = $this->JsonRpcRequestClient->request('getTransactions', ['groupAlias' => $group_alias, 'lastKnownSequenceNumber' => $last_transaction->id]); + if(isset($result['state']) && $result['state'] == 'error') { + return $this->returnJson(['state' => 'error', 'msg' => 'jsonrpc error', 'details' => $result]); + } + $part_count = -1; + $temp_record = new Record; + $errors = []; + foreach($result as $_record) { + $parse_result = $temp_record->parseRecord($_record); + if($parse_result == true) { + $sequenceNumber = $temp_record->getSequenceNumber(); + if($part_count == -1) { + $part_count = $temp_record->getPartCount(); + } + $part_count--; + + if($part_count == 0) { + $finalize_result = $temp_record->finalize(); + if($finalize_result != true) { + $errors[] = ['msg' => 'error in finalize', 'record' => $_record, 'details' => $finalize_result, 'sequenceNumber' => $sequenceNumber]; + } + $temp_record = new Record; + $part_count = -1; + } + } else { + $temp_record = new Record; + $part_count = -1; + $errors[] = ['msg' => 'error in parse record', 'record' => $_record, 'details' => $parse_result]; + } + } + if(count($errors)) { + return $this->returnJson(['state' => 'error', 'msg' => 'error in parsing records', 'details' => $errors]); + } return $this->returnJson(['state' => 'success']); } diff --git a/src/Controller/StateBalancesController.php b/src/Controller/StateBalancesController.php index bddf35125..2436d83d3 100644 --- a/src/Controller/StateBalancesController.php +++ b/src/Controller/StateBalancesController.php @@ -170,17 +170,22 @@ class StateBalancesController extends AppController foreach ($transferTransactions as $sendCoins) { $type = ''; $otherUser = null; + $other_user_public = ''; if ($sendCoins->state_user_id == $user['id']) { $type = 'send'; if(isset($involvedUserIndices[$sendCoins->receiver_user_id])) { $otherUser = $involvedUserIndices[$sendCoins->receiver_user_id]; } + $other_user_public = bin2hex(stream_get_contents($sendCoins->receiver_public_key)); } else if ($sendCoins->receiver_user_id == $user['id']) { $type = 'receive'; if(isset($involvedUserIndices[$sendCoins->state_user_id])) { $otherUser = $involvedUserIndices[$sendCoins->state_user_id]; } + if($sendCoins->sender_public_key) { + $other_user_public = bin2hex(stream_get_contents($sendCoins->sender_public_key)); + } } if(null == $otherUser) { $otherUser = $this->StateBalances->StateUsers->newEntity(); @@ -192,7 +197,8 @@ class StateBalancesController extends AppController 'transaction_id' => $sendCoins->transaction_id, 'date' => $sendCoins->transaction->received, 'balance' => $sendCoins->amount, - 'memo' => $sendCoins->transaction->memo + 'memo' => $sendCoins->transaction->memo, + 'pubkey' => $other_user_public ]); } uasort($transactions, array($this, 'sortTransactions')); diff --git a/src/Model/Entity/AddressType.php b/src/Model/Entity/AddressType.php index 08dbba281..87d64d61a 100644 --- a/src/Model/Entity/AddressType.php +++ b/src/Model/Entity/AddressType.php @@ -8,7 +8,7 @@ use Cake\ORM\Entity; * * @property int $id * @property string $name - * @property string|null $text + * @property string $text * * @property \App\Model\Entity\StateGroupAddress[] $state_group_addresses * @property \App\Model\Entity\TransactionGroupAddaddres[] $transaction_group_addaddress @@ -28,6 +28,6 @@ class AddressType extends Entity 'name' => true, 'text' => true, 'state_group_addresses' => true, - 'transaction_group_addaddress' => true + 'transaction_group_addaddress' => true, ]; } diff --git a/src/Model/Entity/TransactionGroupAddaddres.php b/src/Model/Entity/TransactionGroupAddaddres.php index 3cb73b9ee..0559a6302 100644 --- a/src/Model/Entity/TransactionGroupAddaddres.php +++ b/src/Model/Entity/TransactionGroupAddaddres.php @@ -28,6 +28,7 @@ class TransactionGroupAddaddres extends Entity protected $_accessible = [ 'transaction_id' => true, 'address_type_id' => true, + 'remove_from_group' => true, 'public_key' => true, 'transaction' => true, 'address_type' => true diff --git a/src/Model/Table/AddressTypesTable.php b/src/Model/Table/AddressTypesTable.php index ea0c86d6e..ba94c99c7 100644 --- a/src/Model/Table/AddressTypesTable.php +++ b/src/Model/Table/AddressTypesTable.php @@ -38,10 +38,10 @@ class AddressTypesTable extends Table $this->setPrimaryKey('id'); $this->hasMany('StateGroupAddresses', [ - 'foreignKey' => 'address_type_id' + 'foreignKey' => 'address_type_id', ]); $this->hasMany('TransactionGroupAddaddress', [ - 'foreignKey' => 'address_type_id' + 'foreignKey' => 'address_type_id', ]); } @@ -54,19 +54,20 @@ class AddressTypesTable extends Table public function validationDefault(Validator $validator) { $validator - ->integer('id') + ->nonNegativeInteger('id') ->allowEmptyString('id', null, 'create'); $validator ->scalar('name') - ->maxLength('name', 25) + ->maxLength('name', 45) ->requirePresence('name', 'create') ->notEmptyString('name'); $validator ->scalar('text') ->maxLength('text', 255) - ->allowEmptyString('text'); + ->requirePresence('text', 'create') + ->notEmptyString('text'); return $validator; } diff --git a/src/Model/Transactions/Record.php b/src/Model/Transactions/Record.php new file mode 100644 index 000000000..da52db8ac --- /dev/null +++ b/src/Model/Transactions/Record.php @@ -0,0 +1,471 @@ +signature = $signature; + $this->publicKey = $pubkey; + } + + public function finalize($transactionId) + { + $signaturesTable = TableRegistry::getTableLocator()->get('TransactionSignatures'); + $entity = $signaturesTable->newEntity(); + $entity->transaction_id = $transactionId; + if(count($this->signature) != 128) { + return ['state' => 'error', 'msg' => 'invalid signature size', 'details' => count($this->signature)]; + } + if(count($this->publicKey) != 64) { + return ['state' => 'error', 'msg' => 'invalid pubkey size', 'details' => count($this->publicKey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->signature)) { + return ['state' => 'error', 'msg' => 'signature isn\'t in hex format']; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->publicKey)) { + return ['state' => 'error', 'msg' => 'publicKey isn\'t in hex format']; + } + $entity->signature = hex2bin($this->signature); + $entity->pubkey = hex2bin($this->publicKey); + + if(!$signaturesTable->save($entity)) { + return ['state' => 'error', 'msg' => 'error saving signature', 'details' => $entity->getErrors()]; + } + return true; + } +} + + +class ManageNodeGroupAdd +{ + /* + "add_user": { + "user\": " << user << ", + }, + OR + + "move_user_inbound|move_user_outbound": { + "user": " << user << ", + "other_group": " << other_group << ", + "paired_transaction_id": { + "seconds": << ts.seconds <<, + "nanos": << ts.nanos + } + }, + + */ + + private $user_pubkey; + private $other_group = ''; + private $remove_from_group = false; + + public function __construct($data) + { + $this->user_pubkey = $data['user']; + if(isset($data['other_group'])) { + $this->other_group = $data['other_group']; + } + } + + public function finalize($transactionId, $received) + { + $transactionGroupAddadressTable = TableRegistry::getTableLocator()->get('TransactionGroupAddaddress'); + $stateGroupAddresses = TableRegistry::getTableLocator()->get('StateGroupAddresses'); + $transactionGroupEntity = $transactionGroupAddadressTable->newEntity(); + $transactionGroupEntity->transaction_id = $transactionId; + if(count($this->user_pubkey) != 64) { + return ['state' => 'error', 'msg' => 'invalid size user pubkey', 'details' => count($this->user_pubkey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->user_pubkey)) { + return ['state' => 'error', 'msg' => 'user_pubkey isn\'t in hex format']; + } + + $transactionGroupEntity->public_key = hex2bin($this->user_pubkey); + $transactionGroupEntity->remove_from_group = $this->remove_from_group; + if(!$transactionGroupAddadressTable->save($transactionGroupEntity)) { + return ['state' => 'error', 'msg' => 'error saving TransactionGroupAddaddress Entity', 'details' => $transactionGroupEntity->getErrors()]; + } + $userPubkeyBin = hex2bin($this->user_pubkey); + if($this->remove_from_group) { + $stateGroup_query = $stateGroupAddresses->find('all')->where(['public_key' => hex2bin($this->user_pubkey)]); + if(!$stateGroup_query->isEmpty()) { + $stateGroupAddresses->delete($stateGroup_query->first()); + } + } else { + $stateGroupAddressesEntity = $stateGroupAddresses->newEntity(); + $stateGroupAddressesEntity->group_id = 1; + $stateGroupAddressesEntity->public_key = $userPubkeyBin; + $stateGroupAddressesEntity->address_type_id = 1; + if(!$stateGroupAddresses->save($stateGroupAddressesEntity)) { + return ['state' => 'error', 'msg' => 'error saving state group addresses entity', 'details' => $stateGroupAddressesEntity->getErrors()]; + } + } + + return true; + } + + public function setRemoveFromGroup($removeFromGroup) { + $this->remove_from_group = $removeFromGroup; + } +} + +class GradidoModifieUserBalance +{ + + public function getUserId($userPublicKey) + { + $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); + $stateUser = $stateUsersTable->find('all')->where(['public_key' => hex2bin($userPublicKey)]); + if($stateUser->isEmpty()) { + return ['state' => 'error', 'msg' => 'couldn\'t find user via public key']; + } + return $stateUser->first()->id; + } + + public function updateBalance($newBalance, $recordDate, $userId) + { + $stateBalancesTable = TableRegistry::getTableLocator()->get('StateBalances'); + $stateBalanceQuery = $stateBalancesTable->find('all')->where(['state_user_id' => $userId]); + $entity = null; + + if(!$stateBalanceQuery->isEmpty()) { + $entity = $stateBalanceQuery->first(); + if($entity->record_date != NULL && $entity->record_date > $recordDate) { + return false; + } + } else { + $entity = $stateBalancesTable->newEntity(); + $entity->state_user_id = $userId; + } + $entity->record_date = $recordDate; + $entity->amount = $newBalance; + if(!$stateBalancesTable->save($entity)) { + return ['state' => 'error', 'msg' => 'error saving state balance', 'details' => $entity->getErrors()]; + } + return true; + } +} + +class GradidoCreation extends GradidoModifieUserBalance +{ + /* + * "gradido_creation": { + "user": " << user << ", + "new_balance": << v.new_balance << , + "prev_transfer_rec_num": << v.prev_transfer_rec_num <<, + "amount": << v.amount << + } + */ + private $userPubkey; + private $amount; + private $targetDate; // seems currently not in node server implementet, use hedera date until it is implemented + private $new_balance; + + public function __construct($data) + { + $this->userPubkey = $data['user']; + $this->amount = $data['amount']; + $this->new_balance = $data['new_balance']; + //$this->targetDate = $received; + } + + public function finalize($transactionId, $received) + { + // TODO: don't use, after node server transmit correct date + $this->targetDate = $received; + + $transactionCreationTable = TableRegistry::getTableLocator()->get('TransactionCreations'); + + + $state_user_id = $this->getUserId($this->userPubkey); + if(!is_int($state_user_id)) { + return $state_user_id; + } + + $entity = $transactionCreationTable->newEntity(); + $entity->transaction_id = $transactionId; + $entity->amount = $this->amount; + $entity->target_date = $this->targetDate; + $entity->state_user_id = $state_user_id; + + if(!$transactionCreationTable->save($entity)) { + return ['state' => 'error', 'msg' => 'error saving create transaction', 'details' => $entity->getErrors()]; + } + + $balance_result = $this->updateBalance($this->new_balance, $received, $state_user_id); + if(is_array($balance_result)) { + return $balance_result; + } + + return true; + } + +} + +class GradidoTransfer extends GradidoModifieUserBalance +{ + /* + "local_transfer|inbound_transfer|outbound_transfer": { + "sender": { + "user": " << sender << ", + "new_balance": << tt.sender.new_balance << , + "prev_transfer_rec_num": << tt.sender.prev_transfer_rec_num << + }, + "receiver": { + "user": " << receiver << ", + "new_balance": << tt.receiver.new_balance << , + "prev_transfer_rec_num": << tt.receiver.prev_transfer_rec_num << + }, + "amount": << tt.amount << + }, + * */ + private $amount; + private $sender_new_balance; + private $sender_pubkey; + + private $receiver_pubkey; + private $receiver_new_balance; + + public function __construct($data) + { + $this->amount = $data['amount']; + + $sender = $data['sender']; + $this->sender_pubkey = $sender['user']; + $this->sender_new_balance = $sender['new_balance']; + + $receiver = $data['receiver']; + $this->receiver_pubkey = $receiver['user']; + $this->receiver_new_balance = $receiver['new_balance']; + + } + + public function finalize($transactionId, $received) + { + $transactionTransferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins'); + if(count($this->sender_pubkey) != 64) { + return ['state' => 'error', 'msg' => 'invalid size sender pubkey', 'details' => count($this->user_pubkey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->sender_pubkey)) { + return ['state' => 'error', 'msg' => 'sender_pubkey isn\'t in hex format']; + } + if(count($this->receiver_pubkey) != 64) { + return ['state' => 'error', 'msg' => 'invalid size receiver pubkey', 'details' => count($this->user_pubkey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->receiver_pubkey)) { + return ['state' => 'error', 'msg' => 'receiver_pubkey isn\'t in hex format']; + } + + $sender_id = $this->getUserId($this->sender_pubkey); + $receiver_id = $this->getUserId($this->receiver_pubkey); + if(is_array($sender_id) && is_array($receiver_id)) { + return ['state' => 'error', 'msg' => 'neither sender or receiver known']; + } + $transferEntity = $transactionTransferTable->newEntity(); + $transferEntity->transaction_id = $transactionId; + $transferEntity->sender_public_key = hex2bin($this->sender_pubkey); + $transferEntity->receiver_public_key = hex2bin($this->receiver_pubkey); + $transferEntity->amount = $this->amount; + $transferEntity->sender_final_balance = $this->sender_new_balance; + + if(is_int($sender_id) && $sender_id > 0) { + $transferEntity->state_user_id = $sender_id; + $balance_result = $this->updateBalance($this->sender_new_balance, $received, $sender_id); + if(is_array($balance_result)) { + return $balance_result; + } + } + if(is_int($receiver_id) && $receiver_id > 0) { + $transferEntity->receiver_user_id = $receiver_id; + $balance_result = $this->updateBalance($this->receiver_new_balance, $received, $receiver_id); + if(is_array($balance_result)) { + return $balance_result; + } + } + + if(!$transactionTransferTable->save($transferEntity)) { + return ['state' => 'error', 'msg' => 'error saving transaction send coins entity', 'details' => $transferEntity->getErrors()]; + } + + return true; + } +} + + + + +class Record +{ + private $sequenceNumber = 0; + private $transactionType = ''; + private $memo = ''; + private $signatures = []; + private $received; + private $transactionObj = null; + private $result; + private $partCount = 0; + + public function __construct() + { + + } + + + public function parseRecord($json) { + switch($json['record_type']) { + case 'GRADIDO_TRANSACTION': + return $this->parseTransaction($json['transaction']); + case 'MEMO': + $this->memo = $json['memo']; + return true; + case 'SIGNATURES': + return $this->parseSignatures($json['signature']); + case 'STRUCTURALLY_BAD_MESSAGE': + case 'RAW_MESSAGE': + case 'BLANK': + return false; + } + } + + /*! + * \brief save data parts in db + */ + public function finalize() + { + $transactionTypesTable = TableRegistry::getTableLocator()->get('TransactionTypes'); + $transactionsTable = TableRegistry::getTableLocator()->get('Transactions'); + + $transactionTypeName = $this->nodeTransactionTypeToDBTransactionType($this->transactionType); + $transactionTypeResults = $transactionTypesTable->find('all')->where(['name' => $transactionTypeName]); + if($transactionTypeResults->isEmpty()) { + return [ + 'state' => 'error', 'msg' => 'transaction type not found', + 'details' => ['nodeType' => $this->transactionType, 'dbType' => $transactionTypeName] + ]; + } + if(!$this->transactionObj) { + return ['state' => 'error', 'msg' => 'transaction obj is null']; + } + if($this->sequenceNumber <= 0) { + return ['state' => 'error', 'msg' => 'sequence number invalid', 'details' => $this->sequenceNumber]; + } + $transactionExistResult = $transactionsTable->find('all')->where(['id' => $this->sequenceNumber]); + if(!$transactionExistResult->isEmpty()) { + return ['state' => 'warning', 'msg' => 'transaction already exist in db', 'details' => $this->sequenceNumber]; + } + $newTransaction = $transactionsTable->newEntity(); + $newTransaction->id = $this->sequenceNumber; + $newTransaction->transaction_type_id = $transactionTypeResults->first()->id; + $newTransaction->memo = $this->memo; + $newTransaction->received = $this->received; + + if(!$transactionsTable->save($newTransaction)) { + return ['state' => 'error', 'msg' => 'error saving transaction', 'details' => $newTransaction->getErrors()]; + } + foreach($this->signatures as $sign) { + $sign_result = $sign->finalize($this->sequenceNumber); + iF($sign_result != true) { + return ['state' => 'error', 'msg', 'error finalizing signature', 'details' => $sign_result]; + } + } + $transaction_obj_result = $this->transactionObj->finalize($newTransaction->id, $this->received); + if($transaction_obj_result != true) { + return ['state' => 'error', 'msg' => 'error finalizing transaction object', 'details' => $transaction_obj_result]; + } + return true; + + } + + private function nodeTransactionTypeToDBTransactionType($nodeTransactionType) + { + switch($nodeTransactionType) { + case 'GRADIDO_CREATION': + return 'creation'; + + case 'MOVE_USER_INBOUND': + case 'ADD_USER': + return 'group add member'; + + case 'MOVE_USER_OUTBOUND': + return 'group remove member'; + + case 'LOCAL_TRANSFER': + case 'INBOUND_TRANSFER': + case 'OUTBOUND_TRANSFER': + return 'transfer'; + } + return 'unknown'; + } + + private function parseSignatures($signaturesArray) + { + foreach($signaturesArray as $sign) { + $this->signatures[] = new Signature($sign['signature'], $sign['pubkey']); + } + return true; + } + + private function parseTransaction($data) + { + $this->transactionType = $data['transaction_type']; + $sign = $data['signature']; + $this->signatures[] = new Signature($sign['signature'], $sign['pubkey']); + + $hedera = $data['hedera_transaction']; + $this->sequenceNumber = $hedera['sequenceNumber']; + $this->received = Time::createFromTimestamp($hedera['consensusTimestamp']['seconds']); + + $field_index = ''; + $class_name = ''; + + $removeFromGroup = false; + switch($this->transactionType) + { + case 'GRADIDO_CREATION': $field_index = 'gradido_creation'; $class_name = 'GradidoCreation'; break; + case 'ADD_USER': $field_index = 'add_user'; $class_name = 'ManageNodeGroupAdd'; break; + case 'MOVE_USER_INBOUND': $field_index = 'move_user_inbound'; $class_name = 'ManageNodeGroupAdd'; break; + case 'MOVE_USER_OUTBOUND': $field_index = 'move_user_outbound'; $class_name = 'ManageNodeGroupAdd'; $removeFromGroup = true; break; + case 'LOCAL_TRANSFER': $field_index = 'local_transfer'; $class_name = 'GradidoTransfer'; break; + case 'INBOUND_TRANSFER': $field_index = 'inbound_transfer'; $class_name = 'GradidoTransfer'; break; + case 'OUTBOUND_TRANSFER': $field_index = 'outbound_transfer'; $class_name = 'GradidoTransfer'; break; + } + if($class_name == '' || $field_index == '') { + return ['state' => 'error', 'msg' => 'node transaction type unknown', 'details' => $this->transactionType]; + } + $this->transactionObj = new $class_name($data[$field_index]); + if($class_name == 'ManageNodeGroupAdd') { + $this->transactionObj->setRemoveFromGroup($removeFromGroup); + } + + $this->result = $data['result']; + $this->partCount = intval($data['parts']); + $this->memo = $data['memo']; + return true; + } + + public function getSequenceNumber() { + return $this->sequenceNumber; + } + public function getPartCount() { + return $this->partCount; + } + +} \ No newline at end of file diff --git a/src/Template/AddressTypes/add.ctp b/src/Template/AddressTypes/add.ctp index 7422b666a..f62c5115e 100644 --- a/src/Template/AddressTypes/add.ctp +++ b/src/Template/AddressTypes/add.ctp @@ -4,8 +4,8 @@ * @var \App\Model\Entity\AddressType $addressType */ ?> -