update transfer

This commit is contained in:
Dario Rekowski on RockPI 2019-12-04 16:10:08 +00:00
parent abfaf577ca
commit da84873379
10 changed files with 290 additions and 51 deletions

View File

@ -9,15 +9,35 @@
return [
// Container element used by control().
'inputContainer' => '<div class="form-group row showcase_row_area">{{content}}</div>',
// Container element used by control() when a field has an error.
//'inputContainerError' => '<div class="input {{type}}{{required}} error">{{content}}{{error}}</div>',
'inputContainerError' => '<div class="form-group row showcase_row_area {{type}}{{required}} is-invalid">{{content}}{{error}}</div>',
// Label element when inputs are not nested inside the label.
'label' => '<div class="col-md-3 showcase_text_area">'
. '<label{{attrs}}>{{text}}</label>'
. '</div>',
// Generic input element.
'input' => '<div class="col-md-9 showcase_content_area">'
. '<input type="{{type}}" name="{{name}}"{{attrs}}/>'
. '<input type="{{type}}" class="form-control" name="{{name}}"{{attrs}}/>'
. '</div>',
// Textarea input element,
'textarea' => '<div class="col-md-9 showcase_content_area">'
. '<textarea class="form-control" name="{{name}}"{{attrs}}>{{value}}</textarea>'
. '</div>',
// Error message wrapper elements.
//'error' => '<div class="error-message">{{content}}</div>',
//'error' => '{{content}}',
'error' => '<div class="col-md-9 offset-md-3 showcase_content_area invalid-feedback">'
. '{{content}}'
. '</div>',
// Container for error items.
//'errorList' => '<ul>{{content}}</ul>',
'errorList' => '{{content}}',
// Error item wrapper.
//'errorItem' => '<li>{{text}}</li>',
'errorItem' => '<div>{{text}}</div>'
];
/*

View File

@ -2,8 +2,14 @@
namespace App\Controller;
use App\Controller\AppController;
use App\Form\CreationForm;
use Cake\ORM\TableRegistry;
use Cake\Http\Client;
use Cake\Core\Configure;
use Cake\Routing\Router;
use App\Form\TransferForm;
use Model\Transactions\TransactionTransfer;
/**
* TransactionSendCoins Controller
*
@ -118,12 +124,114 @@ class TransactionSendCoinsController extends AppController
}
$user = $session->read('StateUser');
}
$transferForm = new TransferForm();
$this->set('transferForm', $transferForm);
$this->set('timeUsed', microtime(true) - $startTime);
if ($this->request->is('post')) {
$this->Flash->error(__('Wird zurzeit noch entwickelt!'));
//$this->Flash->error(__('Wird zurzeit noch entwickelt!'));
$requestData = $this->request->getData();
$mode = 'next';
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;
}
$stateUserTable = TableRegistry::getTableLocator()->get('StateUsers');
$receiverUser = $stateUserTable
->find('all')
->select(['public_key'])
->contain(false)
->where(['email' => $receiverEmail])->first();
//var_dump($receiverUser);
if(!$receiverUser) {
$this->Flash->error(__('Diese E-Mail ist mir nicht bekannt, hat dein Empfänger denn schon ein Gradido-Konto?'));
return;
}
$receiverPubKeyHex = bin2hex(stream_get_contents($receiverUser->public_key));
//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(Router::url('/', true) . '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(Router::url('/', true) . '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'));
}
// */
} else {
$this->Flash->error(__('Something was invalid, please try again!'));
}
}
$creationForm = new CreationForm();
$this->set('creationForm', $creationForm);
$this->set('timeUsed', microtime(true) - $startTime);
}

View File

