Adding Notification Emails and make larger textbox for creation transactions

This commit is contained in:
Dario Rekowski on RockPI 2020-02-04 17:43:13 +00:00
parent b4e7ad02aa
commit 2862d7824d
11 changed files with 132 additions and 189 deletions

View File

@ -6,6 +6,7 @@ use App\Controller\AppController;
use Cake\ORM\TableRegistry;
use Cake\Routing\Router;
use Model\Transactions\Transaction;
/*!
* @author: Dario Rekowski#
@ -63,6 +64,8 @@ class JsonRequestHandlerController extends AppController {
}
if ($transaction->save()) {
// success
return $this->returnJson(['state' => 'success']);
} else {

View File

@ -15,7 +15,7 @@ class CreationForm extends Form
//->addField('receiver_pubkey_hex', ['type' => 'string'])
->addField('receiver', ['type' => 'select'])
->addField('amount', ['type' => 'decimal', 'precision' => 2])
->addField('memo', ['type' =>'string', 'default' => '']);
->addField('memo', ['type' =>'text', 'default' => '', 'rows' => 5, 'maxlength' => 150]);
}
function validationDefault(Validator $validator)

View File

@ -43,4 +43,12 @@ class StateUser extends Entity
'transaction_creations' => true,
'transaction_send_coins' => true
];
public function getEmailWithName() {
return $this->first_name . ' ' . $this->last_name . ' <' . $this->email . '>';
}
public function getNames() {
return $this->first_name . ' ' . $this->last_name;
}
}

View File

@ -151,9 +151,10 @@ class Transaction extends TransactionBase {
return false;
}
$connection->commit();
$this->mTransactionBody->getSpecificTransaction()->sendNotificationEmail($this->mTransactionBody->getMemo());
return true;
}

View File

@ -6,6 +6,7 @@ use Cake\ORM\TableRegistry;
class TransactionBase {
private $errors = [];
static $stateUsersTable = null;
public function getErrors() {
return $this->errors;
@ -23,8 +24,18 @@ class TransactionBase {
return count($this->errors) > 0;
}
public static function getStateUsersTable()
{
if(!self::$stateUsersTable) {
self::$stateUsersTable = TableRegistry::getTableLocator()->get('state_users');
}
return self::$stateUsersTable;
}
protected function getStateUserId($publicKey) {
$stateUsersTable = TableRegistry::getTableLocator()->get('state_users');
$stateUsersTable = self::getStateUsersTable();
$stateUser = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $publicKey])->first();
if($stateUser) {
return $stateUser->id;
@ -41,6 +52,17 @@ class TransactionBase {
return NULL;
}
protected function getStateUser($id) {
$stateUsersTable = self::getStateUsersTable();
$stateUser = $stateUsersTable->get($id);
if($stateUser) {
return $stateUser;
}
return NULL;
}
protected function updateStateBalance($stateUserId, $addAmountCent) {
$finalBalance = 0;
$stateBalancesTable = TableRegistry::getTableLocator()->get('stateBalances');

View File

@ -90,10 +90,15 @@ class TransactionBody extends TransactionBase {
$previousTxHash = null;
if($this->mTransactionID > 1) {
try {
$previousTransaction = $transactionsTable->get($this->mTransactionID - 1, [
$previousTransaction = $transactionsTable
->find('all', ['contain' => false])
->select(['tx_hash'])
->where(['id' => $this->mTransactionID - 1])
->first();
/*$previousTransaction = $transactionsTable->get($this->mTransactionID - 1, [
'contain' => false,
'fields' => ['tx_hash']
]);
]);*/
} catch(Cake\Datasource\Exception\RecordNotFoundException $ex) {
$this->addError('TransactionBody::save', 'previous transaction (with id ' . ($this->mTransactionID-1) . ' not found');
return false;
@ -105,7 +110,17 @@ class TransactionBody extends TransactionBase {
}
$previousTxHash = $previousTransaction->tx_hash;
}
$transactionEntity->received = $transactionsTable->get($transactionEntity->id, ['contain' => false, 'fields' => ['received']])->received;
try {
//$transactionEntity->received = $transactionsTable->get($transactionEntity->id, ['contain' => false, 'fields' => ['received']])->received;
$transactionEntity->received = $transactionsTable
->find('all', ['contain' => false])
->where(['id' => $transactionEntity->id])
->select(['received'])->first()->received;
} catch(Cake\Datasource\Exception\RecordNotFoundException $ex) {
$this->addError('TransactionBody::save', 'current transaction (with id ' . ($transactionEntity->id) . ' not found');
$this->addError('exception: ', $ex->getMessage());
return false;
}
// calculate tx hash
// previous tx hash + id + received + sigMap as string

