diff --git a/community_server/.gitmodules b/community_server/.gitmodules
index ed2d79ec1..e7045e507 100644
--- a/community_server/.gitmodules
+++ b/community_server/.gitmodules
@@ -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
\ No newline at end of file
diff --git a/community_server/composer.json b/community_server/composer.json
index 784c6d123..6a5700b0d 100644
--- a/community_server/composer.json
+++ b/community_server/composer.json
@@ -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",
diff --git a/community_server/config/routes.php b/community_server/config/routes.php
index ec3b5fd27..f92b66b8b 100644
--- a/community_server/config/routes.php
+++ b/community_server/config/routes.php
@@ -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,10 @@ Router::scope('/', function (RouteBuilder $routes) {
*/
//$routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
$routes->connect('/', ['controller' => 'Dashboard', 'action' => 'index']);
+ //$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));
/**
diff --git a/community_server/docu/community-server.api.md b/community_server/docu/community-server.api.md
new file mode 100644
index 000000000..6032ce0a2
--- /dev/null
+++ b/community_server/docu/community-server.api.md
@@ -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
+
+
diff --git a/community_server/parse_proto.sh b/community_server/parse_proto.sh
index 576b99691..e6ccb451f 100755
--- a/community_server/parse_proto.sh
+++ b/community_server/parse_proto.sh
@@ -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
diff --git a/community_server/skeema/gradido_community/address_types.sql b/community_server/skeema/gradido_community/address_types.sql
new file mode 100644
index 000000000..cb5b1b943
--- /dev/null
+++ b/community_server/skeema/gradido_community/address_types.sql
@@ -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;
+
diff --git a/community_server/skeema/gradido_community/insert/address_types.sql b/community_server/skeema/gradido_community/insert/address_types.sql
new file mode 100644
index 000000000..2a6dc00a5
--- /dev/null
+++ b/community_server/skeema/gradido_community/insert/address_types.sql
@@ -0,0 +1,2 @@
+INSERT INTO `address_types` (`id`, `name`, `text`) VALUES
+(1, 'user main', 'user main address');
diff --git a/community_server/skeema/gradido_community/insert/insert_transaction_types.sql b/community_server/skeema/gradido_community/insert/insert_transaction_types.sql
index 9dbf5b93f..02ef8374a 100644
--- a/community_server/skeema/gradido_community/insert/insert_transaction_types.sql
+++ b/community_server/skeema/gradido_community/insert/insert_transaction_types.sql
@@ -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');
diff --git a/community_server/skeema/gradido_community/state_group_addresses.sql b/community_server/skeema/gradido_community/state_group_addresses.sql
index 1d256f3e0..698a79b98 100644
--- a/community_server/skeema/gradido_community/state_group_addresses.sql
+++ b/community_server/skeema/gradido_community/state_group_addresses.sql
@@ -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;
diff --git a/community_server/skeema/gradido_community/state_user_transactions.sql b/community_server/skeema/gradido_community/state_user_transactions.sql
index 272552845..5e01cac4a 100644
--- a/community_server/skeema/gradido_community/state_user_transactions.sql
+++ b/community_server/skeema/gradido_community/state_user_transactions.sql
@@ -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;
diff --git a/community_server/skeema/gradido_community/transaction_group_addaddress.sql b/community_server/skeema/gradido_community/transaction_group_addaddress.sql
index dceac273c..cb21ed99f 100644
--- a/community_server/skeema/gradido_community/transaction_group_addaddress.sql
+++ b/community_server/skeema/gradido_community/transaction_group_addaddress.sql
@@ -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;
diff --git a/community_server/skeema/gradido_community/transaction_send_coins.sql b/community_server/skeema/gradido_community/transaction_send_coins.sql
index f57a2175e..49423fdbc 100644
--- a/community_server/skeema/gradido_community/transaction_send_coins.sql
+++ b/community_server/skeema/gradido_community/transaction_send_coins.sql
@@ -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`)
diff --git a/community_server/skeema/gradido_community/transaction_types.sql b/community_server/skeema/gradido_community/transaction_types.sql
index 87492e1fe..a3e6779d9 100644
--- a/community_server/skeema/gradido_community/transaction_types.sql
+++ b/community_server/skeema/gradido_community/transaction_types.sql
@@ -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;
diff --git a/community_server/skeema/gradido_community/transactions.sql b/community_server/skeema/gradido_community/transactions.sql
index 0e8c00ce6..566cfc048 100644
--- a/community_server/skeema/gradido_community/transactions.sql
+++ b/community_server/skeema/gradido_community/transactions.sql
@@ -2,7 +2,7 @@ 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,
PRIMARY KEY (`id`)
diff --git a/community_server/src/Controller/AddressTypesController.php b/community_server/src/Controller/AddressTypesController.php
index 348a8e9e6..9b13a7720 100644
--- a/community_server/src/Controller/AddressTypesController.php
+++ b/community_server/src/Controller/AddressTypesController.php
@@ -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());
diff --git a/community_server/src/Controller/AppController.php b/community_server/src/Controller/AppController.php
index fb0577034..b9522c2e7 100644
--- a/community_server/src/Controller/AppController.php
+++ b/community_server/src/Controller/AppController.php
@@ -91,12 +91,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');
}
}
@@ -147,6 +146,10 @@ class AppController extends Controller
//$this->Cookie->configKey('User', 'encryption', false);
if(!$session_id) {
$session_id = intval($this->request->getCookie('GRADIDO_LOGIN', ''));
+ // TODO: This is unclear if correct
+ if($session_id == 0 && $session->check('session_id')) {
+ $session_id = intval($session->read('session_id'));
+ }
}
$ip = $this->request->clientIp();
if (!$session->check('client_ip')) {
@@ -158,14 +161,16 @@ class AppController extends Controller
if ($session_id != 0) {
$userStored = $session->read('StateUser');
-
- $transactionPendings = $session->read('Transaction.pending');
- $transactionExecutings = $session->read('Transaction.executing');
-
+
+ $transactionPendings = $session->read('Transactions.pending');
+ $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 {
@@ -187,11 +192,13 @@ class AppController extends Controller
$session->write('StateUser.' . $key, $value);
}
//var_dump($json);
- $transactionPendings = $json['Transaction.pending'];
- $transactionExecuting = $json['Transaction.executing'];
+ $transactionPendings = $json['Transactions.pending'];
+ $transactionExecuting = $json['Transactions.executing'];
+ $transaction_can_signed = $json['Transactions.can_signed'];
//echo "read transaction pending: $transactionPendings
";
- $session->write('Transaction.pending', $transactionPendings);
- $session->write('Transaction.executing', $transactionExecuting);
+ $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 +207,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 +231,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 +269,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);
}
}
diff --git a/community_server/src/Controller/AppRequestsController.php b/community_server/src/Controller/AppRequestsController.php
new file mode 100644
index 000000000..c36ddf161
--- /dev/null
+++ b/community_server/src/Controller/AppRequestsController.php
@@ -0,0 +1,61 @@
+loadComponent('JsonRequestClient');
+ $this->loadComponent('JsonRpcRequestClient');
+ //$this->Auth->allow(['add', 'edit']);
+ $this->Auth->allow('index');
+ }
+
+
+ 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 acquireAccessToken($session_id)
+ {
+
+ }
+
+}
+
\ No newline at end of file
diff --git a/community_server/src/Controller/Component/JsonRequestClientComponent.php b/community_server/src/Controller/Component/JsonRequestClientComponent.php
index 8a071b70b..4132894eb 100644
--- a/community_server/src/Controller/Component/JsonRequestClientComponent.php
+++ b/community_server/src/Controller/Component/JsonRequestClientComponent.php
@@ -41,6 +41,11 @@ class JsonRequestClientComponent extends Component
}
+ public function findePublicKeyForEmailHash($emailHash) {
+ //'ask' = ['account_publickey' => '']
+ $results = $this->sendRequestLoginServerNeighbors(json_encode(['ask' => ['account_publickey' => $emailHash]]), 'search');
+ }
+
public function getRunningUserTasks($email)
{
if($email == "") {
@@ -121,6 +126,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');
diff --git a/community_server/src/Controller/Component/JsonRpcRequestClientComponent.php b/community_server/src/Controller/Component/JsonRpcRequestClientComponent.php
index d5ca72808..579eafb22 100644
--- a/community_server/src/Controller/Component/JsonRpcRequestClientComponent.php
+++ b/community_server/src/Controller/Component/JsonRpcRequestClientComponent.php
@@ -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('GradidoNode');
+ 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'];
}
diff --git a/community_server/src/Controller/ErrorController.php b/community_server/src/Controller/ErrorController.php
index 43bd2fb52..c5421a24d 100644
--- a/community_server/src/Controller/ErrorController.php
+++ b/community_server/src/Controller/ErrorController.php
@@ -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');
}
diff --git a/community_server/src/Controller/JsonRequestHandlerController.php b/community_server/src/Controller/JsonRequestHandlerController.php
index e5823397e..ba68f2b5a 100644
--- a/community_server/src/Controller/JsonRequestHandlerController.php
+++ b/community_server/src/Controller/JsonRequestHandlerController.php
@@ -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) {
diff --git a/community_server/src/Controller/PagesController.php b/community_server/src/Controller/PagesController.php
index 94508ad8b..69f57356b 100644
--- a/community_server/src/Controller/PagesController.php
+++ b/community_server/src/Controller/PagesController.php
@@ -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 {
diff --git a/community_server/src/Controller/RolesController.php b/community_server/src/Controller/RolesController.php
new file mode 100644
index 000000000..80aa493d3
--- /dev/null
+++ b/community_server/src/Controller/RolesController.php
@@ -0,0 +1,108 @@
+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']);
+ }
+}
diff --git a/community_server/src/Controller/StateBalancesController.php b/community_server/src/Controller/StateBalancesController.php
index bddf35125..5d469ca35 100644
--- a/community_server/src/Controller/StateBalancesController.php
+++ b/community_server/src/Controller/StateBalancesController.php
@@ -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,33 +41,145 @@ class StateBalancesController extends AppController
$this->set(compact('stateBalances'));
}
-
- private function updateBalances($state_user_id)
+
+ private function updateBalance($stateUserId)
{
- $state_balances = $this->StateBalances->find('all')->where(['state_user_id' => $state_user_id]);
- if($state_balances->count() == 1) {
- $stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
- $state_user_transactions = $stateUserTransactionsTable
+ $stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
+ $transactionsTable = TableRegistry::getTableLocator()->get('Transactions');
+ // info: cakephp use lazy loading, query will be executed later only if needed
+ $state_balances = $this->StateBalances->find('all')->where(['state_user_id' => $stateUserId]);
+ $state_user_transactions = $stateUserTransactionsTable
->find('all')
- ->where(['state_user_id' => $state_user_id])
+ ->where(['state_user_id' => $stateUserId])
->order(['transaction_id ASC'])
- ->contain(['']);
- if($state_user_transactions->count() == 0){
- return;
- }
- $last_state_user_transaction = $state_user_transactions->last();
- $last_transaction = $this->StateBalance->newEntity();
- $last_transaction->amount = $last_state_user_transaction->balance;
- $last_transaction->record_date = $last_state_user_transaction->balance_date;
- // if entrys are nearly the same, we don't need doing anything
- if(abs($last_transaction->decay - $state_balances->decay) < 100) {
- return;
- }
- foreach($state_user_transactions as $state_user_transaction) {
-
- }
-
+ ->contain(false);
+
+ if(!$state_user_transactions) {
+ //debug($state_user_transactions);
+ return true;
}
+
+ // first: decide what todo
+ $create_state_balance = false;
+ $recalculate_state_user_transactions_balance = false;
+ $clear_state_balance = false;
+ $update_state_balance = false;
+ if($state_balances->count() == 0) {
+ $create_state_balance = true;
+ }
+ if($state_balances->count() > 1) {
+ $clear_state_balance = true;
+ $create_state_balance = true;
+ }
+ if($state_balances->count() == 1) {
+ if($state_user_transactions->count() == 0){
+ $clear_state_balance = true;
+ } else {
+ $last_state_user_transaction = $state_user_transactions->last();
+ $last_transaction = $this->StateBalances->newEntity();
+ $last_transaction->amount = $last_state_user_transaction->balance;
+ $last_transaction->record_date = $last_state_user_transaction->balance_date;
+ // if entrys are nearly the same, we don't need doing anything
+ if(abs($last_transaction->decay - $state_balances->first()->decay) > 100) {
+ $recalculate_state_user_transactions_balance = true;
+ $update_state_balance = true;
+ }
+ }
+ }
+
+ if(!$recalculate_state_user_transactions_balance) {
+ $last_state_user_transaction = $state_user_transactions->last();
+ if($last_state_user_transaction->balance <= 0) {
+ $recalculate_state_user_transactions_balance = true;
+ if(!$create_state_balance) {
+ $update_state_balance = true;
+ }
+ }
+ }
+ // second: do what is needed
+ if($clear_state_balance) {
+ $this->StateBalances->deleteAll(['state_user_id' => $stateUserId]);
+ }
+
+ $transaction_ids = [];
+ if($recalculate_state_user_transactions_balance) {
+ $state_user_transactions_array = $state_user_transactions->toArray();
+ foreach($state_user_transactions_array as $i => $state_user_transaction) {
+ $transaction_ids[$state_user_transaction->transaction_id] = $i;
+ }
+
+ $transactions = $transactionsTable
+ ->find('all')
+ ->where(['id IN' => array_keys($transaction_ids)])
+ ->contain(['TransactionCreations', 'TransactionSendCoins']);
+
+ $balance_cursor = $this->StateBalances->newEntity();
+ $i = 0;
+ foreach($transactions as $transaction) {
+ if($transaction->transaction_type_id > 2) {
+ continue;
+ }
+ $amount_date = null;
+ $amount = 0;
+
+ if($transaction->transaction_type_id == 1) {
+ $temp = $transaction->transaction_creations[0];
+
+ $balance_temp = $this->StateBalances->newEntity();
+ $balance_temp->amount = $temp->amount;
+ $balance_temp->record_date = $temp->target_date;
+
+ $amount = $balance_temp->partDecay($transaction->received);
+ $amount_date = $transaction->received;
+ //$amount_date =
+ } else if($transaction->transaction_type_id == 2) {
+ $temp = $transaction->transaction_send_coins[0];
+ $amount = intval($temp->amount);
+ // reverse if sender
+ if($stateUserId == $temp->state_user_id) {
+ $amount *= -1.0;
+ }
+ $amount_date = $transaction->received;
+ }
+ if($i == 0) {
+ $balance_cursor->amount = $amount;
+ } else {
+ $balance_cursor->amount = $balance_cursor->partDecay($amount_date) + $amount;
+ }
+ $balance_cursor->record_date = $amount_date;
+ $state_user_transaction_index = $transaction_ids[$transaction->id];
+ $state_user_transactions_array[$state_user_transaction_index]->balance = $balance_cursor->amount;
+ $state_user_transactions_array[$state_user_transaction_index]->balance_date = $balance_cursor->record_date;
+ $i++;
+ }
+ $results = $stateUserTransactionsTable->saveMany($state_user_transactions_array);
+ $errors = [];
+ foreach($results as $i => $result) {
+ if(!$result) {
+ $errors[$i] = $state_user_transactions_array[$i]->getErrors();
+ }
+ }
+ if(count($errors)) {
+ return ['success' => false, 'error' => 'error saving one ore more state user transactions', 'details' => $errors];
+ }
+ }
+ $state_balance = null;
+ if($update_state_balance) {
+ $state_balance = $state_balances->first();
+ }
+ else if($create_state_balance) {
+ $state_balance = $this->StateBalances->newEntity();
+ $state_balance->state_user_id = $stateUserId;
+ }
+ if($state_balance) {
+ $state_balance->amount = $state_user_transactions->last()->balance;
+ $state_balance->record_date = $state_user_transactions->last()->balance_date;
+ if(!$this->StateBalances->save($state_balance)) {
+ return ['success' => false, 'error' => 'error saving state balance', 'details' => $state_balance->getErrors()];
+ }
+ }
+ return true;
+
}
public function overview()
@@ -83,6 +198,10 @@ class StateBalancesController extends AppController
return $result;
}
$user = $session->read('StateUser');
+ $update_balance_result = $this->updateBalance($user['id']);
+ if($update_balance_result !== true) {
+ $this->addAdminError('StateBalances', 'overview', $update_balance_result, $user['id']);
+ }
// sendRequestGDT
// listPerEmailApi
@@ -102,6 +221,7 @@ class StateBalancesController extends AppController
//}
//
//
+ $stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
$creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations');
$creationTransactions = $creationsTable
@@ -170,17 +290,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();
@@ -192,17 +317,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 "
";
+ echo "prev balance: $prev->balance
diff: $diff_amount
";
+ echo "current balance: $current->balance
";
+ *
+ */
+ //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('Transaction.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) {
@@ -243,8 +452,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']);
@@ -377,6 +587,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(
@@ -422,9 +668,9 @@ class StateBalancesController extends AppController
//echo "gdtSum: $gdtSum
";
$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'];
@@ -435,6 +681,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
";
+ //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
";
+
+ 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)
{
diff --git a/community_server/src/Controller/StateGroupAddressesController.php b/community_server/src/Controller/StateGroupAddressesController.php
index 13f2b1f78..25afc82c7 100644
--- a/community_server/src/Controller/StateGroupAddressesController.php
+++ b/community_server/src/Controller/StateGroupAddressesController.php
@@ -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());
diff --git a/community_server/src/Controller/StateUserRolesController.php b/community_server/src/Controller/StateUserRolesController.php
new file mode 100644
index 000000000..9238c7ad6
--- /dev/null
+++ b/community_server/src/Controller/StateUserRolesController.php
@@ -0,0 +1,185 @@
+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 .= "
".$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);
+ }
+
+}
diff --git a/community_server/src/Controller/StateUserTransactionsController.php b/community_server/src/Controller/StateUserTransactionsController.php
index 8c252218c..e9008179e 100644
--- a/community_server/src/Controller/StateUserTransactionsController.php
+++ b/community_server/src/Controller/StateUserTransactionsController.php
@@ -20,6 +20,7 @@ class StateUserTransactionsController extends AppController
$this->Auth->allow(['ajaxListTransactions']);
//$this->loadComponent('JsonRequestClient');
}
+
/**
* Index method
*
diff --git a/community_server/src/Controller/StateUsersController.php b/community_server/src/Controller/StateUsersController.php
index d85f8b449..ddb3b695f 100644
--- a/community_server/src/Controller/StateUsersController.php
+++ b/community_server/src/Controller/StateUsersController.php
@@ -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();
@@ -101,151 +130,149 @@ class StateUsersController extends AppController
$this->set(compact('timeUsed', 'searchForm', 'csfr_token'));
if ($this->request->is('post')) {
- $requestData = $this->request->getData();
+ $requestData = $this->request->getData();
- if ($searchForm->validate($requestData)) {
- //var_dump($requestData);
- $searchString = $requestData['search'];
- $searchType = 'unknown';
- if (GenericValidation::email($searchString, [])) {
- $searchType = 'email';
+ 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);
+ $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' => []];
}
- // find users on login server
- $resultJson = $this->JsonRequestClient->getUsers($session->read('session_id'), $searchString);
- $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' => []];
- }
- array_push($pubkeySorted[$u['public_hex']]['login'], $u);
- }
- }
- // find user on community server db
- $globalSearch = '%' . $searchString . '%';
- $communityUsers = $this->StateUsers
+ array_push($pubkeySorted[$u['public_hex']]['login'], $u);
+ }
+ }
+ // find user on community server db
+ $globalSearch = '%' . $searchString . '%';
+ $communityUsers = $this->StateUsers
->find('all')
->contain(['StateBalances' => ['fields' => ['amount', 'state_user_id']]]);
- $communityUsers->where(['OR' => [
+ $communityUsers->where(['OR' => [
'first_name LIKE' => $globalSearch,
'last_name LIKE' => $globalSearch,
- //'username LIKE' => $globalSearch,
'email LIKE' => $globalSearch
- ]]);
+ ]]);
- //var_dump($communityUsers->toArray());
- 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);
+ //var_dump($communityUsers->toArray());
+ 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);
+ }
+ $finalUserEntrys = [];
+ // 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;
}
- $finalUserEntrys = [];
- // 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['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;
}
+ } 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']);
+ }
- 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);
+ } else {
+ $state = 'email not activated';
+ $color = 'warning';
}
- //var_dump($pubkeySorted);
- } else {
- $this->Flash->error(__('Something was invalid, please try again!'));
+
+ $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);
@@ -253,187 +280,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)
@@ -541,9 +570,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'));
}
/**
diff --git a/community_server/src/Controller/TransactionCreationsController.php b/community_server/src/Controller/TransactionCreationsController.php
index 5e29a7997..5acfce2d7 100644
--- a/community_server/src/Controller/TransactionCreationsController.php
+++ b/community_server/src/Controller/TransactionCreationsController.php
@@ -335,6 +335,7 @@ class TransactionCreationsController extends AppController
if (isset($requestData['add'])) {
$mode = 'add';
}
+ //echo "mode: $mode
";
$memo = $requestData['memo'];
$amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']);
//$targetDate = $requestData['target_date'];
@@ -342,17 +343,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;
@@ -369,25 +373,87 @@ class TransactionCreationsController extends AppController
$pendings[$id] = $localAmountCent;
}
$pubKeyHex = bin2hex(stream_get_contents($receiverUser->public_key));
- $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 "
";
- //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
+ ]), '/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
";
+ } 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);
@@ -399,49 +465,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.'));
}
}
}
diff --git a/community_server/src/Controller/TransactionSendCoinsController.php b/community_server/src/Controller/TransactionSendCoinsController.php
index 2f48de063..12aa3e69a 100644
--- a/community_server/src/Controller/TransactionSendCoinsController.php
+++ b/community_server/src/Controller/TransactionSendCoinsController.php
@@ -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,93 @@ 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
+ ]), '/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);
}
diff --git a/community_server/src/Form/AssignRoleForm.php b/community_server/src/Form/AssignRoleForm.php
new file mode 100644
index 000000000..158fa2296
--- /dev/null
+++ b/community_server/src/Form/AssignRoleForm.php
@@ -0,0 +1,30 @@
+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;
+ }
+}
\ No newline at end of file
diff --git a/community_server/src/Form/TransferForm.php b/community_server/src/Form/TransferForm.php
index 5572ddaf9..cb135ab9e 100644
--- a/community_server/src/Form/TransferForm.php
+++ b/community_server/src/Form/TransferForm.php
@@ -1,5 +1,5 @@
-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 > or < 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;
}
-}
+}
\ No newline at end of file
diff --git a/community_server/src/Model/Entity/AddressType.php b/community_server/src/Model/Entity/AddressType.php
index 08dbba281..87d64d61a 100644
--- a/community_server/src/Model/Entity/AddressType.php
+++ b/community_server/src/Model/Entity/AddressType.php
@@ -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,
];
}
diff --git a/community_server/src/Model/Entity/Role.php b/community_server/src/Model/Entity/Role.php
new file mode 100644
index 000000000..ae0ddd0ba
--- /dev/null
+++ b/community_server/src/Model/Entity/Role.php
@@ -0,0 +1,26 @@
+ true,
+ ];
+}
diff --git a/community_server/src/Model/Entity/StateBalance.php b/community_server/src/Model/Entity/StateBalance.php
index 174e785b4..0381864b6 100644
--- a/community_server/src/Model/Entity/StateBalance.php
+++ b/community_server/src/Model/Entity/StateBalance.php
@@ -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
@@ -35,6 +36,15 @@ class StateBalance extends Entity
protected $_virtual = ['decay'];
+ private function convertToTimestamp($dateOrTime)
+ {
+ if(method_exists($dateOrTime, 'getTimestamp')) {
+ return $dateOrTime->getTimestamp();
+ } else {
+ return $dateOrTime->i18nFormat(Time::UNIX_TIMESTAMP_FORMAT);
+ }
+ }
+
protected function _getDecay()
{
// decay factor in seconds per year
@@ -44,7 +54,8 @@ 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 = intval(Time::now()->getTimestamp() - $this->record_date->getTimestamp());
+
+ $decay_duration = intval(Time::now()->getTimestamp() - $this->convertToTimestamp($this->record_date));
if($decay_duration === 0) {
return $this->amount;
}
@@ -53,7 +64,7 @@ class StateBalance extends Entity
}
public function partDecay($target_date)
{
- $decay_duration = intval($target_date->getTimestamp() - $this->record_date->getTimestamp());
+ $decay_duration = intval($this->convertToTimestamp($target_date) - $this->convertToTimestamp($this->record_date));
if($decay_duration <= 0) {
return $this->amount;
}
@@ -62,6 +73,7 @@ class StateBalance extends Entity
public function decayDuration($target_date)
{
- return intval($target_date->getTimestamp() - $this->record_date->getTimestamp());
+ return intval($this->convertToTimestamp($target_date) - $this->convertToTimestamp($this->record_date));
}
}
+
diff --git a/community_server/src/Model/Entity/StateGroupAddress.php b/community_server/src/Model/Entity/StateGroupAddress.php
index e5ce71681..e2d669d09 100644
--- a/community_server/src/Model/Entity/StateGroupAddress.php
+++ b/community_server/src/Model/Entity/StateGroupAddress.php
@@ -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,
];
}
diff --git a/community_server/src/Model/Entity/StateUserRole.php b/community_server/src/Model/Entity/StateUserRole.php
new file mode 100644
index 000000000..d510bb025
--- /dev/null
+++ b/community_server/src/Model/Entity/StateUserRole.php
@@ -0,0 +1,30 @@
+ true,
+ 'role_id' => true
+ ];
+}
diff --git a/community_server/src/Model/Entity/TransactionGroupAddaddres.php b/community_server/src/Model/Entity/TransactionGroupAddaddres.php
index 3cb73b9ee..30819209f 100644
--- a/community_server/src/Model/Entity/TransactionGroupAddaddres.php
+++ b/community_server/src/Model/Entity/TransactionGroupAddaddres.php
@@ -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
];
}
diff --git a/community_server/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php b/community_server/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php
new file mode 100644
index 000000000..781ac8f25
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php
@@ -0,0 +1,146 @@
+proto.gradido.CrossGroupTransfer
+ */
+class CrossGroupTransfer extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field .proto.gradido.TransferAmount sender = 1;
+ */
+ private $sender = null;
+ /**
+ * Generated from protobuf field bytes receiver = 2;
+ */
+ private $receiver = '';
+ /**
+ * Generated from protobuf field string other_group = 3;
+ */
+ private $other_group = '';
+ /**
+ * this matches related OutboundTransfer.paired_transaction_id
+ *
+ * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4;
+ */
+ 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 .proto.gradido.TransferAmount sender = 1;
+ * @return \Proto\Gradido\TransferAmount
+ */
+ public function getSender()
+ {
+ return $this->sender;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.TransferAmount sender = 1;
+ * @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 bytes receiver = 2;
+ * @return string
+ */
+ public function getReceiver()
+ {
+ return $this->receiver;
+ }
+
+ /**
+ * Generated from protobuf field bytes receiver = 2;
+ * @param string $var
+ * @return $this
+ */
+ public function setReceiver($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->receiver = $var;
+
+ return $this;
+ }
+
+ /**
+ * Generated from protobuf field string other_group = 3;
+ * @return string
+ */
+ public function getOtherGroup()
+ {
+ return $this->other_group;
+ }
+
+ /**
+ * Generated from protobuf field string other_group = 3;
+ * @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 .proto.gradido.Timestamp paired_transaction_id = 4;
+ * @return \Proto\Gradido\Timestamp
+ */
+ public function getPairedTransactionId()
+ {
+ return $this->paired_transaction_id;
+ }
+
+ /**
+ * this matches related OutboundTransfer.paired_transaction_id
+ *
+ * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4;
+ * @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;
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/GradidoCreation.php b/community_server/src/Model/Messages/Proto/Gradido/GradidoCreation.php
new file mode 100644
index 000000000..9b4c3208d
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/GradidoCreation.php
@@ -0,0 +1,102 @@
+proto.gradido.GradidoCreation
+ */
+class GradidoCreation extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * 40 Byte
+ *
+ * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1;
+ */
+ private $receiver = null;
+ /**
+ * 8 Byte
+ *
+ * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3;
+ */
+ 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 .proto.gradido.TransferAmount receiver = 1;
+ * @return \Proto\Gradido\TransferAmount
+ */
+ public function getReceiver()
+ {
+ return $this->receiver;
+ }
+
+ /**
+ * 40 Byte
+ *
+ * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1;
+ * @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 .proto.gradido.TimestampSeconds target_date = 3;
+ * @return \Proto\Gradido\TimestampSeconds
+ */
+ public function getTargetDate()
+ {
+ return $this->target_date;
+ }
+
+ /**
+ * 8 Byte
+ *
+ * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3;
+ * @param \Proto\Gradido\TimestampSeconds $var
+ * @return $this
+ */
+ public function setTargetDate($var)
+ {
+ GPBUtil::checkMessage($var, \Proto\Gradido\TimestampSeconds::class);
+ $this->target_date = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/GradidoTransaction.php b/community_server/src/Model/Messages/Proto/Gradido/GradidoTransaction.php
new file mode 100644
index 000000000..b4b34c77e
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/GradidoTransaction.php
@@ -0,0 +1,116 @@
+proto.gradido.GradidoTransaction
+ */
+class GradidoTransaction extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1;
+ */
+ 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 bytes body_bytes = 2;
+ */
+ 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 .proto.gradido.SignatureMap sig_map = 1;
+ * @return \Proto\Gradido\SignatureMap
+ */
+ public function getSigMap()
+ {
+ return $this->sig_map;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1;
+ * @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 bytes body_bytes = 2;
+ * @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 bytes body_bytes = 2;
+ * @param string $var
+ * @return $this
+ */
+ public function setBodyBytes($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->body_bytes = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/GradidoTransfer.php b/community_server/src/Model/Messages/Proto/Gradido/GradidoTransfer.php
new file mode 100644
index 000000000..a76954c2e
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/GradidoTransfer.php
@@ -0,0 +1,109 @@
+proto.gradido.GradidoTransfer
+ */
+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 .proto.gradido.LocalTransfer local = 1;
+ * @return \Proto\Gradido\LocalTransfer
+ */
+ public function getLocal()
+ {
+ return $this->readOneof(1);
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.LocalTransfer local = 1;
+ * @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 .proto.gradido.CrossGroupTransfer inbound = 2;
+ * @return \Proto\Gradido\CrossGroupTransfer
+ */
+ public function getInbound()
+ {
+ return $this->readOneof(2);
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.CrossGroupTransfer inbound = 2;
+ * @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 .proto.gradido.CrossGroupTransfer outbound = 3;
+ * @return \Proto\Gradido\CrossGroupTransfer
+ */
+ public function getOutbound()
+ {
+ return $this->readOneof(3);
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.CrossGroupTransfer outbound = 3;
+ * @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");
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php
new file mode 100644
index 000000000..22e86d3e1
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php
@@ -0,0 +1,92 @@
+proto.gradido.GroupFriendsUpdate
+ */
+class GroupFriendsUpdate extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * char[16], alias
+ *
+ * Generated from protobuf field string group = 1;
+ */
+ private $group = '';
+ /**
+ * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2;
+ */
+ 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 string group = 1;
+ * @return string
+ */
+ public function getGroup()
+ {
+ return $this->group;
+ }
+
+ /**
+ * char[16], alias
+ *
+ * Generated from protobuf field string group = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setGroup($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->group = $var;
+
+ return $this;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2;
+ * @return int
+ */
+ public function getAction()
+ {
+ return $this->action;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2;
+ * @param int $var
+ * @return $this
+ */
+ public function setAction($var)
+ {
+ GPBUtil::checkEnum($var, \Proto\Gradido\GroupFriendsUpdate_Action::class);
+ $this->action = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php
new file mode 100644
index 000000000..2a3396c55
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php
@@ -0,0 +1,51 @@
+proto.gradido.GroupFriendsUpdate.Action
+ */
+class Action
+{
+ /**
+ * Generated from protobuf enum ADD_FRIEND = 0;
+ */
+ const ADD_FRIEND = 0;
+ /**
+ * Generated from protobuf enum REMOVE_FRIEND = 1;
+ */
+ 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);
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php
new file mode 100644
index 000000000..24f8cef70
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php
@@ -0,0 +1,16 @@
+proto.gradido.GroupMemberUpdate
+ */
+class GroupMemberUpdate extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field bytes user_pubkey = 1;
+ */
+ private $user_pubkey = '';
+ /**
+ * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2;
+ */
+ private $member_update_type = 0;
+ /**
+ * this only makes sense for user move, TODO: probably restructure
+ *
+ * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3;
+ */
+ private $paired_transaction_id = null;
+ /**
+ * Generated from protobuf field string target_group = 4;
+ */
+ 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 bytes user_pubkey = 1;
+ * @return string
+ */
+ public function getUserPubkey()
+ {
+ return $this->user_pubkey;
+ }
+
+ /**
+ * Generated from protobuf field bytes user_pubkey = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setUserPubkey($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->user_pubkey = $var;
+
+ return $this;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2;
+ * @return int
+ */
+ public function getMemberUpdateType()
+ {
+ return $this->member_update_type;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2;
+ * @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 .proto.gradido.Timestamp paired_transaction_id = 3;
+ * @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 .proto.gradido.Timestamp paired_transaction_id = 3;
+ * @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 string target_group = 4;
+ * @return string
+ */
+ public function getTargetGroup()
+ {
+ return $this->target_group;
+ }
+
+ /**
+ * Generated from protobuf field string target_group = 4;
+ * @param string $var
+ * @return $this
+ */
+ public function setTargetGroup($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->target_group = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php b/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php
new file mode 100644
index 000000000..57580cd75
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php
@@ -0,0 +1,56 @@
+proto.gradido.GroupMemberUpdate.MemberUpdateType
+ */
+class MemberUpdateType
+{
+ /**
+ * Generated from protobuf enum ADD_USER = 0;
+ */
+ const ADD_USER = 0;
+ /**
+ * Generated from protobuf enum MOVE_USER_INBOUND = 1;
+ */
+ const MOVE_USER_INBOUND = 1;
+ /**
+ * Generated from protobuf enum MOVE_USER_OUTBOUND = 2;
+ */
+ 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);
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php b/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php
new file mode 100644
index 000000000..b7080cf75
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php
@@ -0,0 +1,16 @@
+proto.gradido.Key
+ */
+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 bytes ed25519 = 2;
+ * @return string
+ */
+ public function getEd25519()
+ {
+ return $this->readOneof(2);
+ }
+
+ /**
+ * ed25519 signature (libsodium default)
+ *
+ * Generated from protobuf field bytes ed25519 = 2;
+ * @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 bytes ed25519_ref10 = 3;
+ * @return string
+ */
+ public function getEd25519Ref10()
+ {
+ return $this->readOneof(3);
+ }
+
+ /**
+ * ed25519 ref10 signature
+ *
+ * Generated from protobuf field bytes ed25519_ref10 = 3;
+ * @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");
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/LocalTransfer.php b/community_server/src/Model/Messages/Proto/Gradido/LocalTransfer.php
new file mode 100644
index 000000000..58f5e23ae
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/LocalTransfer.php
@@ -0,0 +1,85 @@
+proto.gradido.LocalTransfer
+ */
+class LocalTransfer extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field .proto.gradido.TransferAmount sender = 1;
+ */
+ private $sender = null;
+ /**
+ * Generated from protobuf field bytes receiver = 2;
+ */
+ 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 .proto.gradido.TransferAmount sender = 1;
+ * @return \Proto\Gradido\TransferAmount
+ */
+ public function getSender()
+ {
+ return $this->sender;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.TransferAmount sender = 1;
+ * @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 bytes receiver = 2;
+ * @return string
+ */
+ public function getReceiver()
+ {
+ return $this->receiver;
+ }
+
+ /**
+ * Generated from protobuf field bytes receiver = 2;
+ * @param string $var
+ * @return $this
+ */
+ public function setReceiver($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->receiver = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/SignatureMap.php b/community_server/src/Model/Messages/Proto/Gradido/SignatureMap.php
new file mode 100644
index 000000000..0977169d7
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/SignatureMap.php
@@ -0,0 +1,65 @@
+proto.gradido.SignatureMap
+ */
+class SignatureMap extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Each signature pair corresponds to a unique Key required to sign the transaction.
+ *
+ * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1;
+ */
+ 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 repeated .proto.gradido.SignaturePair sigPair = 1;
+ * @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 repeated .proto.gradido.SignaturePair sigPair = 1;
+ * @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;
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/SignaturePair.php b/community_server/src/Model/Messages/Proto/Gradido/SignaturePair.php
new file mode 100644
index 000000000..2ef0e81c5
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/SignaturePair.php
@@ -0,0 +1,123 @@
+proto.gradido.SignaturePair
+ */
+class SignaturePair extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field bytes pubKey = 1;
+ */
+ 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 bytes pubKey = 1;
+ * @return string
+ */
+ public function getPubKey()
+ {
+ return $this->pubKey;
+ }
+
+ /**
+ * Generated from protobuf field bytes pubKey = 1;
+ * @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 bytes ed25519 = 2;
+ * @return string
+ */
+ public function getEd25519()
+ {
+ return $this->readOneof(2);
+ }
+
+ /**
+ * ed25519 signature (libsodium default)
+ *
+ * Generated from protobuf field bytes ed25519 = 2;
+ * @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 bytes ed25519_ref10 = 3;
+ * @return string
+ */
+ public function getEd25519Ref10()
+ {
+ return $this->readOneof(3);
+ }
+
+ /**
+ * ed25519 ref10 signature
+ *
+ * Generated from protobuf field bytes ed25519_ref10 = 3;
+ * @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");
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/Timestamp.php b/community_server/src/Model/Messages/Proto/Gradido/Timestamp.php
new file mode 100644
index 000000000..ae3ecea0e
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/Timestamp.php
@@ -0,0 +1,101 @@
+proto.gradido.Timestamp
+ */
+class Timestamp extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Number of complete seconds since the start of the epoch
+ *
+ * Generated from protobuf field int64 seconds = 1;
+ */
+ private $seconds = 0;
+ /**
+ * Number of nanoseconds since the start of the last second
+ *
+ * Generated from protobuf field int32 nanos = 2;
+ */
+ 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 int64 seconds = 1;
+ * @return int|string
+ */
+ public function getSeconds()
+ {
+ return $this->seconds;
+ }
+
+ /**
+ * Number of complete seconds since the start of the epoch
+ *
+ * Generated from protobuf field int64 seconds = 1;
+ * @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 int32 nanos = 2;
+ * @return int
+ */
+ public function getNanos()
+ {
+ return $this->nanos;
+ }
+
+ /**
+ * Number of nanoseconds since the start of the last second
+ *
+ * Generated from protobuf field int32 nanos = 2;
+ * @param int $var
+ * @return $this
+ */
+ public function setNanos($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->nanos = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/TimestampSeconds.php b/community_server/src/Model/Messages/Proto/Gradido/TimestampSeconds.php
new file mode 100644
index 000000000..d31aa40d2
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/TimestampSeconds.php
@@ -0,0 +1,67 @@
+proto.gradido.TimestampSeconds
+ */
+class TimestampSeconds extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Number of complete seconds since the start of the epoch
+ *
+ * Generated from protobuf field int64 seconds = 1;
+ */
+ 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 int64 seconds = 1;
+ * @return int|string
+ */
+ public function getSeconds()
+ {
+ return $this->seconds;
+ }
+
+ /**
+ * Number of complete seconds since the start of the epoch
+ *
+ * Generated from protobuf field int64 seconds = 1;
+ * @param int|string $var
+ * @return $this
+ */
+ public function setSeconds($var)
+ {
+ GPBUtil::checkInt64($var);
+ $this->seconds = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/TransactionBody.php b/community_server/src/Model/Messages/Proto/Gradido/TransactionBody.php
new file mode 100644
index 000000000..0484ecc92
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/TransactionBody.php
@@ -0,0 +1,193 @@
+proto.gradido.TransactionBody
+ */
+class TransactionBody extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * max 150 chars
+ *
+ * Generated from protobuf field string memo = 1;
+ */
+ private $memo = '';
+ /**
+ * Generated from protobuf field uint64 version_number = 6;
+ */
+ 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\GradidoTransfer $transfer
+ * @type \Proto\Gradido\GradidoCreation $creation
+ * @type \Proto\Gradido\GroupFriendsUpdate $group_friends_update
+ * @type \Proto\Gradido\GroupMemberUpdate $group_member_update
+ * @type int|string $version_number
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Gradido\TransactionBody::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * max 150 chars
+ *
+ * Generated from protobuf field string memo = 1;
+ * @return string
+ */
+ public function getMemo()
+ {
+ return $this->memo;
+ }
+
+ /**
+ * max 150 chars
+ *
+ * Generated from protobuf field string memo = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setMemo($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->memo = $var;
+
+ return $this;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 2;
+ * @return \Proto\Gradido\GradidoTransfer
+ */
+ public function getTransfer()
+ {
+ return $this->readOneof(2);
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 2;
+ * @param \Proto\Gradido\GradidoTransfer $var
+ * @return $this
+ */
+ public function setTransfer($var)
+ {
+ GPBUtil::checkMessage($var, \Proto\Gradido\GradidoTransfer::class);
+ $this->writeOneof(2, $var);
+
+ return $this;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GradidoCreation creation = 3;
+ * @return \Proto\Gradido\GradidoCreation
+ */
+ public function getCreation()
+ {
+ return $this->readOneof(3);
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GradidoCreation creation = 3;
+ * @param \Proto\Gradido\GradidoCreation $var
+ * @return $this
+ */
+ public function setCreation($var)
+ {
+ GPBUtil::checkMessage($var, \Proto\Gradido\GradidoCreation::class);
+ $this->writeOneof(3, $var);
+
+ return $this;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 4;
+ * @return \Proto\Gradido\GroupFriendsUpdate
+ */
+ public function getGroupFriendsUpdate()
+ {
+ return $this->readOneof(4);
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 4;
+ * @param \Proto\Gradido\GroupFriendsUpdate $var
+ * @return $this
+ */
+ public function setGroupFriendsUpdate($var)
+ {
+ GPBUtil::checkMessage($var, \Proto\Gradido\GroupFriendsUpdate::class);
+ $this->writeOneof(4, $var);
+
+ return $this;
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 5;
+ * @return \Proto\Gradido\GroupMemberUpdate
+ */
+ public function getGroupMemberUpdate()
+ {
+ return $this->readOneof(5);
+ }
+
+ /**
+ * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 5;
+ * @param \Proto\Gradido\GroupMemberUpdate $var
+ * @return $this
+ */
+ public function setGroupMemberUpdate($var)
+ {
+ GPBUtil::checkMessage($var, \Proto\Gradido\GroupMemberUpdate::class);
+ $this->writeOneof(5, $var);
+
+ return $this;
+ }
+
+ /**
+ * Generated from protobuf field uint64 version_number = 6;
+ * @return int|string
+ */
+ public function getVersionNumber()
+ {
+ return $this->version_number;
+ }
+
+ /**
+ * Generated from protobuf field uint64 version_number = 6;
+ * @param int|string $var
+ * @return $this
+ */
+ public function setVersionNumber($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->version_number = $var;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getData()
+ {
+ return $this->whichOneof("data");
+ }
+
+}
+
diff --git a/community_server/src/Model/Messages/Proto/Gradido/TransferAmount.php b/community_server/src/Model/Messages/Proto/Gradido/TransferAmount.php
new file mode 100644
index 000000000..7673582fa
--- /dev/null
+++ b/community_server/src/Model/Messages/Proto/Gradido/TransferAmount.php
@@ -0,0 +1,85 @@
+proto.gradido.TransferAmount
+ */
+class TransferAmount extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field bytes pubkey = 1;
+ */
+ private $pubkey = '';
+ /**
+ * Generated from protobuf field sint64 amount = 2;
+ */
+ 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 bytes pubkey = 1;
+ * @return string
+ */
+ public function getPubkey()
+ {
+ return $this->pubkey;
+ }
+
+ /**
+ * Generated from protobuf field bytes pubkey = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setPubkey($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->pubkey = $var;
+
+ return $this;
+ }
+
+ /**
+ * Generated from protobuf field sint64 amount = 2;
+ * @return int|string
+ */
+ public function getAmount()
+ {
+ return $this->amount;
+ }
+
+ /**
+ * Generated from protobuf field sint64 amount = 2;
+ * @param int|string $var
+ * @return $this
+ */
+ public function setAmount($var)
+ {
+ GPBUtil::checkInt64($var);
+ $this->amount = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/community_server/src/Model/Table/AddressTypesTable.php b/community_server/src/Model/Table/AddressTypesTable.php
index ea0c86d6e..ba94c99c7 100644
--- a/community_server/src/Model/Table/AddressTypesTable.php
+++ b/community_server/src/Model/Table/AddressTypesTable.php
@@ -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;
}
diff --git a/community_server/src/Model/Table/RolesTable.php b/community_server/src/Model/Table/RolesTable.php
new file mode 100644
index 000000000..940b7f246
--- /dev/null
+++ b/community_server/src/Model/Table/RolesTable.php
@@ -0,0 +1,72 @@
+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;
+ }
+}
diff --git a/community_server/src/Model/Table/StateBalancesTable.php b/community_server/src/Model/Table/StateBalancesTable.php
index 85b2f7837..cae6e0fe8 100644
--- a/community_server/src/Model/Table/StateBalancesTable.php
+++ b/community_server/src/Model/Table/StateBalancesTable.php
@@ -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() . "
";
+ $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;
+ }
}
diff --git a/community_server/src/Model/Table/StateGroupAddressesTable.php b/community_server/src/Model/Table/StateGroupAddressesTable.php
index 62fcf9470..a63e2ae1c 100644
--- a/community_server/src/Model/Table/StateGroupAddressesTable.php
+++ b/community_server/src/Model/Table/StateGroupAddressesTable.php
@@ -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;
diff --git a/community_server/src/Model/Table/StateUserRolesTable.php b/community_server/src/Model/Table/StateUserRolesTable.php
new file mode 100644
index 000000000..895e788b2
--- /dev/null
+++ b/community_server/src/Model/Table/StateUserRolesTable.php
@@ -0,0 +1,86 @@
+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;
+ }
+
+
+}
diff --git a/community_server/src/Model/Table/TransactionGroupAddaddressTable.php b/community_server/src/Model/Table/TransactionGroupAddaddressTable.php
index 3fd03f32a..cb9912083 100644
--- a/community_server/src/Model/Table/TransactionGroupAddaddressTable.php
+++ b/community_server/src/Model/Table/TransactionGroupAddaddressTable.php
@@ -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;
}
diff --git a/community_server/src/Model/Transactions/Record.php b/community_server/src/Model/Transactions/Record.php
new file mode 100644
index 000000000..862399af5
--- /dev/null
+++ b/community_server/src/Model/Transactions/Record.php
@@ -0,0 +1,575 @@
+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;
+ }
+
+}
\ No newline at end of file
diff --git a/community_server/src/Template/AddressTypes/add.ctp b/community_server/src/Template/AddressTypes/add.ctp
index 7422b666a..f62c5115e 100644
--- a/community_server/src/Template/AddressTypes/add.ctp
+++ b/community_server/src/Template/AddressTypes/add.ctp
@@ -4,8 +4,8 @@
* @var \App\Model\Entity\AddressType $addressType
*/
?>
-