@ -39,7 +39,8 @@ class CreationForm extends Form
->add('memo', 'custom', [
'rule' => 'alphaNumeric',
'provider' => 'custom',
'message' => __('Only Alpha Numeric Character allowed')
//'message' => __('Only Alpha Numeric Character allowed')
'message' => __('No HTML Tags like &gt; or &lt; please.')
])
->allowEmptyString('memo', null, 'create')
/*->add('receiver_pubkey_hex', 'custom', [

View File

@ -1,8 +1,75 @@
<?php
<?php
// in src/Form/ContactForm.php
namespace App\Form;
/*
* 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.
*/
use Cake\Form\Form;
use Cake\Form\Schema;
use Cake\Validation\Validator;
class TransferForm extends Form
{
protected function _buildSchema(Schema $schema)
{
return $schema
->addField('email', ['type' => 'string'])
->addField('amount', ['type' => 'decimal', 'precision' => 2])
->addField('memo', ['type' =>'text', 'default' => '', 'rows' => 5, 'maxlength' => 150]);
}
function validationDefault(Validator $validator)
{
$validator->setProvider('custom', 'App\Model\Validation\TransactionValidation');
/*
$validator->add('receiver_pubkey_hex', 'length', [
'rule' => ['length', 64],
'message' => 'a valid pubkey in hex format is required (64 character)'
])->add('receiver_pubkey_hex_select', 'length', [
'rule' => ['length', 64],
'message' => 'a valid pubkey in hex format is required (64 character)',
]);
*/
// TODO: add validation for used character to prevent hacking attempts
$validator->add('email', 'format', [
'rule' => 'email',
'message' => __('A valid email address is required')
])
->add('memo', 'length', [
'rule' => ['maxLength', 150],
'message' => __('The memo should contain max 150 character')
])
//->alphaNumeric('memo', __('Only Alpha Numeric Character allowed'))
->add('memo', 'custom', [
'rule' => 'alphaNumeric',
'provider' => 'custom',
//'message' => __('Only Alpha Numeric Character allowed')
'message' => __('No HTML Tags like &gt; or &lt; please.')
])
->allowEmptyString('memo', null, 'create')
/*->add('receiver_pubkey_hex', 'custom', [
'rule' => 'hexKey64',
'provider' => 'custom',
'message' => 'a valid pubkey in hex format is required (64 character)'
])
->allowEmptyString('receiver_pubkey_hex', null, 'create')*/
->add('amount', 'custom', [
'rule' => 'amount',
'provider' => 'custom',
'message' => __('Please give a valid positive number with maximal 2 decimal places')
]);
return $validator;
}
/*
* $validator->add('title', 'custom', [
'rule' => 'customRule',
'provider' => 'custom',
'message' => 'The title is not unique enough'
]);
*/
protected function _execute(array $data)
{
// Send an email.
return true;
}
}

View File

@ -22,7 +22,7 @@ class TransactionCreation extends TransactionBase {
{
$receiver = new \Model\Messages\Gradido\ReceiverAmount();
$receiver->setAmount($amount);
$this->receiver_pubkey_hex = $receiver_public_hex;
//$this->receiver_pubkey_hex = $receiver_public_hex;
if(strlen($receiver_public_hex) != 64) {
return ['state' => 'error', 'msg' => 'invalid pubkey'];
}

View File

@ -6,17 +6,59 @@ namespace Model\Transactions;
class TransactionTransfer extends TransactionBase {
private $protoTransactionTransfer;
private $receiver_pubkey_hex;
private $sender_pubkey_hex;
public function __construct($protoTransactionTransfer) {
$this->protoTransactionTransfer = $protoTransactionTransfer;
}
static public function build($amount, $memo, $receiver_public_hex, $sender_public_hex)
{
// repeated SenderAmount senderAmounts = 1;
// repeated ReceiverAmount receiverAmounts = 2;
$receiver = new \Model\Messages\Gradido\ReceiverAmount();
$sender = new \Model\Messages\Gradido\SenderAmount();
$receiver->setAmount($amount);
$sender->setAmount($amount);
if(strlen($receiver_public_hex) != 64) {
return ['state' => 'error', 'msg' => 'invalid receiver pubkey'];
}
if(strlen($sender_public_hex) != 64) {
return ['state' => 'error', 'msg' => 'invalid sender pubkey'];
}
$receiverPubKeyBin = hex2bin($receiver_public_hex);
$receiver->setEd25519ReceiverPubkey($receiverPubKeyBin);
$senderPubKeyBin = hex2bin($sender_public_hex);
$sender->setEd25519SenderPubkey($senderPubKeyBin);
//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\Transfer();
$transaction->setReceiverAmounts([$receiver]);
$transaction->setSenderAmounts([$sender]);
$transactionBody->setTransfer($transaction);
return ['state' => 'success', 'transactionBody' => $transactionBody];
}
public function validate($sigPairs) {
return true;
$this->addError('TransactionTransfer::validate', 'not implemented yet');
return false;
//return true;
}
public function save($transaction_id, $firstPublic) {
return true;
$this->addError('TransactionTransfer::save', 'not implemented yet');
return false;
//return true;
}
}

View File

@ -20,7 +20,7 @@ class TransactionValidation
$floatVal = floatval(Number::format($value, ['places' => 4, 'locale' => 'en_GB']));
//echo "floatVal: $floatVal<br>";
return $floatVal != 0.0;
return $floatVal >= 0.0;
}
public static function hexKey64($value, array $context) {
@ -32,9 +32,10 @@ class TransactionValidation
}
public static function alphaNumeric($value, array $context) {
if(preg_match('/^[a-zA-Z0-9äöüÄÖÜß _-]*$/', $value)) {
return true;
//if(preg_match('/^[a-zA-Z0-9äöüÄÖÜß _;:()-]\n\r*$/', $value)) {
if(preg_match('/([<>]|&gt;|&lt;|javascript:){1,}/', $value)) {
return false;
}
return false;
return true;
}
}

View File

@ -30,12 +30,12 @@ class NavHeaderEntry
'<i class="mdi mdi-alert-outline grd-alert-color mdi-1x"></i>'
. '<span class="notification-indicator notification-indicator-warning notification-indicator-ripple"></span>',
['controller' => 'StateErrors', 'action' => 'ShowForUser'],
['class' => 'nav-link', 'escape' => false, 'title' => "($errorCount) " . __('Fehler')]) ?>
['class' => 'nav-link', 'escape' => false, 'title' => "$errorCount " . __('Fehler')]) ?>
</li>
<?php endif; ?>
<?php if($transactionPendings > 0) : ?>
<li class="nav-item">
<a class="nav-link" title="<?= "($transactionPendings) " . __('Transaktionen sind noch zu unterzeichnen')?>" href="<?= Router::url('./', true) ?>account/checkTransactions">
<a class="nav-link" title="<?= "$transactionPendings " . __('Transaktionen sind noch zu unterzeichnen')?>" href="<?= Router::url('./', true) ?>account/checkTransactions">
<i class="mdi mdi-signature-freehand mdi-1x"></i>
<!--(<?= $transactionPendings ?>)-->
<span class="notification-indicator notification-indicator-primary notification-indicator-ripple"></span>

