diff --git a/src/Controller/ServerUsersController.php b/src/Controller/ServerUsersController.php index 238090123..4a04fe9b4 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/Controller/StateUsersController.php b/src/Controller/StateUsersController.php index ad86e651a..87da4e5cb 100644 --- a/src/Controller/StateUsersController.php +++ b/src/Controller/StateUsersController.php @@ -3,6 +3,8 @@ namespace App\Controller; use App\Controller\AppController; +use Model\Transactions\TransactionCreation; + /** * StateUsers Controller * @@ -26,6 +28,15 @@ class StateUsersController extends AppController $this->set(compact('stateUsers')); } + + public function listIdentHashes() + { + $stateUsers = $this->StateUsers->find('all')->toArray(); + foreach($stateUsers as $i => $user) { + $stateUsers[$i]->identHash = TransactionCreation::DRMakeStringHash($user->email); + } + $this->set('stateUsers', $stateUsers); + } /** * View method diff --git a/src/Controller/TransactionCreationsController.php b/src/Controller/TransactionCreationsController.php index a4c9434b0..a79550170 100644 --- a/src/Controller/TransactionCreationsController.php +++ b/src/Controller/TransactionCreationsController.php @@ -11,10 +11,9 @@ use Cake\Datasource\ConnectionManager; use App\Form\CreationForm; // protobuf transactions -use Model\Messages\Gradido\TransactionCreation; -use Model\Messages\Gradido\TransactionBody; -use Model\Messages\Gradido\ReceiverAmount; -use Model\Messages\Gradido\TimestampSeconds; +//use Model\Messages\Gradido\TransactionCreation; +use Model\Transactions\TransactionCreation; + /** * TransactionCreations Controller * @@ -92,7 +91,7 @@ class TransactionCreationsController extends AppController if($name === NULL) { $name = $stateUser->first_name . ' ' . $stateUser->last_name; } - array_push($receiverProposal, ['name' => $name, 'key' => $keyHex]); + array_push($receiverProposal, ['name' => $name, 'key' => $keyHex, 'email' => $stateUser->email]); //$stateUser->public_key } $timeUsed = microtime(true) - $startTime; @@ -103,42 +102,23 @@ class TransactionCreationsController extends AppController $mode = 'next'; if(isset($requestData['add'])) {$mode = 'add'; } if($creationForm->validate($requestData)) { - + $pubKeyHex = ''; - $receiver = new ReceiverAmount(); + $identHash = ''; + $amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']); + $receiverIndex = intval($requestData['receiver'])-1; - $receiver->setAmount($this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount'])); - - if(intval($requestData['receiver']) == 0) { - if(strlen($requestData['receiver_pubkey_hex']) != 64) { - $this->Flash->error(__('Invalid public Key, must contain 64 Character')); - } else { - $pubKeyHex = $requestData['receiver_pubkey_hex']; - } - } else { - $receiverIndex = intval($requestData['receiver'])-1; - - if(count($receiverProposal) > $receiverIndex) { - $pubKeyHex = $receiverProposal[$receiverIndex]['key']; - } + if(count($receiverProposal) > $receiverIndex) { + $pubKeyHex = $receiverProposal[$receiverIndex]['key']; + $identHash = TransactionCreation::DRMakeStringHash($receiverProposal[$receiverIndex]['email']); } - if($pubKeyHex != '') { - $pubKeyBin = hex2bin($pubKeyHex); - - $receiver->setEd25519ReceiverPubkey($pubKeyBin); - //var_dump($requestData); - - $creationDate = new TimestampSeconds(); - $creationDate->setSeconds(time()); - - $transactionBody = new TransactionBody(); - $transactionBody->setMemo($requestData['memo']); - $transactionBody->setCreated($creationDate); - - $transaction = new TransactionCreation(); - $transaction->setReceiverAmount($receiver); - $transaction->setIdentHash($user['ident_hash']); - $transactionBody->setCreation($transaction); + $builderResult = TransactionCreation::build( + $amountCent, + $requestData['memo'], + $pubKeyHex, + $identHash + ); + if($builderResult['state'] == 'success') { $http = new Client(); try { @@ -147,7 +127,7 @@ class TransactionCreationsController extends AppController $session_id = $session->read('session_id'); $response = $http->get($url . '/checkTransaction', [ 'session_id' => $session_id, - 'transaction_base64' => base64_encode($transactionBody->serializeToString()) + 'transaction_base64' => base64_encode($builderResult['transactionBody']->serializeToString()) ]); $json = $response->getJson(); if($json['state'] != 'success') { @@ -262,7 +242,23 @@ class TransactionCreationsController extends AppController if ($this->request->is('post')) { $requestData = $this->request->getData(); - var_dump($requestData); + // memo + // amount + $memo = $requestData['memo']; + $amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']); + if(!isset($requestData['user']) || count($requestData['user']) == 0) { + $this->Flash->error(__('no user choosen')); + } else { + $users = $requestData['user']; + var_dump($users); + $receiverUsers = $stateUserTable + ->find('all') + ->where(['id' => array_keys($users)]) + ->select(['public_key', 'email']); + //$identHash = TransactionCreation::DRMakeStringHash($receiverProposal[$receiverIndex]['email']); + + } + } diff --git a/src/Model/Table/TransactionCreationsTable.php b/src/Model/Table/TransactionCreationsTable.php index 70ab54071..bc9592ccf 100644 --- a/src/Model/Table/TransactionCreationsTable.php +++ b/src/Model/Table/TransactionCreationsTable.php @@ -45,10 +45,6 @@ class TransactionCreationsTable extends Table 'foreignKey' => 'state_user_id', 'joinType' => 'INNER' ]); - $this->belongsTo('StateUsers', [ - 'foreignKey' => 'receiver_user_id', - 'joinType' => 'INNER' - ]); } /** diff --git a/src/Model/Transactions/TransactionBase.php b/src/Model/Transactions/TransactionBase.php index 50eb72738..81060dbfe 100644 --- a/src/Model/Transactions/TransactionBase.php +++ b/src/Model/Transactions/TransactionBase.php @@ -1,69 +1,69 @@ -errors; - } - - public function addError($functionName, $errorName) { - array_push($this->errors, [$functionName => $errorName]); - } - - public function addErrors($errors) { - $this->errors = array_merge($this->errors, $errors); - } - - public function hasErrors() { - return count($this->errors) > 0; - } - - protected function getStateUserId($publicKey) { - $stateUsersTable = TableRegistry::getTableLocator()->get('state_users'); - $stateUser = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $publicKey])->first(); - if($stateUser) { - return $stateUser->id; - } - // create new entry - $stateUserEntity = $stateUsersTable->newEntity(); - $stateUserEntity->public_key = $publicKey; - if($stateUsersTable->save($stateUserEntity)) { - return $stateUserEntity->id; - } else { - $this->addError('TransactionBase::getStateUserId', 'error saving new state user with error: ' . json_encode($stateUserEntity->getErrors())); - } - - return NULL; - } - - protected function updateStateBalance($stateUserId, $newAmountCent) { - $stateBalancesTable = TableRegistry::getTableLocator()->get('stateBalances'); - $stateBalanceQuery = $stateBalancesTable - ->find('all') - ->select(['amount']) - ->contain(false) - ->where(['state_user_id' => $stateUserId]);//->first(); - //debug($stateBalanceQuery); - - if($stateBalanceQuery->count() > 0) { - $stateBalanceEntry = $stateBalanceQuery->first(); - $stateBalanceEntry->amount += $newAmountCent; - } else { - $stateBalanceEntry = $stateBalancesTable->newEntity(); - $stateBalanceEntry->state_user_id = $stateUserId; - $stateBalanceEntry->amount = $newAmountCent; - } - - if(!$stateBalancesTable->save($stateBalanceEntry)) { - $errors = $stateBalanceEntry->getErrors(); - $this->addError('TransactionBase::updateStateBalance', 'error saving state balance with: ' . json_encode($errors)); - return false; - } - return true; - } +errors; + } + + public function addError($functionName, $errorName) { + array_push($this->errors, [$functionName => $errorName]); + } + + public function addErrors($errors) { + $this->errors = array_merge($this->errors, $errors); + } + + public function hasErrors() { + return count($this->errors) > 0; + } + + protected function getStateUserId($publicKey) { + $stateUsersTable = TableRegistry::getTableLocator()->get('state_users'); + $stateUser = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $publicKey])->first(); + if($stateUser) { + return $stateUser->id; + } + // create new entry + $stateUserEntity = $stateUsersTable->newEntity(); + $stateUserEntity->public_key = $publicKey; + if($stateUsersTable->save($stateUserEntity)) { + return $stateUserEntity->id; + } else { + $this->addError('TransactionBase::getStateUserId', 'error saving new state user with error: ' . json_encode($stateUserEntity->getErrors())); + } + + return NULL; + } + + protected function updateStateBalance($stateUserId, $newAmountCent) { + $stateBalancesTable = TableRegistry::getTableLocator()->get('stateBalances'); + $stateBalanceQuery = $stateBalancesTable + ->find('all') + ->select(['amount', 'id']) + ->contain(false) + ->where(['state_user_id' => $stateUserId]);//->first(); + //debug($stateBalanceQuery); + + if($stateBalanceQuery->count() > 0) { + $stateBalanceEntry = $stateBalanceQuery->first(); + $stateBalanceEntry->amount += $newAmountCent; + } else { + $stateBalanceEntry = $stateBalancesTable->newEntity(); + $stateBalanceEntry->state_user_id = $stateUserId; + $stateBalanceEntry->amount = $newAmountCent; + } + //echo "\ntry to save: "; var_dump($stateBalanceEntry); echo "\n"; + if(!$stateBalancesTable->save($stateBalanceEntry)) { + $errors = $stateBalanceEntry->getErrors(); + $this->addError('TransactionBase::updateStateBalance', 'error saving state balance with: ' . json_encode($errors)); + return false; + } + return true; + } } \ No newline at end of file diff --git a/src/Model/Transactions/TransactionCreation.php b/src/Model/Transactions/TransactionCreation.php index 073ae2bf7..d495556fb 100644 --- a/src/Model/Transactions/TransactionCreation.php +++ b/src/Model/Transactions/TransactionCreation.php @@ -10,10 +10,57 @@ class TransactionCreation extends TransactionBase { private $protoTransactionCreation; private $transactionCreationsTable; + private $receiver_pubkey_hex; public function __construct($protoTransactionCreation) { $this->protoTransactionCreation = $protoTransactionCreation; $this->transactionCreationsTable = TableRegistry::getTableLocator()->get('transaction_creations'); + $this->receiver_pubkey_hex = bin2hex($this->getReceiverPublic()); + } + + static public function build($amount, $memo, $receiver_public_hex, $ident_hash) + { + $receiver = new \Model\Messages\Gradido\ReceiverAmount(); + $receiver->setAmount($amount); + $this->receiver_pubkey_hex = $receiver_public_hex; + if(strlen($receiver_public_hex) != 64) { + return ['state' => 'error', 'msg' => 'invalid pubkey']; + } + $pubKeyBin = hex2bin($receiver_public_hex); + $receiver->setEd25519ReceiverPubkey($pubKeyBin); + //var_dump($requestData); + + $creationDate = new \Model\Messages\Gradido\TimestampSeconds(); + $creationDate->setSeconds(time()); + + $transactionBody = new \Model\Messages\Gradido\TransactionBody(); + $transactionBody->setMemo($memo); + $transactionBody->setCreated($creationDate); + + $transaction = new \Model\Messages\Gradido\TransactionCreation(); + $transaction->setReceiverAmount($receiver); + $transaction->setIdentHash($ident_hash); + $transactionBody->setCreation($transaction); + return ['state' => 'success', 'transactionBody' => $transactionBody]; + } + + static protected function DRHashRotateLeft( $hash, $rotateBy ) + { + return ($hash<<$rotateBy)|($hash>>(32-$rotateBy)); + } + + static public function DRMakeStringHash($str) + { + $ret = 0; + + if( $str ) + { + for ($i=0; $i < strlen($str); $i++) + { + $ret = TransactionCreation::DRHashRotateLeft($ret, 7) + ord($str{$i}); + } + } + return $ret; } public function getAmount() { @@ -28,6 +75,7 @@ class TransactionCreation extends TransactionBase { return $this->protoTransactionCreation->getIdentHash(); } + public function validate($sigPairs) { // check if receiver public is not in signature list $receiverPublic = $this->getReceiverPublic(); @@ -43,25 +91,33 @@ class TransactionCreation extends TransactionBase { //$identHashBin = sprintf("%0d", $this->getIdentHash()); // padding with zero in case hash is smaller than 32 bytes, static length binary field in db + // ident hash isn't collision ressistent, it is for speed up search $identHashBin = pack('a32', $this->getIdentHash()); $existingCreations = $this->transactionCreationsTable ->find('all') - ->group('ident_hash') + ->select(['amount', 'state_user_id']) + ->contain(['StateUsers' => ['fields' => ['StateUsers.public_key']]]) ->where(['ident_hash' => $identHashBin]); - $existingCreations->select(['amount_sum' => $existingCreations->func()->sum('amount')]); + //$existingCreations->select(['amount_sum' => $existingCreations->func()->sum('amount')]); + $existingCreations->select(['amount', 'state_user_id']); $existingCreations->matching('Transactions', function ($q) { return $q->where(['EXTRACT(YEAR_MONTH FROM Transactions.received) LIKE EXTRACT(YEAR_MONTH FROM NOW())']); }); //debug($existingCreations); - if($existingCreations->count() > 0) { - //var_dump($existingCreations->toArray()); - //echo "amount sum: " . $existingCreations->first()->amount_sum . "\n"; - if($this->getAmount() + $existingCreations->first()->amount_sum > 10000000) { - $this->addError('TransactionCreation::validate', 'Creation more than 1000 gr per Month not allowed'); - return false; + $newSum = $this->getAmount(); + //var_dump($existingCreations->toArray()); + foreach($existingCreations as $creation) { + $keyHex = bin2hex(stream_get_contents($creation->state_user->public_key)); + //echo "\ncompare \n$keyHex\nwith: \n". $this->receiver_pubkey_hex."\n"; + if($keyHex == $this->receiver_pubkey_hex) { + $newSum += $creation->amount; } - } + } + if($newSum > 10000000) { + $this->addError('TransactionCreation::validate', 'Creation more than 1000 gr per Month not allowed'); + return false; + } //die("\n"); return true; } diff --git a/src/Template/Element/printGradido.ctp b/src/Template/Element/printGradido.ctp index 2f288d9be..0e4d71173 100644 --- a/src/Template/Element/printGradido.ctp +++ b/src/Template/Element/printGradido.ctp @@ -14,5 +14,5 @@ else if($number > 0) $class = "grd-positive-currency";*/ ?> - Number->format(intval($number) / 10000.0, ['precision' => 2]) . ' grd';?> + Number->format(intval($number) / 10000.0, ['precision' => 2]) . ' GDD';?> \ No newline at end of file diff --git a/src/Template/TransactionCreations/create_multi.ctp b/src/Template/TransactionCreations/create_multi.ctp index 407afff45..fa2547436 100644 --- a/src/Template/TransactionCreations/create_multi.ctp +++ b/src/Template/TransactionCreations/create_multi.ctp @@ -44,7 +44,7 @@ $this->assign('title', __('Schöpfungstransaktion')); Form->control('amount'); ?>
- Form->checkbox('user[' .$possibleReceiver['id'] . ']', ['hiddenField' => false]); ?> + Form->checkbox('user[' .$possibleReceiver['id'] . ']', ['value' => $possibleReceiver['id'], 'hiddenField' => false]); ?> <> diff --git a/src/Template/TransactionSendCoins/create.ctp b/src/Template/TransactionSendCoins/create.ctp index d43942439..83987ee99 100644 --- a/src/Template/TransactionSendCoins/create.ctp +++ b/src/Template/TransactionSendCoins/create.ctp @@ -20,7 +20,7 @@ $this->assign('title', __('Überweisung')); Form->create($creationForm) ?>
- +
diff --git a/tests/Fixture/StateBalancesFixture.php b/tests/Fixture/StateBalancesFixture.php index 2e969e749..8db926511 100644 --- a/tests/Fixture/StateBalancesFixture.php +++ b/tests/Fixture/StateBalancesFixture.php @@ -15,7 +15,7 @@ class StateBalancesFixture extends TestFixture */ // @codingStandardsIgnoreStart public $fields = [ - 'id' => ['type' => 'integer', 'length' => 11, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null], + 'id' => ['type' => 'integer', 'length' => 11, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => true], 'state_user_id' => ['type' => 'integer', 'length' => 11, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null], 'modified' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], 'amount' => ['type' => 'biginteger', 'length' => 20, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null], diff --git a/tests/Fixture/StateUsersFixture.php b/tests/Fixture/StateUsersFixture.php index e2baced86..28e03e3f3 100644 --- a/tests/Fixture/StateUsersFixture.php +++ b/tests/Fixture/StateUsersFixture.php @@ -44,8 +44,8 @@ class StateUsersFixture extends TestFixture 'id' => 1, 'index_id' => 0, 'group_id' => 0, - 'public_key' => '0x94ae135b93cd9f33752b4e55c41903a3faa13a75bb90bfd411ea1d4a1a5e711f', - 'email' => NULL, + 'public_key' => hex2bin('94ae135b93cd9f33752b4e55c41903a3faa13a75bb90bfd411ea1d4a1a5e711f'), + 'email' => '***REMOVED***', 'first_name' => 'Dario', 'last_name' => 'Rekowski' ], @@ -53,8 +53,8 @@ class StateUsersFixture extends TestFixture 'id' => 11, 'index_id' => 0, 'group_id' => 0, - 'public_key' => '0x61b923c218cb63a64a8c62f3860121283b9577f374d0a31590ba02cdc2912999', - 'email' => NULL, + 'public_key' => hex2bin('61b923c218cb63a64a8c62f3860121283b9577f374d0a31590ba02cdc2912999'), + 'email' => 'em741@gmx.de', 'first_name' => 'Dario', 'last_name' => 'Rekowski' ],