Merge pull request #49 from gradido/stage2

Stage2
This commit is contained in:
einhornimmond 2021-04-13 14:56:00 +02:00 committed by GitHub
commit 279021eb8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
485 changed files with 34307 additions and 7042 deletions

48
.gitmodules vendored
View File

@ -2,24 +2,30 @@
path = gn
url = https://github.com/gradido/gn.git
branch = master
#[submodule "mithril_client"]
# path = community_server/mithril_client
# url = https://github.com/gradido/gradido_mithrilJS_client.git
[submodule "src/protobuf"]
path = community_server/src/protobuf
url = https://github.com/gradido/gradido_protocol.git
[submodule "dependencies/tinf"]
path = login_server/dependencies/tinf
url = https://github.com/jibsen/tinf.git
[submodule "dependencies/mariadb-connector-c"]
path = login_server/dependencies/mariadb-connector-c
url = https://github.com/MariaDB/mariadb-connector-c.git
[submodule "src/proto"]
path = login_server/src/proto
url = https://github.com/gradido/gradido_protocol.git
[submodule "dependencies/iroha-ed25519"]
path = login_server/dependencies/iroha-ed25519
url = https://github.com/gradido/iroha-ed25519.git
[submodule "dependencies/spirit-po"]
path = login_server/dependencies/spirit-po
url = https://github.com/cbeck88/spirit-po.git
[submodule "login_server/dependencies/tinf"]
path = login_server/dependencies/tinf
url = https://github.com/jibsen/tinf.git
[submodule "login_server/dependencies/mariadb-connector-c"]
path = login_server/dependencies/mariadb-connector-c
url = https://github.com/MariaDB/mariadb-connector-c.git
[submodule "login_server/src/proto"]
path = login_server/src/proto
url = https://github.com/gradido/gradido_protocol.git
[submodule "login_server/dependencies/spirit-po"]
path = login_server/dependencies/spirit-po
url = https://github.com/cbeck88/spirit-po.git
[submodule "login_server/dependencies/grpc"]
path = login_server/dependencies/grpc
url = https://github.com/grpc/grpc.git
[submodule "login_server/dependencies/poco"]
path = login_server/dependencies/poco
url = https://github.com/pocoproject/poco.git
[submodule "login_server/dependencies/cmake-modules"]
path = login_server/dependencies/cmake-modules
url = https://github.com/viaduck/cmake-modules.git
[submodule "community_server/src/protobuf"]
path = community_server/src/protobuf
url = git@github.com:gradido/gradido_protocol.git

View File

@ -3,7 +3,6 @@ logs/
src/GPBMetadata/
tmp/
vendor/
composer.lock
websrc/node_modules/
websrc/package-lock.json
mithril_client/

View File

@ -1,6 +1,3 @@
#[submodule "mithril_client"]
# path = mithril_client
# url = git@github.com:gradido/gradido_mithrilJS_client.git
[submodule "src/protobuf"]
path = src/protobuf
url = git@github.com:gradido/gradido_protocol.git

View File