View File

@ -7,8 +7,16 @@
*/
$this->assign('title', __('Überweisung'));
// In a View class
$this->loadHelper('Form', [
'templates' => 'ripple_horizontal_form',
]);
?>
<style type="text/css">
.showcase_content_area .invalid-feedback {
display:block;
}
</style>
<div class="row">
<div class="col-md-10 equel-grid">
<div class="grid">
@ -17,33 +25,12 @@ $this->assign('title', __('Überweisung'));
<div class="item-wrapper">
<div class="row mb-3">
<div class="col-md-10 mx-auto">
<?= $this->Form->create($creationForm) ?>
<div class="form-group row showcase_row_area">
<div class="col-md-3 showcase_text_area">
<label for="inputAmount">Betrag in GDD</label>
</div>
<div class="col-md-9 showcase_content_area">
<input type="number" step="0.01" class="form-control" id="inputAmount" name="inputAmount" >
</div>
</div>
<div class="form-group row showcase_row_area">
<div class="col-md-3 showcase_text_area">
<label for="inputMemo">Verwendungszweck</label>
</div>
<div class="col-md-9 showcase_content_area">
<textarea class="form-control" id="inputMemo" name="inputMemo" cols="12" rows="5"></textarea>
</div>
</div>
<div class="form-group row showcase_row_area">
<div class="col-md-3 showcase_text_area">
<label for="inputReceiver">Empfänger</label>
</div>
<div class="col-md-9 showcase_content_area">
<input type="email" class="form-control" id="inputReceiver" name="inputReceiver" placeholder="E-Mail">
</div>
</div>
<button type="submit" class="btn btn-sm btn-primary" name="next">Transaktion(n) abschließen</button>
<button type="submit" class="btn btn-sm" name="add">Weitere Transaktion erstellen</button>
<?= $this->Form->create($transferForm) ?>
<?= $this->Form->control('amount', ['label' => __('Betrag in GDD')]) ?>
<?= $this->Form->control('memo', ['label' => __('Verwendungszweck')]) ?>
<?= $this->Form->control('email', ['label' => __('Empfänger'), 'placeholder' => 'E-Mail']) ?>
<?= $this->Form->button(__('Transaktion(n) abschließen'), ['name' => 'next', 'class' => 'btn btn-sm btn-primary']) ?>
<?= $this->Form->button(__('Weitere Transaktion erstellen'), ['name' => 'add', 'class' => 'btn btn-sm']) ?>
<?= $this->Form->end() ?>
</div>
</div>
@ -51,4 +38,17 @@ $this->assign('title', __('Überweisung'));
</div>
</div>
</div>
</div>
</div>
<?php // adding scripts vendor and core from ripple ui for validation effect ?>
<?= $this->Html->script(['core', 'vendor.addons']); ?>
<script type="text/javascript">
(function ($) {
'use strict';
$('textarea').maxlength({
alwaysShow: true,
warningClass: "badge mt-1 badge-success",
limitReachedClass: "badge mt-1 badge-danger"
});
})(jQuery);
</script>

File diff suppressed because one or more lines are too long