diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php
index 206277509..fc7365d66 100644
--- a/src/Controller/DashboardController.php
+++ b/src/Controller/DashboardController.php
@@ -79,6 +79,14 @@ class DashboardController extends AppController
$stateUserQuery = $stateUserTable->find('all')->where(['public_key' => $public_key_bin]);
if($stateUserQuery->count() == 1) {
$stateUser = $stateUserQuery->first();
+ if($stateUser->first_name != $json['user']['first_name'] ||
+ $stateUser->last_name != $json['user']['last_name']) {
+ $stateUser->first_name = $json['user']['first_name'];
+ $stateUser->last_name = $json['user']['last_name'];
+ if(!$stateUserTable->save($stateUser)) {
+ $this->Flash->error(__('error updating state user ' . json_encode($stateUser->errors())));
+ }
+ }
$session->write('StateUser.id', $stateUser['id']);
//echo $stateUser['id'];
} else {
@@ -86,7 +94,9 @@ class DashboardController extends AppController
$newStateUser->public_key = $public_key_bin;
$newStateUser->first_name = $json['user']['first_name'];
$newStateUser->last_name = $json['user']['last_name'];
- $stateUserTable->save($newStateUser);
+ if(!$stateUserTable->save($newStateUser)) {
+ $this->Flash->error(__('error saving state user ' . json_encode($newStateUser->errors())));
+ }
$session->write('StateUser.id', $newStateUser->id);
//echo $newStateUser->id;
}
diff --git a/src/Model/Entity/StateUser.php b/src/Model/Entity/StateUser.php
index 59bd19e9a..a6e8c40da 100644
--- a/src/Model/Entity/StateUser.php
+++ b/src/Model/Entity/StateUser.php
@@ -33,6 +33,9 @@ class StateUser extends Entity
'index_id' => true,
'state_group_id' => true,
'public_key' => true,
+ 'email' => true,
+ 'first_name' => true,
+ 'last_name' => true,
'index' => true,
'state_group' => true,
'state_balances' => true,
diff --git a/src/Model/Entity/Transaction.php b/src/Model/Entity/Transaction.php
index 98948adae..d4ebf68c4 100644
--- a/src/Model/Entity/Transaction.php
+++ b/src/Model/Entity/Transaction.php
@@ -37,6 +37,7 @@ class Transaction extends Entity
'state_group_id' => true,
'transaction_type_id' => true,
'tx_hash' => true,
+ 'memo' => true,
'received' => true,
'state_group' => true,
'transaction_type' => true,
diff --git a/src/Model/Table/TransactionsTable.php b/src/Model/Table/TransactionsTable.php
index 99c2473b8..75659a5b2 100644
--- a/src/Model/Table/TransactionsTable.php
+++ b/src/Model/Table/TransactionsTable.php
@@ -87,8 +87,11 @@ class TransactionsTable extends Table
->allowEmptyString('id', null, 'create');
$validator
- ->requirePresence('tx_hash', 'create')
- ->notEmptyString('tx_hash');
+ //->requirePresence('tx_hash', 'create')
+ ->allowEmptyString('tx_hash', null, 'create');
+
+ $validator
+ ->allowEmptyString('memo', null, 'create');
$validator
->dateTime('received')
diff --git a/src/Model/Transactions/Transaction.php b/src/Model/Transactions/Transaction.php
index eb818f38b..eae0546fc 100644
--- a/src/Model/Transactions/Transaction.php
+++ b/src/Model/Transactions/Transaction.php
@@ -10,57 +10,115 @@ namespace Model\Transactions;
//use Model\Messages\Gradido\Transaction;
//use Model\Messages\Gradido\TransactionBody;
+use Cake\ORM\TableRegistry;
+use Cake\Datasource\ConnectionManager;
class Transaction extends TransactionBase {
private $mProtoTransaction = null;
- private $mProtoTransactionBody = null;
- private $errors = [];
+ private $mTransactionBody = null;
public function __construct($base64Data) {
$transactionBin = base64_decode($base64Data);
if($transactionBin == FALSE) {
//$this->addError('base64 decode failed');
- $this->addError(['data' => $base64Data, 'bin' => $transactionBin, 'msg' => 'base64 decode error']);
+ $this->addError('Transaction', ['data' => $base64Data, 'bin' => $transactionBin, 'msg' => 'base64 decode error']);
} else {
$this->mProtoTransaction = new \Model\Messages\Gradido\Transaction();
$this->mProtoTransaction->mergeFromString($transactionBin);
+ //echo 'serialize to json:
';
+ //echo $this->mProtoTransaction->serializeToJsonString();
- $this->mProtoTransactionBody = new \Model\Messages\Gradido\TransactionBody();
- $this->mProtoTransactionBody->mergeFromString($this->mProtoTransaction->getBodyBytes());
-
- $data = $this->mProtoTransactionBody->getData();
- var_dump($data);
+ $this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes());
}
}
+ public function getTransactionBody() {
+ return $this->mTransactionBody;
+ }
+
+ public function getFirstPublic() {
+ $sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
+ return $sigPairs[0]->getPubKey();
+ }
+
public function validate() {
$sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
$bodyBytes = $this->mProtoTransaction->getBodyBytes();
+
+ if(!$sigPairs || count($sigPairs) < 1) {
+ $this->addError('Transaction::validate', 'no signature found');
+ return false;
+ }
+
// check signature(s)
foreach($sigPairs as $sigPair) {
+ //echo 'sig Pair: '; var_dump($sigPair); echo "
";
$pubkey = $sigPair->getPubKey();
$signature = $sigPair->getEd25519();
if (!\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) {
- $this->addError('signature for key ' . bin2hex($pubkey) . ' isn\'t valid ' );
+ $this->addError('Transaction::validate', 'signature for key ' . bin2hex($pubkey) . ' isn\'t valid ' );
return false;
}
}
+ if(!$this->mTransactionBody->validate($sigPairs)) {
+ $this->addErrors($this->mTransactionBody->getErrors());
+ return false;
+ }
+
return true;
}
- public function getErrors() {
- return $this->errors;
+ public function save()
+ {
+ $connection = ConnectionManager::get('default');
+ $connection->begin();
+ //id transaction_id signature pubkey
+
+ if (!$this->mTransactionBody->save($this->getFirstPublic())) {
+ $this->addErrors($this->mTransactionBody->getErrors());
+ $connection->rollback();
+ return false;
+ }
+
+ // save transaction signatures
+ $transactionsSignaturesTable = TableRegistry::getTableLocator()->get('transaction_signatures');
+ $transactionId = $this->mTransactionBody->getTransactionID();
+ //signature pubkey
+
+ $sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
+ echo "sigPairs: "; var_dump($sigPairs);
+ $signatureEntitys = [];
+ foreach($sigPairs as $sigPair) {
+ $signatureEntity = $transactionsSignaturesTable->newEntity();
+
+ $signatureEntity->transaction_id = $transactionId;
+ $signatureEntity->signature = $sigPair->getEd25519();
+ $signatureEntity->pubkey = $sigPair->getPubKey();
+ array_push($signatureEntitys, $signatureEntity);
+ }
+ //debug($signatureEntitys);
+ if(!$transactionsSignaturesTable->saveMany($signatureEntitys)) {
+ foreach($signatureEntitys as $entity) {
+ $errors = $entity->getErrors();
+ if(!$errors && count($errors) > 0) {
+ $pubkeyHex = bin2hex($entity->pubkey);
+ $this->addError('Transaction::save', 'error saving signature for pubkey: ' . $pubkeyHex . ', with errors: ' . json_encode($errors) );
+ }
+ }
+ $connection->rollback();
+ return false;
+ }
+
+ $connection->commit();
+ return true;
}
+
+
+
- public function hasErrors() {
- return count($this->errors) > 0;
- }
-
- private function addError($message) {
- array_push($this->errors, $message);
- }
+
}
\ No newline at end of file
diff --git a/src/Model/Transactions/TransactionBase.php b/src/Model/Transactions/TransactionBase.php
index c9ba5cdcd..e8f299216 100644
--- a/src/Model/Transactions/TransactionBase.php
+++ b/src/Model/Transactions/TransactionBase.php
@@ -2,6 +2,42 @@
namespace Model\Transactions;
+use Cake\ORM\TableRegistry;
+
class TransactionBase {
+ private $errors = [];
+ public function getErrors() {
+ return 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;
+ }
}
\ No newline at end of file
diff --git a/src/Model/Transactions/TransactionBody.php b/src/Model/Transactions/TransactionBody.php
index 175552736..943e46dc8 100644
--- a/src/Model/Transactions/TransactionBody.php
+++ b/src/Model/Transactions/TransactionBody.php
@@ -2,6 +2,76 @@
namespace Model\Transactions;
+use Cake\ORM\TableRegistry;
+
class TransactionBody extends TransactionBase {
+ private $mProtoTransactionBody = null;
+ private $mSpecificTransaction = null;
+ private $mTransactionID = 0;
+
+ public function __construct($bodyBytes) {
+ $this->mProtoTransactionBody = new \Model\Messages\Gradido\TransactionBody();
+ $this->mProtoTransactionBody->mergeFromString($bodyBytes);
+ switch($this->mProtoTransactionBody->getData()) {
+ case 'creation' : $this->mSpecificTransaction = new TransactionCreation($this->mProtoTransactionBody->getCreation()); break;
+ case 'transfer' : $this->mSpecificTransaction = new TransactionTransfer($this->mProtoTransactionBody->getTransfer()); break;
+ }
+ }
+
+ public function validate($sigPairs) {
+ if(!$this->mSpecificTransaction->validate($sigPairs)) {
+ $this->addErrors($this->mSpecificTransaction->getErrors());
+ return false;
+ }
+ return true;
+ }
+
+ public function getSpecificTransaction() {
+ return $this->mSpecificTransaction;
+ }
+
+ public function getMemo() {
+ return $this->mProtoTransactionBody->getMemo();
+ }
+
+ public function getTransactionTypeName()
+ {
+ return $this->mProtoTransactionBody->getData();
+ }
+
+ public function save($firstPublic) {
+ $transactionsTable = TableRegistry::getTableLocator()->get('transactions');
+ $transactionEntity = $transactionsTable->newEntity();
+
+ // transaction type id
+ $transactionTypesTable = TableRegistry::getTableLocator()->get('transaction_types');
+
+ $typeName = $this->getTransactionTypeName();
+ $transactionType = $transactionTypesTable->find('all')->where(['name' => $typeName])->select(['id'])->first();
+ if($transactionType == NULL) {
+ $this->addError('TransactionBody::save', 'zero type id for type: ' . $typeName);
+ return false;
+ }
+ $transactionEntity->transaction_type_id = $transactionType->id;
+ $transactionEntity->memo = $this->getMemo();
+
+ if ($transactionsTable->save($transactionEntity)) {
+ // success
+ $this->mTransactionID = $transactionEntity->id;
+ if(!$this->mSpecificTransaction->save($transactionEntity->id, $firstPublic)) {
+ $this->addErrors($this->mSpecificTransaction->getErrors());
+ return false;
+ }
+ } else {
+ $this->addError('TransactionBody::save', 'error saving transaction with: ' . json_encode($transactionEntity->getError()));
+ return false;
+ }
+ return true;
+ }
+
+ public function getTransactionID() {
+ return $this->mTransactionID;
+ }
+
}
diff --git a/src/Model/Transactions/TransactionCreation.php b/src/Model/Transactions/TransactionCreation.php
index 4f60849f2..554f9ce00 100644
--- a/src/Model/Transactions/TransactionCreation.php
+++ b/src/Model/Transactions/TransactionCreation.php
@@ -4,6 +4,76 @@ namespace Model\Transactions;
//use App\Model\Transactions\TransactionBase;
+use Cake\ORM\TableRegistry;
+
class TransactionCreation extends TransactionBase {
+ private $protoTransactionCreation;
+ private $transactionCreationsTable;
+
+ public function __construct($protoTransactionCreation) {
+ $this->protoTransactionCreation = $protoTransactionCreation;
+ $this->transactionCreationsTable = TableRegistry::getTableLocator()->get('transaction_creations');
+ }
+
+ public function getAmount() {
+ return $this->protoTransactionCreation->getReceiverAmount()->getAmount();
+ }
+
+ public function getReceiverPublic() {
+ return $this->protoTransactionCreation->getReceiverAmount()->getEd25519ReceiverPubkey();
+ }
+
+ public function getIdentHash() {
+ return $this->protoTransactionCreation->getIdentHash();
+ }
+
+ public function validate($sigPairs) {
+ // check if receiver public is not in signature list
+ $receiverPublic = $this->getReceiverPublic();
+ foreach($sigPairs as $sigPair) {
+ $pubkey = $sigPair->getPubKey();
+ if($pubkey == $receiverPublic) {
+ $this->addError('TransactionCreation::validate', 'receiver aren\'t allowed to sign creation Transaction');
+ return false;
+ }
+ }
+
+ // check if creation threshold for this month isn't reached
+ $existingCreations = $this->transactionCreationsTable
+ ->find('all')
+ ->group('ident_hash')
+ ->where(['ident_hash' => $this->getIdentHash()]);
+ $existingCreations->select(['amount_sum' => $existingCreations->func()->sum('amount')]);
+ debug($existingCreations);
+ if($existingCreations->count() > 0) {
+ var_dump($existingCreations->toArray());
+ }
+ return true;
+ }
+
+ public function save($transaction_id, $firstPublic) {
+
+ $transactionCreationEntity = $this->transactionCreationsTable->newEntity();
+
+ $transactionCreationEntity->transaction_id = $transaction_id;
+
+ // state user id
+ $state_user_id = $this->getStateUserId($firstPublic);
+ if(!$state_user_id) {
+ $this->addError('TransactionCreation::save', 'couldn\'t get state user id');
+ return false;
+ }
+ $transactionCreationEntity->state_user_id = $state_user_id;
+ $transactionCreationEntity->amount = $this->getAmount();
+ $transactionCreationEntity->ident_hash = $this->getIdentHash();
+
+ if(!$this->transactionCreationsTable->save($transactionCreationEntity)) {
+ $this->addError('TransactionCreation::save', 'error saving transactionCreation with errors: ' . json_encode($transactionCreationEntity->getErrors()));
+ return false;
+ }
+
+ return true;
+ }
+
}
diff --git a/src/Model/Transactions/TransactionTransfer.php b/src/Model/Transactions/TransactionTransfer.php
index e8357cc79..89eb36bda 100644
--- a/src/Model/Transactions/TransactionTransfer.php
+++ b/src/Model/Transactions/TransactionTransfer.php
@@ -5,6 +5,18 @@ namespace Model\Transactions;
//use App\Model\Transactions\TransactionBase;
class TransactionTransfer extends TransactionBase {
-
+ private $protoTransactionTransfer;
+
+ public function __construct($protoTransactionTransfer) {
+ $this->protoTransactionTransfer = $protoTransactionTransfer;
+ }
+
+ public function validate($sigPairs) {
+ return true;
+ }
+
+ public function save($transaction_id, $firstPublic) {
+ return true;
+ }
}
diff --git a/src/Template/Layout/frontend.ctp b/src/Template/Layout/frontend.ctp
index 9c30a36da..d393355b4 100644
--- a/src/Template/Layout/frontend.ctp
+++ b/src/Template/Layout/frontend.ctp
@@ -40,7 +40,7 @@ $transactionPendings = $session->read('Transactions.pending');
Community Server in Entwicklung
-Alpha 0.4.4
+Alpha 0.5.0