diff --git a/skeema/gradido_community/state_balances.sql b/skeema/gradido_community/state_balances.sql index c8b013d44..5f79ce819 100644 --- a/skeema/gradido_community/state_balances.sql +++ b/skeema/gradido_community/state_balances.sql @@ -2,6 +2,7 @@ CREATE TABLE `state_balances` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `state_user_id` int(10) unsigned NOT NULL, `modified` datetime NOT NULL, + `record_date`datetime NULL, `amount` bigint(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 2c59a17e0..6a521cab8 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -139,7 +139,7 @@ class AppController extends Controller } } - protected function requestLogin($session_id = 0) + protected function requestLogin($session_id = 0, $redirect = true) { $session = $this->getRequest()->getSession(); // check login @@ -238,12 +238,18 @@ class AppController extends Controller //echo $newStateUser->id; } } else { + if(!$redirect) { + return ['state' => 'error', 'msg' => 'no pubkey']; + } // we haven't get a pubkey? something seems to gone wrong on the login-server $this->Flash->error(__('no pubkey')); //var_dump($json); return $this->redirect($this->loginServerUrl . 'account/error500/noPubkey', 303); } } else { + if(!$redirect) { + return ['state' => 'not found', 'msg' => 'invalid session']; + } if ($json['state'] === 'not found') { $this->Flash->error(__('invalid session')); } else { @@ -255,6 +261,9 @@ class AppController extends Controller } } catch (\Exception $e) { $msg = $e->getMessage(); + if(!$redirect) { + return ['state' => 'error', 'msg' => 'login-server http request error', 'details' => $msg]; + } $this->Flash->error(__('error http request: ') . $msg); return $this->redirect(['controller' => 'Dashboard', 'action' => 'errorHttpRequest']); //continue; @@ -263,6 +272,9 @@ class AppController extends Controller } else { // no login //die("no login"); + if(!$redirect) { + return ['state' => 'error', 'msg' => 'not logged in']; + } if (isset($loginServer['path'])) { return $this->redirect($loginServer['path'], 303); } else { diff --git a/src/Controller/StateBalancesController.php b/src/Controller/StateBalancesController.php index 5164dce4b..f850f92e8 100644 --- a/src/Controller/StateBalancesController.php +++ b/src/Controller/StateBalancesController.php @@ -177,21 +177,42 @@ class StateBalancesController extends AppController $this->set('gdtSum', $gdtSum); } - public function ajaxGetBalance($session_id) + public function ajaxGetBalance($session_id = 0) { - if(!isset($session_id) || !$session_id) { - return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); + if(!$session_id) { + return $this->returnJson(['state' => 'error', 'msg' => 'invalid session id']); + } + $login_result = $this->requestLogin($session_id, false); + if($login_result !== true) { + return $this->returnJson($login_result); } - $startTime = microtime(true); $session = $this->getRequest()->getSession(); - $result = $this->requestLogin($session_id); - if ($result !== true) { - return $this->returnJson(['state' => 'error', 'msg' => 'session not found']); - } $user = $session->read('StateUser'); - //var_dump($user); - return $this->returnJson(['state' => 'success', 'balance' => $user['balance']]); + $public_key_bin = hex2bin($user['public_hex']); + $stateUserQuery = $this->StateBalances->StateUsers + ->find('all') + ->where(['public_key' => $public_key_bin]) + ->contain(['StateBalances']); + + $result_user_count = $stateUserQuery->count(); + if($result_user_count < 1) { + return $this->returnJson(['state' => 'success', 'balance' => 0]); + } + else if($result_user_count > 1) { + return $this->returnJson([ + 'state' => 'error', + 'msg' => 'multiple entrys found', + 'details' => ['public_key' => $user['public_hex'], 'entry_count' => $result_count] + ]); + } + $state_balances = $stateUserQuery->first()->state_balances; + $state_balances_count = count($state_balances); + if($state_balances_count != 1) { + return $this->returnJson(['state' => 'error', 'msg' => 'state balances count isn\'t as expected, expect 1', 'details' => $state_balances_count]); + } + + return $this->returnJson(['state' => 'success', 'balance' => $state_balances[0]->amount]); } public function ajaxListTransactions($session_id, $page, $count) diff --git a/src/Model/Entity/StateBalance.php b/src/Model/Entity/StateBalance.php index 30d0d091f..f9d549bc4 100644 --- a/src/Model/Entity/StateBalance.php +++ b/src/Model/Entity/StateBalance.php @@ -28,6 +28,39 @@ class StateBalance extends Entity 'state_user_id' => true, 'modified' => true, 'amount' => true, + 'record_date' => true, 'state_user' => true ]; + + protected $_virtual = ['decay']; + + protected function _getDecay() + { + // decay factor in seconds per year + // q = e^((lg Kn - lg K0) / n) + // 0.999999978 + // + // 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()); + if($decay_duration === 0) { + return $this->amount; + } + return $this->amount * pow(0.99999997802044727, $decay_duration); + + } + public function partDecay($target_date) + { + $decay_duration = intval($target_date->getTimestamp() - $this->record_date->getTimestamp()); + if($decay_duration <= 0) { + return $this->amount; + } + return $this->amount * pow(0.99999997802044727, $decay_duration); + } + + public function decayDuration($target_date) + { + return intval($target_date->getTimestamp() - $this->record_date->getTimestamp()); + } } diff --git a/src/Model/Transactions/TransactionBase.php b/src/Model/Transactions/TransactionBase.php index 4198fbaaa..12095a13c 100644 --- a/src/Model/Transactions/TransactionBase.php +++ b/src/Model/Transactions/TransactionBase.php @@ -63,7 +63,7 @@ class TransactionBase { } - protected function updateStateBalance($stateUserId, $addAmountCent) { + protected function updateStateBalance($stateUserId, $addAmountCent, $recordDate) { $finalBalance = 0; $stateBalancesTable = TableRegistry::getTableLocator()->get('stateBalances'); $stateBalanceQuery = $stateBalancesTable @@ -75,12 +75,14 @@ class TransactionBase { if($stateBalanceQuery->count() > 0) { $stateBalanceEntry = $stateBalanceQuery->first(); + //$stateBalanceEntry->amount = $stateBalanceEntry->partDecay($recordDate) + $addAmountCent;; $stateBalanceEntry->amount += $addAmountCent; } else { $stateBalanceEntry = $stateBalancesTable->newEntity(); $stateBalanceEntry->state_user_id = $stateUserId; $stateBalanceEntry->amount = $addAmountCent; } + $stateBalanceEntry->record_date = $recordDate; $finalBalance = $stateBalanceEntry->amount; //echo "\ntry to save: "; var_dump($stateBalanceEntry); echo "\n"; if(!$stateBalancesTable->save($stateBalanceEntry)) { diff --git a/tests/TestCase/Controller/StateBalancesControllerTest.php b/tests/TestCase/Controller/StateBalancesControllerTest.php index cfa59d80b..a17885e48 100644 --- a/tests/TestCase/Controller/StateBalancesControllerTest.php +++ b/tests/TestCase/Controller/StateBalancesControllerTest.php @@ -67,19 +67,52 @@ class StateBalancesControllerTest extends TestCase public function testAjaxGetBalance() { $session_id = rand(); - $balance = rand(); $this->session([ 'session_id' => $session_id, 'Transaction' => ['pending' => 0, 'executing' => 0], 'StateUser' => [ - 'id' => 2, // 1 don't work, I don't know why + 'id' => 1, 'email_checked' => 1, - 'balance' => $balance + 'public_hex' => '8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d' ] ]); //echo "balance: $balance"; $this->getAndParse('/state-balances/ajaxGetBalance/' . $session_id, - ['state' => 'success', 'balance' => $balance] + ['state' => 'success', 'balance' => 1200000] + ); + } + + public function testAjaxGetBalanceInvalidSession() + { + $session_id = rand(); + $this->session([ + 'session_id' => $session_id, + 'Transaction' => ['pending' => 0, 'executing' => 0], + 'StateUser' => [ + 'email_checked' => 1, + 'public_hex' => '8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d' + ] + ]); + //echo "balance: $balance"; + $this->getAndParse('/state-balances/ajaxGetBalance/' . 1211, + ['state' => 'not found', 'msg' => 'invalid session'] + ); + } + + public function testAjaxGetBalanceInvalidSessionId() + { + $session_id = rand(); + $this->session([ + 'session_id' => $session_id, + 'Transaction' => ['pending' => 0, 'executing' => 0], + 'StateUser' => [ + 'email_checked' => 1, + 'public_hex' => '8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d' + ] + ]); + //echo "balance: $balance"; + $this->getAndParse('/state-balances/ajaxGetBalance' , + ['state' => 'error', 'msg' => 'invalid session id'] ); }