View File

@ -5,6 +5,8 @@ namespace Model\Transactions;
//use App\Model\Transactions\TransactionBase;
use Cake\ORM\TableRegistry;
use Cake\Core\Configure;
use Cake\Mailer\Email;
class TransactionCreation extends TransactionBase {
@ -135,12 +137,12 @@ class TransactionCreation extends TransactionBase {
// state user id
//$state_user_id = $this->getStateUserId($firstPublic);
$receiverUser = $this->getStateUserId($this->getReceiverPublic());
if(!$receiverUser) {
$receiverUserId = $this->getStateUserId($this->getReceiverPublic());
if(!$receiverUserId) {
$this->addError('TransactionCreation::save', 'couldn\'t get state user id');
return false;
}
$transactionCreationEntity->state_user_id = $receiverUser;
$transactionCreationEntity->state_user_id = $receiverUserId;
$transactionCreationEntity->amount = $this->getAmount();
$transactionCreationEntity->ident_hash = $this->getIdentHash();
@ -150,10 +152,34 @@ class TransactionCreation extends TransactionBase {
}
// update state balance
if(false === $this->updateStateBalance($receiverUser, $this->getAmount())) {
if(false === $this->updateStateBalance($receiverUserId, $this->getAmount())) {
return false;
}
return true;
}
public function sendNotificationEmail($memo)
{
// send notification email
$receiverUserId = $this->getStateUserId($this->getReceiverPublic());
$receiverUser = $this->getStateUser($receiverUserId);
$noReplyEmail = Configure::read('noReplyEmail');
try {
$email = new Email();
$emailViewBuilder = $email->viewBuilder();
$emailViewBuilder->setTemplate('notificationCreation')
->setVars(['user' => $receiverUser, 'gdd_cent' => $this->getAmount(), 'memo' => $memo]);
$email->setFrom([$noReplyEmail => 'Nicht antworten'])
->setTo([$receiverUser->email => $receiverUser->getNames()])
->setSubject(__('Gradido Schöpfung erhalten'))
->send();
} catch(Exception $e) {
$this->addError('TransactionCreation::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage());
return false;
}
return true;
}

View File

@ -4,6 +4,8 @@ namespace Model\Transactions;
//use App\Model\Transactions\TransactionBase;
use Cake\ORM\TableRegistry;
use Cake\Core\Configure;
use Cake\Mailer\Email;
class TransactionTransfer extends TransactionBase {
private $protoTransactionTransfer;
@ -167,7 +169,7 @@ class TransactionTransfer extends TransactionBase {
$senderAmount = $this->protoTransactionTransfer->getSenderAmounts()[0];
if(count($this->protoTransactionTransfer->getReceiverAmounts()) !== 1) {
$this->addError($functionName, 'not more tahn one receiver currently supported');
$this->addError($functionName, 'not more than one receiver currently supported');
return false;
}
$receiverAmount = $this->protoTransactionTransfer->getReceiverAmounts()[0];
@ -201,11 +203,48 @@ class TransactionTransfer extends TransactionBase {
return false;
}
//$this->addError('TransactionTransfer::save', 'not implemented yet');
//return false;
return true;
}
public function sendNotificationEmail($memo)
{
// send notification email
$senderAmount = $this->protoTransactionTransfer->getSenderAmounts()[0];
$receiverAmount = $this->protoTransactionTransfer->getReceiverAmounts()[0];
$senderUserId = $this->getStateUserId($senderAmount->getEd25519SenderPubkey());
$receiverUserId = $this->getStateUserId($receiverAmount->getEd25519ReceiverPubkey());
$receiverUser = $this->getStateUser($receiverUserId);
$senderUser = $this->getStateUser($senderUserId);
$serverAdminEmail = Configure::read('ServerAdminEmail');
try {
$email = new Email();
$emailViewBuilder = $email->viewBuilder();
$emailViewBuilder->setTemplate('notificationTransfer')
->setVars(['receiverUser' => $receiverUser,
'senderUser' => $senderUser,
'gdd_cent' => $receiverAmount->getAmount(),
'memo' => $memo]);
$email->setFrom([$serverAdminEmail => $senderUser->getNames() . ' via Gradido Community'])
->setTo([$receiverUser->email => $receiverUser->getNames()])
->setReplyTo($senderUser->email)
->setSubject(__('Gradidos erhalten'))
->send();
} catch(Exception $e) {
$this->addError('TransactionTransfer::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage());
return false;
}
return true;
}
static public function fromEntity($transactionTransferEntity)
{
$protoTransfer = new \Model\Messages\Gradido\Transfer();

View File

@ -15,7 +15,10 @@ if($number < 0) {
$class = 'grd-negative-currency';
}
?>
?><?php if(isset($raw) && true == $raw): ?>
<?= $this->Number->format(intval($number) / 10000.0, ['precision' => 2]) . ' GDD';?>
<?php else : ?>
<span class="<?php echo $class;?>">
<?= $this->Number->format(intval($number) / 10000.0, ['precision' => 2]) . ' GDD';?>
</span>
</span>
<?php endif; ?>

View File

@ -24,7 +24,7 @@ $this->assign('title', __('Fehlermeldungen'));
$type = $transactionTypes[$error->transaction_type_id-1];
$errorMessage = "";
$errorArray = json_decode($error->message_json, true);
if(isset($errorArray['details'])) {
if(isset($errorArray['details']) && is_array($errorArray['details'])) {
foreach($errorArray['details'][0] as $function => $errorString) {
$errorMessage = '<b>' . $function . '</b><br> ' . $errorString;

View File

@ -1,174 +0,0 @@
<?php
namespace App\Test\TestCase\Controller;
use App\Controller\JsonRequestHandlerController;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
/**
* App\Controller\TransactionJsonRequestHandlerController Test Case
*
* @uses \App\Controller\TransactionJsonRequestHandlerController
*/
class TransactionJsonRequestHandlerControllerTest extends TestCase
{
use IntegrationTestTrait;
/**
* Fixtures
*
* @var array
*/
public $fixtures = [
'app.TransactionCreations',
'app.Transactions',
'app.StateUsers',
'app.StateErrors',
'app.TransactionSignatures',
'app.TransactionSendCoins',
'app.StateBalances',
'app.TransactionTypes'
];
public $transactions = [
'validCreation' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQJ8wF12eZo3hcMAlAKKJ9WLT-zuSkNmGh7D98UEqH4KoIysnCkXqEya9EBZl9o11_nJ8xmm_nOevuVjR-GfLMQ8qSQoOSGFsbG8gV2VsdCAxMjMSBgiZm4ruBUovCicKIJSuE1uTzZ8zdStOVcQZA6P6oTp1u5C_1BHqHUoaXnEfEKDakwEQtYntlgo',
'validCreation900' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQNVZ8Ae3Zbg3G0wZ840fzKan6N4KtTcSe0KYi17kQwFmsl18oFxXv8_s6j1xXFrIKjy1_1Olq0a7xYLErDMkjwYqORIGCNb5iu4FSi8KJwoglK4TW5PNnzN1K05VxBkDo_qhOnW7kL_UEeodShpecR8QgNHKCBC1ie2WCg',
'validCreation1200' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQEEey5QMAdldoOTP_jTETHgOQriGsixEY0cziQeRfT_J5YtbI_A6AizEYD-JcxmRmXzv1xjjTgsV39Y32ta2CQkqORIGCIeGi-4FSi8KJwoglK4TW5PNnzN1K05VxBkDo_qhOnW7kL_UEeodShpecR8QgOy4CxC1ie2WCg',
'notBase64' => 'CgpIYWxsbyBXZW-0EgYIyfSG7gV_LwonCiCboKikqwjZfes9xuqgthFH3',
'validTransfer' => 'GmYKZAoggZC9pYXuXx2fv30G6B5p7BjhM3YQTP9Ut0V-t9PvcQ0SQDddHyKzAX3LBV0PuDiPc6lxkUipss5tyuLRpMtFJQnT30tsbYIkA1FXimjMKOoiuLswf4OLLV3bAIYehW-b9AgqYQoFSGFsbG8SBgiJlaPvBUJQCiYKIIGQvaWF7l8dn799BugeaewY4TN2EEz_VLdFfrfT73ENEICfSRImCiDtdleSLxhUgEbMW9DpqIwsykFj3-z_enKEOuGnXrmW8xCAn0k',
'errornusTransfer' => 'ClxGcm9oZXMgTmV1ZXMgSmFociB1bmQgREFOS0UsIGRhc3MgZHUgZGljaCBzbyBlaW5zZXR6dCBmw7xyIEdyYWRpZG8hIEhlcnpsaWNoZSBHcsO8w59lIFRlcmVzYRIGCPjjgvEFQlAKJgogUQwFYeVlGlfWDrkXNN7rHwejoCDJKt+YkYJfbJVyj3EQwIQ9EiYKIPXIRnUhVJ/zCs5+y/VaTBjTIoYizJNwS+JC//xsbQrHEMCEPQ=='
];
/*public function setUp() {
parent::setUp();
}
*/
public function testWrongMethod()
{
$this->configRequest([
'headers' => ['Accept' => 'application/json']
]);
$this->get('/TransactionJsonRequestHandler');
$this->assertResponseOk();
$expected = json_encode(['state' => 'error', 'msg' => 'no post']);
$this->assertEquals($expected, (string)$this->_response->getBody());
}
public function testInvalidJson()
{
$this->configRequest([
'headers' => ['Accept' => 'application/json']
]);
$this->post('/TransactionJsonRequestHandler', '{This isn\'t valid json}');
$this->assertResponseOk();
$expected = json_encode(['state' => 'error', 'msg' => 'parameter error']);
$this->assertEquals($expected, (string)$this->_response->getBody());
}
public function testNotSetTransaction()
{
$this->postAndParse(
['method' => 'putTransaction'],
['state' => 'error', 'msg' => 'parameter error']
);
}
public function testNotSetMethod()
{
$this->postAndParse(
['transaction' => $this->transactions['validCreation']],
['state' => 'error', 'msg' => 'parameter error']
);
}
public function testUnknownMethod()
{
//$this->post('/TransactionJsonRequestHandler', ['method' => 'putTransaction', 'transaction' => 'CgpIYWxsbyBXZWx0EgYIyfSG7gVKLwonCiCboKikqwjZfes9xuqgthFH3/cHHaWchkUhWiGhQjB23xCg2pMBELWJ7ZYK']);
$this->postAndParse(
['method' => 'foobar', 'transaction' => $this->transactions['validCreation']],
['state' => 'error', 'msg' => 'unknown method', 'details' => 'foobar']
);
}
public function testInvalidEncodedTransaction() {
//"msg":"error parsing transaction","details":[{"Transaction":"base64 decode error"}]
$this->postAndParse(
['method' => 'putTransaction', 'transaction' => $this->transactions['notBase64']],
['state' => 'error', 'msg' => 'error parsing transaction', 'details' => [
['Transaction' => 'invalid base64 string']
]]
);
}
public function testInvalidTransaction() {
$this->postAndParse(
['method' => 'putTransaction', 'transaction' => base64_encode('Hallo Miau Welt')],
['state' => 'error', 'msg' => 'error parsing transaction', 'details' => [
['Transaction' => 'Error occurred during parsing: Unexpected wire type.']
]]
);
}
public function testToLargeCreationSum()
{
$this->postAndParse(
['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation900']],
'{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1000 gr per Month not allowed"}]}'
);
}
public function testToLargeCreation()
{
$this->postAndParse(
['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation1200']],
'{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1000 gr per Month not allowed"}]}'
);
}
public function testValidTransfer()
{
$this->postAndParse(
['method' => 'putTransaction', 'transaction' => $this->transactions['validTransfer']],
['state' => 'success']
);
}
/*public function testMissingPreviousTransaction()
{
}*/
public function testValidTransaction()
{
$this->postAndParse(
['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation']],
['state' => 'success']
);
}
private function postAndParse($params, $expected)
{
$this->configRequest([
'headers' => ['Accept' => 'application/json']
]);
$this->disableErrorHandlerMiddleware();
$this->post('/TransactionJsonRequestHandler', json_encode($params));
// Check that the response was a 200
$this->assertResponseOk();
$responseBodyString = (string)$this->_response->getBody();
$json = json_decode($responseBodyString);
$this->assertNotFalse($json);
if(is_array($expected)) {
$expected = json_encode($expected);
}
$this->assertEquals($expected, $responseBodyString);
}
}