@ -6,7 +6,7 @@
"license": "MIT",
"require": {
"php": ">=5.6",
"cakephp/cakephp": "3.8.*",
"cakephp/cakephp": "3.9.*",
"cakephp/migrations": "^2.0.0",
"cakephp/plugin-installer": "^1.0",
"datto/json-rpc": "^6.0",
@ -30,9 +30,9 @@
"autoload": {
"psr-4": {
"App\\": "src/",
"" : "src/",
"GPBMetadata\\": "src/GPBMetadata",
"Model\\Messages\\Gradido\\" : "src/Model/Messages/Gradido"
"" : "src/",
"GPBMetadata\\Gradido\\": "src/Model/Messages/GPBMetadata/Gradido/",
"Proto\\Gradido\\" : "src/Model/Messages/Proto/Gradido/"
}
},
"autoload-dev": {

5577
community_server/composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -57,12 +57,12 @@ Router::scope('/', function (RouteBuilder $routes) {
$csrf->whitelistCallback(function ($request) {
// Skip token check for API URLs.
//die($request->getParam('controller'));
$whitelist = ['JsonRequestHandler', 'ElopageWebhook'];
$whitelist = ['JsonRequestHandler', 'ElopageWebhook', 'AppRequests'];
$ajaxWhitelist = ['TransactionSendCoins', 'TransactionCreations'];
foreach($whitelist as $entry) {
if($request->getParam('controller') === $entry) {
if($entry == 'ElopageWebhook') {
if($entry == 'ElopageWebhook' || $entry == 'AppRequests') {
return true;
}
if($request->clientIp() == '127.0.0.1' || $request->clientIp() == 'localhost') {
@ -110,7 +110,11 @@ Router::scope('/', function (RouteBuilder $routes) {
*/
//$routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
$routes->connect('/', ['controller' => 'Dashboard', 'action' => 'index']);
$routes->connect('/api/:action/*', ['controller' => 'AppRequests'], ['routeClass' => 'DashedRoute']);
//$routes->connect('/client', ['controller' => 'Pages', 'action' => 'display', 'js']);
$routes->connect('/server', ['controller' => 'Dashboard', 'action' => 'serverIndex']);
$routes->connect('/client', ['controller' => 'Pages', 'action' => 'display', 'vue']);
$routes->connect('/vue-dev', ['controller' => 'Pages', 'action' => 'display', 'vue-dev']);
//$routes->connect('/', 'https://gradido2.dario-rekowski.de/account', array('status' => 303));
/**

View File

@ -0,0 +1,132 @@
# community server api
In this examples I assume that you use gradido with docker-compose build on your local maschine
## Konto Overview
return current account balance
GET http://localhost/state-balances/ajaxGetBalance/-127182
If session is valid, return:
```json
{"state":"success","balance":174500}
```
- balance: Gradido Cent, 4 Nachkommastellen (2 Reserve), 174500 = 17,45 GDD
## List Transactions
List all transactions from logged in user, currently without paging
Ajax:
GET http://localhost/state-balances/ajaxListTransactions/-127182/
or
GET http://localhost/state-balances/ajaxListTransactions/-127182/DESC
to get transaction in descending order
Antwort:
Wenn alles okay:
```json
{"state":"success", "transactions":
[
{
"name": "Max Mustermann",
"email": "Maxim Mustermann",
"type": "send",
"transaction_id": 2,
"date": "2021-02-19T13:25:36+00:00",
"balance": 1920000,
"memo": "a piece of cake :)",
"pubkey": "038a6f93270dc57b91d76bf110ad3863fcb7d1b08e7692e793fcdb4467e5b6a7"
}
],
"transactionExecutingCount": 0,
"count": 1,
"gdtSum": 0,
"timeUsed": 0.04562687873840332
}
```
- name: name of other involved party or empty if unknown (if other party don't belong to group)
- if type is send, name is name of receiver
- if type is receive, name is name of sender
- if type is creation currently I use a static string ("Gradido Akademie)
- email: optional, only if type is send or receive and other user is known
- pubkey: optional, only if type is send or receive and other user isn't known
- type: type of transaction
- creation: user has get gradidos created
- send: user has send another user gradidos
- receiver: user has received gradidos from another user
- transaction_id: id of transaction in db, in stage2 also the hedera sequence number of transaction
- date: date of ordering transaction (booking date)
- balance: Gradido Cent, 4 Nachkommastellen (2 Reserve), 1920000 = 192,00 GDD
- memo: Details about transaction
- pubkey: optional, if other party isn't known, hexadecimal representation of 32 Byte public key of user [0-9a-f]
- transactionExecutingCount: how many transaction for this user currently pending and waiting for signing
- count: sum of finished transactions user is involved
- gdtSum: sum of gdt of user in cent with 2 places (Nachkommastellen)
- timeUsed: time used for getting data from db in seconds, only for analyse backend performance
## Creation Transaction
Make a creation transaction
With new Option set in Login-Server:
```ini
unsecure.allow_auto_sign_transactions = 1
```
transactions can be auto-signed directly with handing in transaction.
Normally a forwarding to login-server check transactions side is neccessary to minimize security risks.
POST http://localhost/transaction-creations/ajaxCreate
```json
{
"session_id" : -127182,
"email": "max.musterman@gmail.de",
"amount": 10000000,
"target_date":"2021-02-19T13:25:36+00:00",
"memo":"AGE",
"auto_sign": true
}
```
return if everything is ok:
```json
{"state":"success", "timeUsed": 0.0122}
```
- timeUsed: time used for getting data from db in seconds, only for analyse backend performance
## Send Coins Transaction
Make a simple GDD Transaction, send Coins from one user to other.
With new Option set in Login-Server:
```ini
unsecure.allow_auto_sign_transactions = 1
```
transactions can be auto-signed directly with handing in transaction.
Normally a forwarding to login-server check transactions side is neccessary to minimize security risks.
POST http://localhost/transaction-send-coins/ajaxCreate
```json
{
"session_id" : -127182,
"amount": 2000000,
"email": "max.musterman@gmail.de",
"memo":"Thank you :)",
"auto_sign": true
}
```
- amout: amount to transfer, 2000000 = 200,00 GDD
- email: receiver email address, must be differ from user email
- memo: Details about transaction
- auto_sign: set to true to directly sign transaction if unsecure.allow_auto_sign_transactions = 1 is set
return if everything is ok:
```json
{"state":"success", "timeUsed": 0.0122}
```
- timeUsed: time used for getting data from db in seconds, only for analyse backend performance
Than the transaction was created on community server, send to login-server, signed (if unsecure.allow_auto_sign_transactions = 1 and auto_sign = true)
and send back to community server and put into db.
After you get this answear you see the new transaction if you list transactions or call for the balance.
Without auto-sign the transaction is pending on login-server and waits for the user to review it at
http://localhost/account/checkTransactions

View File

@ -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

View File

@ -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;

View File

@ -0,0 +1,17 @@
/*
* 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.
*/
/**
* Author: einhornimmond
* Created: 06.04.2021
*/
CREATE TABLE `blockchain_types` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`text` varchar(255) NULL,
`symbol` varchar(10) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@ -0,0 +1,2 @@
INSERT INTO `address_types` (`id`, `name`, `text`) VALUES
(1, 'user main', 'user main address');

View File

@ -0,0 +1,5 @@
INSERT INTO `blockchain_types` (`id`, `name`, `text`, `symbol`) VALUES
(1, 'mysql', 'use mysql db as blockchain, work only with single community-server', NULL),
(2, 'hedera', 'use hedera for transactions', 'HBAR');

View File

@ -1,5 +1,10 @@
INSERT INTO `transaction_types` (`id`, `name`, `text`) VALUES
(1, 'creation', 'Aktives oder Bedingungsloses Grundeinkommen.'),
(2, 'transfer', 'Einfache Überweisung');
(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');

View File

@ -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;

View File

@ -4,6 +4,6 @@ CREATE TABLE `state_user_transactions` (
`transaction_id` int UNSIGNED NOT NULL,
`transaction_type_id` int UNSIGNED NOT NULL,
`balance` bigint(20) DEFAULT 0,
`balance_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`balance_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@ -1,7 +1,9 @@
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,
`id` int unsigned NOT NULL AUTO_INCREMENT,
`transaction_id` int unsigned NOT NULL,
`address_type_id` int unsigned NOT NULL,
`remove_from_group` BOOLEAN DEFAULT FALSE,
`public_key` binary(32) NOT NULL,
`state_user_id` int unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@ -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`)

View File

@ -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;

View File

@ -2,8 +2,9 @@ CREATE TABLE `transactions` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`state_group_id` int(10) unsigned DEFAULT NULL,
`transaction_type_id` int(10) unsigned NOT NULL,
`tx_hash` binary(32) DEFAULT NULL,
`tx_hash` binary(48) DEFAULT NULL,
`memo` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`received` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`blockchain_type_id` bigint(20) unsigned NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@ -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());

View File

@ -35,6 +35,7 @@ class AppController extends Controller
{
var $loginServerUrl = '';
var $blockchainType = 'mysql';
/**
* Initialization hook method.
*
@ -91,12 +92,11 @@ class AppController extends Controller
$stateBalancesTable = TableRegistry::getTableLocator()->get('stateBalances');
$stateBalanceQuery = $stateBalancesTable
->find('all')
->select('amount')
->contain(false)
->where(['state_user_id' => $state_user_id]);
if ($stateBalanceQuery->count() == 1) {
//var_dump($stateBalanceEntry->first());
$session->write('StateUser.balance', $stateBalanceQuery->first()->amount);
$session->write('StateUser.balance', $stateBalanceQuery->first()->decay);
//echo "stateUser.balance: " . $session->read('StateUser.balance');
}
}
@ -137,16 +137,42 @@ class AppController extends Controller
} else {
$this->loginServerUrl = Router::url('/', true);
}
/*
*
* 'GradidoBlockchain' => [
* // type:
* // - mysql: centralized blockchain in mysql db, no cross group transactions
* // - hedera: send transaction over hedera
* 'type' => 'hedera',
* // gradido nodes with blockchain (if type != mysql)
* 'nodes' => [
* ['host' => 'http://192.168.178.225', 'port' => 13702]
* ]
* ],
*/
$blockchain = Configure::read('GradidoBlockchain');
if($blockchain && isset($blockchain['type'])) {
$this->blockchainType = $blockchain['type'];
}
}
protected function requestLogin($session_id = 0, $redirect = true)
protected function requestLogin($sessionId = 0, $redirect = true)
{
$session = $this->getRequest()->getSession();
// check login
// disable encryption for cookies
//$this->Cookie->configKey('User', 'encryption', false);
if(!$session_id) {
$session_id = intval($this->request->getCookie('GRADIDO_LOGIN', ''));
$session_id = 0;
$php_session_id = 0;
if($session->check('session_id')) {
$php_session_id = intval($session->read('session_id'));
}
$cookie_session_id = intval($this->request->getCookie('GRADIDO_LOGIN', ''));
if($php_session_id != 0) {
$session_id = $php_session_id;
} else if($cookie_session_id != 0) {
$session_id = $cookie_session_id;
} else {
$session_id = $sessionId;
}
$ip = $this->request->clientIp();
if (!$session->check('client_ip')) {
@ -158,14 +184,16 @@ class AppController extends Controller
if ($session_id != 0) {
$userStored = $session->read('StateUser');
$transactionPendings = $session->read('Transactions.pending');
$transactionExecutings = $session->read('Transactions.executing');
$transactionExecutings = $session->read('Transactions.executing');
$transaction_can_signed = $session->read('Transactions.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 {
@ -189,9 +217,11 @@ class AppController extends Controller
//var_dump($json);
$transactionPendings = $json['Transactions.pending'];
$transactionExecuting = $json['Transactions.executing'];
$transaction_can_signed = $json['Transactions.can_signed'];
//echo "read transaction pending: $transactionPendings<br>";
$session->write('Transactions.pending', $transactionPendings);
$session->write('Transactions.executing', $transactionExecuting);
$session->write('Transactions.can_signed', $transaction_can_signed);
$session->write('session_id', $session_id);
$stateUserTable = TableRegistry::getTableLocator()->get('StateUsers');
@ -200,12 +230,15 @@ class AppController extends Controller
$stateUserQuery = $stateUserTable
->find('all')
->where(['public_key' => $public_key_bin])
->contain(['StateBalances']);
->contain('StateBalances', function ($q) {
return $q->order(['record_date' => 'DESC'])
->limit(1);
});
if ($stateUserQuery->count() == 1) {
$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']
@ -221,7 +254,8 @@ class AppController extends Controller
}
//var_dump($stateUser);
if (count($stateUser->state_balances) > 0) {
$session->write('StateUser.balance', $stateUser->state_balances[0]->amount);
$session->write('StateUser.balance', $stateUser->state_balances[0]->decay);
}
$session->write('StateUser.id', $stateUser->id);
//echo $stateUser['id'];
@ -258,6 +292,9 @@ class AppController extends Controller
$this->Flash->error(__('Konto ist nicht aktiviert!'));
}
//die(json_encode($json));
if(preg_match('/client ip/', $json['msg'])) {
return $this->redirect($this->loginServerUrl . 'account/error500/ipError', 303);
}
return $this->redirect($this->loginServerUrl . 'account/', 303);
}
}

View File

@ -0,0 +1,274 @@
<?php
/*!
* @author: Dario Rekowski
* @date : 2020-12-01
* @brief: Controller for all ajax-json requests caming from mobile app
*
* Everything is allowed to call them, so caution!
*/
namespace App\Controller;
use App\Controller\AppController;
use Cake\ORM\TableRegistry;
use Cake\Http\Client;
use Cake\Core\Configure;
class AppRequestsController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent('JsonRequestClient');
//$this->loadComponent('JsonRpcRequestClient');
//$this->Auth->allow(['add', 'edit']);
$this->Auth->allow(['index', 'sendCoins', 'createCoins']);
}
public function index()
{
if($this->request->is('get')) {
$method = $this->request->getQuery('method');
switch($method) {
}
return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for get', 'details' => $method]);
}
else if($this->request->is('post')) {
$jsonData = $this->request->input('json_decode');
//var_dump($jsonData);
if($jsonData == NULL || !isset($jsonData->method)) {
return $this->returnJson(['state' => 'error', 'msg' => 'parameter error']);
}
$method = $jsonData->method;
switch($method) {
}
return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]);
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post or get']);
}
private function checkAndCopyRequiredFields($fields, &$param, $data = null) {
if($data == null) {
$data = $this->request->input('json_decode');
}
foreach($fields as $field) {
if(is_array($field)) {
$one_exist = false;
foreach($field as $oneField) {
if(isset($data[$oneField])) {
$param[$oneField] = $data[$oneField];
$one_exist = true;
break;
}
}
if(!$one_exist) {
return ['state' => 'error', 'msg' => 'missing field of set', 'details' => $field];
}
} else {
if(!isset($data[$field])) {
return ['state' => 'error', 'msg' => 'missing field', 'details' => $field . ' not found'];
} else {
$param[$field] = $data[$field];
}
}
}
return true;
}
private function rewriteKeys(&$data, $replaceKeys)
{
foreach(array_keys($replaceKeys) as $key) {
$newKey = $replaceKeys[$key];
if(isset($data[$key])) {
$data[$newKey] = $data[$key];
unset($data[$key]);
}
}
}
private function parseParameterForCreateTransaction(&$param, $data = null)
{
if($data == null) {
$data = $this->request->input('json_decode');
}
$session_id = 0;
if(isset($data['session_id'])) {
$session_id = $data['session_id'];
}
$login_request_result = $this->requestLogin($session_id, false);
if($login_request_result !== true) {
return $login_request_result;
}
$session = $this->getRequest()->getSession();
$param['session_id'] = $session->read('session_id');
$param['blockchain_type'] = $this->blockchainType;
$this->rewriteKeys($data, ['email' => 'target_email', 'username' => 'target_username', 'pubkey' => 'target_pubkey']);
$required_fields = $this->checkAndCopyRequiredFields(['amount', ['target_email', 'target_username', 'target_pubkey']], $param, $data);
if($required_fields !== true) {
return $required_fields;
}
if(intval($param['amount']) <= 0) {
return ['state' => 'error', 'msg' => 'amount is invalid', 'details' => $param['amount']];
}
if(isset($data['memo'])) {
$param['memo'] = $data['memo'];
}
if(isset($data['auto_sign'])) {
$param['auto_sign'] = boolval($data['auto_sign']);
}
return true;
}
public function sendCoins()
{
/*
* {
"session_id" : -127182,
"amount": 2000000,
"email": "max.musterman@gmail.de",
"memo":"Thank you :)",
"group": "gdd1",
"auto_sign": true
*/
if(!$this->request->is('post')) {
return $this->returnJson(['state' => 'error', 'msg' => 'no post']);
}
$data = $this->request->input('json_decode');
$params = [];
$result = $this->parseParameterForCreateTransaction($params, $data);
if($result !== true) {
return $this->returnJson($result);
}
$required_fields = $this->checkAndCopyRequiredFields(['target_date'], $params, $data);
if($required_fields !== true) {
return $this->returnJson($required_fields);
}
$params['transaction_type'] = 'transfer';
$requestAnswear = $this->JsonRequestClient->sendRequest(json_encode($params), '/createTransaction');
if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) {
$session = $this->getRequest()->getSession();
$pendingTransactionCount = $session->read('Transactions.pending');
if($pendingTransactionCount == null) {
$pendingTransactionCount = 1;
} else {
$pendingTransactionCount++;
}
$session->write('Transactions.pending', $pendingTransactionCount);
//echo "pending: " . $pendingTransactionCount;
return $this->returnJson(['state' => 'success']);
} 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'];
return $this->returnJson($answear_data);
}
}
public function createCoins()
{
/*
* "session_id" : -127182,
* "email": "max.musterman@gmail.de",
* "amount": 10000000,
* "target_date":"2021-02-19T13:25:36+00:00",
* "memo":"AGE",
* "auto_sign": true
*/
if(!$this->request->is('post')) {
return $this->returnJson(['state' => 'error', 'msg' => 'no post']);
}
$data = $this->request->input('json_decode');
$params = [];
$result = $this->parseParameterForCreateTransaction($params, $data);
if($result !== true) {
return $this->returnJson($result);
}
$required_fields = $this->checkAndCopyRequiredFields(['target_date'], $params, $data);
if($required_fields !== true) {
return $this->returnJson($required_fields);
}
$params['transaction_type'] = 'creation';
$requestAnswear = $this->JsonRequestClient->sendRequest(json_encode($params), '/createTransaction');
if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) {
$session = $this->getRequest()->getSession();
$pendingTransactionCount = $session->read('Transactions.pending');
if($pendingTransactionCount == null) {
$pendingTransactionCount = 1;
} else {
$pendingTransactionCount++;
}
$session->write('Transactions.pending', $pendingTransactionCount);
//echo "pending: " . $pendingTransactionCount;
return $this->returnJson(['state' => 'success']);
} 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'];
return $this->returnJson($answear_data);
}
}
private function acquireAccessToken($session_id)
{
}
}

View File

@ -0,0 +1,106 @@
<?php
namespace App\Controller;
use App\Controller\AppController;
/**
* BlockchainTypes Controller
*
* @property \App\Model\Table\BlockchainTypesTable $BlockchainTypes
*
* @method \App\Model\Entity\BlockchainType[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class BlockchainTypesController extends AppController
{
/**
* Index method
*
* @return \Cake\Http\Response|null
*/
public function index()
{
$blockchainTypes = $this->paginate($this->BlockchainTypes);
$this->set(compact('blockchainTypes'));
}
/**
* View method
*
* @param string|null $id Blockchain Type id.
* @return \Cake\Http\Response|null
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function view($id = null)
{
$blockchainType = $this->BlockchainTypes->get($id, [
'contain' => [],
]);
$this->set('blockchainType', $blockchainType);
}
/**
* Add method
*
* @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
*/
public function add()
{
$blockchainType = $this->BlockchainTypes->newEntity();
if ($this->request->is('post')) {
$blockchainType = $this->BlockchainTypes->patchEntity($blockchainType, $this->request->getData());
if ($this->BlockchainTypes->save($blockchainType)) {
$this->Flash->success(__('The blockchain type has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The blockchain type could not be saved. Please, try again.'));
}
$this->set(compact('blockchainType'));
}
/**
* Edit method
*
* @param string|null $id Blockchain Type 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)
{
$blockchainType = $this->BlockchainTypes->get($id, [
'contain' => [],
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$blockchainType = $this->BlockchainTypes->patchEntity($blockchainType, $this->request->getData());
if ($this->BlockchainTypes->save($blockchainType)) {
$this->Flash->success(__('The blockchain type has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The blockchain type could not be saved. Please, try again.'));
}
$this->set(compact('blockchainType'));
}
/**
* Delete method
*
* @param string|null $id Blockchain Type 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']);
$blockchainType = $this->BlockchainTypes->get($id);
if ($this->BlockchainTypes->delete($blockchainType)) {
$this->Flash->success(__('The blockchain type has been deleted.'));
} else {
$this->Flash->error(__('The blockchain type could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
}

View File

@ -15,7 +15,7 @@ use Cake\Core\Configure;
class JsonRequestClientComponent extends Component
{
public function sendTransaction($session_id, $base64Message, $user_balance = 0, $auto_sign = false) {
public function sendTransaction($session_id, $base64Message, $user_balance = 0, $auto_sign = false, $blockchain_type = 'mysql') {
if(!is_numeric($session_id)) {
return ['state' => 'error', 'type' => 'parameter error', 'msg' => 'session_id isn\'t numeric'];
}
@ -36,11 +36,17 @@ class JsonRequestClientComponent extends Component
'session_id' => $session_id,
'transaction_base64' => $base64Message,
'balance' => $user_balance,
'auto_sign' => $auto_sign
'auto_sign' => $auto_sign,
'blockchain_type' => $this->blockchainType
]), '/checkTransaction');
}
public function findePublicKeyForEmailHash($emailHash) {
//'ask' = ['account_publickey' => '<email_blake2b_base64>']
$results = $this->sendRequestLoginServerNeighbors(json_encode(['ask' => ['account_publickey' => $emailHash]]), 'search');
}
public function getRunningUserTasks($email)
{
if($email == "") {
@ -122,6 +128,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');

View File

@ -41,7 +41,15 @@ class JsonRpcRequestClientComponent extends Component
public function sendRequest($message) {
$http = new Client();
$response = $http->post($this->getGradidoNodeUrl(), $message, ['type' => 'json']);
try {
$url = $this->pickGradidoNodeUrl();
if(is_array($url)) {
return $url;
}
$response = $http->post($url, $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];
@ -55,14 +63,18 @@ class JsonRpcRequestClientComponent extends Component
//$responseType = $response->getType();
return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t valid json'];
}
return $json;
return $json['result'];
//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('GradidoBlockchain.nodes');
if(count($gradidoNodes) == 0) {
return ['state' => 'error', 'msg' => 'no gradido nodes in config'];
}
$i = rand(0, count($gradidoNodes)-1);
return $gradidoNodes[$i]['host'] . ':' . $gradidoNodes[$i]['port'];
}

View File

@ -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');
}

View File

@ -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');
}
@ -58,28 +60,277 @@ 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);
case 'updateReadNode': return $this->updateReadNode();
case 'addUser' : return $this->addUser($jsonData->user);
}
return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]);
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post or get']);
}
private function addUser($newUser)
{
$stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers');
$entity = $stateUsersTable->newEntity();
$required_fields = ['first_name', 'last_name', 'email', 'public_key', 'disabled'];
foreach($required_fields as $required_field) {
if(!isset($newUser->$required_field)) {
return $this->returnJson(['state' => 'error', 'msg' => 'missing required field in addUser', 'details' => $required_field]);
}
if('public_key' == $required_field) {
$entity->$required_field = hex2bin($newUser->public_hex);
} else {
$entity->$required_field = $newUser->$required_field;
}
}
if($stateUsersTable->save($entity)) {
return $this->returnJson(['state' => 'success']);
} else {
return $this->returnJson(['state' => 'error', 'msg' => 'error saving state_user', 'details' => $entity->getErrors()]);
}
}
// 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_query = $transactionsTable->find('all')->order(['id' => 'DESC']);
$last_transaction_id = 0;
if(!$last_transaction_query->isEmpty()) {
$last_transaction_id = $last_transaction_query->first()->id;
}
$last_known_sequence_number = $last_transaction_id;
if($last_transaction_query->count() < $last_transaction_id) {
$last_transaction_id = $last_transaction_query->count();
}
//$last_transaction_id = 0;
$group_alias = Configure::read('GroupAlias');
$result = (array)$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' => ['return' => $result, 'groupAlias' => $group_alias]]);
}
/* example
$result = json_decode("[
{
\"record_type\":\"GRADIDO_TRANSACTION\",
\"transaction\":{
\"version_number\":1,
\"signature\":{
\"pubkey\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\",
\"signature\":\"aed6725baacabf903e51f92503d49fa7e6b93c6402d56d9e3784be9a3366a77459213d858af46b579287aba8b1b63d206febce18bc80cec6fa63da6289e56403\"
},
\"signature_count\":1,
\"hedera_transaction\":{
\"consensusTimestamp\":{
\"seconds\":1604392811,
\"nanos\":172812
},
\"runningHash\":\"f9ccf04137be418c3117a28bb5add6dced9745bcab74b7a2f46c182c8c98eeabf0127c131d15ebea7d0ac376f5d2de45\",
\"sequenceNumber\":94,
\"runningHashVersion\":3
},
\"transaction_type\":\"ADD_USER\",
\"add_user\":{
\"user\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\"
},
\"result\":\"result\",
\"parts\":1,
\"memo\":\"\"
}
},
{
\"record_type\":\"GRADIDO_TRANSACTION\",
\"transaction\":{
\"version_number\":1,
\"signature\":{
\"pubkey\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\",
\"signature\":\"3134adcd6cbccee17c2db398f91b6b6bdd098b6306fb2fa213eb9eb5a322af9078acca4d8b0383d4e906f3139eb3369e7c1ef0f3ac5fec724be0d085ba44af0b\"
},
\"signature_count\":2,
\"hedera_transaction\":{
\"consensusTimestamp\":{
\"seconds\":1604392886,
\"nanos\":1528
},
\"runningHash\":\"e1df5526331e3def11d6b652b8f248d20c250739b6eb98f1fe7b338901753d9d573a14601ba84f61318a48940b3c237a\",
\"sequenceNumber\":95,
\"runningHashVersion\":3
},
\"transaction_type\":\"ADD_USER\",
\"add_user\":{
\"user\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\"
},
\"result\":\"result\",
\"parts\":2,
\"memo\":\"\"
}
},
{
\"record_type\":\"SIGNATURES\",
\"signature\":[
{
\"pubkey\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\",
\"signature\":\"401717e768617c0f3311931c34a61e66ab362599a0e2a48ae7c4955645aec6573773985dafb84a11bfaf2bc12140c30b2f8c8ee094bc35d609bc56d15b4e9f04\"
}
]
},
{
\"record_type\": \"GRADIDO_TRANSACTION\",
\"transaction\":{
\"version_number\":1,
\"signature\":{
\"pubkey\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\",
\"signature\":\"99665dee9f2b475e426a2f449d0dae61924f6cf025903666ff72f2c7ef1af27523ebcd5fb684d17813fe7906b2f8cfe5ef4bdbb264ebf3ef80363491d9b86807\"
},
\"signature_count\":1,
\"hedera_transaction\":{
\"consensusTimestamp\":{
\"seconds\":1604392904,
\"nanos\":798541
},
\"runningHash\":\"f1fd03610a9788e9bac01e1efb8b99bafae450f9088cb940db954842e0799235c57d842be83d998e6c21786f77f967a7\",
\"sequenceNumber\":96,
\"runningHashVersion\":3
},
\"transaction_type\":\"GRADIDO_CREATION\",
\"gradido_creation\":{
\"user\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\",
\"new_balance\":10000000,
\"prev_transfer_rec_num\":0,
\"amount\":10000000
},
\"result\":\"result\",
\"parts\":1,
\"memo\":\"\"
}
},
{
\"record_type\": \"GRADIDO_TRANSACTION\",
\"transaction\":{
\"version_number\":1,
\"signature\":{
\"pubkey\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\",
\"signature\":\"90125e0cfce61397d50ed9ba6c5df4cd4e0cf6fee8b10c70fee2898765982570d9a1208c222981429ae3c229e3fd36c2bf2333518cd0a4f0515937822e499d0b\"
},
\"signature_count\":1,
\"hedera_transaction\":{
\"consensusTimestamp\":{
\"seconds\":1604392929,
\"nanos\":52539
},
\"runningHash\":\"a4be8f54be4f806b61d31f6bd770d7742822f14f03ffe09c07f08bac3031a06d12de5e38fec5c307149c7faf6e9879b8\",
\"sequenceNumber\":97,
\"runningHashVersion\":3
},
\"transaction_type\":\"LOCAL_TRANSFER\",
\"local_transfer\":{
\"sender\":{
\"user\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\",
\"new_balance\":9825500,
\"prev_transfer_rec_num\":0
},
\"receiver\":{
\"user\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\",
\"new_balance\":174500,
\"prev_transfer_rec_num\":0
},
\"amount\":174500
},
\"result\":\"result\",
\"parts\":1,
\"memo\":\"\"
}
}
]", true);*/
$part_count = -1;
$temp_record = new Record;
$errors = [];
foreach($result['blocks'] as $_record) {
if(is_string($_record)) continue;
$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) {
if($sequenceNumber > $last_known_sequence_number) {
$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']);
}
/*
* 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
//! 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) {
/*
* payload.set("created", created);
* payload.set("id", task_model->getID());
* payload.set("public_key", user_model->getPublicKeyHex());
* payload.set("error", error);
* payload.set("errorMessage", errorDetails);
*/
//! \param $errorDetails more detailed error message in user language
private function errorInTransaction($jsonData) {
$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) {

View File

@ -46,6 +46,7 @@ class PagesController extends AppController
*/
public function display(...$path)
{
$count = count($path);
if (!$count) {
return $this->redirect('/');
@ -61,6 +62,16 @@ class PagesController extends AppController
if (!empty($path[1])) {
$subpage = $path[1];
}
/*$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if($result !== true) {
return $result;
}
$user = $session->read('StateUser');
$login_server_session = $this->request->getCookie('GRADIDO_LOGIN', '');*/
if($page == "vue" || $page == "vue-dev") {
$this->viewBuilder()->setLayout(false);
}
$this->set(compact('page', 'subpage'));
try {

View File

@ -0,0 +1,108 @@
<?php
namespace App\Controller;
use App\Controller\AppController;
use Model\Navigation\NaviHierarchy;
use Model\Navigation\NaviHierarchyEntry;
/**
* Roles Controller
*
*
* @method \App\Model\Entity\Role[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class RolesController extends AppController
{
/**
* Index method
*
* @return \Cake\Http\Response|null
*/
public function index()
{
$roles = $this->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']);
}
}

View File

@ -2,11 +2,14 @@
namespace App\Controller;
use Cake\ORM\TableRegistry;
use App\Controller\AppController;
use Cake\I18n\Time;
use Model\Navigation\NaviHierarchy;
use Model\Navigation\NaviHierarchyEntry;
use App\Controller\AppController;
/**
* StateBalances Controller
*
@ -21,7 +24,7 @@ class StateBalancesController extends AppController
{
parent::initialize();
//$this->Auth->allow(['add', 'edit']);
$this->Auth->allow(['overview', 'overviewGdt', 'ajaxGetBalance', 'ajaxListTransactions']);
$this->Auth->allow(['overview', 'overviewGdt', 'ajaxListTransactions', 'ajaxGdtOverview', 'ajaxGetBalance', 'ajaxGdtTransactions']);
$this->loadComponent('JsonRequestClient');
}
/**
@ -38,8 +41,8 @@ class StateBalancesController extends AppController
$this->set(compact('stateBalances'));
}
private function updateBalances($stateUserId)
private function updateBalance($stateUserId)
{
$stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
$transactionsTable = TableRegistry::getTableLocator()->get('Transactions');
@ -51,7 +54,7 @@ class StateBalancesController extends AppController
->order(['transaction_id ASC'])
->contain(false);
if(!$state_user_transactions) {
if(!$state_user_transactions || !$state_user_transactions->count()) {
//debug($state_user_transactions);
return true;
}
@ -91,6 +94,28 @@ class StateBalancesController extends AppController
if(!$create_state_balance) {
$update_state_balance = true;
}
} else if(!$last_state_user_transaction) {
$creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations');
$creationTransactions = $creationsTable
->find('all')
->where(['state_user_id' => $stateUserId])
->contain(false);
$transferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins');
$transferTransactions = $transferTable
->find('all')
->where(['OR' => ['state_user_id' => $stateUserId, 'receiver_user_id' => $stateUserId]])
->contain(false);
if($creationTransactions->count() > 0 || $transferTransactions->count() > 0) {
$this->addAdminError(
'StateBalances',
'updateBalance', [
'state' => 'error',
'msg' => 'state_user_transactions is empty but it exist transactions for user'
],
$stateUserId);
}
}
}
// second: do what is needed
@ -176,6 +201,7 @@ class StateBalancesController extends AppController
}
}
return true;
}
public function overview()
@ -195,7 +221,10 @@ class StateBalancesController extends AppController
}
$user = $session->read('StateUser');
$this->updateBalances($user['id']);
$update_balance_result = $this->updateBalance($user['id']);
if($update_balance_result !== true) {
$this->addAdminError('StateBalances', 'overview', $update_balance_result, $user['id']);
}
// sendRequestGDT
// listPerEmailApi
@ -215,6 +244,7 @@ class StateBalancesController extends AppController
//}
//
//
$stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
$creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations');
$creationTransactions = $creationsTable
@ -283,17 +313,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();
@ -305,17 +340,101 @@ 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'));
$this->set('transactions', $transactions);
// add decay transactions
$month_start_state_balance = null;
$current_state_balance = null;
$cursor = 0;
$transactions_reversed = array_reverse($transactions);
$maxI = count($transactions_reversed);
foreach($transactions_reversed as $i => $transaction) {
if(!isset($transaction['transaction_id'])) {
continue;
}
$transaction_id = $transaction['transaction_id'];
$decay_transaction = NULL;
$state_balance = $this->StateBalances->newEntity();
if($i > 0 && isset($transactions_reversed[$i-1]['transaction_id'])) {
$prev_transaction = $transactions_reversed[$i-1];
$stateUserTransactions = $stateUserTransactionsTable
->find()
->where([
'transaction_id IN' => [$transaction_id, $prev_transaction['transaction_id']],
'state_user_id' => $user['id']
])
->order(['transaction_id ASC'])
->toArray();
$prev = $stateUserTransactions[0];
if($prev->balance > 0) {
// var_dump($stateUserTransactions);
$current = $stateUserTransactions[1];
$interval = $current->balance_date->diff($prev->balance_date);
$state_balance->amount = $prev->balance;
$state_balance->record_date = $prev->balance_date;
$diff_amount = $state_balance->partDecay($current->balance_date);
/* echo "prev date: $prev->balance_date, current date: $current->balance_date, interval: ";
var_dump($interval);
echo "<br>";
echo "prev balance: $prev->balance<br>diff: $diff_amount<br>";
echo "current balance: $current->balance<br>";
*
*/
//echo $interval->format('%R%a days');
$decay_transaction = [
'type' => 'decay',
'balance' => -($prev->balance - $diff_amount),
'decay_duration' => $interval->format('%a days, %H hours, %I minutes, %S seconds'),
'memo' => ''
];
}
}
if($decay_transaction) {
array_splice($transactions_reversed, $i + $cursor, 0, [$decay_transaction]);
$cursor++;
}
if($i == $maxI-1) {
$stateUserTransaction = $stateUserTransactionsTable
->find()
->where(['transaction_id' => $transaction_id, 'state_user_id' => $user['id']])
->order(['transaction_id ASC'])->first();
//var_dump($stateUserTransaction);
$state_balance->amount = $stateUserTransaction->balance;
$state_balance->record_date = $stateUserTransaction->balance_date;
$transactions_reversed[] = [
'type' => 'decay',
'balance' => -($stateUserTransaction->balance - $state_balance->decay),
'decay_duration' => $stateUserTransaction->balance_date->timeAgoInWords(),
'memo' => ''
];
}
}
// for debugging
$calculated_balance = 0;
foreach($transactions_reversed as $tr) {
if($tr['type'] == 'send') {
$calculated_balance -= intval($tr['balance']);
} else {
$calculated_balance += intval($tr['balance']);
}
}
$this->set('calculated_balance', $calculated_balance);
$this->set('transactions', array_reverse($transactions_reversed));
$this->set('transactionExecutingCount', $session->read('Transactions.executing'));
$this->set('balance', $session->read('StateUser.balance'));
$this->set('timeUsed', microtime(true) - $startTime);
$this->set('gdtSum', $gdtSum);
}
public function ajaxGetBalance($session_id = 0)
{
if(!$session_id) {
@ -357,8 +476,9 @@ class StateBalancesController extends AppController
return $this->returnJson(['state' => 'success', 'balance' => $state_balances[0]->amount]);
}
public function ajaxListTransactions($session_id = 0, $sort = 'ASC')
public function ajaxListTransactions($session_id, $page, $count)
{
if(!$session_id) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session id']);
@ -491,6 +611,42 @@ class StateBalancesController extends AppController
]);
}
public function ajaxGdtOverview()
{
$gdtSum = 0;
$gdtCount = -1;
$session = $this->getRequest()->getSession();
$user = $session->read('StateUser');
if(!$user) {
return $this->returnJson(['state' => 'error', 'msg' => 'user not found', 'details' => 'exist a valid session cookie?']);
}
$gdtEntries = $this->JsonRequestClient->sendRequestGDT(['email' => $user['email']], 'GdtEntries' . DS . 'sumPerEmailApi');
if('success' == $gdtEntries['state'] && 'success' == $gdtEntries['data']['state']) {
$gdtSum = intval($gdtEntries['data']['sum']);
if(isset($gdtEntries['data']['count'])) {
$gdtCount = intval($gdtEntries['data']['count']);
}
} else {
if($user) {
$this->addAdminError('StateBalancesController', 'ajaxGdtOverview', $gdtEntries, $user['id']);
} else {
$this->addAdminError('StateBalancesController', 'ajaxGdtOverview', $gdtEntries, 0);
}
}
return $this->returnJson([
'state' => 'success',
'transactions' => $transactions,
'transactionExecutingCount' => $session->read('Transaction.executing'),
'count' => $all_user_transactions_count
]);
}
public function overviewGdt()
{
$this->set(
@ -536,9 +692,9 @@ class StateBalancesController extends AppController
//echo "gdtSum: $gdtSum<br>";
$this->set('gdtSum', $gdtSum);
$this->set('ownEntries', $ownEntries);
$this->set('gdtSumPerEmail', $requestResult['data']['gdtSumPerEmail']);
$this->set('moreEntrysAsShown', $requestResult['data']['moreEntrysAsShown']);
$this->set('user', $user);
$this->set('gdtSumPerEmail', $requestResult['data']['gdtSumPerEmail']);
$this->set('moreEntrysAsShown', $requestResult['data']['moreEntrysAsShown']);
$this->set('user', $user);
if (isset($requestResult['data']['publishers'])) {
$publishers = $requestResult['data']['publishers'];
@ -549,6 +705,66 @@ class StateBalancesController extends AppController
$this->Flash->error(__('Fehler beim GDT Server, bitte abwarten oder den Admin benachrichtigen!'));
}
}
public function ajaxGdtTransactions()
{
$startTime = microtime(true);
$session = $this->getRequest()->getSession();
$user = $session->read('StateUser');
if(!$user) {
return $this->returnJson(['state' => 'error', 'msg' => 'user not found', 'details' => 'exist a valid session cookie?']);
}
$requestResult = $this->JsonRequestClient->sendRequestGDT(['email' => $user['email']], 'GdtEntries' . DS . 'listPerEmailApi');
$connectEntries = [];
$publishers = [];
//var_dump($requestResult);
if('success' === $requestResult['state'] && 'success' === $requestResult['data']['state']) {
//var_dump(array_keys($requestResult['data']));
$ownEntries = $requestResult['data']['ownEntries'];
//$gdtEntries = $requestResult['data']['entries'];
$gdtSum = 0;
foreach ($ownEntries as $i => $gdtEntry) {
$gdtSum += $gdtEntry['gdt'];
//echo "index: $i<br>";
//var_dump($gdtEntry);
}
if (isset($requestResult['data']['connectEntrys'])) {
$connectEntries = $requestResult['data']['connectEntrys'];
foreach ($connectEntries as $entry) {
//if(!$count) var_dump($entry);
//$count++;
$gdtSum += $entry['connect']['gdt_entry']['gdt'];
}
}
//echo "gdtSum: $gdtSum<br>";
if (isset($requestResult['data']['publishers'])) {
$publishers = $requestResult['data']['publishers'];
}
} else {
$this->addAdminError('StateBalancesController', 'ajaxGdtTransactions', $requestResult, $user['id']);
//$this->Flash->error(__('Fehler beim GDT Server, bitte abwarten oder den Admin benachrichtigen!'));
return $this->returnJson(['state' => 'error', 'msg' => 'error from gdt server', 'details' => $requestResult]);
}
return $this->returnJson([
'state' => 'success',
'gdtSum' => $gdtSum,
'ownEntries' => $ownEntries,
'connectEntries' => $connectEntries,
'publishers' => $publishers,
'gdtSumPerEmail' => $requestResult['data']['gdtSumPerEmail'],
'moreEntrysAsShown' => $requestResult['data']['moreEntrysAsShown'],
'timeUsed' => microtime(true) - $startTime
]);
}
public function sortTransactions($a, $b)
{

View File

@ -20,7 +20,7 @@ class StateGroupAddressesController extends AppController
public function index()
{
$this->paginate = [
'contain' => ['StateGroups', 'AddressTypes']
'contain' => ['AddressTypes'],
];
$stateGroupAddresses = $this->paginate($this->StateGroupAddresses);
@ -37,7 +37,7 @@ class StateGroupAddressesController extends AppController
public function view($id = null)
{
$stateGroupAddress = $this->StateGroupAddresses->get($id, [
'contain' => ['StateGroups', 'AddressTypes']
'contain' => ['StateGroups', 'AddressTypes'],
]);
$this->set('stateGroupAddress', $stateGroupAddress);
@ -75,7 +75,7 @@ class StateGroupAddressesController extends AppController
public function edit($id = null)
{
$stateGroupAddress = $this->StateGroupAddresses->get($id, [
'contain' => []
'contain' => [],
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$stateGroupAddress = $this->StateGroupAddresses->patchEntity($stateGroupAddress, $this->request->getData());

View File

@ -0,0 +1,185 @@
<?php
namespace App\Controller;
use Cake\Routing\Router;
use Cake\I18n\I18n;
use Cake\I18n\FrozenTime;
use Cake\ORM\TableRegistry;
use App\Controller\AppController;
use App\Form\UserSearchForm;
use App\Model\Validation\GenericValidation;
use Model\Navigation\NaviHierarchy;
use Model\Navigation\NaviHierarchyEntry;
use Model\Transactions\TransactionCreation;
use App\Model\Table\StateUsersTable;
use App\Form\AssignRoleForm;
/**
* StateUserRoles Controller
*
* @property \App\Model\Table\StateUsersTable $StateUsers
*
* @method \App\Model\Entity\StateUser[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class StateUserRolesController extends AppController
{
public function initialize()
{
parent::initialize();
$this->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');
$searchForm = new UserSearchForm();
$timeUsed = microtime(true) - $startTime;
//$this->set('timeUsed', $timeUsed);
$this->set(compact('timeUsed', 'searchForm'));
if ($this->request->is('post')) {
$requestData = $this->request->getData();
if ($searchForm->validate($requestData)) {
//var_dump($requestData);
$searchString = $requestData['search'];
// find user on community server db
$globalSearch = '%' . $searchString . '%';
$communityUsers = $this->StateUsers
->find('all')
->contain([]);
$communityUsers->where(['OR' => [
'first_name LIKE' => $globalSearch,
'last_name LIKE' => $globalSearch,
//'username LIKE' => $globalSearch,
'email LIKE' => $globalSearch
]]);
//var_dump($communityUsers->toArray());
$finalUserEntrys = [];
// detect states
$this->loadModel('Roles');
// foreach ($pubkeySorted as $pubhex => $user) {
foreach($communityUsers as $communityUser) {
$finalUser = $communityUser;
$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();
$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 .= "<br/>".$role->title;
else
$role_names = $role->title;
}
$finalUser['role_name'] = $role_names;
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);
}
}

View File

@ -20,6 +20,7 @@ class StateUserTransactionsController extends AppController
$this->Auth->allow(['ajaxListTransactions']);
//$this->loadComponent('JsonRequestClient');
}
/**
* Index method
*

View File

@ -5,8 +5,8 @@ use Cake\Routing\Router;
use Cake\I18n\I18n;
use Cake\I18n\FrozenTime;
use Cake\ORM\TableRegistry;
use Cake\Http\Client;
use Cake\Core\Configure;
use Cake\Http\Client;
use App\Controller\AppController;
use App\Form\UserSearchForm;
@ -42,10 +42,11 @@ class StateUsersController extends AppController
parent::initialize();
$this->loadComponent('GradidoNumber');
$this->loadComponent('JsonRequestClient');
$this->loadComponent('Cookie');
$this->Auth->allow([
'search', 'ajaxCopyLoginToCommunity', 'ajaxCopyCommunityToLogin',
'ajaxDelete', 'ajaxCountTransactions', 'ajaxVerificationEmailResend',
'ajaxGetUserEmailVerificationCode', 'ajaxGetCSFRToken'
'ajaxGetUserEmailVerificationCode', 'ajaxGetCSFRToken', 'login'
]);
$this->set(
'naviHierarchy',
@ -72,11 +73,39 @@ class StateUsersController extends AppController
/*public function listIdentHashes()
{
$stateUsers = $this->StateUsers->find('all')->toArray();
foreach ($stateUsers as $i => $user) {
$stateUsers[$i]->identHash = TransactionCreation::DRMakeStringHash($user->email);
foreach($stateUsers as $i => $user) {
$stateUsers[$i]->identHash = TransactionCreation::DRMakeStringHash($user->email);
}
$this->set('stateUsers', $stateUsers);
}*/
public function login($session_id)
{
if(isset($session_id) && intval($session_id) !== 0) {
$loginServer = Configure::read('LoginServer');
$http = new Client();
try {
$url = $loginServer['host'] . ':' . $loginServer['port'];
$response = $http->get($url . '/login', ['session_id' => $session_id]);
$json = $response->getJson();
if (isset($json) && count($json) > 0) {
if ($json['state'] === 'success') {
$this->Cookie->configKey('GRADIDO_LOGIN', 'encryption', false);
$this->Cookie->write('GRADIDO_LOGIN', $session_id);
return $this->redirect(['controller' => 'Dashboard', 'action' => 'index']);
}
}
} catch (\Exception $e) {
$msg = $e->getMessage();
$this->Flash->error(__('error http request: ') . $msg);
return $this->redirect(['controller' => 'Dashboard', 'action' => 'errorHttpRequest']);
}
}
throw new NotFoundException();
}
public function search()
{
@ -85,12 +114,12 @@ class StateUsersController extends AppController
$this->viewBuilder()->setLayout('frontend');
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if ($result !== true) {
return $result;
if($result !== true) {
return $result;
}
$user = $session->read('StateUser');
if ($user['role'] != 'admin') {
return $this->redirect(['controller' => 'dashboard', 'action' => 'index']);
if($user['role'] != 'admin') {
return $this->redirect(['controller' => 'dashboard', 'action' => 'index']);
}
$searchForm = new UserSearchForm();
@ -102,55 +131,55 @@ class StateUsersController extends AppController
$empty_string = '... empty ...';
if ($this->request->is('post')) {
$finalUserEntrys = [];
$requestData = $this->request->getData();
$requestData = $this->request->getData();
$account_state = $requestData['account_state'];
if($requestData['search'] == '' && $account_state != 'all') {
$requestData['search'] = $empty_string;
}
if ($searchForm->validate($requestData)) {
//var_dump($requestData);
$searchString = $requestData['search'];
$searchType = 'unknown';
if (GenericValidation::email($searchString, [])) {
$searchType = 'email';
}
// find users on login server
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, $account_state);
$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'];
}
$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' => []];
}
$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
array_push($pubkeySorted[$u['public_hex']]['login'], $u);
}
}
// find user on community server db
$communityUsers = $this->StateUsers
$communityUsers = $this->StateUsers
->find('all')
->contain(['StateBalances' => ['fields' => ['amount', 'state_user_id']]]);
if($account_state == 'email not activated') {
if(count($pubkeySorted) > 0) {
$communityUsers->where(['hex(public_key) IN' => array_keys($pubkeySorted)]);
@ -159,112 +188,110 @@ class StateUsersController extends AppController
}
} else {
$globalSearch = '%' . $searchString . '%';
$communityUsers->where(['OR' => [
'first_name LIKE' => $globalSearch,
'last_name LIKE' => $globalSearch,
//'username LIKE' => $globalSearch,
'email LIKE' => $globalSearch
]]);
$communityUsers->where(['OR' => [
'first_name LIKE' => $globalSearch,
'last_name LIKE' => $globalSearch,
'email LIKE' => $globalSearch
]]);
}
//var_dump($communityUsers->toArray());
//var_dump($communityUsers->toArray());
if($communityUsers) {
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);
}
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);
}
}
// detect states
foreach ($pubkeySorted as $pubhex => $user) {
$finalUser = [];
$state = 'account created';
$color = 'secondary';
$finalUser['balance'] = 0;
$finalUser['pubkeyhex'] = $pubhex;
$finalUser['created'] = null;
// 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';
}
$finalUser['indicator'] = ['name' => $state, 'color' => $color];
array_push($finalUserEntrys, $finalUser);
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;
}
}
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);
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['email'] = $c_user->email;
}
//var_dump($pubkeySorted);
} else {
$this->Flash->error(__('Something was invalid, please try again!'));
} else if(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['email'] = $l_user['email'];
$finalUser['created'] = new FrozenTime($l_user['created']);
} else {
$state = 'account multiple times on login-server';
$color = 'danger';
}
$finalUser['indicator'] = ['name' => $state, 'color' => $color];
array_push($finalUserEntrys, $finalUser);
}
$this->set('finalUserEntrys', $finalUserEntrys);
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['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);
@ -272,187 +299,189 @@ class StateUsersController extends AppController
public function ajaxCopyCommunityToLogin()
{
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if ($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if ($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
if ($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
if($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
}
public function ajaxCopyLoginToCommunity()
{
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if ($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if ($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
if ($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
//$user = $jsonData['user'];
//var_dump($jsonData);
if($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
//$user = $jsonData['user'];
//var_dump($jsonData);
$newStateUser = $this->StateUsers->newEntity();
$this->StateUsers->patchEntity($newStateUser, $jsonData);
$newStateUser->public_key = hex2bin($jsonData['pubkeyhex']);
$newStateUser = $this->StateUsers->newEntity();
$this->StateUsers->patchEntity($newStateUser, $jsonData);
$newStateUser->public_key = hex2bin($jsonData['pubkeyhex']);
if (!$this->StateUsers->save($newStateUser)) {
return $this->returnJson(['state' => 'error', 'msg' => 'error by saving', 'details' => json_encode($newStateUser->errors())]);
}
if(!$this->StateUsers->save($newStateUser)) {
return $this->returnJson(['state' => 'error', 'msg' => 'error by saving', 'details' => json_encode($newStateUser->errors())]);
}
return $this->returnJson(['state' => 'success']);
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
return $this->returnJson(['state' => 'success']);
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
}
public function ajaxVerificationEmailResend()
{
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if ($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if ($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
if ($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
$email = $jsonData['email'];
$session_id = $session->read('session_id');
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
if($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
$email = $jsonData['email'];
$session_id = $session->read('session_id');
return $this->returnJson($this->JsonRequestClient->sendRequest(json_encode([
return $this->returnJson($this->JsonRequestClient->sendRequest(json_encode([
'session_id' => $session_id,
'email' => $email
]), '/adminEmailVerificationResend'));
/*return $this->sendRequest(json_encode([
]), '/adminEmailVerificationResend'));
/*return $this->sendRequest(json_encode([
'session_id' => $session_id,
'search' => $searchString
]), '/getUsers');*/
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
]), '/getUsers');*/
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
}
public function ajaxGetUserEmailVerificationCode()
{
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if ($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if ($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
if ($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
$email = $jsonData['email'];
$session_id = $session->read('session_id');
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
if($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
$email = $jsonData['email'];
$session_id = $session->read('session_id');
return $this->returnJson($this->JsonRequestClient->sendRequest(json_encode([
return $this->returnJson($this->JsonRequestClient->sendRequest(json_encode([
'session_id' => $session_id,
'email' => $email,
'ask' => ['EmailVerificationCode.Register', 'loginServer.path']
]), '/getUserInfos'));
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
]), '/getUserInfos'));
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
}
public function ajaxDelete()
{
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if ($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if ($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
if ($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
//$user = $jsonData['user'];
//var_dump($jsonData);
$pubkey = hex2bin($jsonData['pubkeyhex']);
$stateUsers = $this->StateUsers->find('all')->where(['public_key' => $pubkey]);
if ($stateUsers->count() != 1) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid result count']);
}
if($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
//$user = $jsonData['user'];
//var_dump($jsonData);
$pubkey = hex2bin($jsonData['pubkeyhex']);
$stateUsers = $this->StateUsers->find('all')->where(['public_key' => $pubkey]);
if($stateUsers->count() != 1) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid result count']);
}
if ($this->StateUsers->delete($stateUsers->first())) {
return $this->returnJson(['state' => 'success']);
} else {
return $this->returnJson(['state' => 'error', 'msg' => 'error by deleting', 'details' => json_encode($stateUser->errors())]);
}
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
if ($this->StateUsers->delete($stateUsers->first())) {
return $this->returnJson(['state' => 'success']);
} else {
return $this->returnJson(['state' => 'error', 'msg' => 'error by deleting', 'details' => json_encode($stateUser->errors())]);
}
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
}
public function ajaxCountTransactions()
{
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if ($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if ($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
$session = $this->getRequest()->getSession();
$result = $this->requestLogin();
if($result !== true) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']);
}
$user = $session->read('StateUser');
if($user['role'] != 'admin') {
return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']);
}
if ($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
//$user = $jsonData['user'];
//var_dump($jsonData);
$pubkey = hex2bin($jsonData['pubkeyhex']);
$stateUsers = $this->StateUsers
if($this->request->is('post')) {
$jsonData = $this->request->input('json_decode', true);
//$user = $jsonData['user'];
//var_dump($jsonData);
$pubkey = hex2bin($jsonData['pubkeyhex']);
$stateUsers = $this->StateUsers
->find('all')
->where(['public_key' => $pubkey])
->select(['id']);
if ($stateUsers->count() != 1) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid result count']);
}
$stateUser = $stateUsers->first();
//var_dump($stateUser);
//var_dump($stateUser->toArray());
$creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations');
$creationTransactions = $creationsTable
if($stateUsers->count() != 1) {
return $this->returnJson(['state' => 'error', 'msg' => 'invalid result count']);
}
$stateUser = $stateUsers->first();
//var_dump($stateUser);
//var_dump($stateUser->toArray());
$creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations');
$creationTransactions = $creationsTable
->find('all')
->select(['id'])
->where(['state_user_id' => $stateUser->id]);
$transferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins');
$transferTransactions = $transferTable
$transferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins');
$transferTransactions = $transferTable
->find('all')
->where(['OR' => ['state_user_id' => $stateUser->id, 'receiver_user_id' => $stateUser->id]])
->select(['state_user_id', 'receiver_user_id']);
$counts = ['creation' => $creationTransactions->count(), 'receive' => 0, 'sended' => 0];
foreach ($transferTransactions as $transfer) {
//var_dump($transfer);
if ($transfer->state_user_id == $stateUser->id) {
$counts['sended']++;
}
if ($transfer->receiver_user_id == $stateUser->id) {
$counts['receive']++;
}
$counts = ['creation' => $creationTransactions->count(), 'receive' => 0, 'sended' => 0];
foreach($transferTransactions as $transfer) {
//var_dump($transfer);
if($transfer->state_user_id == $stateUser->id) {
$counts['sended']++;
}
return $this->returnJson(['state' => 'success', 'counts' => $counts]);
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
if($transfer->receiver_user_id == $stateUser->id) {
$counts['receive']++;
}
}
return $this->returnJson(['state' => 'success', 'counts' => $counts]);
}
return $this->returnJson(['state' => 'error', 'msg' => 'no post request']);
}
public function ajaxGetCSFRToken($session_id)
@ -560,9 +589,9 @@ class StateUsersController extends AppController
}
$this->Flash->error(__('The state user could not be saved. Please, try again.'));
}
$indices = $this->StateUsers->Indices->find('list', ['limit' => 200]);
$stateGroups = $this->StateUsers->StateGroups->find('list', ['limit' => 200]);
$this->set(compact('stateUser', 'stateGroups'));
$this->set(compact('stateUser', 'indices', 'stateGroups'));
}
/**

View File

@ -130,8 +130,7 @@ class TransactionCreationsController extends AppController
$builderResult = TransactionCreation::build(
$amountCent,
$requestData['memo'],
$pubKeyHex,
$identHash
$pubKeyHex
);
if ($builderResult['state'] == 'success') {
$user_balance = 0;
@ -335,6 +334,7 @@ class TransactionCreationsController extends AppController
if (isset($requestData['add'])) {
$mode = 'add';
}
//echo "mode: $mode<br>";
$memo = $requestData['memo'];
$amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']);
//$targetDate = $requestData['target_date'];
@ -342,17 +342,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;
@ -385,22 +388,85 @@ class TransactionCreationsController extends AppController
//$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 "<br>";
//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,
'blockchain_type' => $this->blockchainType
]), '/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<br>";
} 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);
@ -412,49 +478,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.'));
}
}
}
@ -533,7 +567,6 @@ class TransactionCreationsController extends AppController
$amount,
$memo,
$receiverPubKeyHex,
$requestAnswear['data']['userData']['identHash'],
new FrozenDate($jsonData['target_date'])
);
$transaction_base64 = '';
@ -546,7 +579,8 @@ class TransactionCreationsController extends AppController
$session_id,
$transaction_base64,
$user['balance'],
$auto_sign
$auto_sign,
$this->blockchainType
);
if ($requestResult['state'] != 'success') {
$msg = 'error returned from login server';

View File

@ -57,8 +57,9 @@ class TransactionSendCoinsController extends AppController
'contain' => ['Transactions', 'StateUsers', 'ReceiverUsers']
];
$transactionSendCoins = $this->paginate($this->TransactionSendCoins);
$simple = $this->TransactionSendCoins->find('all');
$this->set(compact('transactionSendCoins'));
$this->set(compact('transactionSendCoins', 'simple'));
}
/**
@ -146,10 +147,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 +167,94 @@ 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,
'blockchain_type' => $this->blockchainType
]), '/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($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;
}
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);
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);
}

View File

@ -0,0 +1,30 @@
<?php
// in src/Form/AssignRoleForm.php
namespace App\Form;
use Cake\Form\Form;
use Cake\Form\Schema;
use Cake\Validation\Validator;
class AssignRoleForm extends Form
{
protected function _buildSchema(Schema $schema)
{
return $schema->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;
}
}

View File

@ -1,5 +1,5 @@
<?php
// in src/Form/TransferForm.php
<?php
// in src/Form/ContactForm.php
namespace App\Form;
use Cake\Form\Form;
@ -13,13 +13,14 @@ class TransferForm extends Form
{
return $schema
->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 &gt; or &lt; 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;
}
}
}

View File

@ -1,41 +0,0 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: BasicTypes.proto
namespace GPBMetadata;
class BasicTypes
{
public static $is_initialized = false;
public static function initOnce() {
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
if (static::$is_initialized == true) {
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0afe030a10426173696354797065732e70726f746f12166d6f64656c2e6d" .
"657373616765732e6772616469646f22380a034b657912110a0765643235" .
"35313918022001280c480012170a0d656432353531395f72656631301803" .
"2001280c480042050a036b657922580a0d5369676e617475726550616972" .
"120e0a067075624b657918012001280c12110a0765643235353139180220" .
"01280c480012170a0d656432353531395f726566313018032001280c4800" .
"420b0a097369676e617475726522460a0c5369676e61747572654d617012" .
"360a077369675061697218012003280b32252e6d6f64656c2e6d65737361" .
"6765732e6772616469646f2e5369676e617475726550616972222b0a0954" .
"696d657374616d70120f0a077365636f6e6473180120012803120d0a056e" .
"616e6f7318022001280522230a1054696d657374616d705365636f6e6473" .
"120f0a077365636f6e647318012001280322590a0c53656e646572416d6f" .
"756e74121d0a15656432353531395f73656e6465725f7075626b65791801" .
"2001280c120e0a06616d6f756e74180220012812121a0a1273656e646572" .
"46696e616c42616c616e636518032001281222410a0e5265636569766572" .
"416d6f756e74121f0a17656432353531395f72656365697665725f707562" .
"6b657918012001280c120e0a06616d6f756e74180220012812620670726f" .
"746f33"
), true);
static::$is_initialized = true;
}
}

View File

@ -1,32 +0,0 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: StateCreateGroup.proto
namespace GPBMetadata;
class StateCreateGroup
{
public static $is_initialized = false;
public static function initOnce() {
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
if (static::$is_initialized == true) {
return;
}
\GPBMetadata\BasicTypes::initOnce();
$pool->internalAddGeneratedFile(hex2bin(
"0ae4010a16537461746543726561746547726f75702e70726f746f12166d" .
"6f64656c2e6d657373616765732e6772616469646f22a9010a1053746174" .
"6543726561746547726f7570120c0a046e616d6518012001280912330a0e" .
"67726f75705075626c69634b657918022001280b321b2e6d6f64656c2e6d" .
"657373616765732e6772616469646f2e4b657912390a14706172656e7447" .
"726f75705075626c69634b657918032001280b321b2e6d6f64656c2e6d65" .
"7373616765732e6772616469646f2e4b65794a0408041005521168656465" .
"7261436f6e73656e7375734964620670726f746f33"
), true);
static::$is_initialized = true;
}
}

View File

@ -1,33 +0,0 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: StateGroupChangeParent.proto
namespace GPBMetadata;
class StateGroupChangeParent
{
public static $is_initialized = false;
public static function initOnce() {
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
if (static::$is_initialized == true) {
return;
}
\GPBMetadata\BasicTypes::initOnce();
$pool->internalAddGeneratedFile(hex2bin(
"0a8a020a1c537461746547726f75704368616e6765506172656e742e7072" .
"6f746f12166d6f64656c2e6d657373616765732e6772616469646f22c901" .
"0a16537461746547726f75704368616e6765506172656e7412330a0e6772" .
"6f75705075626c69634b657918012001280b321b2e6d6f64656c2e6d6573" .
"73616765732e6772616469646f2e4b6579123c0a176e6577506172656e74" .
"47726f75705075626c69634b657918022001280b321b2e6d6f64656c2e6d" .
"657373616765732e6772616469646f2e4b6579123c0a176f6c6450617265" .
"6e7447726f75705075626c69634b657918032001280b321b2e6d6f64656c" .
"2e6d657373616765732e6772616469646f2e4b6579620670726f746f33"
), true);
static::$is_initialized = true;
}
}

View File

@ -1,32 +0,0 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: Transaction.proto
namespace GPBMetadata;
class Transaction
{
public static $is_initialized = false;
public static function initOnce() {
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
if (static::$is_initialized == true) {
return;
}
\GPBMetadata\BasicTypes::initOnce();
$pool->internalAddGeneratedFile(hex2bin(
"0ae4010a115472616e73616374696f6e2e70726f746f12166d6f64656c2e" .
"6d657373616765732e6772616469646f22ae010a0b5472616e7361637469" .
"6f6e120a0a026964180120012804123a0a08726563656976656418022001" .
"280b32282e6d6f64656c2e6d657373616765732e6772616469646f2e5469" .
"6d657374616d705365636f6e647312340a067369674d617018032001280b" .
"32242e6d6f64656c2e6d657373616765732e6772616469646f2e5369676e" .
"61747572654d6170120e0a0674784861736818042001280c12110a09626f" .
"6479427974657318052001280c620670726f746f33"
), true);
static::$is_initialized = true;
}
}

View File

@ -1,46 +0,0 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: TransactionBody.proto
namespace GPBMetadata;
class TransactionBody
{
public static $is_initialized = false;
public static function initOnce() {
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
if (static::$is_initialized == true) {
return;
}
\GPBMetadata\Transfer::initOnce();
\GPBMetadata\StateCreateGroup::initOnce();
\GPBMetadata\StateGroupChangeParent::initOnce();
\GPBMetadata\TransactionCreation::initOnce();
\GPBMetadata\BasicTypes::initOnce();
$pool->internalAddGeneratedFile(hex2bin(
"0a84040a155472616e73616374696f6e426f64792e70726f746f12166d6f" .
"64656c2e6d657373616765732e6772616469646f1a165374617465437265" .
"61746547726f75702e70726f746f1a1c537461746547726f75704368616e" .
"6765506172656e742e70726f746f1a195472616e73616374696f6e437265" .
"6174696f6e2e70726f746f1a10426173696354797065732e70726f746f22" .
"e7020a0f5472616e73616374696f6e426f6479120c0a046d656d6f180120" .
"01280912390a076372656174656418022001280b32282e6d6f64656c2e6d" .
"657373616765732e6772616469646f2e54696d657374616d705365636f6e" .
"6473123f0a0b63726561746547726f757018062001280b32282e6d6f6465" .
"6c2e6d657373616765732e6772616469646f2e5374617465437265617465" .
"47726f75704800124b0a1167726f75704368616e6765506172656e741807" .
"2001280b322e2e6d6f64656c2e6d657373616765732e6772616469646f2e" .
"537461746547726f75704368616e6765506172656e74480012340a087472" .
"616e7366657218082001280b32202e6d6f64656c2e6d657373616765732e" .
"6772616469646f2e5472616e736665724800123f0a086372656174696f6e" .
"18092001280b322b2e6d6f64656c2e6d657373616765732e677261646964" .
"6f2e5472616e73616374696f6e4372656174696f6e480042060a04646174" .
"61620670726f746f33"
), true);
static::$is_initialized = true;
}
}

View File

@ -1,32 +0,0 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: TransactionCreation.proto
namespace GPBMetadata;
class TransactionCreation
{
public static $is_initialized = false;
public static function initOnce() {
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
if (static::$is_initialized == true) {
return;
}
\GPBMetadata\BasicTypes::initOnce();
$pool->internalAddGeneratedFile(hex2bin(
"0ae6010a195472616e73616374696f6e4372656174696f6e2e70726f746f" .
"12166d6f64656c2e6d657373616765732e6772616469646f22a8010a1354" .
"72616e73616374696f6e4372656174696f6e123e0a0e7265636569766572" .
"416d6f756e7418012001280b32262e6d6f64656c2e6d657373616765732e" .
"6772616469646f2e5265636569766572416d6f756e7412120a0a6964656e" .
"745f68617368180220012811123d0a0b7461726765745f64617465180320" .
"01280b32282e6d6f64656c2e6d657373616765732e6772616469646f2e54" .
"696d657374616d705365636f6e6473620670726f746f33"
), true);
static::$is_initialized = true;
}
}

View File

@ -1,31 +0,0 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: Transfer.proto
namespace GPBMetadata;
class Transfer
{
public static $is_initialized = false;
public static function initOnce() {
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
if (static::$is_initialized == true) {
return;
}
\GPBMetadata\BasicTypes::initOnce();
$pool->internalAddGeneratedFile(hex2bin(
"0abb010a0e5472616e736665722e70726f746f12166d6f64656c2e6d6573" .
"73616765732e6772616469646f2288010a085472616e73666572123b0a0d" .
"73656e646572416d6f756e747318012003280b32242e6d6f64656c2e6d65" .
"7373616765732e6772616469646f2e53656e646572416d6f756e74123f0a" .
"0f7265636569766572416d6f756e747318022003280b32262e6d6f64656c" .
"2e6d657373616765732e6772616469646f2e5265636569766572416d6f75" .
"6e74620670726f746f33"
), true);
static::$is_initialized = true;
}
}

View File

@ -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,
];
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Model\Entity;
use Cake\ORM\Entity;
/**
* BlockchainType Entity
*
* @property int $id
* @property string $name
* @property string|null $text
* @property string|null $symbol
*/
class BlockchainType extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array
*/
protected $_accessible = [
'name' => true,
'text' => true,
'symbol' => true,
];
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Model\Entity;
use Cake\ORM\Entity;
/**
* Role Entity
*
* @property int $id
* @property string|null $title
*/
class Role extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array
*/
protected $_accessible = [
'title' => true,
];
}

View File

@ -28,6 +28,7 @@ class StateBalance extends Entity
protected $_accessible = [
'state_user_id' => true,
'modified' => true,
'record_date' => true,
'amount' => true,
'record_date' => true,
'state_user' => true
@ -39,8 +40,12 @@ class StateBalance extends Entity
{
if(method_exists($dateOrTime, 'getTimestamp')) {
return $dateOrTime->getTimestamp();
} else {
} else if(method_exists($dateOrTime, 'i18nFormat')) {
return $dateOrTime->i18nFormat(Time::UNIX_TIMESTAMP_FORMAT);
} else {
var_dump($dateOrTime);
debug_print_backtrace(0, 4);
die("date or time unexpected object");
}
}
@ -53,28 +58,28 @@ class StateBalance extends Entity
// SELECT TIMESTAMPDIFF(SECOND, modified, CURDATE()) AS age_in_seconds from state_balances
// decay_for_duration = decay_factor^seconds
// decay = gradido_cent * decay_for_duration
$decay_duration = $this->decayDuration(Time::now());
$decay_duration = intval(Time::now()->getTimestamp() - $this->convertToTimestamp($this->record_date));
if($decay_duration === 0) {
return $this->amount;
}
return $this->amount;
//return $this->amount * pow(0.99999997802044727, $decay_duration);
//return $this->amount;
return $this->amount * pow(0.99999997802044727, $decay_duration);
}
public function partDecay($target_date)
{
if($target_date == null) return 0;
$decay_duration = $this->decayDuration($target_date);
$decay_duration = intval($this->convertToTimestamp($target_date) - $this->convertToTimestamp($this->record_date));
if($decay_duration <= 0) {
return $this->amount;
}
return 0;
//return $this->amount * pow(0.99999997802044727, $decay_duration);
//return 0;
return $this->amount * pow(0.99999997802044727, $decay_duration);
}
public function decayDuration($target_date)
{
if($this->record_date == null) return 0;
return intval($this->convertToTimestamp($target_date) - $this->record_date->getTimestamp());
{
return intval($this->convertToTimestamp($target_date) - $this->convertToTimestamp($this->record_date));
}
}

View File

@ -7,7 +7,7 @@ use Cake\ORM\Entity;
* StateGroupAddress Entity
*
* @property int $id
* @property int $state_group_id
* @property int $group_id
* @property string|resource $public_key
* @property int $address_type_id
*
@ -26,10 +26,10 @@ class StateGroupAddress extends Entity
* @var array
*/
protected $_accessible = [
'state_group_id' => true,
'group_id' => true,
'public_key' => true,
'address_type_id' => true,
'state_group' => true,
'address_type' => true
'address_type' => true,
];
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Model\Entity;
use Cake\ORM\Entity;
/**
* StateUserRole Entity
*
* @property int $id
* @property int $state_user_id
* @property int $role_id
*
* @property \App\Model\Entity\StateUser $state_user
*/
class StateUserRole extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array
*/
protected $_accessible = [
'state_user_id' => true,
'role_id' => true
];
}

View File

@ -39,6 +39,7 @@ class Transaction extends Entity
'tx_hash' => true,
'memo' => true,
'received' => true,
'blockchain_type_id' => true,
'state_group' => true,
'transaction_type' => true,
'state_created' => true,

View File

@ -28,8 +28,10 @@ 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
'address_type' => true,
'state_user_id' => true
];
}

View File

@ -0,0 +1,146 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GradidoTransfer.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.CrossGroupTransfer</code>
*/
class CrossGroupTransfer extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>.proto.gradido.TransferAmount sender = 1;</code>
*/
private $sender = null;
/**
* Generated from protobuf field <code>bytes receiver = 2;</code>
*/
private $receiver = '';
/**
* Generated from protobuf field <code>string other_group = 3;</code>
*/
private $other_group = '';
/**
* this matches related OutboundTransfer.paired_transaction_id
*
* Generated from protobuf field <code>.proto.gradido.Timestamp paired_transaction_id = 4;</code>
*/
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 <code>.proto.gradido.TransferAmount sender = 1;</code>
* @return \Proto\Gradido\TransferAmount
*/
public function getSender()
{
return $this->sender;
}
/**
* Generated from protobuf field <code>.proto.gradido.TransferAmount sender = 1;</code>
* @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 <code>bytes receiver = 2;</code>
* @return string
*/
public function getReceiver()
{
return $this->receiver;
}
/**
* Generated from protobuf field <code>bytes receiver = 2;</code>
* @param string $var
* @return $this
*/
public function setReceiver($var)
{
GPBUtil::checkString($var, False);
$this->receiver = $var;
return $this;
}
/**
* Generated from protobuf field <code>string other_group = 3;</code>
* @return string
*/
public function getOtherGroup()
{
return $this->other_group;
}
/**
* Generated from protobuf field <code>string other_group = 3;</code>
* @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 <code>.proto.gradido.Timestamp paired_transaction_id = 4;</code>
* @return \Proto\Gradido\Timestamp
*/
public function getPairedTransactionId()
{
return $this->paired_transaction_id;
}
/**
* this matches related OutboundTransfer.paired_transaction_id
*
* Generated from protobuf field <code>.proto.gradido.Timestamp paired_transaction_id = 4;</code>
* @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;
}
}

View File

@ -0,0 +1,102 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GradidoCreation.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* need signature from group admin or
* percent of group users another than the receiver
*
* Generated from protobuf message <code>proto.gradido.GradidoCreation</code>
*/
class GradidoCreation extends \Google\Protobuf\Internal\Message
{
/**
* 40 Byte
*
* Generated from protobuf field <code>.proto.gradido.TransferAmount receiver = 1;</code>
*/
private $receiver = null;
/**
* 8 Byte
*
* Generated from protobuf field <code>.proto.gradido.TimestampSeconds target_date = 3;</code>
*/
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 <code>.proto.gradido.TransferAmount receiver = 1;</code>
* @return \Proto\Gradido\TransferAmount
*/
public function getReceiver()
{
return $this->receiver;
}
/**
* 40 Byte
*
* Generated from protobuf field <code>.proto.gradido.TransferAmount receiver = 1;</code>
* @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 <code>.proto.gradido.TimestampSeconds target_date = 3;</code>
* @return \Proto\Gradido\TimestampSeconds
*/
public function getTargetDate()
{
return $this->target_date;
}
/**
* 8 Byte
*
* Generated from protobuf field <code>.proto.gradido.TimestampSeconds target_date = 3;</code>
* @param \Proto\Gradido\TimestampSeconds $var
* @return $this
*/
public function setTargetDate($var)
{
GPBUtil::checkMessage($var, \Proto\Gradido\TimestampSeconds::class);
$this->target_date = $var;
return $this;
}
}

View File

@ -0,0 +1,116 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GradidoTransaction.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.GradidoTransaction</code>
*/
class GradidoTransaction extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>.proto.gradido.SignatureMap sig_map = 1;</code>
*/
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 <code>bytes body_bytes = 2;</code>
*/
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 <code>.proto.gradido.SignatureMap sig_map = 1;</code>
* @return \Proto\Gradido\SignatureMap
*/
public function getSigMap()
{
return $this->sig_map;
}
/**
* Generated from protobuf field <code>.proto.gradido.SignatureMap sig_map = 1;</code>
* @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 <code>bytes body_bytes = 2;</code>
* @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 <code>bytes body_bytes = 2;</code>
* @param string $var
* @return $this
*/
public function setBodyBytes($var)
{
GPBUtil::checkString($var, False);
$this->body_bytes = $var;
return $this;
}
}

View File

@ -0,0 +1,109 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GradidoTransfer.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.GradidoTransfer</code>
*/
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 <code>.proto.gradido.LocalTransfer local = 1;</code>
* @return \Proto\Gradido\LocalTransfer
*/
public function getLocal()
{
return $this->readOneof(1);
}
/**
* Generated from protobuf field <code>.proto.gradido.LocalTransfer local = 1;</code>
* @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 <code>.proto.gradido.CrossGroupTransfer inbound = 2;</code>
* @return \Proto\Gradido\CrossGroupTransfer
*/
public function getInbound()
{
return $this->readOneof(2);
}
/**
* Generated from protobuf field <code>.proto.gradido.CrossGroupTransfer inbound = 2;</code>
* @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 <code>.proto.gradido.CrossGroupTransfer outbound = 3;</code>
* @return \Proto\Gradido\CrossGroupTransfer
*/
public function getOutbound()
{
return $this->readOneof(3);
}
/**
* Generated from protobuf field <code>.proto.gradido.CrossGroupTransfer outbound = 3;</code>
* @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");
}
}

View File

@ -0,0 +1,92 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GroupFriendsUpdate.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.GroupFriendsUpdate</code>
*/
class GroupFriendsUpdate extends \Google\Protobuf\Internal\Message
{
/**
* char[16], alias
*
* Generated from protobuf field <code>string group = 1;</code>
*/
private $group = '';
/**
* Generated from protobuf field <code>.proto.gradido.GroupFriendsUpdate.Action action = 2;</code>
*/
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 <code>string group = 1;</code>
* @return string
*/
public function getGroup()
{
return $this->group;
}
/**
* char[16], alias
*
* Generated from protobuf field <code>string group = 1;</code>
* @param string $var
* @return $this
*/
public function setGroup($var)
{
GPBUtil::checkString($var, True);
$this->group = $var;
return $this;
}
/**
* Generated from protobuf field <code>.proto.gradido.GroupFriendsUpdate.Action action = 2;</code>
* @return int
*/
public function getAction()
{
return $this->action;
}
/**
* Generated from protobuf field <code>.proto.gradido.GroupFriendsUpdate.Action action = 2;</code>
* @param int $var
* @return $this
*/
public function setAction($var)
{
GPBUtil::checkEnum($var, \Proto\Gradido\GroupFriendsUpdate_Action::class);
$this->action = $var;
return $this;
}
}

View File

@ -0,0 +1,51 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GroupFriendsUpdate.proto
namespace Proto\Gradido\GroupFriendsUpdate;
use UnexpectedValueException;
/**
* Protobuf type <code>proto.gradido.GroupFriendsUpdate.Action</code>
*/
class Action
{
/**
* Generated from protobuf enum <code>ADD_FRIEND = 0;</code>
*/
const ADD_FRIEND = 0;
/**
* Generated from protobuf enum <code>REMOVE_FRIEND = 1;</code>
*/
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);

View File

@ -0,0 +1,16 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GroupFriendsUpdate.proto
namespace Proto\Gradido;
if (false) {
/**
* This class is deprecated. Use Proto\Gradido\GroupFriendsUpdate\Action instead.
* @deprecated
*/
class GroupFriendsUpdate_Action {}
}
class_exists(GroupFriendsUpdate\Action::class);
@trigger_error('Proto\Gradido\GroupFriendsUpdate_Action is deprecated and will be removed in the next major release. Use Proto\Gradido\GroupFriendsUpdate\Action instead', E_USER_DEPRECATED);

View File

@ -0,0 +1,146 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GroupMemberUpdate.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.GroupMemberUpdate</code>
*/
class GroupMemberUpdate extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>bytes user_pubkey = 1;</code>
*/
private $user_pubkey = '';
/**
* Generated from protobuf field <code>.proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2;</code>
*/
private $member_update_type = 0;
/**
* this only makes sense for user move, TODO: probably restructure
*
* Generated from protobuf field <code>.proto.gradido.Timestamp paired_transaction_id = 3;</code>
*/
private $paired_transaction_id = null;
/**
* Generated from protobuf field <code>string target_group = 4;</code>
*/
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 <code>bytes user_pubkey = 1;</code>
* @return string
*/
public function getUserPubkey()
{
return $this->user_pubkey;
}
/**
* Generated from protobuf field <code>bytes user_pubkey = 1;</code>
* @param string $var
* @return $this
*/
public function setUserPubkey($var)
{
GPBUtil::checkString($var, False);
$this->user_pubkey = $var;
return $this;
}
/**
* Generated from protobuf field <code>.proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2;</code>
* @return int
*/
public function getMemberUpdateType()
{
return $this->member_update_type;
}
/**
* Generated from protobuf field <code>.proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2;</code>
* @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 <code>.proto.gradido.Timestamp paired_transaction_id = 3;</code>
* @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 <code>.proto.gradido.Timestamp paired_transaction_id = 3;</code>
* @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 <code>string target_group = 4;</code>
* @return string
*/
public function getTargetGroup()
{
return $this->target_group;
}
/**
* Generated from protobuf field <code>string target_group = 4;</code>
* @param string $var
* @return $this
*/
public function setTargetGroup($var)
{
GPBUtil::checkString($var, True);
$this->target_group = $var;
return $this;
}
}

View File

@ -0,0 +1,56 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GroupMemberUpdate.proto
namespace Proto\Gradido\GroupMemberUpdate;
use UnexpectedValueException;
/**
* Protobuf type <code>proto.gradido.GroupMemberUpdate.MemberUpdateType</code>
*/
class MemberUpdateType
{
/**
* Generated from protobuf enum <code>ADD_USER = 0;</code>
*/
const ADD_USER = 0;
/**
* Generated from protobuf enum <code>MOVE_USER_INBOUND = 1;</code>
*/
const MOVE_USER_INBOUND = 1;
/**
* Generated from protobuf enum <code>MOVE_USER_OUTBOUND = 2;</code>
*/
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);

View File

@ -0,0 +1,16 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GroupMemberUpdate.proto
namespace Proto\Gradido;
if (false) {
/**
* This class is deprecated. Use Proto\Gradido\GroupMemberUpdate\MemberUpdateType instead.
* @deprecated
*/
class GroupMemberUpdate_MemberUpdateType {}
}
class_exists(GroupMemberUpdate\MemberUpdateType::class);
@trigger_error('Proto\Gradido\GroupMemberUpdate_MemberUpdateType is deprecated and will be removed in the next major release. Use Proto\Gradido\GroupMemberUpdate\MemberUpdateType instead', E_USER_DEPRECATED);

View File

@ -0,0 +1,96 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/BasicTypes.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.Key</code>
*/
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 <code>bytes ed25519 = 2;</code>
* @return string
*/
public function getEd25519()
{
return $this->readOneof(2);
}
/**
* ed25519 signature (libsodium default)
*
* Generated from protobuf field <code>bytes ed25519 = 2;</code>
* @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 <code>bytes ed25519_ref10 = 3;</code>
* @return string
*/
public function getEd25519Ref10()
{
return $this->readOneof(3);
}
/**
* ed25519 ref10 signature
*
* Generated from protobuf field <code>bytes ed25519_ref10 = 3;</code>
* @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");
}
}

View File

@ -0,0 +1,85 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/GradidoTransfer.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.LocalTransfer</code>
*/
class LocalTransfer extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>.proto.gradido.TransferAmount sender = 1;</code>
*/
private $sender = null;
/**
* Generated from protobuf field <code>bytes receiver = 2;</code>
*/
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 <code>.proto.gradido.TransferAmount sender = 1;</code>
* @return \Proto\Gradido\TransferAmount
*/
public function getSender()
{
return $this->sender;
}
/**
* Generated from protobuf field <code>.proto.gradido.TransferAmount sender = 1;</code>
* @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 <code>bytes receiver = 2;</code>
* @return string
*/
public function getReceiver()
{
return $this->receiver;
}
/**
* Generated from protobuf field <code>bytes receiver = 2;</code>
* @param string $var
* @return $this
*/
public function setReceiver($var)
{
GPBUtil::checkString($var, False);
$this->receiver = $var;
return $this;
}
}

View File

@ -0,0 +1,65 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/BasicTypes.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.SignatureMap</code>
*/
class SignatureMap extends \Google\Protobuf\Internal\Message
{
/**
* Each signature pair corresponds to a unique Key required to sign the transaction.
*
* Generated from protobuf field <code>repeated .proto.gradido.SignaturePair sigPair = 1;</code>
*/
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 <code>repeated .proto.gradido.SignaturePair sigPair = 1;</code>
* @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 <code>repeated .proto.gradido.SignaturePair sigPair = 1;</code>
* @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;
}
}

View File

@ -0,0 +1,123 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/BasicTypes.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.SignaturePair</code>
*/
class SignaturePair extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>bytes pubKey = 1;</code>
*/
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 <code>bytes pubKey = 1;</code>
* @return string
*/
public function getPubKey()
{
return $this->pubKey;
}
/**
* Generated from protobuf field <code>bytes pubKey = 1;</code>
* @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 <code>bytes ed25519 = 2;</code>
* @return string
*/
public function getEd25519()
{
return $this->readOneof(2);
}
/**
* ed25519 signature (libsodium default)
*
* Generated from protobuf field <code>bytes ed25519 = 2;</code>
* @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 <code>bytes ed25519_ref10 = 3;</code>
* @return string
*/
public function getEd25519Ref10()
{
return $this->readOneof(3);
}
/**
* ed25519 ref10 signature
*
* Generated from protobuf field <code>bytes ed25519_ref10 = 3;</code>
* @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");
}
}

View File

@ -0,0 +1,101 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/BasicTypes.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* An exact date and time. This is the same data structure as the protobuf Timestamp.proto (see the comments in https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto)
*
* Generated from protobuf message <code>proto.gradido.Timestamp</code>
*/
class Timestamp extends \Google\Protobuf\Internal\Message
{
/**
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
*/
private $seconds = 0;
/**
* Number of nanoseconds since the start of the last second
*
* Generated from protobuf field <code>int32 nanos = 2;</code>
*/
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 <code>int64 seconds = 1;</code>
* @return int|string
*/
public function getSeconds()
{
return $this->seconds;
}
/**
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
* @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 <code>int32 nanos = 2;</code>
* @return int
*/
public function getNanos()
{
return $this->nanos;
}
/**
* Number of nanoseconds since the start of the last second
*
* Generated from protobuf field <code>int32 nanos = 2;</code>
* @param int $var
* @return $this
*/
public function setNanos($var)
{
GPBUtil::checkInt32($var);
$this->nanos = $var;
return $this;
}
}

View File

@ -0,0 +1,67 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/BasicTypes.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* An exact date and time, with a resolution of one second (no nanoseconds).
*
* Generated from protobuf message <code>proto.gradido.TimestampSeconds</code>
*/
class TimestampSeconds extends \Google\Protobuf\Internal\Message
{
/**
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
*/
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 <code>int64 seconds = 1;</code>
* @return int|string
*/
public function getSeconds()
{
return $this->seconds;
}
/**
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
* @param int|string $var
* @return $this
*/
public function setSeconds($var)
{
GPBUtil::checkInt64($var);
$this->seconds = $var;
return $this;
}
}

View File

@ -0,0 +1,220 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/TransactionBody.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.TransactionBody</code>
*/
class TransactionBody extends \Google\Protobuf\Internal\Message
{
/**
* max 150 chars
*
* Generated from protobuf field <code>string memo = 1;</code>
*/
private $memo = '';
/**
* Generated from protobuf field <code>.proto.gradido.TimestampSeconds created = 2;</code>
*/
private $created = null;
/**
* Generated from protobuf field <code>uint64 version_number = 3;</code>
*/
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\TimestampSeconds $created
* @type int|string $version_number
* @type \Proto\Gradido\GradidoTransfer $transfer
* @type \Proto\Gradido\GradidoCreation $creation
* @type \Proto\Gradido\GroupFriendsUpdate $group_friends_update
* @type \Proto\Gradido\GroupMemberUpdate $group_member_update
* }
*/
public function __construct($data = NULL) {
\GPBMetadata\Gradido\TransactionBody::initOnce();
parent::__construct($data);
}
/**
* max 150 chars
*
* Generated from protobuf field <code>string memo = 1;</code>
* @return string
*/
public function getMemo()
{
return $this->memo;
}
/**
* max 150 chars
*
* Generated from protobuf field <code>string memo = 1;</code>
* @param string $var
* @return $this
*/
public function setMemo($var)
{
GPBUtil::checkString($var, True);
$this->memo = $var;
return $this;
}
/**
* Generated from protobuf field <code>.proto.gradido.TimestampSeconds created = 2;</code>
* @return \Proto\Gradido\TimestampSeconds
*/
public function getCreated()
{
return $this->created;
}
/**
* Generated from protobuf field <code>.proto.gradido.TimestampSeconds created = 2;</code>
* @param \Proto\Gradido\TimestampSeconds $var
* @return $this
*/
public function setCreated($var)
{
GPBUtil::checkMessage($var, \Proto\Gradido\TimestampSeconds::class);
$this->created = $var;
return $this;
}
/**
* Generated from protobuf field <code>uint64 version_number = 3;</code>
* @return int|string
*/
public function getVersionNumber()
{
return $this->version_number;
}
/**
* Generated from protobuf field <code>uint64 version_number = 3;</code>
* @param int|string $var
* @return $this
*/
public function setVersionNumber($var)
{
GPBUtil::checkUint64($var);
$this->version_number = $var;
return $this;
}
/**
* Generated from protobuf field <code>.proto.gradido.GradidoTransfer transfer = 6;</code>
* @return \Proto\Gradido\GradidoTransfer
*/
public function getTransfer()
{
return $this->readOneof(6);
}
/**
* Generated from protobuf field <code>.proto.gradido.GradidoTransfer transfer = 6;</code>
* @param \Proto\Gradido\GradidoTransfer $var
* @return $this
*/
public function setTransfer($var)
{
GPBUtil::checkMessage($var, \Proto\Gradido\GradidoTransfer::class);
$this->writeOneof(6, $var);
return $this;
}
/**
* Generated from protobuf field <code>.proto.gradido.GradidoCreation creation = 7;</code>
* @return \Proto\Gradido\GradidoCreation
*/
public function getCreation()
{
return $this->readOneof(7);
}
/**
* Generated from protobuf field <code>.proto.gradido.GradidoCreation creation = 7;</code>
* @param \Proto\Gradido\GradidoCreation $var
* @return $this
*/
public function setCreation($var)
{
GPBUtil::checkMessage($var, \Proto\Gradido\GradidoCreation::class);
$this->writeOneof(7, $var);
return $this;
}
/**
* Generated from protobuf field <code>.proto.gradido.GroupFriendsUpdate group_friends_update = 8;</code>
* @return \Proto\Gradido\GroupFriendsUpdate
*/
public function getGroupFriendsUpdate()
{
return $this->readOneof(8);
}
/**
* Generated from protobuf field <code>.proto.gradido.GroupFriendsUpdate group_friends_update = 8;</code>
* @param \Proto\Gradido\GroupFriendsUpdate $var
* @return $this
*/
public function setGroupFriendsUpdate($var)
{
GPBUtil::checkMessage($var, \Proto\Gradido\GroupFriendsUpdate::class);
$this->writeOneof(8, $var);
return $this;
}
/**
* Generated from protobuf field <code>.proto.gradido.GroupMemberUpdate group_member_update = 9;</code>
* @return \Proto\Gradido\GroupMemberUpdate
*/
public function getGroupMemberUpdate()
{
return $this->readOneof(9);
}
/**
* Generated from protobuf field <code>.proto.gradido.GroupMemberUpdate group_member_update = 9;</code>
* @param \Proto\Gradido\GroupMemberUpdate $var
* @return $this
*/
public function setGroupMemberUpdate($var)
{
GPBUtil::checkMessage($var, \Proto\Gradido\GroupMemberUpdate::class);
$this->writeOneof(9, $var);
return $this;
}
/**
* @return string
*/
public function getData()
{
return $this->whichOneof("data");
}
}

View File

@ -0,0 +1,85 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: gradido/BasicTypes.proto
namespace Proto\Gradido;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>proto.gradido.TransferAmount</code>
*/
class TransferAmount extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>bytes pubkey = 1;</code>
*/
private $pubkey = '';
/**
* Generated from protobuf field <code>sint64 amount = 2;</code>
*/
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 <code>bytes pubkey = 1;</code>
* @return string
*/
public function getPubkey()
{
return $this->pubkey;
}
/**
* Generated from protobuf field <code>bytes pubkey = 1;</code>
* @param string $var
* @return $this
*/
public function setPubkey($var)
{
GPBUtil::checkString($var, False);
$this->pubkey = $var;
return $this;
}
/**
* Generated from protobuf field <code>sint64 amount = 2;</code>
* @return int|string
*/
public function getAmount()
{
return $this->amount;
}
/**
* Generated from protobuf field <code>sint64 amount = 2;</code>
* @param int|string $var
* @return $this
*/
public function setAmount($var)
{
GPBUtil::checkInt64($var);
$this->amount = $var;
return $this;
}
}

View File

@ -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;
}

View File

@ -0,0 +1,68 @@
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* BlockchainTypes Model
*
* @method \App\Model\Entity\BlockchainType get($primaryKey, $options = [])
* @method \App\Model\Entity\BlockchainType newEntity($data = null, array $options = [])
* @method \App\Model\Entity\BlockchainType[] newEntities(array $data, array $options = [])
* @method \App\Model\Entity\BlockchainType|false save(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\BlockchainType saveOrFail(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\BlockchainType patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method \App\Model\Entity\BlockchainType[] patchEntities($entities, array $data, array $options = [])
* @method \App\Model\Entity\BlockchainType findOrCreate($search, callable $callback = null, $options = [])
*/
class BlockchainTypesTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('blockchain_types');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
}
/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->nonNegativeInteger('id')
->allowEmptyString('id', null, 'create');
$validator
->scalar('name')
->maxLength('name', 45)
->requirePresence('name', 'create')
->notEmptyString('name');
$validator
->scalar('text')
->maxLength('text', 255)
->allowEmptyString('text');
$validator
->scalar('symbol')
->maxLength('symbol', 10)
->allowEmptyString('symbol');
return $validator;
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Roles Model
*
* @method \App\Model\Entity\Role get($primaryKey, $options = [])
* @method \App\Model\Entity\Role newEntity($data = null, array $options = [])
* @method \App\Model\Entity\Role[] newEntities(array $data, array $options = [])
* @method \App\Model\Entity\Role|false save(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\Role saveOrFail(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\Role patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method \App\Model\Entity\Role[] patchEntities($entities, array $data, array $options = [])
* @method \App\Model\Entity\Role findOrCreate($search, callable $callback = null, $options = [])
*/
class RolesTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->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;
}
}

View File

@ -6,6 +6,10 @@ use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\ORM\TableRegistry;
use Cake\I18n\Date;
use Cake\I18n\Time;
/**
* StateBalances Model
*
@ -78,4 +82,271 @@ class StateBalancesTable extends Table
return $rules;
}
/*
* create new state balance at beginning of next month from $previousStateBalance
* calculate decay for the time diff
*/
private function calculateStateBalance($previousStateBalance)
{
$entity = $this->newEntity();
$entity->state_user_id = $previousStateBalance->state_user_id;
$newDate = $previousStateBalance->record_date;
$newDate->day(1);
if($newDate->month <= 12) {
$newDate->month($newDate->month + 1);
} else {
$newDate->month(1);
$newDate->year($newDate->year + 1);
}
$entity->record_date = $newDate;
$entity->amount = $previousStateBalance->partDecay($newDate);
if($this->save($entity)) {
return $entity;
}
return ['state' => 'error', 'msg' => 'couldn\'t save', 'details' => $entity->getErrors()];
}
public function sortTransactions($a, $b)
{
if ($a['date'] == $b['date']) {
return 0;
}
return ($a['date'] > $b['date']) ? -1 : 1;
}
/*
* calculate balance at end of month
* work only if state balance at begin of month exist
* use transaction_send_coins and transaction_creations
*/
public function updateLastStateBalanceOfMonth($month, $year, $state_user_id)
{
$first_of_month = new Time("$year-$month-01 00:00");
$last_of_month = new Time($first_of_month);
$last_of_month->addMonth(1);
$last_of_month->subSecond(1);
$query = $this->find('all')
->where(['AND' => [
'state_user_id' => $state_user_id,
'record_date >=' => $first_of_month,
'record_date <=' => $last_of_month
]])
->order(['record_date' => 'ASC']);
if($query->isEmpty()) {
return [
'state' => 'error',
'msg' => 'no state balance in this month found',
'details' => [
'month' => $month,
'year' => $year,
'state_user_id' => $state_user_id
]
];
}
// get transactions from this month
$balance_changes = [];
$transactionCreationsTable = TableRegistry::getTableLocator()->get('TransactionCreations');
$transactionTransfersTable = TableRegistry::getTableLocator()->get('TransactionSendCoins');
$relevant_creations = $transactionCreationsTable
->find('all')
->where(['AND' => [
'state_user_id' => $state_user_id,
'target_date >=' => $first_of_month,
'target_date <=' => $last_of_month
]])->contain(false);
foreach($relevant_creations as $creation) {
$balance_changes[] = ['amount' => $creation->amount, 'date' => $creation->target_date];
}
$relevant_transfers = $transactionTransfersTable
->find('all')
->where(['AND' => [
'OR' => [
'state_user_id' => $state_user_id,
'receiver_user_id' => $state_user_id
],
'transaction.received >= ' => $first_of_month,
'transaction.received <=' => $last_of_month
]])->contain(['Transactions']);
debug($relevant_transfers);
foreach($relevant_transfers as $transfer) {
$amount = $transfer->amount;
// if it is a send transaction, negate the value
if($transfer->state_user_id == $state_user_id) {
$amount *= -1.0;
}
$balance_changes[] = ['amount' => $amount, 'date' => $transfer->transaction->received];
}
uasort($balance_changes, array($this, 'sortTransactions'));
$current_state_balance = null;
if($query->count() == 1) {
$current_state_balance = $this->newEntity();
$current_state_balance->amount = $query->first()->amount;
$current_state_balance->state_user_id = $state_user_id;
$current_state_balance->record_date = $query->first()->record_date;
} else if($query->count() == 2) {
$array = $query->toArray();
$current_state_balance = $array[1];
} else {
throw new Exception('Should\'n occure, never');
}
foreach($balance_changes as $change) {
$current_state_balance->amount = $current_state_balance->getDecay($change['date']);
$current_state_balance->amount += $change['amount'];
$current_state_balance->record_date = $change['date'];
}
if(!$this->save($current_state_balance)) {
return ['state' => 'error', 'msg' => 'couldn\'t save', 'details' => $current_state_balance->getErrors()];
}
return $current_state_balance;
}
/*
* getting start balance for month
* create and create all missing state_balances before if not exist
* in while loop
*/
public function chooseForMonthAndUser($month, $year, $state_user_id)
{
$first_of_month = new Time("$year-$month-01 00:00");
$last_of_month = new Time($first_of_month);
$last_of_month->addMonth(1);
$last_of_month->subSecond(1);
//echo "first of month: " . $first_of_month->i18nFormat() . ", last of month: " . $last_of_month->i18nFormat() . "<br>";
$query = $this->find('all');
$query->select([
'month' => $query->func()->month(['record_date' => 'identifier']),
'year' => $query->func()->year(['record_date' => 'identifier'])
])->select($this)
//->where(['month' => $month, 'year' => $year, 'state_user_id' => $state_user_id])
->where(['AND' => [
'state_user_id' => $state_user_id,
'record_date >=' => $first_of_month,
'record_date <=' => $last_of_month
]
])
->order(['record_date' => 'ASC'])
->limit(1)
->contain([]);
if($query->count() == 0)
{
// if any state balance for user exist, pick last one
$state_balances = $this->find('all')
->where(['state_user_id' => $state_user_id])
->limit(1)
->order(['record_date' => 'DESC'])
;
// create one for first user transaction
if($state_balances->isEmpty())
{
$state_user_transactions_table = TableRegistry::getTableLocator()->get('StateUserTransactions');
$state_user_transaction = $state_user_transactions_table->find('all')
->where(['state_user_id' => $state_user_id, 'StateUserTransactions.transaction_type_id <' => 3])
->contain(['Transactions' => ['TransactionCreations', 'TransactionSendCoins']])
->limit(1)
->order(['transaction_id' => 'ASC'])
->first()
;
if(!$state_user_transaction) {
return null;
}
$entity = $this->newEntity();
$entity->state_user_id = $state_user_id;
if($state_user_transaction->transaction_type_id == 1) {
$creation = $state_user_transaction->transaction->transaction_creations[0];
$entity->amount = $creation->amount;
$entity->record_date = $creation->target_date;
} else if($state_user_transaction->transaction_type_id == 2) {
$transfer = $state_user_transaction->transaction->transaction_send_coins[0];
$entity->amount = $transfer->amount;
$entity->record_date = $state_user_transaction->transaction->received;
}
if(!$this->save($entity)) {
return ['state' => 'error', 'msg' => 'error by saving state balance', 'details' => $entity->getErrors()];
}
}
$state_balances = $this->find('all')
->where(['state_user_id' => $state_user_id])
->limit(1)
->order(['record_date' => 'DESC'])
;
if($state_balances->count() == 1)
{
$current_state_balance = $state_balances->first();
while(true)
{
$new_state_balance_begin = $this->calculateStateBalance($current_state_balance);
if(is_array($new_state_balance_begin)) {
return ['state' => 'error', 'msg' => 'error calculate state balance', 'details' => $new_state_balance_begin];
}
$record_date = $new_state_balance_begin->record_date;
if($record_date->month === $month && $record_date->year === $year) {
return $new_state_balance_begin;
}
$current_state_balance = $this->updateLastStateBalanceOfMonth($month, $year, $state_user_id);
}
}
else
{
return ['state' => 'error', 'msg' => 'creation of first state_balance failes'];
}
}
return $query->first();
}
public function updateBalanceWithTransaction($newBalance, $recordDate, $userId)
{
// max 2 StateBalance Entrys per month:
// 1. first of month or first transaction of user
// 2. last of month or last transaction of user
$first_state_balance_of_month = $this->chooseForMonthAndUser($recordDate->month, $recordDate->year, $userId);
$updated_state_balance = null;
if($first_state_balance_of_month == null || is_array($first_state_balance_of_month)) {
return $first_state_balance_of_month;
}
if($first_state_balance_of_month->record_date->day == $recordDate->day &&
$recordDate > $first_state_balance_of_month->record_date) {
if($first_state_balance_of_month->amount == $newBalance) {
// nothing to do here
return true;
}
$updated_state_balance = $first_state_balance_of_month;
$updated_state_balance->amount = $newBalance;
// copy complete record date, inclusive time
$first_state_balance_of_month->record_date = $recordDate;
} else {
$query = $this->find('all')
->where(['AND' => [
'record_date >' => $first_state_balance_of_month->record_date,
'record_date <=' => $recordDate,
'state_user_id' => $userId
]]);
if(!$query->isEmpty()) {
$updated_state_balance = $query->first();
if($updated_state_balance->record_date == $recordDate) {
return true;
}
} else {
$updated_state_balance = $this->newEntity();
$updated_state_balance->state_user_id = $userId;
}
$updated_state_balance->record_date = $recordDate;
$updated_state_balance->amount = $newBalance;
}
if($updated_state_balance) {
if(!$this->save($updated_state_balance)) {
return ['state' => 'error', 'msg' => 'error by saving state balance', 'details' => $entity->getErrors()];
}
// delete all state_balances which came after
// they will be automaticlly recovered by next call of chooseForMonthAndUser
$this->deleteAll(['state_user_id' => $userId, 'record_date >' => $recordDate]);
}
return true;
}
}

View File

@ -9,7 +9,7 @@ use Cake\Validation\Validator;
/**
* StateGroupAddresses Model
*
* @property \App\Model\Table\StateGroupsTable&\Cake\ORM\Association\BelongsTo $StateGroups
* @property &\Cake\ORM\Association\BelongsTo $Groups
* @property \App\Model\Table\AddressTypesTable&\Cake\ORM\Association\BelongsTo $AddressTypes
*
* @method \App\Model\Entity\StateGroupAddress get($primaryKey, $options = [])
@ -37,13 +37,13 @@ class StateGroupAddressesTable extends Table
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsTo('StateGroups', [
'foreignKey' => 'state_group_id',
'joinType' => 'INNER'
]);
/*$this->belongsTo('Groups', [
'foreignKey' => 'group_id',
'joinType' => 'INNER',
]);*/
$this->belongsTo('AddressTypes', [
'foreignKey' => 'address_type_id',
'joinType' => 'INNER'
'joinType' => 'INNER',
]);
}
@ -56,12 +56,13 @@ class StateGroupAddressesTable extends Table
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->nonNegativeInteger('id')
->allowEmptyString('id', null, 'create');
$validator
->requirePresence('public_key', 'create')
->notEmptyString('public_key');
->notEmptyString('public_key')
->add('public_key', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
return $validator;
}
@ -75,7 +76,8 @@ class StateGroupAddressesTable extends Table
*/
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['state_group_id'], 'StateGroups'));
$rules->add($rules->isUnique(['public_key']));
//$rules->add($rules->existsIn(['group_id'], 'Groups'));
$rules->add($rules->existsIn(['address_type_id'], 'AddressTypes'));
return $rules;

View File

@ -0,0 +1,86 @@
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* StateUserRoles Model
*
* @property \App\Model\Table\StateUsersTable&\Cake\ORM\Association\BelongsTo $StateUser
* @property \App\Model\Table\RolesTable&\Cake\ORM\Association\BelongsTo $Roles
*
* @method \App\Model\Entity\StateUserRole get($primaryKey, $options = [])
* @method \App\Model\Entity\StateUserRole newEntity($data = null, array $options = [])
* @method \App\Model\Entity\StateUserRole[] newEntities(array $data, array $options = [])
* @method \App\Model\Entity\StateUserRole|false save(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\StateUserRole saveOrFail(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\StateUserRole patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method \App\Model\Entity\StateUserRole[] patchEntities($entities, array $data, array $options = [])
* @method \App\Model\Entity\StateUserRole findOrCreate($search, callable $callback = null, $options = [])
*/
class StateUserRolesTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->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;
}
}

View File

@ -45,6 +45,10 @@ class TransactionGroupAddaddressTable extends Table
'foreignKey' => 'address_type_id',
'joinType' => 'INNER'
]);
$this->belongsTo('StateUsers', [
'foreignKey' => 'state_user_id',
'joinType' => 'INNER'
]);
}
/**
@ -77,6 +81,7 @@ class TransactionGroupAddaddressTable extends Table
{
$rules->add($rules->existsIn(['transaction_id'], 'Transactions'));
$rules->add($rules->existsIn(['address_type_id'], 'AddressTypes'));
$rules->add($rules->existsIn(['state_user_id'], 'StateUsers'));
return $rules;
}

View File

@ -52,6 +52,10 @@ class TransactionsTable extends Table
'foreignKey' => 'transaction_type_id',
'joinType' => 'INNER'
]);
$this->belongsTo('BlockchainTypes', [
'foreignKey' => 'blockchain_type_id',
'joinType' => 'INNER'
]);
$this->hasMany('StateCreated', [
'foreignKey' => 'transaction_id'
]);
@ -114,6 +118,7 @@ class TransactionsTable extends Table
{
$rules->add($rules->existsIn(['state_group_id'], 'StateGroups'));
$rules->add($rules->existsIn(['transaction_type_id'], 'TransactionTypes'));
$rules->add($rules->existsIn(['blockchain_type_id'], 'BlockchainTypes'));
return $rules;
}

View File

@ -0,0 +1,575 @@
<?php
namespace Model\Transactions;
use Cake\I18n\Time;
use Cake\ORM\TableRegistry;
/*
* @author: Dario Rekowski
*
* @date: 2020-11-05
*
* @brief: Class for reading records from gradido node (pauls json dump format) and translate into community server transaction db format
*
*
*/
class Signature
{
private $signature;
private $publicKey;
public function __construct($signature, $pubkey)
{
$this->signature = $signature;
$this->publicKey = $pubkey;
}
public function finalize($transactionId)
{
$signaturesTable = TableRegistry::getTableLocator()->get('TransactionSignatures');
$entity = $signaturesTable->newEntity();
$entity->transaction_id = $transactionId;
if(strlen($this->signature) != 128) {
return ['state' => 'error', 'msg' => 'invalid signature size', 'details' => strlen($this->signature)];
}
if(strlen($this->publicKey) != 64) {
return ['state' => 'error', 'msg' => 'invalid pubkey size', 'details' => strlen($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 GradidoModifieUserBalance
{
private $state_users = [];
private $user_balances = [];
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' => '[GradidoModifieUserBalance::getUserId] couldn\'t find user via public key'];
}
$id = $stateUser->first()->id;
if($id && is_int($id) && (int)$id > 0 && !in_array((int)$id, $this->state_users)) {
array_push($this->state_users, (int)$id);
}
return $id;
}
public function updateBalance($newBalance, $recordDate, $userId)
{
$stateBalancesTable = TableRegistry::getTableLocator()->get('StateBalances');
$state_balance_query = $stateBalancesTable->find()->where(['state_user_id' => $userId])->order(['record_date ASC']);
$state_balance = null;
if($state_balance_query->count() > 0) {
$state_balance = $state_balance_query->last();
} else {
$state_balance = $stateBalancesTable->newEntity();
$state_balance->state_user_id = $userId;
}
$state_balance->amount = $newBalance;
$state_balance->record_date = $recordDate;
$this->user_balances[$userId] = $state_balance;
$stateBalancesTable->save($state_balance);
return true;
//$this->user_balances[$userId] = ['balance' => $newBalance, '']
//
//return $stateBalancesTable->updateBalanceWithTransaction($newBalance, $recordDate, $userId);
/*$first_of_month = new Time("$year-$month-01 00:00");
$stateBalanceQuery = $stateBalancesTable
->find('all')
->where(['state_user_id' => $userId])
->order(['record_date' => 'DESC'])
->limit(1);
$entity = null;
if(!$stateBalanceQuery->isEmpty()) {
$entity = $stateBalanceQuery->first();
if($entity->record_date != NULL &&
($entity->record_date > $recordDate || $entity->record_date->day == 1)) {
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;
}
public function getAllStateUsers()
{
return $this->state_users;
}
public function getAllStateUserBalances()
{
return $this->user_balances;
}
}
class ManageNodeGroupAdd extends GradidoModifieUserBalance
{
/*
"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();
if(!is_int($transactionId)) {
return ['state' => 'error', 'msg' => '[ManageNodeGroupAdd::finalize] transaction id is not int', 'details' => $transactionId];
}
$transactionGroupEntity->transaction_id = $transactionId;
$transactionGroupEntity->address_type_id = 1;
if(strlen($this->user_pubkey) != 64) {
return ['state' => 'error', 'msg' => 'invalid size user pubkey', 'details' => strlen($this->user_pubkey)];
}
if(!preg_match('/^[0-9a-fA-F]*$/', $this->user_pubkey)) {
return ['state' => 'error', 'msg' => 'user_pubkey isn\'t in hex format'];
}
$userPubkeyBin = hex2bin($this->user_pubkey);
$transactionGroupEntity->public_key = $userPubkeyBin;
$user_id = $this->getUserId($this->user_pubkey);
if(!is_int($user_id)) {
return ['state' => 'error', 'msg' => '[ManageNodeGroupAdd::finalize] user id is not int', 'details' => $user_id];
}
$transactionGroupEntity->state_user_id = $user_id;
$transactionGroupEntity->remove_from_group = $this->remove_from_group;
if(!$transactionGroupAddadressTable->save($transactionGroupEntity)) {
return ['state' => 'error', 'msg' => 'error saving TransactionGroupAddaddress Entity', 'details' => $transactionGroupEntity->getErrors()];
}
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 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']['amount'];
$this->new_balance = $data['new_balance']['amount'];
//$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 = null;
private $sender_pubkey;
private $receiver_pubkey;
private $receiver_new_balance = null;
public function __construct($data)
{
$this->amount = $data['amount']['amount'];
$sender = $data['sender'];
$this->sender_pubkey = $sender['user'];
if(isset($sender['new_balance'])) {
$this->sender_new_balance = $sender['new_balance']['amount'];
}
$receiver = $data['receiver'];
$this->receiver_pubkey = $receiver['user'];
if(isset($receiver['new_balance'])) {
$this->receiver_new_balance = $receiver['new_balance']['amount'];
}
}
public function finalize($transactionId, $received)
{
$transactionTransferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins');
if(strlen($this->sender_pubkey) != 64) {
return ['state' => 'error', 'msg' => 'invalid size sender pubkey', 'details' => strlen($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(strlen($this->receiver_pubkey) != 64) {
return ['state' => 'error', 'msg' => 'invalid size receiver pubkey', 'details' => strlen($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;
if($this->sender_new_balance != null) {
$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($this->receiver_new_balance != null && 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 $runningHash = null;
private $transactionType = '';
private $memo = '';
private $signatures = [];
private $received;
private $transactionObj = null;
private $result;
private $partCount = 0;
public function __construct()
{
}
public function parseRecord($json) {
if(!isset($json['record_type'])) {
return false;
}
//var_dump($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');
$stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
$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' => intval($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;
if($this->runningHash != '' && strlen($this->runningHash) % 2 == 0) {
$newTransaction->tx_hash = hex2bin($this->runningHash);
}
$newTransaction->received = $this->received;
//! TODO change into transaction, if at least one fail, rollback
/*
// In a controller.
$articles->getConnection()->transactional(function () use ($articles, $entities) {
foreach ($entities as $entity) {
$articles->save($entity, ['atomic' => false]);
}
});
*/
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];
}
$state_users = $this->transactionObj->getAllStateUsers();
$sut_entities = [];
$state_user_balances = $this->transactionObj->getAllStateUserBalances();
foreach($state_users as $state_user_id) {
$entity = $stateUserTransactionsTable->newEntity();
$entity->state_user_id = $state_user_id;
$entity->transaction_id = $newTransaction->id;
$entity->transaction_type_id = $newTransaction->transaction_type_id;
$entity->balance = $state_user_balances[$state_user_id]->amount;
$entity->balance_date = $state_user_balances[$state_user_id]->record_date;
$sut_entities[] = $entity;
}
$sut_results = $stateUserTransactionsTable->saveMany($sut_entities);
foreach($sut_results as $i => $result) {
if(false == $result) {
return ['state' => 'error', 'msg' => 'error saving state_user_transaction', 'details' => $sut_entities[$i]->getErrors()];
}
}
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->runningHash = $hedera['runningHash'];
$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];
}
$class_name = 'Model\\Transactions\\' . $class_name;
$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;
}
}

View File

@ -29,12 +29,12 @@ class SignatureMap {
static public function fromEntity($transactionSignatures)
{
$protoSigMap = new \Model\Messages\Gradido\SignatureMap();
$protoSigMap = new \Proto\Gradido\SignatureMap();
$sigPairs = $protoSigMap->getSigPair();
//echo "sigPairs: "; var_dump($sigPairs); echo "<br>";
//return null;
foreach($transactionSignatures as $signature) {
$sigPair = new \Model\Messages\Gradido\SignaturePair();
$sigPair = new \Proto\Gradido\SignaturePair();
$sigPair->setPubKey(stream_get_contents($signature->pubkey));
$sigPair->setEd25519(stream_get_contents($signature->signature));
@ -46,14 +46,14 @@ class SignatureMap {
static public function build($bodyBytes, array $keys)
{
$protoSigMap = new \Model\Messages\Gradido\SignatureMap();
$protoSigMap = new \Proto\Gradido\SignatureMap();
$sigPairs = $protoSigMap->getSigPair();
//echo "sigPairs: "; var_dump($sigPairs); echo "<br>";
//return null;
// sign with keys
foreach($keys as $key) {
$sigPair = new \Model\Messages\Gradido\SignaturePair();
$sigPair = new \Proto\Gradido\SignaturePair();
$sigPair->setPubKey(hex2bin($key['pub']));
$sigPair->setEd25519(sodium_crypto_sign_detached($bodyBytes, hex2bin($key['priv'])));

View File

@ -25,7 +25,7 @@ class Transaction extends TransactionBase {
//$transactionBin = base64_decode($base64Data, true);
//if($transactionBin == false) {
//sodium_base64_VARIANT_URLSAFE_NO_PADDING
if(is_a($base64Data, '\Model\Messages\Gradido\Transaction')) {
if(is_a($base64Data, '\Proto\Gradido\Transaction')) {
$this->mProtoTransaction = $base64Data;
$this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes());
return;
@ -39,6 +39,7 @@ class Transaction extends TransactionBase {
$transactionBin = base64_decode($base64Data, true);
if($transactionBin == false) {
$this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data);
$this->addError('base64', $base64Data);
return;
}
}
@ -49,7 +50,7 @@ class Transaction extends TransactionBase {
$this->addError('Transaction', 'base64 decode error: ' . $base64Data);
} else {
//var_dump($transactionBin);
$this->mProtoTransaction = new \Model\Messages\Gradido\Transaction();
$this->mProtoTransaction = new \Proto\Gradido\GradidoTransaction();
try {
$this->mProtoTransaction->mergeFromString($transactionBin);
//var_dump($this->mProtoTransaction);
@ -69,11 +70,11 @@ class Transaction extends TransactionBase {
}
}
static public function build(\Model\Messages\Gradido\TransactionBody $transactionBody, $senderKeyPair)
static public function build(\Proto\Gradido\TransactionBody $transactionBody, $senderKeyPair)
{
$protoTransaction = new \Model\Messages\Gradido\Transaction();
$protoTransaction = new \Proto\Gradido\GradidoTransaction();
$recevied = new \Model\Messages\Gradido\TimestampSeconds();
$recevied = new \Proto\Gradido\TimestampSeconds();
$recevied->setSeconds(time());
$protoTransaction->setReceived($recevied);
@ -197,14 +198,14 @@ class Transaction extends TransactionBase {
'TransactionSignatures'])
->first();
//var_dump($transactionEntry->toArray());
$protoTransaction = new \Model\Messages\Gradido\Transaction();
$protoTransaction = new \Proto\Gradido\Transaction();
$protoTransaction->setId($transactionEntry->id);
$recevied = new \Model\Messages\Gradido\TimestampSeconds();
$recevied = new \Proto\Gradido\TimestampSeconds();
$recevied->setSeconds($transactionEntry->received->getTimestamp());
$protoTransaction->setReceived($recevied);
@ -228,7 +229,7 @@ class Transaction extends TransactionBase {
}
//echo "verify bodybytes: <br>" . bin2hex($bodyBytes) . '<br>';
$created = new \Model\Messages\Gradido\TimestampSeconds();
$created = new \Proto\Gradido\TimestampSeconds();
$created->setSeconds($recevied->getSeconds());
$body->setCreated($created);
$bodyBytes = $body->serializeToString();

View File

@ -67,7 +67,7 @@ class TransactionBase {
$stateBalancesTable = self::getTable('stateBalances');
$stateBalanceQuery = $stateBalancesTable
->find('all')
->select(['amount', 'id'])
->select(['amount', 'id', 'record_date'])
->contain(false)
->where(['state_user_id' => $stateUserId]);//->first();
//debug($stateBalanceQuery);
@ -101,9 +101,14 @@ class TransactionBase {
if($stateUserTransactions->count() > 0) {
$stateBalanceTable = self::getTable('state_balances');
$state_user_transaction = $stateUserTransactions->first();
if(!$state_user_transaction) {
$this->addError('TransactionBase::addStateUserTransaction', 'state_user_transaction is zero, no first entry exist?');
return false;
}
$balance_entity = $stateBalanceTable->newEntity();
$balance_entity->amount = $stateUserTransactions->first()->balance;
$balance_entity->record_date = $stateUserTransactions->first()->balance_date;
$balance_entity->amount = $state_user_transaction->balance;
$balance_entity->record_date = $state_user_transaction->balance_date;
$balance = $balance_entity->decay + $balance;
}
$entity = $stateUserTransactionTable->newEntity();

View File

@ -12,7 +12,7 @@ class TransactionBody extends TransactionBase {
private $transactionTypeId = 0;
public function __construct($bodyBytes) {
$this->mProtoTransactionBody = new \Model\Messages\Gradido\TransactionBody();
$this->mProtoTransactionBody = new \Proto\Gradido\TransactionBody();
try {
$this->mProtoTransactionBody->mergeFromString($bodyBytes);
// cannot catch Exception with cakePHP, I don't know why
@ -155,7 +155,7 @@ class TransactionBody extends TransactionBase {
static public function fromEntity($memo, $transaction)
{
$protoBody = new \Model\Messages\Gradido\TransactionBody();
$protoBody = new \Proto\Gradido\TransactionBody();
$protoBody->setMemo($memo);
//$created->setSeconds($var);
@ -176,7 +176,7 @@ class TransactionBody extends TransactionBase {
static public function build($memo, $specificTransaction)
{
$protoBody = new \Model\Messages\Gradido\TransactionBody();
$protoBody = new \Proto\Gradido\TransactionBody();
$protoBody->setMemo($memo);
if(is_a($specificTransaction, 'TransactionCreation')) {

View File

@ -26,34 +26,33 @@ class TransactionCreation extends TransactionBase {
return $this->protoTransactionCreation;
}
static public function build($amount, $memo, $receiver_public_hex, $ident_hash, $targetDate = null)
static public function build($amount, $memo, $receiver_public_hex, $targetDate = null)
{
$receiver = new \Model\Messages\Gradido\ReceiverAmount();
$receiver = new \Proto\Gradido\TransferAmount();
$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);
$receiver->setPubkey($pubKeyBin);
//var_dump($requestData);
$creationDate = new \Model\Messages\Gradido\TimestampSeconds();
$creationDate = new \Proto\Gradido\TimestampSeconds();
$creationDate->setSeconds(time());
$transactionBody = new \Model\Messages\Gradido\TransactionBody();
$transactionBody = new \Proto\Gradido\TransactionBody();
$transactionBody->setMemo($memo);
$transactionBody->setCreated($creationDate);
$transaction = new \Model\Messages\Gradido\TransactionCreation();
$transaction->setReceiverAmount($receiver);
$transaction->setIdentHash($ident_hash);
$transaction = new \Proto\Gradido\GradidoTransaction();
$transaction->setReceiver($receiver);
//echo "target date: ";
//var_dump($targetDate);
//die('die');
if($targetDate) {
$targetDateTimestamp = new \Model\Messages\Gradido\TimestampSeconds();
$targetDateTimestamp = new \Proto\Gradido\TimestampSeconds();
$targetDateTimestamp->setSeconds($targetDate->getTimestamp());
//var_dump($targetDateTimestamp); die('target');
$transaction->setTargetDate($targetDateTimestamp);
@ -65,16 +64,13 @@ class TransactionCreation extends TransactionBase {
public function getAmount() {
return $this->protoTransactionCreation->getReceiverAmount()->getAmount();
return $this->protoTransactionCreation->getReceiver()->getAmount();
}
public function getReceiverPublic() {
return $this->protoTransactionCreation->getReceiverAmount()->getEd25519ReceiverPubkey();
return $this->protoTransactionCreation->getReceiver()->getPubkey();
}
public function getIdentHash() {
return $this->protoTransactionCreation->getIdentHash();
}
public function validate($sigPairs) {
@ -88,54 +84,6 @@ class TransactionCreation extends TransactionBase {
}
}
// check if creation threshold for this month isn't reached
//$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());
////////// old validation not more than 3k GDD for 3 Month ///////////////
/*$existingCreations = $this->transactionCreationsTable
->find('all')
->select(['amount', 'state_user_id', 'target_date'])
->contain(['StateUsers' => ['fields' => ['StateUsers.public_key']]])
->where(['target_date' => NULL]);
//$targetDate = $this->protoTransactionCreation->getTargetDate();
//echo "choose existing transactions<br>";
//$existingCreations->where([$q->func()->extract('YEAR_MONTH', 'target_date') . ' LIKE ' . $q->func()->extract('YEAR_MONTH', $targetDate)]);
// ->where(['EXTRACT(YEAR_MONTH FROM target_date) LIKE EXTRACT(YEAR_MONTH FROM']);
// uncomment because ident hash didn't work at the moment
//->where(['ident_hash' => $identHashBin]);
//$existingCreations->select(['amount_sum' => $existingCreations->func()->sum('amount')]);
$existingCreations->matching('Transactions', function ($q) {
return $q->where(
['OR' =>
['EXTRACT(YEAR_MONTH FROM Transactions.received) LIKE EXTRACT(YEAR_MONTH FROM NOW())',
'EXTRACT(YEAR_MONTH FROM DATE_ADD(Transactions.received, INTERVAL 2 MONTH)) LIKE EXTRACT(YEAR_MONTH FROM NOW())']
])->select('received');
});
//debug($existingCreations);
//echo "after choose existing transactions<br>";
$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 > 30000000) {
$this->addError('TransactionCreation::validate', 'Creation more than 1.000 GDD per Month (3 Month) not allowed');
return false;
}//*/
/////////////// new validation, not more than 1K GDD per month via target_date ///////////////////////////
$existingCreations2 = $this->transactionCreationsTable
@ -204,7 +152,6 @@ class TransactionCreation extends TransactionBase {
}
$transactionCreationEntity->state_user_id = $receiverUserId;
$transactionCreationEntity->amount = $this->getAmount();
$transactionCreationEntity->ident_hash = $this->getIdentHash();
$transactionCreationEntity->target_date = $this->protoTransactionCreation->getTargetDate()->getSeconds();
if(!$this->transactionCreationsTable->save($transactionCreationEntity)) {
@ -262,7 +209,7 @@ class TransactionCreation extends TransactionBase {
static public function fromEntity($transactionCreationEntity)
{
$protoCreation = new \Model\Messages\Gradido\TransactionCreation();
$protoCreation = new \Proto\Gradido\GradidoCreation();
//var_dump($transactionCreationEntity);
$stateUsersTable = TableRegistry::getTableLocator()->get('state_users');
@ -273,12 +220,14 @@ class TransactionCreation extends TransactionBase {
$stateUser = $stateUsersTable->get($userId);
$receiverAmount = new \Model\Messages\Gradido\ReceiverAmount();
$receiverAmount->setEd25519ReceiverPubkey(stream_get_contents($stateUser->public_key));
$receiverAmount = new \Proto\Gradido\TransferAmount();
$receiverAmount->setPubkey(stream_get_contents($stateUser->public_key));
$receiverAmount->setAmount($transactionCreationEntity->amount);
$protoCreation->setReceiverAmount($receiverAmount);
$protoCreation->setReceiver($receiverAmount);
// TODO: add target_date
// function currently not used, maybe can even be deleted
//echo "receiver amount: check<br>";
//$identHashBytes = stream_get_contents($transactionCreationEntity->ident_hash);

View File

@ -22,9 +22,8 @@ class TransactionTransfer extends TransactionBase {
{
// repeated SenderAmount senderAmounts = 1;
// repeated ReceiverAmount receiverAmounts = 2;
$receiver = new \Model\Messages\Gradido\ReceiverAmount();
$sender = new \Model\Messages\Gradido\SenderAmount();
$receiver->setAmount($amount);
$sender = new \Proto\Gradido\TransferAmount();
$sender->setAmount($amount);
if(strlen($receiver_public_hex) != 64) {
@ -34,71 +33,56 @@ class TransactionTransfer extends TransactionBase {
return ['state' => 'error', 'msg' => 'invalid sender pubkey'];
}
$receiverPubKeyBin = hex2bin($receiver_public_hex);
$receiver->setEd25519ReceiverPubkey($receiverPubKeyBin);
$senderPubKeyBin = hex2bin($sender_public_hex);
$sender->setEd25519SenderPubkey($senderPubKeyBin);
$sender->setPubkey($senderPubKeyBin);
//var_dump($requestData);
$creationDate = new \Model\Messages\Gradido\TimestampSeconds();
$creationDate = new \Proto\Gradido\TimestampSeconds();
$creationDate->setSeconds(time());
$transactionBody = new \Model\Messages\Gradido\TransactionBody();
$transactionBody = new \Proto\Gradido\TransactionBody();
$transactionBody->setMemo($memo);
$transactionBody->setCreated($creationDate);
$transaction = new \Model\Messages\Gradido\Transfer();
$transaction->setReceiverAmounts([$receiver]);
$transaction->setSenderAmounts([$sender]);
$transactionBody->setTransfer($transaction);
$transfer = new \Proto\Gradido\GradidoTransfer();
$local_transfer = new \Proto\Gradido\LocalTransfer();
$local_transfer->setReceiver($receiverPubKeyBin);
$local_transfer->setSender($sender);
$transfer->setLocal($local_transfer);
$transactionBody->setTransfer($transfer);
return ['state' => 'success', 'transactionBody' => $transactionBody];
}
public function validate($sigPairs) {
//$this->addError('TransactionTransfer::validate', 'not implemented yet');
//return false;
//$time = microtime(true);
static $functionName = 'TransactionCreation::validate';
/*
* // check signature(s)
foreach($sigPairs as $sigPair) {
//echo 'sig Pair: '; var_dump($sigPair); echo "<br>";
$pubkey = $sigPair->getPubKey();
$signature = $sigPair->getEd25519();
if (!\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) {
$this->addError('Transaction::validate', 'signature for key ' . bin2hex($pubkey) . ' isn\'t valid ' );
return false;
}
}
*/
$sigPubHexs = [];
foreach($sigPairs as $sigPair) {
//echo 'sig Pair: '; var_dump($sigPair); echo "<br>";
$pubkey = bin2hex($sigPair->getPubKey());
//$hash = TransactionCreation::DRMakeStringHash($pubkey);
$hash = $pubkey;
if(!isset($sigPubHexs[$hash])) {
$sigPubHexs[$hash] = [$pubkey];
} else {
array_push($sigPubHexs[$hash], $pubkey);
}
//array_push($sigPubHexs, $pubkey);
}
$stateUsersTable = TableRegistry::getTableLocator()->get('state_users');
$senderAmounts = $this->protoTransactionTransfer->getSenderAmounts();
$senderSum = 0;
$receiverSum = 0;
$senderPublics = [];
foreach($senderAmounts as $i => $senderAmount) {
$senderPublic = $senderAmount->getEd25519SenderPubkey();
$senderPublicHex = bin2hex($senderPublic);
array_push($senderPublics, $senderPublic);
//$this->addError('TransactionTransfer::validate', 'not implemented yet');
//return false;
//$time = microtime(true);
static $functionName = 'TransactionCreation::validate';
$sigPubHexs = [];
foreach($sigPairs as $sigPair)
{
$pubkey = $sigPair->getPubKey();
$pubkey_hex = bin2hex($pubkey);
//$hash = TransactionCreation::DRMakeStringHash($pubkey);
$hash = $pubkey_hex;
if(!isset($sigPubHexs[$hash])) {
$sigPubHexs[$hash] = [$pubkey_hex];
} else {
array_push($sigPubHexs[$hash], $pubkey_hex);
}
//array_push($sigPubHexs, $pubkey);
}
$stateUsersTable = TableRegistry::getTableLocator()->get('state_users');
$local_transfer = $this->protoTransactionTransfer->getLocal();
$sender = $local_transfer->getSender();
$senderPublic = $sender->getPubkey();
$senderPublicHex = bin2hex($senderPublic);
if(strlen($senderPublicHex) != 64) {
$this->addError($functionName, 'invalid sender public key');
return false;
$this->addError($functionName, 'invalid sender public key');
return false;
}
// check if signature exist for sender
//$hash = TransactionCreation::DRMakeStringHash($senderPublicHex);
@ -108,7 +92,7 @@ class TransactionTransfer extends TransactionBase {
return false;
}
// check if sender has enough Gradido
$amount = $senderAmount->getAmount();
$amount = $sender->getAmount();
$user = $stateUsersTable
->find('all')
->select(['id'])
@ -123,66 +107,37 @@ class TransactionTransfer extends TransactionBase {
$this->addError($functionName, 'sender ' . $i . ' hasn\t enough GDD');
return false;
}
$senderSum += $amount;
}
$uniqueSenderPublics = array_unique($senderPublics);
if(count($senderPublics) !== count($uniqueSenderPublics)) {
$this->addError($functionName, 'duplicate sender public key');
return false;
}
$receiverAmounts = $this->protoTransactionTransfer->getReceiverAmounts();
$receiverPublics = [];
foreach($receiverAmounts as $reveiverAmount) {
if(strlen($reveiverAmount->getEd25519ReceiverPubkey()) != 32) {
$receiver_public_key = $local_transfer->getReceiver();
if(strlen($receiver_public_key) != 32) {
$this->addError($functionName, 'invalid receiver public key');
return false;
}
array_push($receiverPublics, $reveiverAmount->getEd25519ReceiverPubkey());
$receiverSum += $reveiverAmount->getAmount();
}
$uniqueReceiverPublic = array_unique($receiverPublics);
if(count($uniqueReceiverPublic) !== count($receiverPublics)) {
$this->addError($functionName, 'duplicate receiver public key');
return false;
}
$uniquePublics = array_unique(array_merge($receiverPublics, $senderPublics));
if(count($uniquePublics) !== count($senderPublics) + count($receiverPublics)) {
// means at least one sender is the same as one receiver
$this->addError($functionName, 'duplicate public in sender and receiver');
return false;
}
if($senderSum !== $receiverSum) {
$this->addError($functionName, 'sender amount doesn\'t match receiver amount');
return false;
}
if($senderSum < 0) {
$this->addError($functionName, 'negative amount not supported');
return false;
}
//die("\n");
return true;
// check if receiver exist
$receiver_user = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $receiver_public_key])->first();
if(!$receiver_user) {
$this->addError($functionName, 'couldn\'t find receiver ' . $i .' in db' );
return false;
}
if($amount < 0) {
$this->addError($functionName, 'negative amount not supported');
return false;
}
return true;
}
public function save($transaction_id, $firstPublic, $received) {
static $functionName = 'TransactionCreation::save';
$local_transfer = $this->protoTransactionTransfer->getLocal();
if(count($this->protoTransactionTransfer->getSenderAmounts()) !== 1) {
$this->addError($functionName, 'not more than one sender currently supported');
return false;
}
$senderAmount = $this->protoTransactionTransfer->getSenderAmounts()[0];
$senderAmount = $local_transfer->getSender();
$receiver = $local_transfer->getReceiver();
if(count($this->protoTransactionTransfer->getReceiverAmounts()) !== 1) {
$this->addError($functionName, 'not more than one receiver currently supported');
return false;
}
$receiverAmount = $this->protoTransactionTransfer->getReceiverAmounts()[0];
$transactionTransferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins');
$senderUserId = $this->getStateUserId($senderAmount->getEd25519SenderPubkey());
$receiverUserId = $this->getStateUserId($receiverAmount->getEd25519ReceiverPubkey());
$senderUserId = $this->getStateUserId($senderAmount->getPubkey());
$receiverUserId = $this->getStateUserId($receiver);
if($senderUserId === NULL || $receiverUserId === NULL) {
return false;
@ -192,14 +147,14 @@ class TransactionTransfer extends TransactionBase {
if(false === $finalSenderBalance) {
return false;
}
if(false === $this->updateStateBalance($receiverUserId, $receiverAmount->getAmount(), $received)) {
if(false === $this->updateStateBalance($receiverUserId, $senderAmount->getAmount(), $received)) {
return false;
}
$transactionTransferEntity = $transactionTransferTable->newEntity();
$transactionTransferEntity->transaction_id = $transaction_id;
$transactionTransferEntity->state_user_id = $senderUserId;
$transactionTransferEntity->receiver_public_key = $receiverAmount->getEd25519ReceiverPubkey();
$transactionTransferEntity->receiver_public_key = $receiver;
$transactionTransferEntity->receiver_user_id = $receiverUserId;
$transactionTransferEntity->amount = $senderAmount->getAmount();
$transactionTransferEntity->sender_final_balance = $finalSenderBalance;
@ -227,10 +182,11 @@ class TransactionTransfer extends TransactionBase {
$disable_email = Configure::read('disableEmail', false);
if($disable_email) return true;
$senderAmount = $this->protoTransactionTransfer->getSenderAmounts()[0];
$receiverAmount = $this->protoTransactionTransfer->getReceiverAmounts()[0];
$senderUserId = $this->getStateUserId($senderAmount->getEd25519SenderPubkey());
$receiverUserId = $this->getStateUserId($receiverAmount->getEd25519ReceiverPubkey());
$local_transfer = $this->protoTransactionTransfer->getLocal();
$sender = $local_transfer->getSender();
$senderAmount = $sender->getAmount();
$senderUserId = $this->getStateUserId($sender->getPubkey());
$receiverUserId = $this->getStateUserId($local_transfer->getReceiver());
$receiverUser = $this->getStateUser($receiverUserId);
$senderUser = $this->getStateUser($senderUserId);
@ -242,7 +198,7 @@ class TransactionTransfer extends TransactionBase {
$emailViewBuilder->setTemplate('notificationTransfer')
->setVars(['receiverUser' => $receiverUser,
'senderUser' => $senderUser,
'gdd_cent' => $receiverAmount->getAmount(),
'gdd_cent' => $senderAmount,
'memo' => $memo]);
$receiverNames = $receiverUser->getNames();
if($receiverNames == '' || $receiverUser->email == '') {
@ -263,7 +219,7 @@ class TransactionTransfer extends TransactionBase {
static public function fromEntity($transactionTransferEntity)
{
$protoTransfer = new \Model\Messages\Gradido\Transfer();
$protoTransfer = new \Proto\Gradido\GradidoTransfer();
$stateUsersTable = TableRegistry::getTableLocator()->get('state_users');

View File

@ -4,8 +4,8 @@
* @var \App\Model\Entity\AddressType $addressType
*/
?>
<nav id="actions-sidebar">
<ul class="nav-horizontal nav-smaller">
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('List Address Types'), ['action' => 'index']) ?></li>
<li><?= $this->Html->link(__('List State Group Addresses'), ['controller' => 'StateGroupAddresses', 'action' => 'index']) ?></li>

View File

@ -4,8 +4,8 @@
* @var \App\Model\Entity\AddressType $addressType
*/
?>
<nav id="actions-sidebar">
<ul class="nav-horizontal nav-smaller">
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Form->postLink(
__('Delete'),

View File

@ -4,8 +4,8 @@
* @var \App\Model\Entity\AddressType[]|\Cake\Collection\CollectionInterface $addressTypes
*/
?>
<nav id="actions-sidebar">
<ul class="nav-horizontal nav-smaller">
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('New Address Type'), ['action' => 'add']) ?></li>
<li><?= $this->Html->link(__('List State Group Addresses'), ['controller' => 'StateGroupAddresses', 'action' => 'index']) ?></li>
@ -40,8 +40,8 @@
<?php endforeach; ?>
</tbody>
</table>
<div>
<ul class="nav-horizontal">
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>

View File

@ -4,8 +4,8 @@
* @var \App\Model\Entity\AddressType $addressType
*/
?>
<nav id="actions-sidebar">
<ul class="nav-horizontal nav-smaller">
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('Edit Address Type'), ['action' => 'edit', $addressType->id]) ?> </li>
<li><?= $this->Form->postLink(__('Delete Address Type'), ['action' => 'delete', $addressType->id], ['confirm' => __('Are you sure you want to delete # {0}?', $addressType->id)]) ?> </li>
@ -39,7 +39,7 @@
<table cellpadding="0" cellspacing="0">
<tr>
<th scope="col"><?= __('Id') ?></th>
<th scope="col"><?= __('State Group Id') ?></th>
<th scope="col"><?= __('Group Id') ?></th>
<th scope="col"><?= __('Public Key') ?></th>
<th scope="col"><?= __('Address Type Id') ?></th>
<th scope="col" class="actions"><?= __('Actions') ?></th>
@ -47,7 +47,7 @@
<?php foreach ($addressType->state_group_addresses as $stateGroupAddresses): ?>
<tr>
<td><?= h($stateGroupAddresses->id) ?></td>
<td><?= h($stateGroupAddresses->state_group_id) ?></td>
<td><?= h($stateGroupAddresses->group_id) ?></td>
<td><?= h($stateGroupAddresses->public_key) ?></td>
<td><?= h($stateGroupAddresses->address_type_id) ?></td>
<td class="actions">
@ -68,6 +68,7 @@
<th scope="col"><?= __('Id') ?></th>
<th scope="col"><?= __('Transaction Id') ?></th>
<th scope="col"><?= __('Address Type Id') ?></th>
<th scope="col"><?= __('Remove From Group') ?></th>
<th scope="col"><?= __('Public Key') ?></th>
<th scope="col" class="actions"><?= __('Actions') ?></th>
</tr>
@ -76,6 +77,7 @@
<td><?= h($transactionGroupAddaddress->id) ?></td>
<td><?= h($transactionGroupAddaddress->transaction_id) ?></td>
<td><?= h($transactionGroupAddaddress->address_type_id) ?></td>
<td><?= h($transactionGroupAddaddress->remove_from_group) ?></td>
<td><?= h($transactionGroupAddaddress->public_key) ?></td>
<td class="actions">
<?= $this->Html->link(__('View'), ['controller' => 'TransactionGroupAddaddress', 'action' => 'view', $transactionGroupAddaddress->id]) ?>

View File

@ -0,0 +1,25 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\BlockchainType $blockchainType
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('List Blockchain Types'), ['action' => 'index']) ?></li>
</ul>
</nav>
<div class="blockchainTypes form large-9 medium-8 columns content">
<?= $this->Form->create($blockchainType) ?>
<fieldset>
<legend><?= __('Add Blockchain Type') ?></legend>
<?php
echo $this->Form->control('name');
echo $this->Form->control('text');
echo $this->Form->control('symbol');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>

View File

@ -0,0 +1,31 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\BlockchainType $blockchainType
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Form->postLink(
__('Delete'),
['action' => 'delete', $blockchainType->id],
['confirm' => __('Are you sure you want to delete # {0}?', $blockchainType->id)]
)
?></li>
<li><?= $this->Html->link(__('List Blockchain Types'), ['action' => 'index']) ?></li>
</ul>
</nav>
<div class="blockchainTypes form large-9 medium-8 columns content">
<?= $this->Form->create($blockchainType) ?>
<fieldset>
<legend><?= __('Edit Blockchain Type') ?></legend>
<?php
echo $this->Form->control('name');
echo $this->Form->control('text');
echo $this->Form->control('symbol');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>

View File

@ -0,0 +1,51 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\BlockchainType[]|\Cake\Collection\CollectionInterface $blockchainTypes
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('New Blockchain Type'), ['action' => 'add']) ?></li>
</ul>
</nav>
<div class="blockchainTypes index large-9 medium-8 columns content">
<h3><?= __('Blockchain Types') ?></h3>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th scope="col"><?= $this->Paginator->sort('id') ?></th>
<th scope="col"><?= $this->Paginator->sort('name') ?></th>
<th scope="col"><?= $this->Paginator->sort('text') ?></th>
<th scope="col"><?= $this->Paginator->sort('symbol') ?></th>
<th scope="col" class="actions"><?= __('Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($blockchainTypes as $blockchainType): ?>
<tr>
<td><?= $this->Number->format($blockchainType->id) ?></td>
<td><?= h($blockchainType->name) ?></td>
<td><?= h($blockchainType->text) ?></td>
<td><?= h($blockchainType->symbol) ?></td>
<td class="actions">
<?= $this->Html->link(__('View'), ['action' => 'view', $blockchainType->id]) ?>
<?= $this->Html->link(__('Edit'), ['action' => 'edit', $blockchainType->id]) ?>
<?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $blockchainType->id], ['confirm' => __('Are you sure you want to delete # {0}?', $blockchainType->id)]) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('next') . ' >') ?>
<?= $this->Paginator->last(__('last') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?></p>
</div>
</div>

View File

@ -0,0 +1,36 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\BlockchainType $blockchainType
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('Edit Blockchain Type'), ['action' => 'edit', $blockchainType->id]) ?> </li>
<li><?= $this->Form->postLink(__('Delete Blockchain Type'), ['action' => 'delete', $blockchainType->id], ['confirm' => __('Are you sure you want to delete # {0}?', $blockchainType->id)]) ?> </li>
<li><?= $this->Html->link(__('List Blockchain Types'), ['action' => 'index']) ?> </li>
<li><?= $this->Html->link(__('New Blockchain Type'), ['action' => 'add']) ?> </li>
</ul>
</nav>
<div class="blockchainTypes view large-9 medium-8 columns content">
<h3><?= h($blockchainType->name) ?></h3>
<table class="vertical-table">
<tr>
<th scope="row"><?= __('Name') ?></th>
<td><?= h($blockchainType->name) ?></td>
</tr>
<tr>
<th scope="row"><?= __('Text') ?></th>
<td><?= h($blockchainType->text) ?></td>
</tr>
<tr>
<th scope="row"><?= __('Symbol') ?></th>
<td><?= h($blockchainType->symbol) ?></td>
</tr>
<tr>
<th scope="row"><?= __('Id') ?></th>
<td><?= $this->Number->format($blockchainType->id) ?></td>
</tr>
</table>
</div>

View File

@ -53,9 +53,8 @@ $this->assign(
<div class="content-collection">
<div class="content-item action-button">
<i class="material-icons-outlined">redeem</i>
<!-- insights / redeem -->
<?= $this->Html->link(
__('schöpfen'),
__('viele schöpfen'),
['controller' => 'TransactionCreations', 'action' => 'createMulti'],
['class' => 'action-button-link']
);?>
@ -63,7 +62,7 @@ $this->assign(
</div>
</div>
<div class="content-region">
<h3>Statistik</h3>
<legend>Statistik</legend>
<div class="content-collection">
<div class="content-item info-item">
<i class="material-icons-outlined">cached</i>
@ -111,4 +110,34 @@ $this->assign(
</div>
</div>
</div>
<div class="content-region">
<h3>Login Server ...</h3>
<div class="content-collection">
<div class="content-item action-button">
<i class="material-icons-outlined">groups</i>
<a href="<?= Router::url('./', true) ?>account/groups" class="info-item-link">
<?= __("Gruppen") ?>
</a>
</div>
<div class="content-item action-button">
<i class="material-icons-outlined">servers</i>
<a href="<?= Router::url('./', true) ?>account/nodes" class="info-item-link">
<?= __("Server") ?>
</a>
</div>
<div class="content-item action-button">
<i class="material-icons-outlined">topics</i>
<a href="<?= Router::url('./', true) ?>account/topic" class="info-item-link">
<?= __("Topics") ?>
</a>
</div>
</div>
<div class="content-collection">
<div class="content-item action-button">
<i class="material-icons-outlined">hedera_accounts</i>
<a href="<?= Router::url('./', true) ?>account/hedera_account" class="info-item-link">
<?= __("Hedera Accounts") ?>
</a>
</div>
</div>
<?php endif; ?>

View File

@ -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('Transactions.can_signed');
/*
class NavHeaderEntry
@ -23,19 +24,21 @@ class NavHeaderEntry
}
*/
?>
<?php if($errorCount > 0) : ?>
<?= $this->Html->link(
'<i class="material-icons-outlined grd-alert-color">announcement</i>'
. '<span class="notification-indicator notification-indicator-warning">ss</span>',
['controller' => 'StateErrors', 'action' => 'ShowForUser'],
['class' => 'nav-link', 'escape' => false, 'title' => "$errorCount " . __('Fehler')]) ?>
<?php endif; ?>
<?php if($transactionPendings > 0) : ?>
<a class="notify-link" title="<?= "$transactionPendings " . __('Transaktionen sind noch zu unterzeichnen')?>" href="<?= Router::url('./', true) ?>account/checkTransactions">
<i class="material-icons-outlined notify">verified_user</i>
<a class="nav-link" title="<?= "$transactionPendings " . __('Transaktionen sind noch zu unterzeichnen')?>" href="<?= Router::url('./', true) ?>account/checkTransactions">
<i class="material-icons-outlined">verified_user</i>
<!--
fingerprint
today
-->
<!--(<?= $transactionPendings ?>)-->
(<?= $transactionPendings ?>)
<!--<span class="notification-indicator notification-indicator-primary">ss</span>-->
</a>
<?php endif; ?>
<?php if($errorCount > 0) : ?>
<?= $this->Html->link(
'<i class="material-icons-outlined notify notify-alert">announcement</i>',
['controller' => 'StateErrors', 'action' => 'ShowForUser'],
['class' => 'notify-link', 'escape' => false, 'title' => "$errorCount " . __('Fehler')]) ?>
<?php endif; ?>

View File

@ -55,8 +55,8 @@ $GLOBALS["self"] = $this;
<!-- TODO save last sidebar state so that it remains unchanged, on reload! -->
<a href="/">
<picture class="logo big visible">
<source srcset="/img/logo_schrift_half.webp" type="image/webp">
<source srcset="/img/logo_schrift_half.png" type="image/png">
<source srcset="/img/gradido_logo_web.webp" type="image/webp">
<source srcset="/img/gradido_logo_web.png" type="image/png">
<img src="/img/logo_schrift_half.png" class="logo big visible" alt="Logo">
</picture>
<picture class="logo small">

View File

@ -0,0 +1,41 @@
<?php $this->layout = false;?>
<!--
=========================================================
* BootstrapVue Argon Dashboard - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/bootstrap-vue-argon-dashboard
* Copyright 2020 Creative Tim (https://www.creative-tim.com)
* Coded by www.creative-tim.com
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="icon" type="image/png" sizes="96x96" href="/favicon.png">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>BootstrapVue Argon Dashboard by Creative Tim</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<!-- Fonts -->
<!--<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700">-->
<link rel="stylesheet" href="css/fonts_local.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<!-- add prefatch js dynamiclly, because name change by every build -->
</head>
<body>
<div class="wrapper" id="app">
wird geladen...
</div>
<!-- built files will be auto injected -->
<script type="text/javascript">csfr = "<?= $this->request->getParam('_csrfToken') ?>";</script>
<script type="text/javascript" src="/vue/app.js"></script></body>
</html>

View File

@ -0,0 +1,23 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Role $role
*/
?>
<nav id="actions-sidebar">
<ul class="nav-horizontal nav-smaller">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('List Roles'), ['action' => 'index']) ?></li>
</ul>
</nav>
<div class="roles form large-9 medium-8 columns content">
<?= $this->Form->create($role) ?>
<fieldset>
<legend><?= __('Add Role') ?></legend>
<?php
echo $this->Form->control('title');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>

View File

@ -0,0 +1,29 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Role $role
*/
?>
<nav id="actions-sidebar">
<ul class="nav-horizontal nav-smaller">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Form->postLink(
__('Delete'),
['action' => 'delete', $role->id],
['confirm' => __('Are you sure you want to delete # {0}?', $role->id)]
)
?></li>
<li><?= $this->Html->link(__('List Roles'), ['action' => 'index']) ?></li>
</ul>
</nav>
<div class="roles form large-9 medium-8 columns content">
<?= $this->Form->create($role) ?>
<fieldset>
<legend><?= __('Edit Role') ?></legend>
<?php
echo $this->Form->control('title');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>

Some files were not shown because too many files have changed in this diff Show More