diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 92ac77d86..c6e1bbc8e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,19 +44,19 @@ jobs: - name: Checkout code uses: actions/checkout@v2 with: - submodules: recursive + submodules: true ########################################################################## # BUILD LOGIN SERVER DOCKER IMAGE ######################################## ########################################################################## - - name: login server | Build `test` image + - name: login server | Build `release` image run: | - docker build --target login_server -t "gradido/login_server:test" -f ./login_server/Dockerfile login_server/ - docker save "gradido/login_server:test" > /tmp/login_server.tar - - name: Upload Artifact - uses: actions/upload-artifact@v2 - with: - name: docker-login-server-test - path: /tmp/login_server.tar + docker build --target release -t "gradido/login_server:release" -f ./login_server/Dockerfile login_server/ + #docker save "gradido/login_server:test" > /tmp/login_server.tar + #- name: Upload Artifact + # uses: actions/upload-artifact@v2 + #with: + # name: docker-login-server-test + #path: /tmp/login_server.tar ############################################################################## # JOB: DOCKER BUILD TEST COMMUNITY SERVER #################################### @@ -102,7 +102,7 @@ jobs: ########################################################################## - name: mariadb | Build `test` image run: | - docker build -t "gradido/mariadb:test" -f ./mariadb/Dockerfile ./ + docker build --target mariadb_server_test -t "gradido/mariadb:test" -f ./mariadb/Dockerfile ./ docker save "gradido/mariadb:test" > /tmp/mariadb.tar - name: Upload Artifact uses: actions/upload-artifact@v2 @@ -212,9 +212,138 @@ jobs: report_name: Coverage Frontend type: lcov result_path: ./coverage/lcov.info - min_coverage: 20 + min_coverage: 28 token: ${{ github.token }} + ############################################################################## + # JOB: UNIT TEST LOGIN-SERVER ############################################### + ############################################################################## + unit_test_login_server: + name: Unit tests - Login-Server + runs-on: ubuntu-latest + needs: [] + services: + mariadb: + image: gradido/mariadb:test + env: + MARIADB_ALLOW_EMPTY_PASSWORD: 1 + MARIADB_USER: root + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" + --health-interval=6s + --health-timeout=3s + --health-retries=4 + steps: + - name: Debug service + run: echo "$(docker ps)" + - name: Debug container choosing script + run: echo "$(docker container ls | grep mariadb | awk '{ print $1 }')" + ########################################################################## + # CHECKOUT CODE ########################################################## + ########################################################################## + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: true + ########################################################################## + # Build Login-Server Test Docker image ################################### + ########################################################################## + - name: login server | Build `test` image + run: | + docker build --target test -t "gradido/login_server:test" -f ./login_server/Dockerfile login_server/ + ########################################################################## + # UNIT TESTS BACKEND LOGIN-SERVER ####################################### + ########################################################################## + - name: Login-Server | Unit tests + run: | + docker run --network container:$(docker container ls | grep mariadb | awk '{ print $1 }') -v ~/coverage:/code/build_cov/coverage -v $(pwd)/configs/login_server:/etc/grd_login gradido/login_server:test + cp -r ~/coverage ./coverage + ########################################################################## + # COVERAGE CHECK BACKEND LOGIN-SERVER #################################### + ########################################################################## + - name: backend login | Coverage check + uses: webcraftmedia/coverage-check-action@master + with: + report_name: Coverage Backend Login + type: lcov + result_path: ./coverage/coverage.info + min_coverage: 13 + token: ${{ github.token }} + + ############################################################################## + # JOB: UNIT TEST COMMUNITY-SERVER ########################################### + ############################################################################## + unit_test_community_server: + name: Unit tests - Community Server + runs-on: ubuntu-latest + needs: [build_test_community_server] + services: + mariadb: + image: gradido/mariadb:test + env: + MARIADB_ALLOW_EMPTY_PASSWORD: 1 + MARIADB_USER: root + # ports: + # - 3306:3306 + options: --health-cmd="mysqladmin ping" + --health-interval=5s + --health-timeout=5s + --health-retries=3 + steps: + - name: get mariadb container id + run: echo "::set-output name=id::$(docker container ls | grep mariadb | awk '{ print $1 }')" + id: mariadb_container + - name: show networks + run: echo "$(docker network ls)" + - name: get automatic created network + run: echo "::set-output name=id::$(docker network ls | grep github_network | awk '{ print $1 }')" + id: network + - name: Start Login-Server + run: docker run --network ${{ steps.network.outputs.id }} --name=login-server -d gradido/login_server:default + - name: get login-server container id + run: echo "::set-output name=id::$(docker container ls | grep login_server | awk '{ print $1 }')" + id: login_server_container + ########################################################################## + # CHECKOUT CODE ########################################################## + ########################################################################## + - name: Checkout code + uses: actions/checkout@v2 + ########################################################################## + # DOWNLOAD DOCKER IMAGE ################################################## + ########################################################################## + - name: Download Docker Image (Community-Server) + uses: actions/download-artifact@v2 + with: + name: docker-community-server-test + path: /tmp + - name: Load Docker Image + run: docker load < /tmp/community_server.tar + + # for debugging login-server + - name: check login-server + run: docker logs ${{ steps.login_server_container.outputs.id }} + - name: check mariadb + run: docker logs ${{ steps.mariadb_container.outputs.id }} + ########################################################################## + # UNIT TESTS BACKEND COMMUNITY-SERVER ####################################### + ########################################################################## + - name: community server | Unit tests + run: | + docker run --network ${{ steps.network.outputs.id }} -v ~/coverage:/var/www/cakephp/webroot/coverage gradido/community_server:test + cp -r ~/coverage ./coverage + ######################################################################### + # COVERAGE CHECK BACKEND COMMUNITY-SERVER #################################### + ########################################################################## + - name: backend community | Coverage check + uses: einhornimmond/coverage-check-action@master + with: + report_name: Coverage Backend Community + type: phpunit + result_path: ./coverage/coverage.info + min_coverage: 10 + token: ${{ github.token }} + #test: # runs-on: ubuntu-latest # steps: @@ -228,4 +357,4 @@ jobs: # GN_INSTANCE_FOLDER: /tmp/gradio-node-instance # GN_CONTAINER_NAME: gradido-node-build # run: docker run gradido-node-test - # timeout-minutes: 2 \ No newline at end of file + # timeout-minutes: 2 diff --git a/community_server/Dockerfile b/community_server/Dockerfile index 8129d581d..c553137c6 100644 --- a/community_server/Dockerfile +++ b/community_server/Dockerfile @@ -1,8 +1,8 @@ -FROM phpdockerio/php74-fpm +FROM phpdockerio/php74-fpm as community_server # install php fpm RUN apt-get update \ - && apt-get -y --no-install-recommends install curl unzip php7.4-curl php7.4-fpm php7.4-mbstring php7.4-intl php7.4-xml php7.4-pdo php7.4-mysql \ + && apt-get -y --no-install-recommends install curl unzip php7.4-curl php7.4-fpm php7.4-mbstring php7.4-intl php7.4-xml php7.4-pdo php7.4-mysql php7.4-xdebug \ && apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* WORKDIR /var/www/cakephp @@ -13,5 +13,18 @@ COPY ./configs/community_server/app.php ./config/ RUN composer update RUN composer dump-autoload +######### special for code coverage and testing +FROM community_server as test +RUN apt-get update \ + && apt-get -y --no-install-recommends install php7.4-xdebug \ + && apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* + + +ENV XDEBUG_MODE=coverage +#RUN composer require --dev rregeer/phpunit-coverage-check + +#CMD ./vendor/bin/phpunit --coverage-clover=./webroot/coverage/clover.xml +CMD ./vendor/bin/phpunit --coverage-text=./webroot/coverage/coverage.info + diff --git a/community_server/config/routes.php b/community_server/config/routes.php index 3b0dfedc1..20fc1ff62 100644 --- a/community_server/config/routes.php +++ b/community_server/config/routes.php @@ -60,19 +60,21 @@ Router::scope('/', function (RouteBuilder $routes) { $whitelist = ['JsonRequestHandler', 'ElopageWebhook', 'AppRequests']; $ajaxWhitelist = ['TransactionSendCoins', 'TransactionCreations']; + $callerIp = $request->clientIp(); + foreach($whitelist as $entry) { if($request->getParam('controller') === $entry) { if($entry == 'ElopageWebhook' || $entry == 'AppRequests') { return true; } $allowedIpLocalhost = ['127.0.0.1', 'localhost', '', '::1']; - if(in_array($clientIp, $allowedIpLocalhost)) { + if(in_array($callerIp, $allowedIpLocalhost)) { return true; } $allowedCaller = Configure::read('API.allowedCaller'); $ipPerHost = []; if($allowedCaller && count($allowedCaller) > 0) { - $callerIp = $request->clientIp(); + foreach($allowedCaller as $allowed) { $ip = gethostbyname($allowed); $ipPerHost[$allowed] = $ip; diff --git a/community_server/src/Controller/AppController.php b/community_server/src/Controller/AppController.php index a1416678f..eb11299ce 100644 --- a/community_server/src/Controller/AppController.php +++ b/community_server/src/Controller/AppController.php @@ -88,19 +88,8 @@ class AppController extends Controller // load current balance $session = $this->getRequest()->getSession(); $state_user_id = $session->read('StateUser.id'); - if ($state_user_id) { - $stateBalancesTable = TableRegistry::getTableLocator()->get('stateBalances'); - $stateBalanceQuery = $stateBalancesTable - ->find('all') - ->contain(false) - ->where(['state_user_id' => $state_user_id]); - if ($stateBalanceQuery->count() == 1) { - //var_dump($stateBalanceEntry->first()); - $session->write('StateUser.balance', $stateBalanceQuery->first()->decay); - //echo "stateUser.balance: " . $session->read('StateUser.balance'); - } - } - + + // load error count if ($state_user_id) { $stateErrorsTable = TableRegistry::getTableLocator()->get('stateErrors'); @@ -111,8 +100,6 @@ class AppController extends Controller ->where(['state_user_id' => $state_user_id]); $session->write('StateUser.errorCount', $stateErrorQuery->count()); } - //echo "initialize"; - // put current page into global for navi $GLOBALS["passed"] = null; diff --git a/community_server/src/Controller/AppRequestsController.php b/community_server/src/Controller/AppRequestsController.php index 4d70a68b1..ff3314e94 100644 --- a/community_server/src/Controller/AppRequestsController.php +++ b/community_server/src/Controller/AppRequestsController.php @@ -152,10 +152,7 @@ class AppRequestsController extends AppController if($result !== true) { return $this->returnJson($result); } - $required_fields = $this->checkAndCopyRequiredFields(['target_date'], $params, $data); - if($required_fields !== true) { - return $this->returnJson($required_fields); - } + if(!isset($params['memo']) || strlen($params['memo']) < 5 || strlen($params['memo']) > 150) { return $this->returnJson(['state' => 'error', 'msg' => 'memo is not set or not in expected range [5;150]']); } @@ -276,7 +273,8 @@ class AppRequestsController extends AppController $this->viewBuilder()->setLayout('ajax'); $login_result = $this->requestLogin($session_id, false); if($login_result !== true) { - return $this->returnJson($login_result); + $this->set('body', $login_result); + return; } $session = $this->getRequest()->getSession(); $user = $session->read('StateUser'); @@ -285,16 +283,24 @@ class AppRequestsController extends AppController $state_balance = $state_balances_table->find()->where(['state_user_id' => $user['id']])->first(); - if(!$state_balance) { - return $this->returnJson(['state' => 'success', 'balance' => 0]); - } + $now = new FrozenTime(); - $body = [ - 'state' => 'success', - 'balance' => $state_balance->amount, - 'decay' => $state_balance->partDecay($now), - 'decay_date' => $now - ]; + if(!$state_balance) { + $body = [ + 'state' => 'success', + 'balance' => 0, + 'decay' => 0 + ]; + } else { + + $body = [ + 'state' => 'success', + 'balance' => $state_balance->amount, + 'decay' => $state_balance->partDecay($now), + ]; + } + + $body['decay_date'] = $now; $this->set('body', $body); } @@ -302,35 +308,31 @@ class AppRequestsController extends AppController { $this->viewBuilder()->setLayout('ajax'); $startTime = microtime(true); + $login_result = $this->requestLogin($session_id, false); + if($login_result !== true) { return $this->returnJson($login_result); } $session = $this->getRequest()->getSession(); $user = $session->read('StateUser'); - - + $stateBalancesTable = TableRegistry::getTableLocator()->get('StateBalances'); $stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions'); $transactionsTable = TableRegistry::getTableLocator()->get('Transactions'); - $stateBalancesTable->updateBalances($user['id']); - + $gdtSum = 0; + $gdtEntries = $this->JsonRequestClient->sendRequestGDT(['email' => $user['email']], 'GdtEntries' . DS . 'sumPerEmailApi'); - + if('success' == $gdtEntries['state'] && 'success' == $gdtEntries['data']['state']) { $gdtSum = intval($gdtEntries['data']['sum']); } else { $this->addAdminError('StateBalancesController', 'overview', $gdtEntries, $user['id'] ? $user['id'] : 0); } - $stateUserTransactions_total = $stateUserTransactionsTable - ->find() - ->select(['id']) - ->where(['state_user_id' => $user['id']]) - ->contain([]); $stateUserTransactionsQuery = $stateUserTransactionsTable ->find() @@ -343,17 +345,18 @@ class AppRequestsController extends AppController $decay = true; $transactions = []; $transactions_from_db = $stateUserTransactionsQuery->toArray(); - if($stateUserTransactionsQuery->count() > 0) { + + if(count($transactions_from_db)) { if($orderDirection == 'DESC') { $transactions_from_db = array_reverse($transactions_from_db); } + $transactions = $transactionsTable->listTransactionsHumanReadable($transactions_from_db, $user, $decay); if($orderDirection == 'DESC') { $transactions = array_reverse($transactions); } - - } + } $state_balance = $stateBalancesTable->find()->where(['state_user_id' => $user['id']])->first(); @@ -361,7 +364,7 @@ class AppRequestsController extends AppController 'state' => 'success', 'transactions' => $transactions, 'transactionExecutingCount' => $session->read('Transactions.executing'), - 'count' => $stateUserTransactions_total->count(), + 'count' => $stateUserTransactionsQuery->count(), 'gdtSum' => $gdtSum, 'timeUsed' => microtime(true) - $startTime ]; @@ -375,8 +378,8 @@ class AppRequestsController extends AppController $body['balance'] = $state_balance->amount; $body['decay'] = $stateBalancesTable->calculateDecay($state_balance->amount, $state_balance->record_date, $now); } - - $this->set('body', $body); + + $this->set('body', $body); } private function acquireAccessToken($session_id) diff --git a/community_server/src/Controller/JsonRequestHandlerController.php b/community_server/src/Controller/JsonRequestHandlerController.php index 12e03be8d..611984118 100644 --- a/community_server/src/Controller/JsonRequestHandlerController.php +++ b/community_server/src/Controller/JsonRequestHandlerController.php @@ -340,12 +340,13 @@ class JsonRequestHandlerController extends AppController { return; } $transaction_body = $transaction->getTransactionBody(); - $transaction_type_name = $transaction_body->getTransactionTypeName(); - $senderUser = null; - if($transaction_type_name === 'transfer') { - $senderUser = $transaction_body->getSpecificTransaction()->getSenderUser(); - } else if($transaction_type_name === 'creation') { - $senderUser = $transaction->getFirstSigningUser(); + $senderUser = $transaction->getFirstSigningUser(); + if($transaction_body != null) { + $transaction_type_name = $transaction_body->getTransactionTypeName(); + + if($transaction_type_name === 'transfer') { + $senderUser = $transaction_body->getSpecificTransaction()->getSenderUser(); + } } // send notification email $noReplyEmail = Configure::read('noReplyEmail'); @@ -373,22 +374,29 @@ class JsonRequestHandlerController extends AppController { private function putTransaction($transactionBase64) { $transaction = new Transaction($transactionBase64); - //echo "after new transaction
"; + if($transaction->hasErrors()) { $this->sendEMailTransactionFailed($transaction, 'parse'); return $this->returnJson(['state' => 'error', 'msg' => 'error parsing transaction', 'details' => $transaction->getErrors()]); } - //echo "after check on errors
"; + if(!$transaction->validate()) { //$transaction_details $this->sendEMailTransactionFailed($transaction, 'validate'); - return $this->returnJsonSaveError($transaction, ['state' => 'error', 'msg' => 'error validate transaction', 'details' => $transaction->getErrors()]); + return $this->returnJsonSaveError($transaction, [ + 'state' => 'error', + 'msg' => 'error validate transaction', + 'details' => $transaction->getErrors() + ]); } - //echo "after validate
"; if ($transaction->save()) { + $result = ['state' => 'success']; + if($transaction->hasWarnings()) { + $result['warnings'] = $transaction->getWarnings(); + } // success - return $this->returnJson(['state' => 'success']); + return $this->returnJson($result); } else { $this->sendEMailTransactionFailed($transaction, 'save'); diff --git a/community_server/src/Controller/StateBalancesController.php b/community_server/src/Controller/StateBalancesController.php index 0dc9b672d..f16ed407b 100644 --- a/community_server/src/Controller/StateBalancesController.php +++ b/community_server/src/Controller/StateBalancesController.php @@ -151,35 +151,6 @@ class StateBalancesController extends AppController $this->set('gdtSum', $gdtSum); } - public function ajaxGetBalance($session_id = 0) - { - 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); - } - $session = $this->getRequest()->getSession(); - $user = $session->read('StateUser'); - - $this->StateBalances->updateBalances($user['id']); - - $state_balance = $this->StateBalances->find()->where(['state_user_id' => $user['id']])->first(); - - if(!$state_balance) { - return $this->returnJson(['state' => 'success', 'balance' => 0]); - } - $now = new FrozenTime(); - - return $this->returnJson([ - 'state' => 'success', - 'balance' => $state_balance->amount, - 'decay' => $this->StateBalances->calculateDecay($state_balance->amount, $state_balance->record_date, $now), - 'decay_date' => $now - ]); - } - public function ajaxGdtOverview() { diff --git a/community_server/src/Controller/TransactionsController.php b/community_server/src/Controller/TransactionsController.php index 90e78b7fb..67526dfcc 100644 --- a/community_server/src/Controller/TransactionsController.php +++ b/community_server/src/Controller/TransactionsController.php @@ -7,6 +7,7 @@ use Model\Transactions\Transaction; use Model\Transactions\TransactionBody; use Cake\Core\Configure; +use Cake\I18n\Time; use Cake\ORM\TableRegistry; /** @@ -24,7 +25,7 @@ class TransactionsController extends AppController parent::initialize(); $this->loadComponent('GradidoNumber'); $this->loadComponent('JsonRpcRequestClient'); - $this->Auth->allow(['decode']); + $this->Auth->allow(['decode', 'manualTransaction']); } /** @@ -170,6 +171,78 @@ class TransactionsController extends AppController $this->set('transaction', $transaction); } + public function manualTransaction() + { + if ($this->request->is('post')) { + $data = $this->request->getData(); + $type = $data['type']; + + $transaction = new \Proto\Gradido\GradidoTransaction(); + $transactionBody = new \Proto\Gradido\TransactionBody(); + $transactionBody->setMemo($data['memo']); + $created = new \Proto\Gradido\TimestampSeconds(); + $now = new Time(); + $created->setSeconds($now->getTimestamp()); + $transactionBody->setCreated($created); + if($type == "creation") { + $creation = new \Proto\Gradido\GradidoCreation(); + $target_date = new \Proto\Gradido\TimestampSeconds(); + $target_time = new Time($data['target_date']); + $target_date->setSeconds($target_time->getTimestamp()); + $creation->setTargetDate($target_date); + $receiver = new \Proto\Gradido\TransferAmount(); + $receiver->setAmount(intval($data['amount'])); + $receiver->setPubkey(hex2bin($data['target_public_key'])); + $creation->setReceiver($receiver); + $transactionBody->setCreation($creation); + } else if($type == "transfer") { + $transfer = new \Proto\Gradido\GradidoTransfer(); + $local_transfer = new \Proto\Gradido\LocalTransfer(); + $sender = new \Proto\Gradido\TransferAmount(); + $sender->setAmount(intval($data['amount'])); + $sender->setPubkey(hex2bin($data['sender_public_key'])); + $local_transfer->setSender($sender); + $local_transfer->setReceiver(hex2bin($data['receiver_public_key'])); + $transfer->setLocal($local_transfer); + $transactionBody->setTransfer($transfer); + } + $body_bytes = $transactionBody->serializeToString(); + $transaction->setBodyBytes($body_bytes); + + $protoSigMap = new \Proto\Gradido\SignatureMap(); + $sigPairs = $protoSigMap->getSigPair(); + //echo "sigPairs: "; var_dump($sigPairs); echo "
"; + //return null; + + // sign with keys + //foreach($keys as $key) { + $sigPair = new \Proto\Gradido\SignaturePair(); + $sigPair->setPubKey(hex2bin($data['signer_public_key'])); + + $signature = sodium_crypto_sign_detached($body_bytes, hex2bin($data['signer_private_key'])); + echo "signature: " . bin2hex($signature). "
"; + $sigPair->setEd25519($signature); + + $sigPairs[] = $sigPair; + // SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING + // SODIUM_BASE64_VARIANT_ORIGINAL + $transaction->setSigMap($protoSigMap); + //var_dump($protoSigMap); + $transaction_bin = $transaction->serializeToString(); +// $url_safe = sodium_bin2base64($transaction_bin, sodium_base64_VARIANT_ORIGINAL); + $base64 = [ + //'original' => sodium_bin2base64($transaction_bin, sodium_base64_VARIANT_ORIGINAL), + //'original_nopadding' => sodium_bin2base64($transaction_bin, sodium_base64_VARIANT_ORIGINAL_NO_PADDING), + //'urlsafe' => sodium_bin2base64($transaction_bin, sodium_base64_VARIANT_URLSAFE), + 'urlsafe_nopadding' => sodium_bin2base64($transaction_bin, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING), + 'php' => base64_encode($transaction_bin) + + ]; + + $this->set('base64', $base64); + } + } + public function decode() { $this->viewBuilder()->setLayout('frontend'); diff --git a/community_server/src/Model/Messages/Gradido/Key.php b/community_server/src/Model/Messages/Gradido/Key.php deleted file mode 100644 index b6190304c..000000000 --- a/community_server/src/Model/Messages/Gradido/Key.php +++ /dev/null @@ -1,96 +0,0 @@ -model.messages.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\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/Gradido/ReceiverAmount.php b/community_server/src/Model/Messages/Gradido/ReceiverAmount.php deleted file mode 100644 index 240c5a6fe..000000000 --- a/community_server/src/Model/Messages/Gradido/ReceiverAmount.php +++ /dev/null @@ -1,85 +0,0 @@ -model.messages.gradido.ReceiverAmount - */ -class ReceiverAmount extends \Google\Protobuf\Internal\Message -{ - /** - * Generated from protobuf field bytes ed25519_receiver_pubkey = 1; - */ - private $ed25519_receiver_pubkey = ''; - /** - * Generated from protobuf field sint64 amount = 2; - */ - private $amount = 0; - - /** - * Constructor. - * - * @param array $data { - * Optional. Data for populating the Message object. - * - * @type string $ed25519_receiver_pubkey - * @type int|string $amount - * } - */ - public function __construct($data = NULL) { - \GPBMetadata\BasicTypes::initOnce(); - parent::__construct($data); - } - - /** - * Generated from protobuf field bytes ed25519_receiver_pubkey = 1; - * @return string - */ - public function getEd25519ReceiverPubkey() - { - return $this->ed25519_receiver_pubkey; - } - - /** - * Generated from protobuf field bytes ed25519_receiver_pubkey = 1; - * @param string $var - * @return $this - */ - public function setEd25519ReceiverPubkey($var) - { - GPBUtil::checkString($var, False); - $this->ed25519_receiver_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/Messages/Gradido/SenderAmount.php b/community_server/src/Model/Messages/Gradido/SenderAmount.php deleted file mode 100644 index 52a41f71f..000000000 --- a/community_server/src/Model/Messages/Gradido/SenderAmount.php +++ /dev/null @@ -1,119 +0,0 @@ -model.messages.gradido.SenderAmount - */ -class SenderAmount extends \Google\Protobuf\Internal\Message -{ - /** - * Generated from protobuf field bytes ed25519_sender_pubkey = 1; - */ - private $ed25519_sender_pubkey = ''; - /** - * Generated from protobuf field sint64 amount = 2; - */ - private $amount = 0; - /** - * sender balance after transaction, including perishability - * - * Generated from protobuf field sint64 senderFinalBalance = 3; - */ - private $senderFinalBalance = 0; - - /** - * Constructor. - * - * @param array $data { - * Optional. Data for populating the Message object. - * - * @type string $ed25519_sender_pubkey - * @type int|string $amount - * @type int|string $senderFinalBalance - * sender balance after transaction, including perishability - * } - */ - public function __construct($data = NULL) { - \GPBMetadata\BasicTypes::initOnce(); - parent::__construct($data); - } - - /** - * Generated from protobuf field bytes ed25519_sender_pubkey = 1; - * @return string - */ - public function getEd25519SenderPubkey() - { - return $this->ed25519_sender_pubkey; - } - - /** - * Generated from protobuf field bytes ed25519_sender_pubkey = 1; - * @param string $var - * @return $this - */ - public function setEd25519SenderPubkey($var) - { - GPBUtil::checkString($var, False); - $this->ed25519_sender_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; - } - - /** - * sender balance after transaction, including perishability - * - * Generated from protobuf field sint64 senderFinalBalance = 3; - * @return int|string - */ - public function getSenderFinalBalance() - { - return $this->senderFinalBalance; - } - - /** - * sender balance after transaction, including perishability - * - * Generated from protobuf field sint64 senderFinalBalance = 3; - * @param int|string $var - * @return $this - */ - public function setSenderFinalBalance($var) - { - GPBUtil::checkInt64($var); - $this->senderFinalBalance = $var; - - return $this; - } - -} - diff --git a/community_server/src/Model/Messages/Gradido/SignatureMap.php b/community_server/src/Model/Messages/Gradido/SignatureMap.php deleted file mode 100644 index 228282747..000000000 --- a/community_server/src/Model/Messages/Gradido/SignatureMap.php +++ /dev/null @@ -1,65 +0,0 @@ -model.messages.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 .model.messages.gradido.SignaturePair sigPair = 1; - */ - private $sigPair; - - /** - * Constructor. - * - * @param array $data { - * Optional. Data for populating the Message object. - * - * @type \Model\Messages\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\BasicTypes::initOnce(); - parent::__construct($data); - } - - /** - * Each signature pair corresponds to a unique Key required to sign the transaction. - * - * Generated from protobuf field repeated .model.messages.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 .model.messages.gradido.SignaturePair sigPair = 1; - * @param \Model\Messages\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $var - * @return $this - */ - public function setSigPair($var) - { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Model\Messages\Gradido\SignaturePair::class); - $this->sigPair = $arr; - - return $this; - } - -} - diff --git a/community_server/src/Model/Messages/Gradido/SignaturePair.php b/community_server/src/Model/Messages/Gradido/SignaturePair.php deleted file mode 100644 index 203eb5677..000000000 --- a/community_server/src/Model/Messages/Gradido/SignaturePair.php +++ /dev/null @@ -1,123 +0,0 @@ -model.messages.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\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/Gradido/StateCreateGroup.php b/community_server/src/Model/Messages/Gradido/StateCreateGroup.php deleted file mode 100644 index 4273ef93d..000000000 --- a/community_server/src/Model/Messages/Gradido/StateCreateGroup.php +++ /dev/null @@ -1,114 +0,0 @@ -model.messages.gradido.StateCreateGroup - */ -class StateCreateGroup extends \Google\Protobuf\Internal\Message -{ - /** - * Generated from protobuf field string name = 1; - */ - private $name = ''; - /** - * Generated from protobuf field .model.messages.gradido.Key groupPublicKey = 2; - */ - private $groupPublicKey = null; - /** - * Generated from protobuf field .model.messages.gradido.Key parentGroupPublicKey = 3; - */ - private $parentGroupPublicKey = null; - - /** - * Constructor. - * - * @param array $data { - * Optional. Data for populating the Message object. - * - * @type string $name - * @type \Model\Messages\Gradido\Key $groupPublicKey - * @type \Model\Messages\Gradido\Key $parentGroupPublicKey - * } - */ - public function __construct($data = NULL) { - \GPBMetadata\StateCreateGroup::initOnce(); - parent::__construct($data); - } - - /** - * Generated from protobuf field string name = 1; - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Generated from protobuf field string name = 1; - * @param string $var - * @return $this - */ - public function setName($var) - { - GPBUtil::checkString($var, True); - $this->name = $var; - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.Key groupPublicKey = 2; - * @return \Model\Messages\Gradido\Key - */ - public function getGroupPublicKey() - { - return $this->groupPublicKey; - } - - /** - * Generated from protobuf field .model.messages.gradido.Key groupPublicKey = 2; - * @param \Model\Messages\Gradido\Key $var - * @return $this - */ - public function setGroupPublicKey($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\Key::class); - $this->groupPublicKey = $var; - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.Key parentGroupPublicKey = 3; - * @return \Model\Messages\Gradido\Key - */ - public function getParentGroupPublicKey() - { - return $this->parentGroupPublicKey; - } - - /** - * Generated from protobuf field .model.messages.gradido.Key parentGroupPublicKey = 3; - * @param \Model\Messages\Gradido\Key $var - * @return $this - */ - public function setParentGroupPublicKey($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\Key::class); - $this->parentGroupPublicKey = $var; - - return $this; - } - -} - diff --git a/community_server/src/Model/Messages/Gradido/StateGroupChangeParent.php b/community_server/src/Model/Messages/Gradido/StateGroupChangeParent.php deleted file mode 100644 index c5371d76c..000000000 --- a/community_server/src/Model/Messages/Gradido/StateGroupChangeParent.php +++ /dev/null @@ -1,114 +0,0 @@ -model.messages.gradido.StateGroupChangeParent - */ -class StateGroupChangeParent extends \Google\Protobuf\Internal\Message -{ - /** - * Generated from protobuf field .model.messages.gradido.Key groupPublicKey = 1; - */ - private $groupPublicKey = null; - /** - * Generated from protobuf field .model.messages.gradido.Key newParentGroupPublicKey = 2; - */ - private $newParentGroupPublicKey = null; - /** - * Generated from protobuf field .model.messages.gradido.Key oldParentGroupPublicKey = 3; - */ - private $oldParentGroupPublicKey = null; - - /** - * Constructor. - * - * @param array $data { - * Optional. Data for populating the Message object. - * - * @type \Model\Messages\Gradido\Key $groupPublicKey - * @type \Model\Messages\Gradido\Key $newParentGroupPublicKey - * @type \Model\Messages\Gradido\Key $oldParentGroupPublicKey - * } - */ - public function __construct($data = NULL) { - \GPBMetadata\StateGroupChangeParent::initOnce(); - parent::__construct($data); - } - - /** - * Generated from protobuf field .model.messages.gradido.Key groupPublicKey = 1; - * @return \Model\Messages\Gradido\Key - */ - public function getGroupPublicKey() - { - return $this->groupPublicKey; - } - - /** - * Generated from protobuf field .model.messages.gradido.Key groupPublicKey = 1; - * @param \Model\Messages\Gradido\Key $var - * @return $this - */ - public function setGroupPublicKey($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\Key::class); - $this->groupPublicKey = $var; - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.Key newParentGroupPublicKey = 2; - * @return \Model\Messages\Gradido\Key - */ - public function getNewParentGroupPublicKey() - { - return $this->newParentGroupPublicKey; - } - - /** - * Generated from protobuf field .model.messages.gradido.Key newParentGroupPublicKey = 2; - * @param \Model\Messages\Gradido\Key $var - * @return $this - */ - public function setNewParentGroupPublicKey($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\Key::class); - $this->newParentGroupPublicKey = $var; - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.Key oldParentGroupPublicKey = 3; - * @return \Model\Messages\Gradido\Key - */ - public function getOldParentGroupPublicKey() - { - return $this->oldParentGroupPublicKey; - } - - /** - * Generated from protobuf field .model.messages.gradido.Key oldParentGroupPublicKey = 3; - * @param \Model\Messages\Gradido\Key $var - * @return $this - */ - public function setOldParentGroupPublicKey($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\Key::class); - $this->oldParentGroupPublicKey = $var; - - return $this; - } - -} - diff --git a/community_server/src/Model/Messages/Gradido/Timestamp.php b/community_server/src/Model/Messages/Gradido/Timestamp.php deleted file mode 100644 index 19721729b..000000000 --- a/community_server/src/Model/Messages/Gradido/Timestamp.php +++ /dev/null @@ -1,101 +0,0 @@ -model.messages.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\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/Gradido/TimestampSeconds.php b/community_server/src/Model/Messages/Gradido/TimestampSeconds.php deleted file mode 100644 index 2a588a312..000000000 --- a/community_server/src/Model/Messages/Gradido/TimestampSeconds.php +++ /dev/null @@ -1,67 +0,0 @@ -model.messages.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\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/Gradido/Transaction.php b/community_server/src/Model/Messages/Gradido/Transaction.php deleted file mode 100644 index 065cd80bb..000000000 --- a/community_server/src/Model/Messages/Gradido/Transaction.php +++ /dev/null @@ -1,166 +0,0 @@ -model.messages.gradido.Transaction - */ -class Transaction extends \Google\Protobuf\Internal\Message -{ - /** - * Generated from protobuf field uint64 id = 1; - */ - private $id = 0; - /** - * Generated from protobuf field .model.messages.gradido.TimestampSeconds received = 2; - */ - private $received = null; - /** - * Generated from protobuf field .model.messages.gradido.SignatureMap sigMap = 3; - */ - private $sigMap = null; - /** - * Generated from protobuf field bytes txHash = 4; - */ - private $txHash = ''; - /** - * Generated from protobuf field bytes bodyBytes = 5; - */ - private $bodyBytes = ''; - - /** - * Constructor. - * - * @param array $data { - * Optional. Data for populating the Message object. - * - * @type int|string $id - * @type \Model\Messages\Gradido\TimestampSeconds $received - * @type \Model\Messages\Gradido\SignatureMap $sigMap - * @type string $txHash - * @type string $bodyBytes - * } - */ - public function __construct($data = NULL) { - \GPBMetadata\Transaction::initOnce(); - parent::__construct($data); - } - - /** - * Generated from protobuf field uint64 id = 1; - * @return int|string - */ - public function getId() - { - return $this->id; - } - - /** - * Generated from protobuf field uint64 id = 1; - * @param int|string $var - * @return $this - */ - public function setId($var) - { - GPBUtil::checkUint64($var); - $this->id = $var; - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.TimestampSeconds received = 2; - * @return \Model\Messages\Gradido\TimestampSeconds - */ - public function getReceived() - { - return $this->received; - } - - /** - * Generated from protobuf field .model.messages.gradido.TimestampSeconds received = 2; - * @param \Model\Messages\Gradido\TimestampSeconds $var - * @return $this - */ - public function setReceived($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\TimestampSeconds::class); - $this->received = $var; - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.SignatureMap sigMap = 3; - * @return \Model\Messages\Gradido\SignatureMap - */ - public function getSigMap() - { - return $this->sigMap; - } - - /** - * Generated from protobuf field .model.messages.gradido.SignatureMap sigMap = 3; - * @param \Model\Messages\Gradido\SignatureMap $var - * @return $this - */ - public function setSigMap($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\SignatureMap::class); - $this->sigMap = $var; - - return $this; - } - - /** - * Generated from protobuf field bytes txHash = 4; - * @return string - */ - public function getTxHash() - { - return $this->txHash; - } - - /** - * Generated from protobuf field bytes txHash = 4; - * @param string $var - * @return $this - */ - public function setTxHash($var) - { - GPBUtil::checkString($var, False); - $this->txHash = $var; - - return $this; - } - - /** - * Generated from protobuf field bytes bodyBytes = 5; - * @return string - */ - public function getBodyBytes() - { - return $this->bodyBytes; - } - - /** - * Generated from protobuf field bytes bodyBytes = 5; - * @param string $var - * @return $this - */ - public function setBodyBytes($var) - { - GPBUtil::checkString($var, False); - $this->bodyBytes = $var; - - return $this; - } - -} - diff --git a/community_server/src/Model/Messages/Gradido/TransactionBody.php b/community_server/src/Model/Messages/Gradido/TransactionBody.php deleted file mode 100644 index 3452d4251..000000000 --- a/community_server/src/Model/Messages/Gradido/TransactionBody.php +++ /dev/null @@ -1,193 +0,0 @@ -model.messages.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 .model.messages.gradido.TimestampSeconds created = 2; - */ - private $created = null; - protected $data; - - /** - * Constructor. - * - * @param array $data { - * Optional. Data for populating the Message object. - * - * @type string $memo - * max 150 chars - * @type \Model\Messages\Gradido\TimestampSeconds $created - * @type \Model\Messages\Gradido\StateCreateGroup $createGroup - * @type \Model\Messages\Gradido\StateGroupChangeParent $groupChangeParent - * @type \Model\Messages\Gradido\Transfer $transfer - * @type \Model\Messages\Gradido\TransactionCreation $creation - * } - */ - public function __construct($data = NULL) { - \GPBMetadata\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 .model.messages.gradido.TimestampSeconds created = 2; - * @return \Model\Messages\Gradido\TimestampSeconds - */ - public function getCreated() - { - return $this->created; - } - - /** - * Generated from protobuf field .model.messages.gradido.TimestampSeconds created = 2; - * @param \Model\Messages\Gradido\TimestampSeconds $var - * @return $this - */ - public function setCreated($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\TimestampSeconds::class); - $this->created = $var; - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.StateCreateGroup createGroup = 6; - * @return \Model\Messages\Gradido\StateCreateGroup - */ - public function getCreateGroup() - { - return $this->readOneof(6); - } - - /** - * Generated from protobuf field .model.messages.gradido.StateCreateGroup createGroup = 6; - * @param \Model\Messages\Gradido\StateCreateGroup $var - * @return $this - */ - public function setCreateGroup($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\StateCreateGroup::class); - $this->writeOneof(6, $var); - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.StateGroupChangeParent groupChangeParent = 7; - * @return \Model\Messages\Gradido\StateGroupChangeParent - */ - public function getGroupChangeParent() - { - return $this->readOneof(7); - } - - /** - * Generated from protobuf field .model.messages.gradido.StateGroupChangeParent groupChangeParent = 7; - * @param \Model\Messages\Gradido\StateGroupChangeParent $var - * @return $this - */ - public function setGroupChangeParent($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\StateGroupChangeParent::class); - $this->writeOneof(7, $var); - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.Transfer transfer = 8; - * @return \Model\Messages\Gradido\Transfer - */ - public function getTransfer() - { - return $this->readOneof(8); - } - - /** - * Generated from protobuf field .model.messages.gradido.Transfer transfer = 8; - * @param \Model\Messages\Gradido\Transfer $var - * @return $this - */ - public function setTransfer($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\Transfer::class); - $this->writeOneof(8, $var); - - return $this; - } - - /** - * Generated from protobuf field .model.messages.gradido.TransactionCreation creation = 9; - * @return \Model\Messages\Gradido\TransactionCreation - */ - public function getCreation() - { - return $this->readOneof(9); - } - - /** - * Generated from protobuf field .model.messages.gradido.TransactionCreation creation = 9; - * @param \Model\Messages\Gradido\TransactionCreation $var - * @return $this - */ - public function setCreation($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\TransactionCreation::class); - $this->writeOneof(9, $var); - - return $this; - } - - /** - * @return string - */ - public function getData() - { - return $this->whichOneof("data"); - } - -} - diff --git a/community_server/src/Model/Messages/Gradido/TransactionCreation.php b/community_server/src/Model/Messages/Gradido/TransactionCreation.php deleted file mode 100644 index ae5f86e07..000000000 --- a/community_server/src/Model/Messages/Gradido/TransactionCreation.php +++ /dev/null @@ -1,136 +0,0 @@ -model.messages.gradido.TransactionCreation - */ -class TransactionCreation extends \Google\Protobuf\Internal\Message -{ - /** - * 40 Byte - * - * Generated from protobuf field .model.messages.gradido.ReceiverAmount receiverAmount = 1; - */ - private $receiverAmount = null; - /** - * 4 Byte - * - * Generated from protobuf field sint32 ident_hash = 2; - */ - private $ident_hash = 0; - /** - * 8 Byte - * - * Generated from protobuf field .model.messages.gradido.TimestampSeconds target_date = 3; - */ - private $target_date = null; - - /** - * Constructor. - * - * @param array $data { - * Optional. Data for populating the Message object. - * - * @type \Model\Messages\Gradido\ReceiverAmount $receiverAmount - * 40 Byte - * @type int $ident_hash - * 4 Byte - * @type \Model\Messages\Gradido\TimestampSeconds $target_date - * 8 Byte - * } - */ - public function __construct($data = NULL) { - \GPBMetadata\TransactionCreation::initOnce(); - parent::__construct($data); - } - - /** - * 40 Byte - * - * Generated from protobuf field .model.messages.gradido.ReceiverAmount receiverAmount = 1; - * @return \Model\Messages\Gradido\ReceiverAmount - */ - public function getReceiverAmount() - { - return $this->receiverAmount; - } - - /** - * 40 Byte - * - * Generated from protobuf field .model.messages.gradido.ReceiverAmount receiverAmount = 1; - * @param \Model\Messages\Gradido\ReceiverAmount $var - * @return $this - */ - public function setReceiverAmount($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\ReceiverAmount::class); - $this->receiverAmount = $var; - - return $this; - } - - /** - * 4 Byte - * - * Generated from protobuf field sint32 ident_hash = 2; - * @return int - */ - public function getIdentHash() - { - return $this->ident_hash; - } - - /** - * 4 Byte - * - * Generated from protobuf field sint32 ident_hash = 2; - * @param int $var - * @return $this - */ - public function setIdentHash($var) - { - GPBUtil::checkInt32($var); - $this->ident_hash = $var; - - return $this; - } - - /** - * 8 Byte - * - * Generated from protobuf field .model.messages.gradido.TimestampSeconds target_date = 3; - * @return \Model\Messages\Gradido\TimestampSeconds - */ - public function getTargetDate() - { - return $this->target_date; - } - - /** - * 8 Byte - * - * Generated from protobuf field .model.messages.gradido.TimestampSeconds target_date = 3; - * @param \Model\Messages\Gradido\TimestampSeconds $var - * @return $this - */ - public function setTargetDate($var) - { - GPBUtil::checkMessage($var, \Model\Messages\Gradido\TimestampSeconds::class); - $this->target_date = $var; - - return $this; - } - -} - diff --git a/community_server/src/Model/Messages/Gradido/Transfer.php b/community_server/src/Model/Messages/Gradido/Transfer.php deleted file mode 100644 index 2c031d02b..000000000 --- a/community_server/src/Model/Messages/Gradido/Transfer.php +++ /dev/null @@ -1,85 +0,0 @@ -model.messages.gradido.Transfer - */ -class Transfer extends \Google\Protobuf\Internal\Message -{ - /** - * Generated from protobuf field repeated .model.messages.gradido.SenderAmount senderAmounts = 1; - */ - private $senderAmounts; - /** - * Generated from protobuf field repeated .model.messages.gradido.ReceiverAmount receiverAmounts = 2; - */ - private $receiverAmounts; - - /** - * Constructor. - * - * @param array $data { - * Optional. Data for populating the Message object. - * - * @type \Model\Messages\Gradido\SenderAmount[]|\Google\Protobuf\Internal\RepeatedField $senderAmounts - * @type \Model\Messages\Gradido\ReceiverAmount[]|\Google\Protobuf\Internal\RepeatedField $receiverAmounts - * } - */ - public function __construct($data = NULL) { - \GPBMetadata\Transfer::initOnce(); - parent::__construct($data); - } - - /** - * Generated from protobuf field repeated .model.messages.gradido.SenderAmount senderAmounts = 1; - * @return \Google\Protobuf\Internal\RepeatedField - */ - public function getSenderAmounts() - { - return $this->senderAmounts; - } - - /** - * Generated from protobuf field repeated .model.messages.gradido.SenderAmount senderAmounts = 1; - * @param \Model\Messages\Gradido\SenderAmount[]|\Google\Protobuf\Internal\RepeatedField $var - * @return $this - */ - public function setSenderAmounts($var) - { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Model\Messages\Gradido\SenderAmount::class); - $this->senderAmounts = $arr; - - return $this; - } - - /** - * Generated from protobuf field repeated .model.messages.gradido.ReceiverAmount receiverAmounts = 2; - * @return \Google\Protobuf\Internal\RepeatedField - */ - public function getReceiverAmounts() - { - return $this->receiverAmounts; - } - - /** - * Generated from protobuf field repeated .model.messages.gradido.ReceiverAmount receiverAmounts = 2; - * @param \Model\Messages\Gradido\ReceiverAmount[]|\Google\Protobuf\Internal\RepeatedField $var - * @return $this - */ - public function setReceiverAmounts($var) - { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Model\Messages\Gradido\ReceiverAmount::class); - $this->receiverAmounts = $arr; - - return $this; - } - -} - diff --git a/community_server/src/Model/Table/TransactionsTable.php b/community_server/src/Model/Table/TransactionsTable.php index e3c36bf8a..460759b1e 100644 --- a/community_server/src/Model/Table/TransactionsTable.php +++ b/community_server/src/Model/Table/TransactionsTable.php @@ -188,20 +188,28 @@ class TransactionsTable extends Table if($prev && $decay == true) { if($prev->balance > 0) { - $current = $su_transaction; + $current = $su_transaction; $calculated_decay = $stateBalancesTable->calculateDecay($prev->balance, $prev->balance_date, $current->balance_date, true); - $balance = floatval($prev->balance - $calculated_decay['balance']); + $balance = floatval($prev->balance - $calculated_decay['balance']); - // skip small decays (smaller than 0,00 GDD) - if(abs($balance) >= 100) { - $final_transaction['decay'] = [ - 'balance' => $balance, - 'decay_duration' => $calculated_decay['interval']->format('%a days, %H hours, %I minutes, %S seconds') - ]; + if($balance) + { + $final_transactions['decay'] = [ + 'balance' => $balance, + 'decay_duration' => $calculated_decay['interval']->format('%a days, %H hours, %I minutes, %S seconds') + ]; } } } - + + // sender or receiver when user has sended money + // group name if creation + // type: gesendet / empfangen / geschöpft + // transaktion nr / id + // date + // balance + $transaction = $transaction_indiced[$su_transaction->transaction_id]; + if($su_transaction->transaction_type_id == 1) { // creation $creation = $transaction->transaction_creation; $balance = $stateBalancesTable->calculateDecay($creation->amount, $creation->target_date, $transaction->received); diff --git a/community_server/src/Model/Transactions/Transaction.php b/community_server/src/Model/Transactions/Transaction.php index 40be13cd3..810f20c9d 100644 --- a/community_server/src/Model/Transactions/Transaction.php +++ b/community_server/src/Model/Transactions/Transaction.php @@ -25,7 +25,7 @@ class Transaction extends TransactionBase { //$transactionBin = base64_decode($base64Data, true); //if($transactionBin == false) { //sodium_base64_VARIANT_URLSAFE_NO_PADDING - if(is_a($base64Data, '\Proto\Gradido\Transaction')) { + if(is_a($base64Data, '\Proto\Gradido\GradidoTransaction')) { $this->mProtoTransaction = $base64Data; $this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes()); return; @@ -93,7 +93,11 @@ class Transaction extends TransactionBase { return $this->mTransactionBody; } - public function getFirstPublic() { + public function getFirstPublic() + { + if(!$this->mProtoTransaction || !$this->mProtoTransaction->getSigMap()) { + return ''; + } $sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair(); return $sigPairs[0]->getPubKey(); } @@ -111,6 +115,7 @@ class Transaction extends TransactionBase { $sigMap = $this->mProtoTransaction->getSigMap(); if(!$sigMap) { $this->addError('Transaction', 'signature map is zero'); + //var_dump($this->mProtoTransaction); return false; } //var_dump($sigMap); @@ -193,8 +198,10 @@ class Transaction extends TransactionBase { $connection->commit(); - $this->mTransactionBody->getSpecificTransaction()->sendNotificationEmail($this->mTransactionBody->getMemo()); + $specificTransaction = $this->mTransactionBody->getSpecificTransaction(); + $specificTransaction->sendNotificationEmail($this->mTransactionBody->getMemo()); + $this->addWarnings($specificTransaction->getWarnings()); return true; } diff --git a/community_server/src/Model/Transactions/TransactionBase.php b/community_server/src/Model/Transactions/TransactionBase.php index 607903d8d..6b3817201 100644 --- a/community_server/src/Model/Transactions/TransactionBase.php +++ b/community_server/src/Model/Transactions/TransactionBase.php @@ -6,29 +6,43 @@ use Cake\ORM\TableRegistry; class TransactionBase { private $errors = []; + private $warnings = []; static $tables = []; public function getErrors() { - return $this->errors; + return $this->errors; + } + + public function getWarnings() { + return $this->warnings; } - public function addError($functionName, $errorName) { - array_push($this->errors, [$functionName => $errorName]); + array_push($this->errors, [$functionName => $errorName]); + } + public function addWarning($functionName, $warningName) { + array_push($this->warnings, [$functionName => $warningName]); } public function addErrors($errors) { - $this->errors = array_merge($this->errors, $errors); + $this->errors = array_merge($this->errors, $errors); + } + + public function addWarnings($warnings) { + $this->warnings = array_merge($this->warnings, $warnings); } public function hasErrors() { - return count($this->errors) > 0; + return count($this->errors) > 0; } + public function hasWarnings() { + return count($this->warnings) > 0; + } public static function getTable($tableName) { - if(!isset(self::$tables[$tableName])) { - self::$tables[$tableName] = TableRegistry::getTableLocator()->get($tableName); - } - return self::$tables[$tableName]; + if(!isset(self::$tables[$tableName])) { + self::$tables[$tableName] = TableRegistry::getTableLocator()->get($tableName); + } + return self::$tables[$tableName]; } diff --git a/community_server/src/Model/Transactions/TransactionCreation.php b/community_server/src/Model/Transactions/TransactionCreation.php index f9b3c7657..9150d24eb 100644 --- a/community_server/src/Model/Transactions/TransactionCreation.php +++ b/community_server/src/Model/Transactions/TransactionCreation.php @@ -209,6 +209,7 @@ class TransactionCreation extends TransactionBase { ->send(); } catch(Exception $e) { // $this->addError('TransactionCreation::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage()); + $this->addWarning('TransactionCreation::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage()); return false; } return true; diff --git a/community_server/src/Model/Transactions/TransactionTransfer.php b/community_server/src/Model/Transactions/TransactionTransfer.php index 4f3f4e88c..dc1606f55 100644 --- a/community_server/src/Model/Transactions/TransactionTransfer.php +++ b/community_server/src/Model/Transactions/TransactionTransfer.php @@ -58,7 +58,7 @@ class TransactionTransfer extends TransactionBase { //$this->addError('TransactionTransfer::validate', 'not implemented yet'); //return false; //$time = microtime(true); - static $functionName = 'TransactionCreation::validate'; + static $functionName = 'TransactionTransfer::validate'; $sigPubHexs = []; foreach($sigPairs as $sigPair) @@ -204,13 +204,14 @@ class TransactionTransfer extends TransactionBase { $this->addError('TransactionCreation::sendNotificationEmail', 'to email is empty for user: ' . $receiverUser->id); return false; } - $email->setFrom([$serverAdminEmail => $senderUser->getNames() . ' via Gradido Community']) + $noReplyEmail = Configure::read('noReplyEmail'); + $email->setFrom([$noReplyEmail => 'Gradido (nicht antworten)']) ->setTo([$receiverUser->email => $receiverUser->getNames()]) - ->setReplyTo($senderUser->email) ->setSubject(__('Gradidos erhalten')) ->send(); } catch(Exception $e) { //$this->addError('TransactionTransfer::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage()); + $this->addWarning('TransactionTransfer::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage()); return false; } return true; diff --git a/community_server/src/Template/Email/text/notification_transfer.ctp b/community_server/src/Template/Email/text/notification_transfer.ctp index 2cc692e02..155304c2c 100644 --- a/community_server/src/Template/Email/text/notification_transfer.ctp +++ b/community_server/src/Template/Email/text/notification_transfer.ctp @@ -15,7 +15,7 @@ $senderNames = $senderUser->first_name . ' ' . $senderUser->last_name; - + Gradido Community Server \ No newline at end of file diff --git a/community_server/src/Template/Transactions/manual_transaction.ctp b/community_server/src/Template/Transactions/manual_transaction.ctp new file mode 100644 index 000000000..30bda1175 --- /dev/null +++ b/community_server/src/Template/Transactions/manual_transaction.ctp @@ -0,0 +1,63 @@ +loadHelper('Form', [ + 'templates' => 'horizontal_form', +]); +$now = new \DateTime; +?> + 0) : ?> +
+ +
+ + +
+

+
+ Form->create() ?> + Form->control('type', ['type' => 'hidden', 'value' => 'creation']) ?> + Form->control('target_public_key', ['type'=> 'text']) ?> + Form->control('target_date', ['type'=> 'text', 'placeholder' => 'yyyy-mm-dd hh:ii:ss', 'default' => $now->format('Y-m-d H:i:s')]) ?> + Form->control('amount', ['type'=> 'number']) ?> + Form->control('memo', ['type'=> 'textarea', 'rows' => '8', 'cols' => 40]) ?> + Form->control('signer_public_key', ['type' => 'text']) ?> + Form->control('signer_private_key', ['type'=> 'text']) ?> + Form->submit(); ?> + Form->end() ?> +
+
+
+

+
+ Form->create() ?> + Form->control('type', ['type' => 'hidden', 'value' => 'transfer']) ?> + Form->control('sender_public_key', ['type'=> 'text']) ?> + Form->control('receiver_public_key', ['type'=> 'text']) ?> + Form->control('amount', ['type'=> 'number']) ?> + Form->control('memo', ['type'=> 'textarea', 'rows' => '8', 'cols' => 40]) ?> + Form->control('signer_public_key', ['type' => 'text']) ?> + Form->control('signer_private_key', ['type'=> 'text']) ?> + Form->submit(); ?> + Form->end() ?> +
+
+ +
+ +
+ \ No newline at end of file diff --git a/community_server/tests/Fixture/CommunityProfilesFixture.php b/community_server/tests/Fixture/CommunityProfilesFixture.php index 1259d6e25..0fa7ed764 100644 --- a/community_server/tests/Fixture/CommunityProfilesFixture.php +++ b/community_server/tests/Fixture/CommunityProfilesFixture.php @@ -23,8 +23,7 @@ class CommunityProfilesFixture extends TestFixture 'state_user_id' => ['type' => 'index', 'columns' => ['state_user_id'], 'length' => []], ], '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], - 'community_profiles_ibfk_1' => ['type' => 'foreign', 'columns' => ['state_user_id'], 'references' => ['state_users', 'id'], 'update' => 'restrict', 'delete' => 'restrict', 'length' => []], + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []] ], '_options' => [ 'engine' => 'InnoDB', diff --git a/community_server/tests/Fixture/Migrations2Fixture.php b/community_server/tests/Fixture/Migrations2Fixture.php new file mode 100644 index 000000000..c8608cd18 --- /dev/null +++ b/community_server/tests/Fixture/Migrations2Fixture.php @@ -0,0 +1,45 @@ + ['type' => 'integer', 'length' => 10, 'unsigned' => true, 'null' => false, 'default' => null, 'comment' => '', 'autoIncrement' => true, 'precision' => null], + 'db_version' => ['type' => 'integer', 'length' => 11, 'unsigned' => false, 'null' => true, 'default' => '0', 'comment' => '', 'precision' => null, 'autoIncrement' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8mb4_unicode_ci' + ], + ]; + // @codingStandardsIgnoreEnd + /** + * Init method + * + * @return void + */ + public function init() + { + $this->table = "migrations"; + $this->records = [ + [ + 'id' => 1, + 'db_version' => 2, + ], + ]; + parent::init(); + } +} diff --git a/community_server/tests/Fixture/StateBalancesFixture.php b/community_server/tests/Fixture/StateBalancesFixture.php index f4a6fd7fc..015366c80 100644 --- a/community_server/tests/Fixture/StateBalancesFixture.php +++ b/community_server/tests/Fixture/StateBalancesFixture.php @@ -6,7 +6,7 @@ use Cake\TestSuite\Fixture\TestFixture; /** * StateBalancesFixture */ -class StateBalancesFixture extends TestFixture +class StateBalancesFixture extends BaseTestFixture { /** * Fields @@ -36,8 +36,11 @@ class StateBalancesFixture extends TestFixture */ public function init() { - $this->records = [ + $sql = [ + [4, 4, '2021-05-27 17:47:50', '2021-05-27 17:47:50', 28808497], + [5, 1, '2021-05-27 17:47:51', '2021-05-27 17:47:50', 9823963] ]; + $this->records = $this->sqlEntrysToRecords($sql, $this->fields); parent::init(); } } diff --git a/community_server/tests/Fixture/TransactionCreationsFixture.php b/community_server/tests/Fixture/TransactionCreationsFixture.php index 1833385b4..4221e8729 100644 --- a/community_server/tests/Fixture/TransactionCreationsFixture.php +++ b/community_server/tests/Fixture/TransactionCreationsFixture.php @@ -1,8 +1,6 @@ ['type' => 'integer', 'length' => 10, 'unsigned' => true, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null], 'state_user_id' => ['type' => 'integer', 'length' => 10, 'unsigned' => true, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null], 'amount' => ['type' => 'biginteger', 'length' => 20, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null], - 'ident_hash' => ['type' => 'binary', 'length' => 32, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], 'target_date' => ['type' => 'timestamp', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], '_constraints' => [ 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], @@ -37,9 +34,9 @@ class TransactionCreationsFixture extends BaseTestFixture */ public function init() { - $sql = [ - [2, 1, 4, 10000000, '0000000000000000000000000000000000000000000000000000000000000000', '2021-01-01 00:00:00'], - [3, 2, 1, 10000000, '0000000000000000000000000000000000000000000000000000000000000000', '2021-01-01 00:00:00'] + $sql = [ + [2, 1, 4, 10000000, '2021-01-01 00:00:00'], + [3, 2, 1, 10000000, '2021-01-01 00:00:00'] ]; $this->records = $this->sqlEntrysToRecords($sql, $this->fields); parent::init(); diff --git a/community_server/tests/TestCase/Controller/AppControllerTest.php b/community_server/tests/TestCase/Controller/AppControllerTest.php deleted file mode 100644 index 502ed46da..000000000 --- a/community_server/tests/TestCase/Controller/AppControllerTest.php +++ /dev/null @@ -1,46 +0,0 @@ -session(['StateUser.id' => 1]); - $this->get('/'); - $this->assertSession(1200, 'StateUser.balance'); - //$this->markTestIncomplete('Not implemented yet.'); - } - - -} diff --git a/community_server/tests/TestCase/Controller/AppRequestControllerTest.php b/community_server/tests/TestCase/Controller/AppRequestControllerTest.php new file mode 100644 index 000000000..118f25a32 --- /dev/null +++ b/community_server/tests/TestCase/Controller/AppRequestControllerTest.php @@ -0,0 +1,303 @@ +session([ + 'session_id' => $session_id, + 'Transaction' => ['pending' => 0, 'executing' => 0], + 'StateUser' => [ + 'id' => 1, + 'email_checked' => 1, + 'public_hex' => 'f7f4a49a4ac10379f8b9ddcb731c4d9ec495e6edd16075f52672cd25e3179f0f' + ] + ]); + + $response = $this->getAndParseWithoutCompare('/api/get-balance/' . $session_id); + $this->assertEquals('success', $response->state); + $this->assertEquals(9100000, $response->balance); + $this->assertLessThan(9100000, $response->decay); + + } + + public function testGetBalance2() + { + $session_id = rand(); + $this->session([ + 'session_id' => $session_id, + 'Transaction' => ['pending' => 0, 'executing' => 0], + 'StateUser' => [ + 'id' => 3, + 'email_checked' => 1, + 'public_hex' => '131c7f68dd94b2be4c913400ff7ff4cdc03ac2bda99c2d29edcacb3b065c67e6' + ] + ]); + + $response = $this->getAndParseWithoutCompare('/api/get-balance/' . $session_id); + $this->assertEquals('success', $response->state); + $this->assertEquals(0, $response->balance); + } + public function testGetBalance3() + { + $session_id = rand(); + $this->session([ + 'session_id' => $session_id, + 'Transaction' => ['pending' => 0, 'executing' => 0], + 'StateUser' => [ + 'id' => 4, + 'email_checked' => 1, + 'public_hex' => 'e3369de3623ce8446d0424c4013e7a1d71a2671ae3d7bf1e798ebf0665d145f2' + ] + ]); + + $response = $this->getAndParseWithoutCompare('/api/get-balance/' . $session_id); + $this->assertEquals('success', $response->state); + $this->assertEquals(10900000, $response->balance); + $this->assertLessThan(10900000, $response->decay); + } + + public function testGetBalanceInvalidSession() + { + $session_id = rand(); + $this->session([ + 'session_id' => $session_id, + 'Transaction' => ['pending' => 0, 'executing' => 0], + 'StateUser' => [ + 'email_checked' => 1, + 'public_hex' => '8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d' + ] + ]); + + $this->getAndParse('/api/get-balance/' . 1211, + ['state' => 'not found', 'msg' => 'invalid session'] + ); + } + + public function testGetBalanceInvalidSessionId() + { + $session_id = rand(); + $this->session([ + 'session_id' => $session_id, + 'Transaction' => ['pending' => 0, 'executing' => 0], + 'StateUser' => [ + 'email_checked' => 1, + 'public_hex' => '8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d' + ] + ]); + + $this->getAndParse('/api/get-balance/' , + ['state' => 'not found', 'msg' => 'invalid session'] + ); + } + + /** + * Test ajaxListTransactions method + * + * @return void + */ + public function testListTransactions() + { + //ajaxListTransactions + $session_id = rand(); + $this->session([ + 'session_id' => $session_id, + 'Transactions' => ['pending' => 0, 'executing' => 0], + 'StateUser' => [ + 'id' => 1, + 'first_name' => 'Dario', + 'last_name' => 'Frodo', + 'email_checked' => 1, + 'email' => 'fördertest@gradido.org', + 'public_hex' => '94ae135b93cd9f33752b4e55c41903a3faa13a75bb90bfd411ea1d4a1a5e711f' + ] + ]); + //echo "balance: $balance"; + $expectedResult = '{ + "state": "success", + "transactions": [ + { + "name": "Gradido Akademie", + "type": "creation", + "transaction_id": 2, + "date": "2021-04-12T00:00:00+00:00", + "target_date": "2021-01-01T00:00:00+00:00", + "creation_amount": 10000000, + "balance": 10000000, + "memo": "AGE Januar 2021" + }, + { + "name": "Samuel Schmied", + "email": "test3.yahoo.com", + "type": "send", + "transaction_id": 3, + "date": "2021-04-12T00:00:00+00:00", + "balance": 1000000, + "memo": "test", + "pubkey": "e3369de3623ce8446d0424c4013e7a1d71a2671ae3d7bf1e798ebf0665d145f2" + }, + { + "name": "Samuel Schmied", + "email": "test3.yahoo.com", + "type": "send", + "transaction_id": 4, + "date": "2021-04-14T00:00:00+00:00", + "balance": 100000, + "memo": "test time", + "pubkey": "e3369de3623ce8446d0424c4013e7a1d71a2671ae3d7bf1e798ebf0665d145f2" + }, + { + "name": "Samuel Schmied", + "email": "test3.yahoo.com", + "type": "send", + "transaction_id": 5, + "date": "2021-04-14T09:01:07+00:00", + "balance": 100000, + "memo": "test time", + "pubkey": "e3369de3623ce8446d0424c4013e7a1d71a2671ae3d7bf1e798ebf0665d145f2" + }, + { + "name": "Samuel Schmied", + "email": "test3.yahoo.com", + "type": "receive", + "transaction_id": 6, + "date": "2021-04-14T09:02:28+00:00", + "balance": 100000, + "memo": "test time 3", + "pubkey": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "Samuel Schmied", + "email": "test3.yahoo.com", + "type": "receive", + "transaction_id": 7, + "date": "2021-04-14T09:28:46+00:00", + "balance": 100000, + "memo": "test login crash", + "pubkey": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "Samuel Schmied", + "email": "test3.yahoo.com", + "type": "receive", + "transaction_id": 8, + "date": "2021-04-14T09:31:28+00:00", + "balance": 100000, + "memo": "test login crash", + "pubkey": "0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "transactionExecutingCount": 0, + "count": 7, + "gdtSum": 180000, + "timeUsed": 0.5575470924377441, + "decay_date": "2021-05-28T09:35:02+00:00", + "balance": 9100000, + "decay": 9100000 +}'; + $this->getAndParse('/api/list-transactions/', json_decode($expectedResult, true)); + } + + + private function getAndParse($path, $expected) + { + $this->configRequest([ + 'headers' => ['Accept' => 'application/json'] + ]); + + $this->disableErrorHandlerMiddleware(); + $this->get($path); + + // Check that the response was in 2xx - 3xx + $this->assertResponseSuccess(); + $json = (object)$this->viewVariable('body'); + + if(!$json) { + // Check that the response was a 200 + $this->assertResponseOk(); + + $responseBodyString = (string)$this->_response->getBody(); + $json = json_decode($responseBodyString); + $this->assertNotFalse($json); + } else { + $responseBodyString = json_encode($json); + } + + if(is_array($expected)) { + $dynamic_fields = ['timeUsed', 'decay_date', 'decay', 'gdtSum']; + // copy timeUsed because this value will be variy always + foreach($dynamic_fields as $field) { + if(isset($expected[$field]) && isset($json->$field)) { + $expected[$field] = $json->$field; + } + } + $expected = json_encode($expected); + } + + $this->assertEquals($expected, $responseBodyString); + } + private function getAndParseWithoutCompare($path) + { + $this->configRequest([ + 'headers' => ['Accept' => 'application/json'] + ]); + + $this->disableErrorHandlerMiddleware(); + $this->get($path); + + // Check that the response was in 2xx - 3xx + $this->assertResponseSuccess(); + $view_body = $this->viewVariable('body'); + if($view_body) { + return (object)$view_body; + } + // Check that the response was a 200 + $this->assertResponseOk(); + $responseBodyString = (string)$this->_response->getBody(); + $json = json_decode($responseBodyString, true); + $this->assertNotFalse($json); + + return $json; + } +} diff --git a/community_server/tests/TestCase/Controller/Component/JsonRequestClientComponentTest.php b/community_server/tests/TestCase/Controller/Component/JsonRequestClientComponentTest.php index fb882478a..c1ba84ee3 100644 --- a/community_server/tests/TestCase/Controller/Component/JsonRequestClientComponentTest.php +++ b/community_server/tests/TestCase/Controller/Component/JsonRequestClientComponentTest.php @@ -51,19 +51,7 @@ class JsonRequestClientComponentTest extends TestCase $this->markTestIncomplete('Not implemented yet.'); } - /** - * Test getLoginServerUrl method - * - * @return void - */ - public function testGetLoginServerUrl() - { - //$this->markTestIncomplete('Not implemented yet.'); - $serverUrl = $this->JsonRequestClientComponent->getLoginServerUrl(); - $this->assertEquals($serverUrl, 'http://***REMOVED***'); - } - - /** + /** * Test is_base64 method * * @return void diff --git a/community_server/tests/TestCase/Controller/JsonRequestHandlerControllerTest.php b/community_server/tests/TestCase/Controller/JsonRequestHandlerControllerTest.php index d8a241d7d..f990b3e57 100644 --- a/community_server/tests/TestCase/Controller/JsonRequestHandlerControllerTest.php +++ b/community_server/tests/TestCase/Controller/JsonRequestHandlerControllerTest.php @@ -5,9 +5,9 @@ use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; /** - * App\Controller\TransactionJsonRequestHandlerController Test Case + * App\Controller\JsonRequestHandlerController Test Case * - * @uses \App\Controller\TransactionJsonRequestHandlerController + * @uses \App\Controller\JsonRequestHandlerController */ class JsonRequestHandlerControllerTest extends TestCase { @@ -22,6 +22,7 @@ class JsonRequestHandlerControllerTest extends TestCase 'app.TransactionCreations', 'app.Transactions', 'app.StateUsers', + 'app.StateUserTransactions', 'app.StateErrors', 'app.TransactionSignatures', 'app.TransactionSendCoins', @@ -30,13 +31,12 @@ class JsonRequestHandlerControllerTest extends TestCase ]; public $transactions = [ - 'validCreation' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQJ8wF12eZo3hcMAlAKKJ9WLT-zuSkNmGh7D98UEqH4KoIysnCkXqEya9EBZl9o11_nJ8xmm_nOevuVjR-GfLMQ8qSQoOSGFsbG8gV2VsdCAxMjMSBgiZm4ruBUovCicKIJSuE1uTzZ8zdStOVcQZA6P6oTp1u5C_1BHqHUoaXnEfEKDakwEQtYntlgo', - 'validCreation900' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQNVZ8Ae3Zbg3G0wZ840fzKan6N4KtTcSe0KYi17kQwFmsl18oFxXv8_s6j1xXFrIKjy1_1Olq0a7xYLErDMkjwYqORIGCNb5iu4FSi8KJwoglK4TW5PNnzN1K05VxBkDo_qhOnW7kL_UEeodShpecR8QgNHKCBC1ie2WCg', - 'validCreation1200' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQEEey5QMAdldoOTP_jTETHgOQriGsixEY0cziQeRfT_J5YtbI_A6AizEYD-JcxmRmXzv1xjjTgsV39Y32ta2CQkqORIGCIeGi-4FSi8KJwoglK4TW5PNnzN1K05VxBkDo_qhOnW7kL_UEeodShpecR8QgOy4CxC1ie2WCg', + 'validCreation' => 'CmYKZAog4zad42I86ERtBCTEAT56HXGiZxrj178eeY6_BmXRRfISQDnatUMvitiiP0-sY93JStYPhPKKPU4Vosv_EGrh77BVs48xhPgPj2QHWC3oyuuMh6nN8YNjBQZx20rKvdQ4uwMSRwoMQUdFIE1haSAyMDIxEgYI_c3ChQY6LwolCiD39KSaSsEDefi53ctzHE2exJXm7dFgdfUmcs0l4xefDxDQDxoGCPqbtIQG', + 'validCreation900' => 'CmYKZAog9_SkmkrBA3n4ud3LcxxNnsSV5u3RYHX1JnLNJeMXnw8SQCaZHmvmvJOt336E3qst3rn1pptdAR5ZPzePaUT10x0_Yky8FnEiQtMGNy1yT94QErzwQudJZjJwDY2uyK4cTgkSOxIGCKb1vYUGOjEKJwog4zad42I86ERtBCTEAT56HXGiZxrj178eeY6_BmXRRfIQgNHKCBoGCIDMuf8F', + 'validCreation1200' => 'CmYKZAog9_SkmkrBA3n4ud3LcxxNnsSV5u3RYHX1JnLNJeMXnw8SQF8jptIrosEyVmCf3WEIGVOK0NR8YCcO0j-s8v2yUyR5BKus0ciT6B7IA5LDtn7eQX6zHjg1v5WlsTiZuOpuNgwSRAoHVG8gbXVjaBIGCL3Jv4UGOjEKJwog4zad42I86ERtBCTEAT56HXGiZxrj178eeY6_BmXRRfIQgOy4CxoGCOG5toQG', 'notBase64' => 'CgpIYWxsbyBXZW-0EgYIyfSG7gV_LwonCiCboKikqwjZfes9xuqgthFH3', - 'validTransfer' => 'GmYKZAoggZC9pYXuXx2fv30G6B5p7BjhM3YQTP9Ut0V-t9PvcQ0SQDddHyKzAX3LBV0PuDiPc6lxkUipss5tyuLRpMtFJQnT30tsbYIkA1FXimjMKOoiuLswf4OLLV3bAIYehW-b9AgqYQoFSGFsbG8SBgiJlaPvBUJQCiYKIIGQvaWF7l8dn799BugeaewY4TN2EEz_VLdFfrfT73ENEICfSRImCiDtdleSLxhUgEbMW9DpqIwsykFj3-z_enKEOuGnXrmW8xCAn0k', - 'errornusTransfer' => 'ClxGcm9oZXMgTmV1ZXMgSmFociB1bmQgREFOS0UsIGRhc3MgZHUgZGljaCBzbyBlaW5zZXR6dCBmw7xyIEdyYWRpZG8hIEhlcnpsaWNoZSBHcsO8w59lIFRlcmVzYRIGCPjjgvEFQlAKJgogUQwFYeVlGlfWDrkXNN7rHwejoCDJKt+YkYJfbJVyj3EQwIQ9EiYKIPXIRnUhVJ/zCs5+y/VaTBjTIoYizJNwS+JC//xsbQrHEMCEPQ==', - 'creationValid' => 'GmYKZAogLtKKHPXhFtg2FUBrxXcVIiHC93SlZW9moOdUD3V21xsSQHpXYAGiVmSfhjB3o7OPx0ZJuPXrDk5eu1_AOhQBODU3KpUqBRA9yMX54S_mvGijGubCNRcMLcm7wiYbyAG-3AkqSwoQZWluIE1vbmF0c2dlaGFsdBIGCKqs5vEFSi8KJwoggZC9pYXuXx2fv30G6B5p7BjhM3YQTP9Ut0V-t9PvcQ0QgNrECRDKyd3uAQ' + 'validTransfer' => 'CmYKZAog9_SkmkrBA3n4ud3LcxxNnsSV5u3RYHX1JnLNJeMXnw8SQA0ZVQ9T1qBabzmgDO1NAWNy2J6mlv0YjMP99CiV7bSR0zemt5XoM-kTviR1aTqKggzpSYSyTN5T6gIx2xa-hgkSYwoLTXkgQmlydGhkYXkSBgie0L-FBjJMCkoKJgog9_SkmkrBA3n4ud3LcxxNnsSV5u3RYHX1JnLNJeMXnw8QgIl6EiDjNp3jYjzoRG0EJMQBPnodcaJnGuPXvx55jr8GZdFF8g', + 'errornusTransfer' => 'ClxGcm9oZXMgTmV1ZXMgSmFociB1bmQgREFOS0UsIGRhc3MgZHUgZGljaCBzbyBlaW5zZXR6dCBmw7xyIEdyYWRpZG8hIEhlcnpsaWNoZSBHcsO8w59lIFRlcmVzYRIGCPjjgvEFQlAKJgogUQwFYeVlGlfWDrkXNN7rHwejoCDJKt+YkYJfbJVyj3EQwIQ9EiYKIPXIRnUhVJ/zCs5+y/VaTBjTIoYizJNwS+JC//xsbQrHEMCEPQ==' ]; /*public function setUp() { @@ -51,7 +51,7 @@ class JsonRequestHandlerControllerTest extends TestCase $this->get('/JsonRequestHandler'); $this->assertResponseOk(); - $expected = json_encode(['state' => 'error', 'msg' => 'no post']); + $expected = json_encode(['state' => 'error', 'msg' => 'unknown method for get', 'details' => null]); $this->assertEquals($expected, (string)$this->_response->getBody()); } @@ -87,7 +87,7 @@ class JsonRequestHandlerControllerTest extends TestCase //$this->post('/TransactionJsonRequestHandler', ['method' => 'putTransaction', 'transaction' => 'CgpIYWxsbyBXZWx0EgYIyfSG7gVKLwonCiCboKikqwjZfes9xuqgthFH3/cHHaWchkUhWiGhQjB23xCg2pMBELWJ7ZYK']); $this->postAndParse( ['method' => 'foobar', 'transaction' => $this->transactions['validCreation']], - ['state' => 'error', 'msg' => 'unknown method', 'details' => 'foobar'] + ['state' => 'error', 'msg' => 'unknown method for post', 'details' => 'foobar'] ); } @@ -97,7 +97,8 @@ class JsonRequestHandlerControllerTest extends TestCase $this->postAndParse( ['method' => 'putTransaction', 'transaction' => $this->transactions['notBase64']], ['state' => 'error', 'msg' => 'error parsing transaction', 'details' => [ - ['Transaction' => 'invalid base64 string'] + ['Transaction' => 'invalid base64 string'], + ['base64' => 'CgpIYWxsbyBXZW-0EgYIyfSG7gV_LwonCiCboKikqwjZfes9xuqgthFH3'] ]] ); } @@ -114,9 +115,10 @@ class JsonRequestHandlerControllerTest extends TestCase public function testToLargeCreationSum() { + $this->postAndParse( ['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation900']], - '{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1000 gr per Month not allowed"}]}' + '{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}' ); } @@ -124,49 +126,36 @@ class JsonRequestHandlerControllerTest extends TestCase { $this->postAndParse( ['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation1200']], - '{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1000 gr per Month not allowed"}]}' + '{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}' ); } public function testValidTransfer() - { - $this->postAndParse( - ['method' => 'putTransaction', 'transaction' => $this->transactions['validTransfer']], - ['state' => 'success'] - ); - } - - /*public function testMissingPreviousTransaction() - { - - }*/ - - public function testValidTransaction() - { - $this->postAndParse( - ['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation']], - ['state' => 'success'] + { + $this->postAndParse( + ['method' => 'putTransaction', 'transaction' => $this->transactions['validTransfer']], + ['state' => 'success'] ); } - + public function testValidCreation() { $this->postAndParse( - ['method' => 'putTransaction', 'transaction' => $this->transactions['creationValid']], + ['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation']], ['state' => 'success'] ); } private function postAndParse($params, $expected) { - //$this->enableCsrfToken(); + $this->enableCsrfToken(); //$this->enableSecurityToken(); - $token = 'my-csrf-token'; - $this->cookie('csrfToken', $token); + //$token = 'my-csrf-token'; + //$this->cookie('csrfToken', $token); $this->configRequest([ - 'headers' => ['Accept' => 'application/json', 'X-CSRF-Token' => $token] + 'headers' => ['Accept' => 'application/json']//, 'X-CSRF-Token' => $token] ]); $this->disableErrorHandlerMiddleware(); diff --git a/community_server/tests/TestCase/Controller/PagesControllerTest.php b/community_server/tests/TestCase/Controller/PagesControllerTest.php index 35fe1a13b..004d7c079 100644 --- a/community_server/tests/TestCase/Controller/PagesControllerTest.php +++ b/community_server/tests/TestCase/Controller/PagesControllerTest.php @@ -27,6 +27,10 @@ use Cake\View\Exception\MissingTemplateException; */ class PagesControllerTest extends IntegrationTestCase { + + public $fixtures = [ + 'app.Migrations2' + ]; /** * testMultipleGet method * @@ -35,9 +39,12 @@ class PagesControllerTest extends IntegrationTestCase public function testMultipleGet() { $this->get('/'); - $this->assertRedirect('account/'); + $locations = $this->_response->getHeader('Location'); + $this->assertRegExp('%.*/account/$%', $locations[0]); + $this->get('/'); - $this->assertRedirect('account/'); + $locations = $this->_response->getHeader('Location'); + $this->assertRegExp('%.*/account/$%', $locations[0]); } /** @@ -64,7 +71,7 @@ class PagesControllerTest extends IntegrationTestCase $this->get('/pages/not_existing'); $this->assertResponseError(); - $this->assertResponseContains('Error'); + $this->assertResponseContains('Not Found'); } /** @@ -78,8 +85,7 @@ class PagesControllerTest extends IntegrationTestCase $this->get('/pages/not_existing'); $this->assertResponseFailure(); - $this->assertResponseContains('Missing Template'); - $this->assertResponseContains('Stacktrace'); + $this->assertResponseContains('Template file \u0022Pages\/not_existing.ctp\u0022 is missing.'); $this->assertResponseContains('not_existing.ctp'); } diff --git a/community_server/tests/TestCase/Controller/StateBalancesControllerTest.php b/community_server/tests/TestCase/Controller/StateBalancesControllerTest.php index cfa6bebc4..9ef8d28e9 100644 --- a/community_server/tests/TestCase/Controller/StateBalancesControllerTest.php +++ b/community_server/tests/TestCase/Controller/StateBalancesControllerTest.php @@ -69,142 +69,7 @@ class StateBalancesControllerTest extends TestCase $this->markTestIncomplete('Not implemented yet.'); } - /** - * Test ajaxGetBalance method - * - * @return void - */ - public function testAjaxGetBalance1() - { - $session_id = rand(); - $this->session([ - 'session_id' => $session_id, - 'Transaction' => ['pending' => 0, 'executing' => 0], - 'StateUser' => [ - 'id' => 1, - 'email_checked' => 1, - 'public_hex' => 'f7f4a49a4ac10379f8b9ddcb731c4d9ec495e6edd16075f52672cd25e3179f0f' - ] - ]); - - $response = $this->getAndParseWithoutCompare('/state-balances/ajaxGetBalance/' . $session_id); - - $this->assertEquals('success', $response->state); - $this->assertEquals(7321825, $response->balance); - $this->assertLessThan(7321825, $response->decay); - - } - public function testAjaxGetBalance2() - { - $session_id = rand(); - $this->session([ - 'session_id' => $session_id, - 'Transaction' => ['pending' => 0, 'executing' => 0], - 'StateUser' => [ - 'id' => 3, - 'email_checked' => 1, - 'public_hex' => '131c7f68dd94b2be4c913400ff7ff4cdc03ac2bda99c2d29edcacb3b065c67e6' - ] - ]); - - $response = $this->getAndParseWithoutCompare('/state-balances/ajaxGetBalance/' . $session_id); - $this->assertEquals('success', $response->state); - $this->assertEquals(0, $response->balance); - } - public function testAjaxGetBalance3() - { - $session_id = rand(); - $this->session([ - 'session_id' => $session_id, - 'Transaction' => ['pending' => 0, 'executing' => 0], - 'StateUser' => [ - 'id' => 4, - 'email_checked' => 1, - 'public_hex' => 'e3369de3623ce8446d0424c4013e7a1d71a2671ae3d7bf1e798ebf0665d145f2' - ] - ]); - - $response = $this->getAndParseWithoutCompare('/state-balances/ajaxGetBalance/' . $session_id); - $this->assertEquals('success', $response->state); - $this->assertEquals(9112592, $response->balance); - $this->assertLessThan(9112592, $response->decay); - } - - 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'] - ); - } - - /** - * Test ajaxListTransactions method - * - * @return void - */ - public function testAjaxListTransactions() - { - //ajaxListTransactions - $session_id = rand(); - $this->session([ - 'session_id' => $session_id, - 'Transaction' => ['pending' => 0, 'executing' => 0], - 'StateUser' => [ - 'id' => 1, - 'first_name' => 'Dario', - 'last_name' => 'Frodo', - 'email_checked' => 1, - 'email' => 'fördertest@gradido.org', - 'public_hex' => '94ae135b93cd9f33752b4e55c41903a3faa13a75bb90bfd411ea1d4a1a5e711f' - ] - ]); - //echo "balance: $balance"; - $this->getAndParse('/state-balances/ajaxListTransactions/' . $session_id, - [ - 'state' => 'success', 'transactions' => [[ - 'name' => 'Dario Frodo', - 'email'=> 'dariofrodo@gmx.de', - 'type'=> '', - 'transaction_id' => 4, - 'date' => '2021-02-19T13:27:14+00:00', - 'balance' => 150000001, - 'memo' => '' - ]], - 'transactionExecutingCount' => 0, - 'count' => 1, - 'gdtSum' => 0, - 'timeUsed' => 0.03168010711669922 - ] - ); - } /** * Test overviewGdt method diff --git a/community_server/tests/TestCase/Controller/TransactionJsonRequestHandlerControllerTest.php b/community_server/tests/TestCase/Controller/TransactionJsonRequestHandlerControllerTest.php deleted file mode 100644 index 7ad28760c..000000000 --- a/community_server/tests/TestCase/Controller/TransactionJsonRequestHandlerControllerTest.php +++ /dev/null @@ -1,174 +0,0 @@ - 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQJ8wF12eZo3hcMAlAKKJ9WLT-zuSkNmGh7D98UEqH4KoIysnCkXqEya9EBZl9o11_nJ8xmm_nOevuVjR-GfLMQ8qSQoOSGFsbG8gV2VsdCAxMjMSBgiZm4ruBUovCicKIJSuE1uTzZ8zdStOVcQZA6P6oTp1u5C_1BHqHUoaXnEfEKDakwEQtYntlgo', - 'validCreation900' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQNVZ8Ae3Zbg3G0wZ840fzKan6N4KtTcSe0KYi17kQwFmsl18oFxXv8_s6j1xXFrIKjy1_1Olq0a7xYLErDMkjwYqORIGCNb5iu4FSi8KJwoglK4TW5PNnzN1K05VxBkDo_qhOnW7kL_UEeodShpecR8QgNHKCBC1ie2WCg', - 'validCreation1200' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQEEey5QMAdldoOTP_jTETHgOQriGsixEY0cziQeRfT_J5YtbI_A6AizEYD-JcxmRmXzv1xjjTgsV39Y32ta2CQkqORIGCIeGi-4FSi8KJwoglK4TW5PNnzN1K05VxBkDo_qhOnW7kL_UEeodShpecR8QgOy4CxC1ie2WCg', - 'notBase64' => 'CgpIYWxsbyBXZW-0EgYIyfSG7gV_LwonCiCboKikqwjZfes9xuqgthFH3', - 'validTransfer' => 'GmYKZAoggZC9pYXuXx2fv30G6B5p7BjhM3YQTP9Ut0V-t9PvcQ0SQDddHyKzAX3LBV0PuDiPc6lxkUipss5tyuLRpMtFJQnT30tsbYIkA1FXimjMKOoiuLswf4OLLV3bAIYehW-b9AgqYQoFSGFsbG8SBgiJlaPvBUJQCiYKIIGQvaWF7l8dn799BugeaewY4TN2EEz_VLdFfrfT73ENEICfSRImCiDtdleSLxhUgEbMW9DpqIwsykFj3-z_enKEOuGnXrmW8xCAn0k', - 'errornusTransfer' => 'ClxGcm9oZXMgTmV1ZXMgSmFociB1bmQgREFOS0UsIGRhc3MgZHUgZGljaCBzbyBlaW5zZXR6dCBmw7xyIEdyYWRpZG8hIEhlcnpsaWNoZSBHcsO8w59lIFRlcmVzYRIGCPjjgvEFQlAKJgogUQwFYeVlGlfWDrkXNN7rHwejoCDJKt+YkYJfbJVyj3EQwIQ9EiYKIPXIRnUhVJ/zCs5+y/VaTBjTIoYizJNwS+JC//xsbQrHEMCEPQ==' - ]; - - /*public function setUp() { - parent::setUp(); - } -*/ - public function testWrongMethod() - { - $this->configRequest([ - 'headers' => ['Accept' => 'application/json'] - ]); - $this->get('/TransactionJsonRequestHandler'); - $this->assertResponseOk(); - - $expected = json_encode(['state' => 'error', 'msg' => 'no post']); - $this->assertEquals($expected, (string)$this->_response->getBody()); - } - - public function testInvalidJson() - { - $this->configRequest([ - 'headers' => ['Accept' => 'application/json'] - ]); - $this->post('/TransactionJsonRequestHandler', '{This isn\'t valid json}'); - $this->assertResponseOk(); - - $expected = json_encode(['state' => 'error', 'msg' => 'parameter error']); - $this->assertEquals($expected, (string)$this->_response->getBody()); - } - - public function testNotSetTransaction() - { - $this->postAndParse( - ['method' => 'putTransaction'], - ['state' => 'error', 'msg' => 'parameter error'] - ); - } - public function testNotSetMethod() - { - $this->postAndParse( - ['transaction' => $this->transactions['validCreation']], - ['state' => 'error', 'msg' => 'parameter error'] - ); - } - - public function testUnknownMethod() - { - //$this->post('/TransactionJsonRequestHandler', ['method' => 'putTransaction', 'transaction' => 'CgpIYWxsbyBXZWx0EgYIyfSG7gVKLwonCiCboKikqwjZfes9xuqgthFH3/cHHaWchkUhWiGhQjB23xCg2pMBELWJ7ZYK']); - $this->postAndParse( - ['method' => 'foobar', 'transaction' => $this->transactions['validCreation']], - ['state' => 'error', 'msg' => 'unknown method', 'details' => 'foobar'] - ); - - } - - public function testInvalidEncodedTransaction() { - //"msg":"error parsing transaction","details":[{"Transaction":"base64 decode error"}] - $this->postAndParse( - ['method' => 'putTransaction', 'transaction' => $this->transactions['notBase64']], - ['state' => 'error', 'msg' => 'error parsing transaction', 'details' => [ - ['Transaction' => 'invalid base64 string'] - ]] - ); - } - - public function testInvalidTransaction() { - - $this->postAndParse( - ['method' => 'putTransaction', 'transaction' => base64_encode('Hallo Miau Welt')], - ['state' => 'error', 'msg' => 'error parsing transaction', 'details' => [ - ['Transaction' => 'Error occurred during parsing: Unexpected wire type.'] - ]] - ); - } - - public function testToLargeCreationSum() - { - $this->postAndParse( - ['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation900']], - '{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1000 gr per Month not allowed"}]}' - ); - } - - public function testToLargeCreation() - { - $this->postAndParse( - ['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation1200']], - '{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1000 gr per Month not allowed"}]}' - ); - } - - public function testValidTransfer() - { - $this->postAndParse( - ['method' => 'putTransaction', 'transaction' => $this->transactions['validTransfer']], - ['state' => 'success'] - ); - } - - /*public function testMissingPreviousTransaction() - { - - }*/ - - public function testValidTransaction() - { - $this->postAndParse( - ['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation']], - ['state' => 'success'] - ); - } - - private function postAndParse($params, $expected) - { - - $this->configRequest([ - 'headers' => ['Accept' => 'application/json'] - ]); - - $this->disableErrorHandlerMiddleware(); - $this->post('/TransactionJsonRequestHandler', json_encode($params)); - - // Check that the response was a 200 - $this->assertResponseOk(); - - $responseBodyString = (string)$this->_response->getBody(); - $json = json_decode($responseBodyString); - $this->assertNotFalse($json); - - if(is_array($expected)) { - $expected = json_encode($expected); - } - $this->assertEquals($expected, $responseBodyString); - } -} diff --git a/community_server/tests/TestCase/Model/Entity/TableTest.php b/community_server/tests/TestCase/Model/Entity/TableTest.php deleted file mode 100644 index 5a189942a..000000000 --- a/community_server/tests/TestCase/Model/Entity/TableTest.php +++ /dev/null @@ -1,51 +0,0 @@ -Table = new Table(); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - unset($this->Table); - - parent::tearDown(); - } - - /** - * Test initial setup - * - * @return void - */ - public function testInitialization() - { - $this->markTestIncomplete('Not implemented yet.'); - } -} diff --git a/community_server/tests/TestCase/Model/Transactions/TransactionCreationTest.php b/community_server/tests/TestCase/Model/Transactions/TransactionCreationTest.php index 60a6307ed..e53549a42 100644 --- a/community_server/tests/TestCase/Model/Transactions/TransactionCreationTest.php +++ b/community_server/tests/TestCase/Model/Transactions/TransactionCreationTest.php @@ -30,84 +30,12 @@ class TransactionCreationTest extends TestCase parent::setUp(); } - - public function testHashingFunction() + public function testDummy() { - $pairs = [ - "a" => 97, - "b" => 98, - "c" => 99, - "d" => 100, - "aa" => 12513, - "ab" => 12514, - "@" => 64, - ".d" => 5988, - "gmx" => 1701624, - "@gmx" => 135919352, - "@gmx.de" => 3742152099, - "***REMOVED***" => 2928827813, - "***REMOVED***" => 1899591683, - "***REMOVED***" => 2089074830, - "maximilian.muster@gradido.net" => 793144931, - "coin-info5@gradido.net" => 1829129963, - "coin-info6@gradido.net" => 1830178539, - "coin-info8@gradido.net" => 1832275691, - "coin-info9@gradido.net" => 1833324267, - "coin-info10@gradido.net" => 3877298078, - "coin-info11@gradido.net" => 3878346654, - "coin-info12@gradido.net" => 3879395230, - "***REMOVED***" => 2089074830, - "***REMOVED***" => 3996757473, - "***REMOVED***" => 3788634614, - "***REMOVED***" => 807797884, - "***REMOVED***" => 1640973721, - "***REMOVED***" => 2025729173, - "***REMOVED***" => 1961122507, - "***REMOVED***" => 362466358, - "***REMOVED***" => 3796728871, - "***REMOVED***" => 807797884, - "***REMOVED***" => 3794905967, - "***REMOVED***" => 3077694284, - "***REMOVED***" => 3246159770, - "***REMOVED***" => 3123402690, - "testneu-11-12-3@gradido.net" => 4092403827, - "***REMOVED***" => 3151414199, - "***REMOVED***" => 3526188273, - "***REMOVED***" => 966804823, - "***REMOVED***" => 1309273258, - "***REMOVED***" => 995978784, - "***REMOVED***" => 310113324, - "***REMOVED***" => 1309273258, - "***REMOVED***" => 530108573, - "***REMOVED***" => 1734855679, - "***REMOVED***" => 767779182, - "***REMOVED***" => 2247491519, - "***REMOVED***" => 3248626267, - "***REMOVED***" => 3516649930, - "***REMOVED***" => 231214190, - "***REMOVED***" => 4247461928, - "***REMOVED***" => 324829839, - "***REMOVED***" => 3046147747, - "***REMOVED***" => 3207307415, - "***REMOVED***" => 728893500, - "***REMOVED***" => 3905254663, - "***REMOVED***" => 3207307415, - "***REMOVED***" => 1155733239, - "***REMOVED***" => 2013046423, - "***REMOVED***" => 4033835283, - "***REMOVED***" => 1945541625, - "***REMOVED***" => 2310715309, - "***REMOVED***" => 1221362064, - "***REMOVED***" => 4161339877 - ]; - foreach($pairs as $email => $cpp_hash) { - $php_hash = TransactionCreation::DRMakeStringHash($email); - // assertEquals(mixed $expected, mixed $actual[, string $message = '']) - if($php_hash != $cpp_hash) { - $this->assertEquals($cpp_hash, $php_hash, "hashes for $email don't match"); - } - } + $this->assertEquals(true, true); } + + } diff --git a/configs/community_server/app.php b/configs/community_server/app.php index f0cf46220..5acd4ce51 100644 --- a/configs/community_server/app.php +++ b/configs/community_server/app.php @@ -214,9 +214,8 @@ return [ 'timeout' => 30, 'username' => null, 'password' => null, - 'client' => null, - 'tls' => null, - 'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null), + 'className' => 'Smtp', + 'tls' => true ], ], @@ -304,11 +303,11 @@ return [ 'className' => Connection::class, 'driver' => Mysql::class, 'persistent' => false, - 'host' => 'localhost', + 'host' => 'mariadb', //'port' => 'non_standard_port_number', - 'username' => 'my_app', - 'password' => 'secret', - 'database' => 'test_myapp', + 'username' => 'root', + 'password' => '', + 'database' => 'gradido_community_test', //'encoding' => 'utf8mb4', 'timezone' => 'UTC', 'cacheMetadata' => true, diff --git a/configs/login_server/grd_login_test.properties b/configs/login_server/grd_login_test.properties new file mode 100644 index 000000000..8a269694a --- /dev/null +++ b/configs/login_server/grd_login_test.properties @@ -0,0 +1,57 @@ +HTTPServer.port = 1200 +JSONServer.port = 1201 +Gradido.group_id = 1 + +crypto.server_admin_public = f909a866baec97c5460b8d7a93b72d3d4d20cc45d9f15d78bd83944eb9286b7f +crypto.server_key = a51ef8ac7ef1abf162fb7a65261acd7a +# TODO auto-generate in docker build step +crypto.app_secret = 21ffbbc616fe + +# Server admin Passphrase +# nerve execute merit pool talk hockey basic win cargo spin disagree ethics swear price purchase say clutch decrease slow half forest reform cheese able +# + +phpServer.url = http://localhost/ +phpServer.host = nginx + +loginServer.path = http://localhost/account +loginServer.default_locale = de +loginServer.db.host = mariadb +loginServer.db.name = gradido_login_test +loginServer.db.user = root +loginServer.db.password = +loginServer.db.port = 3306 + +frontend.checkEmailPath = http://localhost/reset + +email.disable = true + +#email.username = +#email.sender = +#email.admin_receiver = +#email.password = +#email.smtp.url = +#email.smtp.port = + +# binary is default, for debugging also json is possible +#hedera.consensus.message_format = json +# TESTNET or MAINNET, TESTNET is default +hedera.nettype = TESTNET + +# server setup types: test, staging or production +ServerSetupType=test +dev.default_group = docker + + +# Session timeout in minutes +# +session.timeout = 15 + +# Disabling security features for faster develop and testing +unsecure.allow_passwort_via_json_request = 1 +unsecure.allow_auto_sign_transactions = 1 +unsecure.allow_cors_all = 1 +# default disable, passwords must contain a number, a lower character, a high character, special character, and be at least 8 characters long + +unsecure.allow_all_passwords = 1 + diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 0e059140f..1060002ba 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -38,7 +38,7 @@ services: - ./login_server/dependencies:/code/dependencies - ./login_server/scripts:/code/scripts - ./configs/login_server:/etc/grd_login - - login_build_3:/code/build + - login_build_3.1:/code/build ######################################################### @@ -47,11 +47,8 @@ services: community-server: build: context: . + target: community_server dockerfile: ./community_server/Dockerfile - environment: - - DB_PASSWORD='' - - DB_USER='root' - - DB_DATABASE='gradido_community' depends_on: - mariadb networks: @@ -103,4 +100,4 @@ services: volumes: frontend_node_modules: - login_build_3: + login_build_3.1: diff --git a/docker-compose.test.yml b/docker-compose.test.yml new file mode 100644 index 000000000..b9d44363e --- /dev/null +++ b/docker-compose.test.yml @@ -0,0 +1,99 @@ +version: "3.4" + +services: + + ######################################################### + ## MARIADB ############################################## + ######################################################### + mariadb: + build: + context: . + dockerfile: ./mariadb/Dockerfile + target: mariadb_server_test + environment: + - MARIADB_ALLOW_EMPTY_PASSWORD=1 + - MARIADB_USER=root + networks: + - internal-net + ports: + - 3306:3306 + volumes: + - db_test_vol:/var/lib/mysql + + ######################################################### + ## LOGIN SERVER ######################################### + ######################################################### + login-server: + build: + context: ./login_server/ + target: test + security_opt: + - seccomp:unconfined + cap_add: + - SYS_PTRACE + depends_on: + - mariadb + networks: + - internal-net + volumes: + - ./logs:/var/log/grd_login + - ./login_server/src:/code/src + - ./configs/login_server:/etc/grd_login + - login_build_cov:/code/build_cov + - ./coverage/login:/code/build_cov/coverage_html + + ######################################################### + ## COMMUNITY SERVER (cakephp with php-fpm) ############## + ######################################################### + community-server: + build: + context: . + target: test + dockerfile: ./community_server/Dockerfile + depends_on: + - mariadb + networks: + - internal-net + volumes: + - ./community_server/config/php-fpm/php-ini-overrides.ini:/etc/php/7.4/fpm/conf.d/99-overrides.ini + - ./community_server/src:/var/www/cakephp/src + - ./coverage/community:/var/www/cakephp/webroot/coverage + + + ######################################################### + ## PHPMYADMIN ########################################### + ######################################################### + phpmyadmin: + image: phpmyadmin + environment: + - PMA_ARBITRARY=1 + #restart: always + ports: + - 8074:80 + networks: + - internal-net + - external-net + volumes: + - /sessions + + ######################################################### + ## skeema for updating dbs if changes happend ########### + ######################################################### + skeema: + build: + context: . + dockerfile: ./skeema/Dockerfile + target: skeema_run + depends_on: + - mariadb + networks: + - internal-net + +networks: + external-net: + internal-net: + internal: true + +volumes: + db_test_vol: + login_build_cov: \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 59e617d71..2cc2ceff7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,7 +38,7 @@ services: build: context: . dockerfile: ./mariadb/Dockerfile - target: mariadb_server + target: mariadb_server_test environment: - MARIADB_ALLOW_EMPTY_PASSWORD=1 - MARIADB_USER=root @@ -47,7 +47,7 @@ services: ports: - 3306:3306 volumes: - - db_vol:/var/lib/mysql + - db_vol:/var/lib/mysql ######################################################### ## LOGIN SERVER ######################################### @@ -80,6 +80,7 @@ services: depends_on: - community-server - login-server + - frontend ports: - 80:80 @@ -89,6 +90,7 @@ services: community-server: build: context: . + target: community_server dockerfile: ./community_server/Dockerfile environment: - DB_PASSWORD='' diff --git a/docu/login_server.api.md b/docu/login_server.api.md index b466be7fc..fb9409cf0 100644 --- a/docu/login_server.api.md +++ b/docu/login_server.api.md @@ -89,6 +89,56 @@ In case of success returns: nginx was wrong configured. - `session_id`: can be also negative +## Check username +### Request +`GET http://localhost/login_api/checkUsername?username=&group_id=` + +`POST http://localhost/login_api/checkUsername` +with +```json +{ + "username": "Maxilein", + "group_id": 1, + "group_alias": "gdd1" +} +``` + +group_id or group_alias, one of both is enough. +group_id is better, because one db request less + +### Response + +If username is not already taken +```json +{ + "state":"success" +} +``` + +If username is already taken +```json +{ + "state":"warning", + "msg":"username already in use" +} +``` + +If only group_alias was given and group with that alias was found in db +```json +{ + "state":"success", + "group_id": 1 +} +``` + +If group_id or group_alias unknown +```json +{ + "state":"error", + "msg": "unknown group" +} +``` + ## Create user Register a new User diff --git a/frontend/package.json b/frontend/package.json index 68b4a5807..910644e2c 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -51,6 +51,7 @@ "nouislider": "^12.1.0", "particles-bg-vue": "1.2.3", "perfect-scrollbar": "^1.3.0", + "portal-vue": "^2.1.7", "prettier": "^2.2.1", "qrcode": "^1.4.4", "quill": "^1.3.6", @@ -58,12 +59,14 @@ "sweetalert2": "^9.5.4", "vee-validate": "^3.4.5", "vue": "^2.6.11", + "vue-bootstrap-toasts": "^1.0.7", "vue-bootstrap-typeahead": "^0.2.6", "vue-chartjs": "^3.5.0", "vue-cli-plugin-i18n": "^1.0.1", "vue-clickaway": "^2.2.2", "vue-clipboard2": "^0.3.0", "vue-flatpickr-component": "^8.1.2", + "vue-focus": "^2.1.0", "vue-good-table": "^2.21.3", "vue-i18n": "^8.22.4", "vue-jest": "^3.0.7", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index a6613bec1..500a7b2e1 100755 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -3,6 +3,7 @@
+
diff --git a/frontend/src/apis/communityAPI.js b/frontend/src/apis/communityAPI.js index 25ef10f43..b2df337b8 100644 --- a/frontend/src/apis/communityAPI.js +++ b/frontend/src/apis/communityAPI.js @@ -35,7 +35,7 @@ const communityAPI = { balance: async (sessionId) => { return apiGet(CONFIG.COMMUNITY_API_URL + 'getBalance/' + sessionId) }, - transactions: async (sessionId, firstPage = 1, items = 1000, order = 'DESC') => { + transactions: async (sessionId, firstPage = 1, items = 5, order = 'DESC') => { return apiGet( `${CONFIG.COMMUNITY_API_URL}listTransactions/${firstPage}/${items}/${order}/${sessionId}`, ) diff --git a/frontend/src/apis/loginAPI.js b/frontend/src/apis/loginAPI.js index 55e32e6dd..3453bd296 100644 --- a/frontend/src/apis/loginAPI.js +++ b/frontend/src/apis/loginAPI.js @@ -78,6 +78,26 @@ const loginAPI = { CONFIG.LOGIN_API_URL + 'loginViaEmailVerificationCode?emailVerificationCode=' + optin, ) }, + getUserInfos: async (sessionId, email) => { + const payload = { + session_id: sessionId, + email: email, + ask: ['user.first_name', 'user.last_name'], + } + return apiPost(CONFIG.LOGIN_API_URL + 'getUserInfos', payload) + }, + updateUserInfos: async (sessionId, email, data) => { + const payload = { + session_id: sessionId, + email, + update: { + 'User.first_name': data.firstName, + 'User.last_name': data.lastName, + 'User.description': data.description, + }, + } + return apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload) + }, changePassword: async (sessionId, email, password) => { const payload = { session_id: sessionId, @@ -88,6 +108,27 @@ const loginAPI = { } return apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload) }, + changePasswordProfile: async (sessionId, email, password, passwordNew) => { + const payload = { + session_id: sessionId, + email, + update: { + 'User.password': password, + 'User.passwordNew': passwordNew, + }, + } + return apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload) + }, + changeUsernameProfile: async (sessionId, email, username) => { + const payload = { + session_id: sessionId, + email, + update: { + 'User.username': username, + }, + } + return apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload) + }, updateLanguage: async (sessionId, email, language) => { const payload = { session_id: sessionId, diff --git a/frontend/src/assets/scss/argon.scss b/frontend/src/assets/scss/argon.scss index 01a002691..1fa663a5f 100644 --- a/frontend/src/assets/scss/argon.scss +++ b/frontend/src/assets/scss/argon.scss @@ -23,38 +23,95 @@ // Bootstrap (4.1.3) components -@import "~bootstrap/scss/root"; -@import "~bootstrap/scss/reboot"; -@import "~bootstrap/scss/type"; -@import "~bootstrap/scss/images"; -@import "~bootstrap/scss/code"; -@import "~bootstrap/scss/grid"; -@import "~bootstrap/scss/tables"; -@import "~bootstrap/scss/forms"; -@import "~bootstrap/scss/buttons"; -@import "~bootstrap/scss/transitions"; -@import "~bootstrap/scss/dropdown"; +@import "~bootstrap/scss/alert"; +@import "~bootstrap/scss/badge"; +@import "~bootstrap/scss/breadcrumb"; @import "~bootstrap/scss/button-group"; -@import "~bootstrap/scss/input-group"; +@import "~bootstrap/scss/buttons"; +@import "~bootstrap/scss/card"; +@import "~bootstrap/scss/carousel"; +@import "~bootstrap/scss/close"; +@import "~bootstrap/scss/code"; @import "~bootstrap/scss/custom-forms"; +@import "~bootstrap/scss/dropdown"; +@import "~bootstrap/scss/forms"; +@import "~bootstrap/scss/grid"; +@import "~bootstrap/scss/images"; +@import "~bootstrap/scss/input-group"; +@import "~bootstrap/scss/jumbotron"; +@import "~bootstrap/scss/list-group"; +@import "~bootstrap/scss/media"; +@import "~bootstrap/scss/modal"; @import "~bootstrap/scss/nav"; @import "~bootstrap/scss/navbar"; -@import "~bootstrap/scss/card"; -@import "~bootstrap/scss/breadcrumb"; @import "~bootstrap/scss/pagination"; -@import "~bootstrap/scss/badge"; -@import "~bootstrap/scss/jumbotron"; -@import "~bootstrap/scss/alert"; -@import "~bootstrap/scss/progress"; -@import "~bootstrap/scss/media"; -@import "~bootstrap/scss/list-group"; -@import "~bootstrap/scss/close"; -@import "~bootstrap/scss/modal"; -@import "~bootstrap/scss/tooltip"; @import "~bootstrap/scss/popover"; -@import "~bootstrap/scss/carousel"; -@import "~bootstrap/scss/utilities"; @import "~bootstrap/scss/print"; +@import "~bootstrap/scss/progress"; +@import "~bootstrap/scss/reboot"; +@import "~bootstrap/scss/root"; +@import "~bootstrap/scss/tables"; +@import "~bootstrap/scss/toasts"; +@import "~bootstrap/scss/tooltip"; +@import "~bootstrap/scss/transitions"; +@import "~bootstrap/scss/type"; +@import "~bootstrap/scss/utilities"; +@import "~bootstrap/scss/variables"; + +// Utilities + +@import "~bootstrap/scss/utilities/align"; +@import "~bootstrap/scss/utilities/background"; +@import "~bootstrap/scss/utilities/borders"; +@import "~bootstrap/scss/utilities/clearfix"; +@import "~bootstrap/scss/utilities/display"; +@import "~bootstrap/scss/utilities/embed"; +@import "~bootstrap/scss/utilities/flex"; +@import "~bootstrap/scss/utilities/float"; +@import "~bootstrap/scss/utilities/overflow"; +@import "~bootstrap/scss/utilities/position"; +@import "~bootstrap/scss/utilities/screenreaders"; +@import "~bootstrap/scss/utilities/shadows"; +@import "~bootstrap/scss/utilities/sizing"; +@import "~bootstrap/scss/utilities/spacing"; +@import "~bootstrap/scss/utilities/stretched-link"; +@import "~bootstrap/scss/utilities/text"; +@import "~bootstrap/scss/utilities/visibility"; + + +// Mixins + +@import "~bootstrap/scss/mixins/alert"; +@import "~bootstrap/scss/mixins/badge"; +@import "~bootstrap/scss/mixins/border-radius"; +@import "~bootstrap/scss/mixins/box-shadow"; +@import "~bootstrap/scss/mixins/breakpoints"; +@import "~bootstrap/scss/mixins/buttons"; +@import "~bootstrap/scss/mixins/caret"; +@import "~bootstrap/scss/mixins/clearfix"; +@import "~bootstrap/scss/mixins/deprecate"; +@import "~bootstrap/scss/mixins/float"; +@import "~bootstrap/scss/mixins/forms"; +@import "~bootstrap/scss/mixins/gradients"; +@import "~bootstrap/scss/mixins/grid-framework"; +@import "~bootstrap/scss/mixins/grid"; +@import "~bootstrap/scss/mixins/hover"; +@import "~bootstrap/scss/mixins/image"; +@import "~bootstrap/scss/mixins/list-group"; +@import "~bootstrap/scss/mixins/lists"; +@import "~bootstrap/scss/mixins/nav-divider"; +@import "~bootstrap/scss/mixins/pagination"; +@import "~bootstrap/scss/mixins/reset-text"; +@import "~bootstrap/scss/mixins/resize"; +@import "~bootstrap/scss/mixins/screen-reader"; +@import "~bootstrap/scss/mixins/size"; +@import "~bootstrap/scss/mixins/table-row"; +@import "~bootstrap/scss/mixins/text-emphasis"; +@import "~bootstrap/scss/mixins/text-hide"; +@import "~bootstrap/scss/mixins/text-truncate"; +@import "~bootstrap/scss/mixins/transition"; +@import "~bootstrap/scss/mixins/visibility"; + // Argon utilities and components diff --git a/frontend/src/assets/scss/core/badges/_badge-circle.scss b/frontend/src/assets/scss/core/badges/_badge-circle.scss deleted file mode 100644 index 88a5d5e5d..000000000 --- a/frontend/src/assets/scss/core/badges/_badge-circle.scss +++ /dev/null @@ -1,17 +0,0 @@ -// -// Circle badge -// - - -// General styles - -.badge-circle { - text-align: center; - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 50%; - width: 2rem; - height: 2rem; - font-size: .875rem; -} diff --git a/frontend/src/assets/scss/core/badges/_badge-dot.scss b/frontend/src/assets/scss/core/badges/_badge-dot.scss deleted file mode 100644 index 1ed6ffa86..000000000 --- a/frontend/src/assets/scss/core/badges/_badge-dot.scss +++ /dev/null @@ -1,42 +0,0 @@ -// -// Dot badge -// - - -// General styles - -.badge-dot { - padding-left: 0; - padding-right: 0; - background: transparent; - font-weight: $font-weight-normal; - font-size: $font-size-sm; - text-transform: none; - - strong { - color: $gray-800; - } - - i { - display: inline-block; - vertical-align: middle; - width: .375rem; - height: .375rem; - border-radius: 50%; - margin-right: .375rem; - } - - &.badge-md { - i { - width: .5rem; - height: .5rem; - } - } - - &.badge-lg { - i { - width: .625rem; - height: .625rem; - } - } -} diff --git a/frontend/src/assets/scss/core/badges/_badge.scss b/frontend/src/assets/scss/core/badges/_badge.scss deleted file mode 100644 index b0d626a1e..000000000 --- a/frontend/src/assets/scss/core/badges/_badge.scss +++ /dev/null @@ -1,55 +0,0 @@ -// -// Badge -// - - -// General styles - -.badge { - text-transform: $badge-text-transfom; - - a { - color: $white; - } -} - - -// Size variations - -.badge-md { - padding: .65em 1em; -} - -.badge-lg { - padding: .85em 1.375em; -} - - -// Multiple inline badges - -.badge-inline { - margin-right: .625rem; - - + span { - top: 2px; - position: relative; - - > a { - text-decoration: underline; - } - } -} - - -// Badge spacing inside a btn with some text - -.btn { - .badge { - &:not(:first-child) { - margin-left: .5rem; - } - &:not(:last-child) { - margin-right: .5rem; - } - } -} diff --git a/frontend/src/assets/scss/custom/_components.scss b/frontend/src/assets/scss/custom/_components.scss index 8a71d41f6..8a18e63be 100644 --- a/frontend/src/assets/scss/custom/_components.scss +++ b/frontend/src/assets/scss/custom/_components.scss @@ -4,7 +4,6 @@ @import "custom/alert"; @import "custom/avatar"; -@import "custom/badge"; @import "custom/buttons"; @import "custom/card"; @import "custom/chart"; diff --git a/frontend/src/components/Badge.vue b/frontend/src/components/Badge.vue deleted file mode 100644 index d3cbf543d..000000000 --- a/frontend/src/components/Badge.vue +++ /dev/null @@ -1,45 +0,0 @@ - - - diff --git a/frontend/src/components/BaseAlert.vue b/frontend/src/components/BaseAlert.vue deleted file mode 100644 index fe17428a2..000000000 --- a/frontend/src/components/BaseAlert.vue +++ /dev/null @@ -1,75 +0,0 @@ - - diff --git a/frontend/src/components/BaseButton.vue b/frontend/src/components/BaseButton.vue deleted file mode 100644 index 009add59b..000000000 --- a/frontend/src/components/BaseButton.vue +++ /dev/null @@ -1,75 +0,0 @@ - - - diff --git a/frontend/src/components/BaseDropdown.vue b/frontend/src/components/BaseDropdown.vue deleted file mode 100644 index 8db496992..000000000 --- a/frontend/src/components/BaseDropdown.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - diff --git a/frontend/src/components/BaseHeader.vue b/frontend/src/components/BaseHeader.vue deleted file mode 100644 index 90e8a1a5a..000000000 --- a/frontend/src/components/BaseHeader.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/frontend/src/components/BasePagination.vue b/frontend/src/components/BasePagination.vue deleted file mode 100755 index 9fc633481..000000000 --- a/frontend/src/components/BasePagination.vue +++ /dev/null @@ -1,67 +0,0 @@ - - diff --git a/frontend/src/components/BaseProgress.vue b/frontend/src/components/BaseProgress.vue deleted file mode 100755 index c2f44bf2c..000000000 --- a/frontend/src/components/BaseProgress.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - diff --git a/frontend/src/components/BaseSlider.vue b/frontend/src/components/BaseSlider.vue deleted file mode 100644 index 14180674a..000000000 --- a/frontend/src/components/BaseSlider.vue +++ /dev/null @@ -1,92 +0,0 @@ - - - diff --git a/frontend/src/components/BaseTable.vue b/frontend/src/components/BaseTable.vue deleted file mode 100644 index 38ecc6039..000000000 --- a/frontend/src/components/BaseTable.vue +++ /dev/null @@ -1,66 +0,0 @@ - - - diff --git a/frontend/src/components/Breadcrumb/Breadcrumb.vue b/frontend/src/components/Breadcrumb/Breadcrumb.vue deleted file mode 100644 index 795816884..000000000 --- a/frontend/src/components/Breadcrumb/Breadcrumb.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/frontend/src/components/Breadcrumb/BreadcrumbItem.vue b/frontend/src/components/Breadcrumb/BreadcrumbItem.vue deleted file mode 100644 index 2bf5a8c6c..000000000 --- a/frontend/src/components/Breadcrumb/BreadcrumbItem.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/frontend/src/components/Breadcrumb/RouteBreadcrumb.vue b/frontend/src/components/Breadcrumb/RouteBreadcrumb.vue deleted file mode 100644 index bd378f312..000000000 --- a/frontend/src/components/Breadcrumb/RouteBreadcrumb.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/frontend/src/components/ButtonCheckbox.vue b/frontend/src/components/ButtonCheckbox.vue deleted file mode 100644 index e408c69a2..000000000 --- a/frontend/src/components/ButtonCheckbox.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - diff --git a/frontend/src/components/ButtonRadioGroup.vue b/frontend/src/components/ButtonRadioGroup.vue deleted file mode 100644 index c757a50d8..000000000 --- a/frontend/src/components/ButtonRadioGroup.vue +++ /dev/null @@ -1,55 +0,0 @@ - - - diff --git a/frontend/src/components/Cards/Card.vue b/frontend/src/components/Cards/Card.vue deleted file mode 100644 index 5ae76922a..000000000 --- a/frontend/src/components/Cards/Card.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - diff --git a/frontend/src/components/Cards/StatsCard.vue b/frontend/src/components/Cards/StatsCard.vue deleted file mode 100644 index 8c5c364d0..000000000 --- a/frontend/src/components/Cards/StatsCard.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - diff --git a/frontend/src/components/Charts/BarChart.js b/frontend/src/components/Charts/BarChart.js deleted file mode 100644 index 057c31163..000000000 --- a/frontend/src/components/Charts/BarChart.js +++ /dev/null @@ -1,30 +0,0 @@ -import { Bar, mixins } from 'vue-chartjs' -import globalOptionsMixin from '@/components/Charts/globalOptionsMixin' - -export default { - name: 'bar-chart', - extends: Bar, - mixins: [mixins.reactiveProp, globalOptionsMixin], - props: { - extraOptions: { - type: Object, - default: () => ({}), - }, - }, - data() { - return { - ctx: null, - } - }, - mounted() { - this.$watch( - 'chartData', - (newVal, oldVal) => { - if (!oldVal) { - this.renderChart(this.chartData, this.extraOptions) - } - }, - { immediate: true }, - ) - }, -} diff --git a/frontend/src/components/Charts/LineChart.js b/frontend/src/components/Charts/LineChart.js deleted file mode 100644 index 81452f14d..000000000 --- a/frontend/src/components/Charts/LineChart.js +++ /dev/null @@ -1,29 +0,0 @@ -import { Line, mixins } from 'vue-chartjs' -import globalOptionsMixin from '@/components/Charts/globalOptionsMixin' -export default { - name: 'line-chart', - extends: Line, - mixins: [mixins.reactiveProp, globalOptionsMixin], - props: { - extraOptions: { - type: Object, - default: () => ({}), - }, - }, - data() { - return { - ctx: null, - } - }, - mounted() { - this.$watch( - 'chartData', - (newVal, oldVal) => { - if (!oldVal) { - this.renderChart(this.chartData, this.extraOptions) - } - }, - { immediate: true }, - ) - }, -} diff --git a/frontend/src/components/Charts/config.js b/frontend/src/components/Charts/config.js deleted file mode 100644 index 694a036b5..000000000 --- a/frontend/src/components/Charts/config.js +++ /dev/null @@ -1,234 +0,0 @@ -import { parseOptions } from '@/components/Charts/optionHelpers' -import Chart from 'chart.js' - -export const Charts = { - mode: 'light', // (themeMode) ? themeMode : 'light'; - fonts: { - base: 'Open Sans', - }, - colors: { - gray: { - 100: '#f6f9fc', - 200: '#e9ecef', - 300: '#dee2e6', - 400: '#ced4da', - 500: '#adb5bd', - 600: '#8898aa', - 700: '#525f7f', - 800: '#32325d', - 900: '#212529', - }, - theme: { - default: '#172b4d', - primary: '#5e72e4', - secondary: '#f4f5f7', - info: '#11cdef', - success: '#2dce89', - danger: '#f5365c', - warning: '#fb6340', - }, - black: '#12263F', - white: '#FFFFFF', - transparent: 'transparent', - }, -} - -function chartOptions() { - const { colors, mode, fonts } = Charts - // Options - const options = { - defaults: { - global: { - responsive: true, - maintainAspectRatio: false, - defaultColor: mode === 'dark' ? colors.gray[700] : colors.gray[600], - defaultFontColor: mode === 'dark' ? colors.gray[700] : colors.gray[600], - defaultFontFamily: fonts.base, - defaultFontSize: 13, - layout: { - padding: 0, - }, - legend: { - display: false, - position: 'bottom', - labels: { - usePointStyle: true, - padding: 16, - }, - }, - elements: { - point: { - radius: 0, - backgroundColor: colors.theme.primary, - }, - line: { - tension: 0.4, - borderWidth: 4, - borderColor: colors.theme.primary, - backgroundColor: colors.transparent, - borderCapStyle: 'rounded', - }, - rectangle: { - backgroundColor: colors.theme.warning, - }, - arc: { - backgroundColor: colors.theme.primary, - borderColor: mode === 'dark' ? colors.gray[800] : colors.white, - borderWidth: 4, - }, - }, - tooltips: { - enabled: true, - mode: 'index', - intersect: false, - }, - }, - pie: { - tooltips: { - mode: 'point', - }, - }, - doughnut: { - tooltips: { - mode: 'point', - }, - cutoutPercentage: 83, - legendCallback: function (chart) { - const data = chart.data - let content = '' - - data.labels.forEach(function (label, index) { - const bgColor = data.datasets[0].backgroundColor[index] - - content += '' - content += - '' - content += label - content += '' - }) - - return content - }, - }, - }, - } - - // yAxes - Chart.scaleService.updateScaleDefaults('linear', { - gridLines: { - borderDash: [2], - borderDashOffset: [2], - color: mode === 'dark' ? colors.gray[900] : colors.gray[200], - drawBorder: false, - drawTicks: true, - zeroLineWidth: 1, - zeroLineColor: mode === 'dark' ? colors.gray[900] : colors.gray[200], - zeroLineBorderDash: [2], - zeroLineBorderDashOffset: [2], - }, - ticks: { - beginAtZero: true, - padding: 10, - callback: function (value) { - if (!(value % 10)) { - return value - } - }, - }, - }) - - // xAxes - Chart.scaleService.updateScaleDefaults('category', { - gridLines: { - drawBorder: false, - drawOnChartArea: false, - drawTicks: false, - lineWidth: 1, - zeroLineWidth: 1, - }, - ticks: { - padding: 20, - }, - maxBarThickness: 10, - }) - - return options -} - -let initialized = false - -export function initGlobalOptions() { - if (initialized) { - return - } - parseOptions(Chart, chartOptions()) - initialized = true -} - -export const basicOptions = { - maintainAspectRatio: false, - legend: { - display: false, - }, - responsive: true, -} -export const blueChartOptions = { - scales: { - yAxes: [ - { - gridLines: { - color: Charts.colors.gray[700], - zeroLineColor: Charts.colors.gray[700], - }, - }, - ], - }, -} - -export const lineChartOptionsBlue = { - ...basicOptions, - tooltips: { - backgroundColor: '#f5f5f5', - titleFontColor: '#333', - bodyFontColor: '#666', - bodySpacing: 4, - xPadding: 12, - mode: 'nearest', - intersect: 0, - position: 'nearest', - }, - responsive: true, - scales: { - yAxes: [ - { - barPercentage: 1.6, - gridLines: { - drawBorder: false, - color: 'rgba(29,140,248,0.0)', - zeroLineColor: 'transparent', - }, - ticks: { - suggestedMin: 60, - suggestedMax: 125, - padding: 20, - fontColor: '#9e9e9e', - }, - }, - ], - - xAxes: [ - { - barPercentage: 1.6, - gridLines: { - drawBorder: false, - color: 'rgba(29,140,248,0.1)', - zeroLineColor: 'transparent', - }, - ticks: { - padding: 20, - fontColor: '#9e9e9e', - }, - }, - ], - }, -} diff --git a/frontend/src/components/Charts/globalOptionsMixin.js b/frontend/src/components/Charts/globalOptionsMixin.js deleted file mode 100644 index 323ac94e4..000000000 --- a/frontend/src/components/Charts/globalOptionsMixin.js +++ /dev/null @@ -1,7 +0,0 @@ -import { initGlobalOptions } from '@/components/Charts/config' -import './roundedCornersExtension' -export default { - mounted() { - initGlobalOptions() - }, -} diff --git a/frontend/src/components/Charts/optionHelpers.js b/frontend/src/components/Charts/optionHelpers.js deleted file mode 100644 index 5b4630b73..000000000 --- a/frontend/src/components/Charts/optionHelpers.js +++ /dev/null @@ -1,10 +0,0 @@ -// Parse global options -export function parseOptions(parent, options) { - for (const item in options) { - if (typeof options[item] !== 'object') { - parent[item] = options[item] - } else { - parseOptions(parent[item], options[item]) - } - } -} diff --git a/frontend/src/components/Charts/roundedCornersExtension.js b/frontend/src/components/Charts/roundedCornersExtension.js deleted file mode 100644 index 2ef8fd1d2..000000000 --- a/frontend/src/components/Charts/roundedCornersExtension.js +++ /dev/null @@ -1,126 +0,0 @@ -// -// Chart extension for making the bars rounded -// Code from: https://codepen.io/jedtrow/full/ygRYgo -// -import Chart from 'chart.js' -Chart.elements.Rectangle.prototype.draw = function () { - const ctx = this._chart.ctx - const vm = this._view - let left, right, top, bottom, signX, signY, borderSkipped - let borderWidth = vm.borderWidth - // Set Radius Here - // If radius is large enough to cause drawing errors a max radius is imposed - const cornerRadius = 6 - - if (!vm.horizontal) { - // bar - left = vm.x - vm.width / 2 - right = vm.x + vm.width / 2 - top = vm.y - bottom = vm.base - signX = 1 - signY = bottom > top ? 1 : -1 - borderSkipped = vm.borderSkipped || 'bottom' - } else { - // horizontal bar - left = vm.base - right = vm.x - top = vm.y - vm.height / 2 - bottom = vm.y + vm.height / 2 - signX = right > left ? 1 : -1 - signY = 1 - borderSkipped = vm.borderSkipped || 'left' - } - - // Canvas doesn't allow us to stroke inside the width so we can - // adjust the sizes to fit if we're setting a stroke on the line - if (borderWidth) { - // borderWidth shold be less than bar width and bar height. - const barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom)) - borderWidth = borderWidth > barSize ? barSize : borderWidth - const halfStroke = borderWidth / 2 - // Adjust borderWidth when bar top position is near vm.base(zero). - const borderLeft = left + (borderSkipped !== 'left' ? halfStroke * signX : 0) - const borderRight = right + (borderSkipped !== 'right' ? -halfStroke * signX : 0) - const borderTop = top + (borderSkipped !== 'top' ? halfStroke * signY : 0) - const borderBottom = bottom + (borderSkipped !== 'bottom' ? -halfStroke * signY : 0) - // not become a vertical line? - if (borderLeft !== borderRight) { - top = borderTop - bottom = borderBottom - } - // not become a horizontal line? - if (borderTop !== borderBottom) { - left = borderLeft - right = borderRight - } - } - - ctx.beginPath() - ctx.fillStyle = vm.backgroundColor - ctx.strokeStyle = vm.borderColor - ctx.lineWidth = borderWidth - - // Corner points, from bottom-left to bottom-right clockwise - // | 1 2 | - // | 0 3 | - const corners = [ - [left, bottom], - [left, top], - [right, top], - [right, bottom], - ] - - // Find first (starting) corner with fallback to 'bottom' - const borders = ['bottom', 'left', 'top', 'right'] - let startCorner = borders.indexOf(borderSkipped, 0) - if (startCorner === -1) { - startCorner = 0 - } - - function cornerAt(index) { - return corners[(startCorner + index) % 4] - } - - // Draw rectangle from 'startCorner' - let corner = cornerAt(0) - ctx.moveTo(corner[0], corner[1]) - - for (let i = 1; i < 4; i++) { - corner = cornerAt(i) - let nextCornerId = i + 1 - if (nextCornerId === 4) { - nextCornerId = 0 - } - - const width = corners[2][0] - corners[1][0] - const height = corners[0][1] - corners[1][1] - const x = corners[1][0] - const y = corners[1][1] - - let radius = cornerRadius - - // Fix radius being too large - if (radius > height / 2) { - radius = height / 2 - } - if (radius > width / 2) { - radius = width / 2 - } - - ctx.moveTo(x + radius, y) - ctx.lineTo(x + width - radius, y) - ctx.quadraticCurveTo(x + width, y, x + width, y + radius) - ctx.lineTo(x + width, y + height - radius) - ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height) - ctx.lineTo(x + radius, y + height) - ctx.quadraticCurveTo(x, y + height, x, y + height - radius) - ctx.lineTo(x, y + radius) - ctx.quadraticCurveTo(x, y, x + radius, y) - } - - ctx.fill() - if (borderWidth) { - ctx.stroke() - } -} diff --git a/frontend/src/components/CloseButton.spec.js b/frontend/src/components/CloseButton.spec.js deleted file mode 100644 index b92422df8..000000000 --- a/frontend/src/components/CloseButton.spec.js +++ /dev/null @@ -1,28 +0,0 @@ -import { mount } from '@vue/test-utils' - -import CloseButton from './CloseButton' - -const localVue = global.localVue - -describe('CloseButton', () => { - let wrapper - const propsData = { - target: 'Target', - expanded: false, - } - - const Wrapper = () => { - return mount(CloseButton, { localVue, propsData }) - } - - describe('mount', () => { - beforeEach(() => { - wrapper = Wrapper() - }) - - it('emmits click event', () => { - wrapper.find('.navbar-toggler').trigger('click') - expect(wrapper.emitted('click')).toBeTruthy() - }) - }) -}) diff --git a/frontend/src/components/CloseButton.vue b/frontend/src/components/CloseButton.vue deleted file mode 100755 index 8c61f4f60..000000000 --- a/frontend/src/components/CloseButton.vue +++ /dev/null @@ -1,36 +0,0 @@ - - - diff --git a/frontend/src/components/Inputs/BaseCheckbox.vue b/frontend/src/components/Inputs/BaseCheckbox.vue deleted file mode 100755 index 2aaa06fba..000000000 --- a/frontend/src/components/Inputs/BaseCheckbox.vue +++ /dev/null @@ -1,78 +0,0 @@ - - diff --git a/frontend/src/components/Inputs/BaseInput.vue b/frontend/src/components/Inputs/BaseInput.vue deleted file mode 100644 index c43e0a265..000000000 --- a/frontend/src/components/Inputs/BaseInput.vue +++ /dev/null @@ -1,187 +0,0 @@ - - - diff --git a/frontend/src/components/Inputs/BaseRadio.vue b/frontend/src/components/Inputs/BaseRadio.vue deleted file mode 100755 index 697812698..000000000 --- a/frontend/src/components/Inputs/BaseRadio.vue +++ /dev/null @@ -1,64 +0,0 @@ - - diff --git a/frontend/src/components/Modal-OLD.vue b/frontend/src/components/Modal-OLD.vue deleted file mode 100644 index 515b510a0..000000000 --- a/frontend/src/components/Modal-OLD.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - diff --git a/frontend/src/components/Modal.vue b/frontend/src/components/Modal.vue deleted file mode 100644 index c43bf6c67..000000000 --- a/frontend/src/components/Modal.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - - diff --git a/frontend/src/components/Navbar/BaseNav.vue b/frontend/src/components/Navbar/BaseNav.vue deleted file mode 100644 index 778f550fc..000000000 --- a/frontend/src/components/Navbar/BaseNav.vue +++ /dev/null @@ -1,120 +0,0 @@ - - - diff --git a/frontend/src/components/NotificationPlugin/Notification.vue b/frontend/src/components/NotificationPlugin/Notification.vue deleted file mode 100644 index e36985036..000000000 --- a/frontend/src/components/NotificationPlugin/Notification.vue +++ /dev/null @@ -1,194 +0,0 @@ - - - diff --git a/frontend/src/components/NotificationPlugin/Notifications.vue b/frontend/src/components/NotificationPlugin/Notifications.vue deleted file mode 100644 index f180a7f37..000000000 --- a/frontend/src/components/NotificationPlugin/Notifications.vue +++ /dev/null @@ -1,52 +0,0 @@ - - diff --git a/frontend/src/components/NotificationPlugin/index.js b/frontend/src/components/NotificationPlugin/index.js deleted file mode 100644 index 5b6bbe67b..000000000 --- a/frontend/src/components/NotificationPlugin/index.js +++ /dev/null @@ -1,66 +0,0 @@ -import Notifications from './Notifications.vue' - -const NotificationStore = { - state: [], // here the notifications will be added - settings: { - overlap: false, - verticalAlign: 'top', - horizontalAlign: 'right', - type: 'info', - timeout: 5000, - closeOnClick: true, - showClose: true, - }, - setOptions(options) { - this.settings = Object.assign(this.settings, options) - }, - removeNotification(timestamp) { - const indexToDelete = this.state.findIndex((n) => n.timestamp === timestamp) - if (indexToDelete !== -1) { - this.state.splice(indexToDelete, 1) - } - }, - addNotification(notification) { - if (typeof notification === 'string' || notification instanceof String) { - notification = { message: notification } - } - notification.timestamp = new Date() - notification.timestamp.setMilliseconds( - notification.timestamp.getMilliseconds() + this.state.length, - ) - notification = Object.assign({}, this.settings, notification) - this.state.push(notification) - }, - notify(notification) { - if (Array.isArray(notification)) { - notification.forEach((notificationInstance) => { - this.addNotification(notificationInstance) - }) - } else { - this.addNotification(notification) - } - }, -} - -const NotificationsPlugin = { - install(Vue, options) { - const app = new Vue({ - data: { - notificationStore: NotificationStore, - }, - methods: { - notify(notification) { - this.notificationStore.notify(notification) - }, - }, - }) - Vue.prototype.$notify = app.notify - Vue.prototype.$notifications = app.notificationStore - Vue.component('Notifications', Notifications) - if (options) { - NotificationStore.setOptions(options) - } - }, -} - -export default NotificationsPlugin diff --git a/frontend/src/components/PaginationButtons.spec.js b/frontend/src/components/PaginationButtons.spec.js new file mode 100644 index 000000000..7a03d0443 --- /dev/null +++ b/frontend/src/components/PaginationButtons.spec.js @@ -0,0 +1,53 @@ +import { mount } from '@vue/test-utils' +import PaginationButtons from './PaginationButtons' + +const localVue = global.localVue + +describe('PaginationButtons', () => { + let wrapper + + const Wrapper = () => { + return mount(PaginationButtons, { localVue }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('renders the component', () => { + expect(wrapper.find('div.pagination-buttons').exists()).toBeTruthy() + }) + + it('has previous page button disabled by default', () => { + expect(wrapper.find('button.previous-page').attributes('disabled')).toBe('disabled') + }) + + it('has bext page button disabled by default', () => { + expect(wrapper.find('button.next-page').attributes('disabled')).toBe('disabled') + }) + + it('shows the text "1 / 1" by default"', () => { + expect(wrapper.find('p.text-center').text()).toBe('1 / 1') + }) + + describe('with active buttons', () => { + beforeEach(async () => { + await wrapper.setProps({ + hasNext: true, + hasPrevious: true, + }) + }) + + it('emits show-previous when previous page button is clicked', () => { + wrapper.find('button.previous-page').trigger('click') + expect(wrapper.emitted('show-previous')).toBeTruthy() + }) + + it('emits show-next when next page button is clicked', () => { + wrapper.find('button.next-page').trigger('click') + expect(wrapper.emitted('show-next')).toBeTruthy() + }) + }) + }) +}) diff --git a/frontend/src/components/PaginationButtons.vue b/frontend/src/components/PaginationButtons.vue new file mode 100644 index 000000000..ac7ff73c6 --- /dev/null +++ b/frontend/src/components/PaginationButtons.vue @@ -0,0 +1,30 @@ + + diff --git a/frontend/src/components/SearchUser.vue b/frontend/src/components/SearchUser.vue deleted file mode 100644 index dd3fe34a6..000000000 --- a/frontend/src/components/SearchUser.vue +++ /dev/null @@ -1,81 +0,0 @@ - - diff --git a/frontend/src/components/SidebarPlugin/SideBar.spec.js b/frontend/src/components/SidebarPlugin/SideBar.spec.js index 9f9ce8a8f..58405f38f 100644 --- a/frontend/src/components/SidebarPlugin/SideBar.spec.js +++ b/frontend/src/components/SidebarPlugin/SideBar.spec.js @@ -41,6 +41,19 @@ describe('SideBar', () => { expect(wrapper.find('#sidenav-main').exists()).toBeTruthy() }) + describe('navbar button', () => { + it('has a navbar button', () => { + expect(wrapper.find('button.navbar-toggler').exists()).toBeTruthy() + }) + + it('calls showSidebar when clicked', async () => { + const spy = jest.spyOn(wrapper.vm.$sidebar, 'displaySidebar') + wrapper.find('button.navbar-toggler').trigger('click') + await wrapper.vm.$nextTick() + expect(spy).toHaveBeenCalledWith(true) + }) + }) + describe('balance', () => { it('shows em-dash as balance while loading', () => { expect(wrapper.find('div.row.text-center').text()).toBe('— GDD') @@ -55,19 +68,6 @@ describe('SideBar', () => { }) }) - describe('navbar button', () => { - it('has a navbar button', () => { - expect(wrapper.find('button.navbar-toggler').exists()).toBeTruthy() - }) - - it('calls showSidebar when clicked', async () => { - const spy = jest.spyOn(wrapper.vm.$sidebar, 'displaySidebar') - wrapper.find('button.navbar-toggler').trigger('click') - await wrapper.vm.$nextTick() - expect(spy).toHaveBeenCalledWith(true) - }) - }) - describe('close siedbar', () => { it('calls closeSidebar when clicked', async () => { const spy = jest.spyOn(wrapper.vm.$sidebar, 'displaySidebar') diff --git a/frontend/src/components/SidebarPlugin/SideBar.vue b/frontend/src/components/SidebarPlugin/SideBar.vue index 60d835a1a..756e72d2a 100755 --- a/frontend/src/components/SidebarPlugin/SideBar.vue +++ b/frontend/src/components/SidebarPlugin/SideBar.vue @@ -14,13 +14,11 @@ @@ -71,15 +69,15 @@ - diff --git a/frontend/src/components/Tabs/Tabs.vue b/frontend/src/components/Tabs/Tabs.vue deleted file mode 100644 index 211c8d0cd..000000000 --- a/frontend/src/components/Tabs/Tabs.vue +++ /dev/null @@ -1,155 +0,0 @@ - - - - - diff --git a/frontend/src/components/index.js b/frontend/src/components/index.js index c75b2a8fa..155b060de 100755 --- a/frontend/src/components/index.js +++ b/frontend/src/components/index.js @@ -1,50 +1,8 @@ -import BaseCheckbox from './Inputs/BaseCheckbox.vue' -import BaseAlert from './BaseAlert.vue' -import BaseRadio from './Inputs/BaseRadio.vue' -import BaseInput from './Inputs/BaseInput.vue' -import Badge from './Badge' -import BaseProgress from './BaseProgress.vue' -import BaseButton from './BaseButton.vue' - -import BaseDropdown from './BaseDropdown.vue' -import BaseTable from './BaseTable.vue' - -import Card from './Cards/Card.vue' -import StatsCard from './Cards/StatsCard.vue' -import BaseNav from './Navbar/BaseNav' import NavbarToggleButton from './Navbar/NavbarToggleButton' -import TabPane from './Tabs/Tab.vue' -import Tabs from './Tabs/Tabs.vue' import Collapse from './Collapse/Collapse.vue' import CollapseItem from './Collapse/CollapseItem.vue' -import Modal from './Modal.vue' -import BaseSlider from './BaseSlider.vue' - -import BasePagination from './BasePagination.vue' import SidebarPlugin from './SidebarPlugin' -export { - BaseCheckbox, - Badge, - BaseAlert, - BaseProgress, - BasePagination, - BaseRadio, - BaseInput, - Card, - StatsCard, - BaseTable, - BaseDropdown, - SidebarPlugin, - BaseNav, - NavbarToggleButton, - TabPane, - Tabs, - Modal, - BaseSlider, - BaseButton, - Collapse, - CollapseItem, -} +export { SidebarPlugin, NavbarToggleButton, Collapse, CollapseItem } diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 81fb90972..6536a143b 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -20,17 +20,25 @@ }, "decay": "Vergänglichkeit", "form": { - "cancel":"Abbrechen", + "cancel": "Abbrechen", "reset": "Zurücksetzen", - "close":"schließen", + "close": "schließen", + "edit": "bearbeiten", + "save": "speichern", "receiver":"Empfänger", "sender":"Absender", + "username":"Username", "firstname":"Vorname", "lastname":"Nachname", + "description": "Beschreibung", "email":"E-Mail", "email_repeat":"eMail wiederholen", "password":"Passwort", - "password_repeat":"Passwort wiederholen", + "passwordRepeat":"Passwort wiederholen", + "password_old":"altes Passwort", + "password_new":"neues Passwort", + "password_new_repeat":"neues Passwort wiederholen", + "change": "ändern", "amount":"Betrag", "memo":"Nachricht für den Empfänger", "message":"Nachricht", @@ -48,9 +56,10 @@ "send_transaction_success":"Deine Transaktion wurde erfolgreich ausgeführt", "send_transaction_error":"Leider konnte die Transaktion nicht ausgeführt werden!", "validation": { - "double": "Das Feld {field} muss eine Dezimalzahl mit zwei Nachkommastellen sein", + "gddSendAmount": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein", "is-not": "Du kannst dir selbst keine Gradidos überweisen" - } + }, + "change_username_info": "Das ändern des Usernamens bedarf mehrerer Schritte." }, "error": { "error":"Fehler" @@ -96,12 +105,13 @@ "add_work":"neuer Gemeinschaftsbeitrag" }, "profil": { - "transactions":"transactions", "activity": { - "chart":"Gemeinschaftsstunden Chart", "new":"Neue Gemeinschaftsstunden eintragen", "list":"Meine Gemeinschaftsstunden Liste" - } + }, + "user-data": { + "change-success": "Deine Daten wurden gespeichert." + } }, "navbar" : { "my-profil":"Mein Profil", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 58ebbf9f1..f611e4b91 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -1,7 +1,7 @@ { "message": "hello gradido !!", "welcome":"Welcome!", - "community": "Gemeinschaft", + "community": "Community", "logout":"Logout", "login":"Login", "signup": "Sign up", @@ -23,14 +23,22 @@ "cancel":"Cancel", "reset": "Reset", "close":"Close", + "edit": "Edit", + "save": "save", "receiver":"Receiver", "sender":"Sender", + "username":"Username", "firstname":"Firstname", "lastname":"Lastname", + "description": "Description", "email":"Email", "email_repeat":"Repeat Email", "password":"Password", - "password_repeat":"Repeat password", + "passwordRepeat":"Repeat password", + "password_old":"Old password", + "password_new":"New password", + "password_new_repeat":"Repeat new password", + "change": "change", "amount":"Amount", "memo":"Message for the recipient", "message":"Message", @@ -48,9 +56,10 @@ "send_transaction_success":"Your transaction was successfully completed", "send_transaction_error":"Unfortunately, the transaction could not be executed!", "validation": { - "double": "The {field} field must be a decimal with two digits", + "gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits", "is-not": "You cannot send Gradidos to yourself" - } + }, + "change_username_info": "Changing the username requires several steps." }, "error": { "error":"Error" @@ -98,10 +107,12 @@ "profil": { "transactions":"transactions", "activity": { - "chart":"Community Hours Chart", "new":"Register new community hours", "list":"My Community Hours List" - } + }, + "user-data": { + "change-success": "Your data has been saved." + } }, "navbar" : { "my-profil":"My profile", diff --git a/frontend/src/main.js b/frontend/src/main.js index 5584ae508..160ff73c7 100755 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -4,7 +4,7 @@ import App from './App.vue' import i18n from './i18n.js' import { configure, extend } from 'vee-validate' // eslint-disable-next-line camelcase -import { required, email, min, between, double, is_not } from 'vee-validate/dist/rules' +import { required, email, min, max, is_not } from 'vee-validate/dist/rules' // store import { store } from './store/store' @@ -46,14 +46,22 @@ extend('min', { message: (_, values) => i18n.t('validations.messages.min', values), }) -extend('double', { - ...double, - message: (_, values) => i18n.t('form.validation.double', values), +extend('max', { + ...max, + message: (_, values) => i18n.t('validations.messages.max', values), }) -extend('between', { - ...between, - message: (_, values) => i18n.t('validations.messages.between', values), +extend('gddSendAmount', { + validate(value, { min, max }) { + value = value.replace(',', '.') + return value.match(/^[0-9]+(\.[0-9]{0,2})?$/) && Number(value) >= min && Number(value) <= max + }, + params: ['min', 'max'], + message: (_, values) => { + values.min = i18n.n(values.min) + values.max = i18n.n(values.max) + return i18n.t('form.validation.gddSendAmount', values) + }, }) // eslint-disable-next-line camelcase diff --git a/frontend/src/plugins/dashboard-plugin.js b/frontend/src/plugins/dashboard-plugin.js index b7c0ea06c..2edac0995 100755 --- a/frontend/src/plugins/dashboard-plugin.js +++ b/frontend/src/plugins/dashboard-plugin.js @@ -1,16 +1,13 @@ -// Polyfills for js features used in the Dashboard but not supported in some browsers (mainly IE) import '@/polyfills' -// Notifications plugin. Used on Notifications page -import Notifications from '@/components/NotificationPlugin' -// Validation plugin used to validate forms import { configure, extend } from 'vee-validate' -// A plugin file where you could register global components used across the app import GlobalComponents from './globalComponents' -// A plugin file where you could register global directives import GlobalDirectives from './globalDirectives' -// Sidebar on the right. Used as a local plugin in DashboardLayout.vue import SideBar from '@/components/SidebarPlugin' +import PortalVue from 'portal-vue' + +import VueBootstrapToasts from 'vue-bootstrap-toasts' + // vue-bootstrap import { BootstrapVue, IconsPlugin } from 'bootstrap-vue' @@ -23,16 +20,12 @@ import { messages } from 'vee-validate/dist/locale/en.json' import VueQrcodeReader from 'vue-qrcode-reader' import VueQrcode from 'vue-qrcode' -import VueFlatPickr from 'vue-flatpickr-component' - -import VueGoodTablePlugin from 'vue-good-table' -// import the styles -import 'vue-good-table/dist/vue-good-table.css' +import FlatPickr from 'vue-flatpickr-component' +import 'flatpickr/dist/flatpickr.css' import VueMoment from 'vue-moment' import Loading from 'vue-loading-overlay' -// import the styles import 'vue-loading-overlay/dist/vue-loading.css' Object.keys(rules).forEach((rule) => { @@ -41,19 +34,20 @@ Object.keys(rules).forEach((rule) => { message: messages[rule], // assign message }) }) + export default { install(Vue) { Vue.use(GlobalComponents) Vue.use(GlobalDirectives) Vue.use(SideBar) - Vue.use(Notifications) + Vue.use(PortalVue) Vue.use(BootstrapVue) Vue.use(IconsPlugin) - Vue.use(VueGoodTablePlugin) + Vue.use(VueBootstrapToasts) Vue.use(VueMoment) Vue.use(VueQrcodeReader) Vue.use(VueQrcode) - Vue.use(VueFlatPickr) + Vue.use(FlatPickr) Vue.use(Loading) configure({ classes: { diff --git a/frontend/src/plugins/globalComponents.js b/frontend/src/plugins/globalComponents.js index 312f19296..b358e274c 100755 --- a/frontend/src/plugins/globalComponents.js +++ b/frontend/src/plugins/globalComponents.js @@ -1,38 +1,7 @@ -import BaseInput from '@/components/Inputs/BaseInput.vue' -import BaseDropdown from '@/components/BaseDropdown.vue' -import Card from '@/components/Cards/Card.vue' -import Modal from '@/components/Modal.vue' -import StatsCard from '@/components/Cards/StatsCard.vue' -import BaseButton from '@/components/BaseButton.vue' -import Badge from '@/components/Badge.vue' -import BaseCheckbox from '@/components/Inputs/BaseCheckbox.vue' -import BaseRadio from '@/components/Inputs/BaseRadio' -import BaseProgress from '@/components/BaseProgress' -import BasePagination from '@/components/BasePagination' -import BaseAlert from '@/components/BaseAlert' -import BaseNav from '@/components/Navbar/BaseNav' -import BaseHeader from '@/components/BaseHeader' import { ValidationProvider, ValidationObserver } from 'vee-validate' -/** - * You can register global components here and use them as a plugin in your main Vue instance - */ const GlobalComponents = { install(Vue) { - Vue.component(Badge.name, Badge) - Vue.component(BaseAlert.name, BaseAlert) - Vue.component(BaseButton.name, BaseButton) - Vue.component(BaseCheckbox.name, BaseCheckbox) - Vue.component(BaseHeader.name, BaseHeader) - Vue.component(BaseInput.name, BaseInput) - Vue.component(BaseDropdown.name, BaseDropdown) - Vue.component(BaseNav.name, BaseNav) - Vue.component(BasePagination.name, BasePagination) - Vue.component(BaseProgress.name, BaseProgress) - Vue.component(BaseRadio.name, BaseRadio) - Vue.component(Card.name, Card) - Vue.component(Modal.name, Modal) - Vue.component(StatsCard.name, StatsCard) Vue.component('validation-provider', ValidationProvider) Vue.component('validation-observer', ValidationObserver) }, diff --git a/frontend/src/plugins/globalDirectives.js b/frontend/src/plugins/globalDirectives.js index 47be32e27..56d8c9e13 100755 --- a/frontend/src/plugins/globalDirectives.js +++ b/frontend/src/plugins/globalDirectives.js @@ -1,4 +1,5 @@ import clickOutside from '@/directives/click-ouside.js' +import { focus } from 'vue-focus' /** * You can register global directives here and use them as a plugin in your main Vue instance @@ -7,6 +8,7 @@ import clickOutside from '@/directives/click-ouside.js' const GlobalDirectives = { install(Vue) { Vue.directive('click-outside', clickOutside) + Vue.directive('focus', focus) }, } diff --git a/frontend/src/routes/routes.js b/frontend/src/routes/routes.js index 16ab3d78f..44ef1f27a 100755 --- a/frontend/src/routes/routes.js +++ b/frontend/src/routes/routes.js @@ -16,25 +16,11 @@ const routes = [ }, { path: '/profile', - component: () => import('../views/Pages/UserProfile.vue'), + component: () => import('../views/Pages/UserProfileOverview.vue'), meta: { requiresAuth: true, }, }, - // { - // path: '/profileedit', - // component: () => import('../views/Pages/UserProfileEdit.vue'), - // meta: { - // requiresAuth: true, - // }, - // }, - // { - // path: '/activity', - // component: () => import('../views/Pages/UserProfileActivity.vue'), - // meta: { - // requiresAuth: true, - // }, - // }, { path: '/transactions', component: () => import('../views/Pages/UserProfileTransactionList.vue'), diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js index 1d89894fb..9b98645bd 100644 --- a/frontend/src/store/store.js +++ b/frontend/src/store/store.js @@ -13,6 +13,18 @@ export const mutations = { sessionId: (state, sessionId) => { state.sessionId = sessionId }, + username: (state, username) => { + state.username = username + }, + firstName: (state, firstName) => { + state.firstName = firstName + }, + lastName: (state, lastName) => { + state.lastName = lastName + }, + description: (state, description) => { + state.description = description + }, } export const actions = { @@ -20,10 +32,18 @@ export const actions = { commit('sessionId', data.sessionId) commit('email', data.user.email) commit('language', data.user.language) + commit('username', data.user.username) + commit('firstName', data.user.first_name) + commit('lastName', data.user.last_name) + commit('description', data.user.description) }, logout: ({ commit, state }) => { commit('sessionId', null) commit('email', null) + commit('username', '') + commit('firstName', '') + commit('lastName', '') + commit('description', '') sessionStorage.clear() }, } @@ -38,7 +58,10 @@ export const store = new Vuex.Store({ sessionId: null, email: '', language: null, - modals: false, + firstName: '', + lastName: '', + username: '', + description: '', }, getters: {}, // Syncronous mutation of the state diff --git a/frontend/src/store/store.test.js b/frontend/src/store/store.test.js index 11dd5949b..6bc004273 100644 --- a/frontend/src/store/store.test.js +++ b/frontend/src/store/store.test.js @@ -40,7 +40,7 @@ describe('Vuex store', () => { { commit, state }, { sessionId: 1234, user: { email: 'someone@there.is', language: 'en' } }, ) - expect(commit).toHaveBeenCalledTimes(3) + expect(commit).toHaveBeenCalledTimes(7) }) it('commits sessionId', () => { @@ -74,7 +74,7 @@ describe('Vuex store', () => { it('calls two commits', () => { logout({ commit, state }) - expect(commit).toHaveBeenCalledTimes(2) + expect(commit).toHaveBeenCalledTimes(6) }) it('commits sessionId', () => { diff --git a/frontend/src/views/Layout/DashboardLayout_gdd.spec.js b/frontend/src/views/Layout/DashboardLayout_gdd.spec.js index 84c955042..62ce94322 100644 --- a/frontend/src/views/Layout/DashboardLayout_gdd.spec.js +++ b/frontend/src/views/Layout/DashboardLayout_gdd.spec.js @@ -78,7 +78,7 @@ describe('DashboardLayoutGdd', () => { }) it('has five items in the navbar', () => { - expect(navbar.findAll('ul > a')).toHaveLength(2) + expect(navbar.findAll('ul > a')).toHaveLength(3) }) it('has first item "send" in navbar', () => { @@ -103,21 +103,21 @@ describe('DashboardLayoutGdd', () => { expect(wrapper.findComponent(RouterLinkStub).props().to).toBe('/transactions') }) - // it('has tree items in the navbar', () => { - // expect(navbar.findAll('ul > li')).toHaveLength(3) - // }) - // - // it('has third item "My profile" in navbar', () => { - // expect(navbar.findAll('ul > li').at(2).text()).toEqual('site.navbar.my-profil') - // }) - // - // it.skip('has third item "My profile" linked to profile in navbar', async () => { - // navbar.findAll('ul > li > a').at(2).trigger('click') - // await flushPromises() - // await jest.runAllTimers() - // await flushPromises() - // expect(wrapper.findComponent(RouterLinkStub).props().to).toBe('/profile') - // }) + it('has tree items in the navbar', () => { + expect(navbar.findAll('ul > a')).toHaveLength(3) + }) + + it('has third item "My profile" in navbar', () => { + expect(navbar.findAll('ul > a').at(2).text()).toEqual('site.navbar.my-profil') + }) + + it.skip('has third item "My profile" linked to profile in navbar', async () => { + navbar.findAll('ul > a').at(2).trigger('click') + await flushPromises() + await jest.runAllTimers() + await flushPromises() + expect(wrapper.findComponent(RouterLinkStub).props().to).toBe('/profile') + }) // it('has fourth item "Settigs" in navbar', () => { // expect(navbar.findAll('ul > li').at(3).text()).toEqual('site.navbar.settings') diff --git a/frontend/src/views/Layout/DashboardLayout_gdd.vue b/frontend/src/views/Layout/DashboardLayout_gdd.vue index d6b9f44ff..4d65aed70 100755 --- a/frontend/src/views/Layout/DashboardLayout_gdd.vue +++ b/frontend/src/views/Layout/DashboardLayout_gdd.vue @@ -1,7 +1,8 @@ diff --git a/frontend/src/views/Pages/Explorer.vue b/frontend/src/views/Pages/Explorer.vue deleted file mode 100644 index 4d1f7ab27..000000000 --- a/frontend/src/views/Pages/Explorer.vue +++ /dev/null @@ -1,32 +0,0 @@ - diff --git a/frontend/src/views/Pages/ForgotPassword.vue b/frontend/src/views/Pages/ForgotPassword.vue index 32331d080..eebba0ced 100644 --- a/frontend/src/views/Pages/ForgotPassword.vue +++ b/frontend/src/views/Pages/ForgotPassword.vue @@ -17,19 +17,31 @@ - + - + v-slot="validationContext" + > + + + + + {{ validationContext.errors[0] }} + + + +
- + {{ $t('site.password.reset_now') }}
@@ -58,14 +70,15 @@ export default { }, } }, + created() {}, methods: { + getValidationState({ dirty, validated, valid = null }) { + return dirty || validated ? valid : null + }, async onSubmit() { - const result = await loginAPI.sendEmail(this.form.email) - if (result.success) { - this.$router.push('/thx/password') - } else { - alert(result.result) - } + await loginAPI.sendEmail(this.form.email) + // always give success to avoid email spying + this.$router.push('/thx/password') }, }, } diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index a6d795bb1..4619dddf2 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -22,34 +22,63 @@
{{ $t('login') }}
- - - + + + v-slot="validationContext" + > + + - - + + {{ validationContext.errors[0] }} + + + - - - - - - + + + + + + + + + + + + + {{ validationContext.errors[0] }} + + + @@ -62,12 +91,8 @@ - - -
- - {{ $t('site.login.signin') }} - +
+ {{ $t('login') }}
@@ -98,7 +123,7 @@ export default { name: 'login', data() { return { - model: { + form: { email: '', password: '', // rememberMe: false @@ -109,6 +134,10 @@ export default { } }, methods: { + getValidationState({ dirty, validated, valid = null }) { + return dirty || validated ? valid : null + }, + togglePasswordVisibility() { this.passwordVisible = !this.passwordVisible }, @@ -118,7 +147,7 @@ export default { const loader = this.$loading.show({ container: this.$refs.submitButton, }) - const result = await loginAPI.login(this.model.email, this.model.password) + const result = await loginAPI.login(this.form.email, this.form.password) if (result.success) { this.$store.dispatch('login', { sessionId: result.result.data.session_id, diff --git a/frontend/src/views/Pages/Register.spec.js b/frontend/src/views/Pages/Register.spec.js index 3d4296567..36ee6987b 100644 --- a/frontend/src/views/Pages/Register.spec.js +++ b/frontend/src/views/Pages/Register.spec.js @@ -53,16 +53,27 @@ describe('Register', () => { expect(wrapper.find('form').exists()).toBeTruthy() }) - it('has 3 text input fields', () => { - expect(wrapper.findAll('input[type="text"]').length).toBe(3) + it('has firstname input fields', () => { + expect(wrapper.find('#registerFirstname').exists()).toBeTruthy() + }) + it('has lastname input fields', () => { + expect(wrapper.find('#registerLastname').exists()).toBeTruthy() }) - it('has 2 password input fields', () => { - expect(wrapper.findAll('input[type="password"]').length).toBe(2) + it('has email input fields', () => { + expect(wrapper.find('#registerEmail').exists()).toBeTruthy() + }) + + it('has password input fields', () => { + expect(wrapper.find('#registerPassword').exists()).toBeTruthy() + }) + + it('has password repeat input fields', () => { + expect(wrapper.find('#registerPasswordRepeat').exists()).toBeTruthy() }) it('has 1 checkbox input fields', () => { - expect(wrapper.findAll('input[type="checkbox"]').length).toBe(1) + expect(wrapper.find('#registerCheckbox').exists()).toBeTruthy() }) it('has no submit button when not completely filled', () => { @@ -70,9 +81,9 @@ describe('Register', () => { }) it('shows a warning when no valid Email is entered', async () => { - wrapper.findAll('input[type="text"]').at(2).setValue('no_valid@Email') + wrapper.find('#registerEmail').setValue('no_valid@Email') await flushPromises() - await expect(wrapper.find('.invalid-feedback').text()).toEqual( + await expect(wrapper.find('#registerEmailLiveFeedback').text()).toEqual( 'The Email field must be a valid email', ) }) diff --git a/frontend/src/views/Pages/Register.vue b/frontend/src/views/Pages/Register.vue index d7b9ab8f0..7f475ebae 100755 --- a/frontend/src/views/Pages/Register.vue +++ b/frontend/src/views/Pages/Register.vue @@ -23,65 +23,137 @@
{{ $t('signup') }}
- - - - - + + + + + + + {{ validationContext.errors[0] }} + + + + + + + + + + {{ validationContext.errors[0] }} + + + + + + v-slot="validationContext" + > + + + + + {{ validationContext.errors[0] }} + + +
- + + + + + + + + + + + + + + {{ validationContext.errors[0] }} + + + + + - - + + - -
    @@ -99,14 +171,13 @@ - - - - - + + - - {{ $t('signup') }} - +
    + {{ $t('form.reset') }} + {{ $t('signup') }} +
@@ -157,41 +229,61 @@ export default { name: 'register', data() { return { - model: { + form: { firstname: '', lastname: '', email: '', agree: false, + password: '', + passwordRepeat: '', }, - password: '', - checkPassword: '', passwordVisible: false, + passwordVisibleRepeat: false, submitted: false, showError: false, messageError: '', } }, methods: { + getValidationState({ dirty, validated, valid = null }) { + return dirty || validated ? valid : null + }, + resetForm() { + this.form = { + firstname: '', + lastname: '', + email: '', + password: '', + passwordRepeat: '', + } + this.$nextTick(() => { + this.$refs.observer.reset() + }) + }, togglePasswordVisibility() { this.passwordVisible = !this.passwordVisible }, + togglePasswordRepeatVisibility() { + this.passwordVisibleRepeat = !this.passwordVisibleRepeat + }, async onSubmit() { const result = await loginAPI.create( - this.model.email, - this.model.firstname, - this.model.lastname, - this.password, + this.form.email, + this.form.firstname, + this.form.lastname, + this.form.password, ) if (result.success) { this.$store.dispatch('login', { sessionId: result.result.data.session_id, - email: this.model.email, + email: this.form.email, }) - this.model.email = '' - this.model.firstname = '' - this.model.lastname = '' + this.form.email = '' + this.form.firstname = '' + this.form.lastname = '' this.password = '' + this.passwordVisibleRepeat = '' this.$router.push('/thx/register') } else { this.showError = true @@ -201,29 +293,29 @@ export default { closeAlert() { this.showError = false this.messageError = '' - this.model.email = '' - this.model.firstname = '' - this.model.lastname = '' - this.password = '' + this.form.email = '' + this.form.firstname = '' + this.form.lastname = '' + this.form.password = '' }, }, computed: { samePasswords() { - return this.password === this.checkPassword + return this.form.password === this.form.passwordRepeat }, passwordsFilled() { - return this.password !== '' && this.checkPassword !== '' + return this.form.password !== '' && this.form.passwordRepeat !== '' }, namesFilled() { return ( - this.model.firstname !== '' && - this.model.firstname.length > 2 && - this.model.lastname !== '' && - this.model.lastname.length > 1 + this.form.firstname !== '' && + this.form.firstname.length > 2 && + this.form.lastname !== '' && + this.form.lastname.length > 1 ) }, emailFilled() { - return this.model.email !== '' + return this.form.email !== '' }, rules() { return [ @@ -236,7 +328,7 @@ export default { passwordValidation() { const errors = [] for (const condition of this.rules) { - if (!condition.regex.test(this.password)) { + if (!condition.regex.test(this.form.password)) { errors.push(condition.message) } } diff --git a/frontend/src/views/Pages/ResetPassword.vue b/frontend/src/views/Pages/ResetPassword.vue index 99892612c..1d62349b7 100644 --- a/frontend/src/views/Pages/ResetPassword.vue +++ b/frontend/src/views/Pages/ResetPassword.vue @@ -20,38 +20,63 @@ - + - + + + + + + + + + + + + + {{ validationContext.errors[0] }} + + + + + - - + + - -
    @@ -90,8 +115,11 @@ export default { name: 'reset', data() { return { + form: { + password: '', + passwordRepeat: '', + }, password: '', - checkPassword: '', passwordVisible: false, submitted: false, authenticated: false, @@ -100,22 +128,25 @@ export default { } }, methods: { + getValidationState({ dirty, validated, valid = null }) { + return dirty || validated ? valid : null + }, togglePasswordVisibility() { this.passwordVisible = !this.passwordVisible }, async onSubmit() { - const result = await loginAPI.changePassword(this.sessionId, this.email, this.password) + const result = await loginAPI.changePassword(this.sessionId, this.email, this.form.password) if (result.success) { - this.password = '' + this.form.password = '' /* - this.$store.dispatch('login', { - sessionId: result.result.data.session_id, - email: result.result.data.user.email, - }) - */ + this.$store.dispatch('login', { + sessionId: result.result.data.session_id, + email: result.result.data.user.email, + }) + */ this.$router.push('/thx/reset') } else { - alert(result.result.message) + this.$toast.error(result.result.message) } }, async authenticate() { @@ -126,16 +157,16 @@ export default { this.sessionId = result.result.data.session_id this.email = result.result.data.user.email } else { - alert(result.result.message) + this.$toast.error(result.result.message) } }, }, computed: { samePasswords() { - return this.password === this.checkPassword + return this.form.password === this.form.passwordRepeat }, passwordsFilled() { - return this.password !== '' && this.checkPassword !== '' + return this.form.password !== '' && this.form.passwordRepeat !== '' }, rules() { return [ @@ -148,7 +179,7 @@ export default { passwordValidation() { const errors = [] for (const condition of this.rules) { - if (!condition.regex.test(this.password)) { + if (!condition.regex.test(this.form.password)) { errors.push(condition.message) } } diff --git a/frontend/src/views/Pages/UserProfile.vue b/frontend/src/views/Pages/UserProfile.vue deleted file mode 100644 index 882b52e78..000000000 --- a/frontend/src/views/Pages/UserProfile.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/frontend/src/views/Pages/UserProfile/EditProfileForm.vue b/frontend/src/views/Pages/UserProfile/EditProfileForm.vue deleted file mode 100755 index dbf9a3064..000000000 --- a/frontend/src/views/Pages/UserProfile/EditProfileForm.vue +++ /dev/null @@ -1,134 +0,0 @@ - - - diff --git a/frontend/src/views/Pages/UserProfile/ImageUploaderAvatar.vue b/frontend/src/views/Pages/UserProfile/ImageUploaderAvatar.vue deleted file mode 100644 index 8c35b918a..000000000 --- a/frontend/src/views/Pages/UserProfile/ImageUploaderAvatar.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - diff --git a/frontend/src/views/Pages/UserProfile/UserCard.vue b/frontend/src/views/Pages/UserProfile/UserCard.vue index ba9678d76..44c933485 100755 --- a/frontend/src/views/Pages/UserProfile/UserCard.vue +++ b/frontend/src/views/Pages/UserProfile/UserCard.vue @@ -1,67 +1,41 @@ diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.vue b/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.vue new file mode 100644 index 000000000..1fa26b5e0 --- /dev/null +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.vue @@ -0,0 +1,146 @@ + + + diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUserMail.vue b/frontend/src/views/Pages/UserProfile/UserCard_FormUserMail.vue new file mode 100644 index 000000000..c41ba367c --- /dev/null +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUserMail.vue @@ -0,0 +1,62 @@ + + + diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.vue b/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.vue new file mode 100644 index 000000000..6bc1d8942 --- /dev/null +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.vue @@ -0,0 +1,158 @@ + + + diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.vue b/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.vue new file mode 100644 index 000000000..2b3b451fe --- /dev/null +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.vue @@ -0,0 +1,94 @@ + + + diff --git a/frontend/src/views/Pages/UserProfileActivity.vue b/frontend/src/views/Pages/UserProfileActivity.vue deleted file mode 100644 index 6d69bc162..000000000 --- a/frontend/src/views/Pages/UserProfileActivity.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - diff --git a/frontend/src/views/Pages/UserProfileEdit.vue b/frontend/src/views/Pages/UserProfileEdit.vue deleted file mode 100644 index 1fb1d220f..000000000 --- a/frontend/src/views/Pages/UserProfileEdit.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - diff --git a/frontend/src/views/Pages/UserProfileOverview.spec.js b/frontend/src/views/Pages/UserProfileOverview.spec.js new file mode 100644 index 000000000..617e0ade0 --- /dev/null +++ b/frontend/src/views/Pages/UserProfileOverview.spec.js @@ -0,0 +1,38 @@ +import { shallowMount } from '@vue/test-utils' +import UserProfileOverview from './UserProfileOverview' + +const localVue = global.localVue + +describe('UserProfileOverview', () => { + let wrapper + + const mocks = { + $t: jest.fn((t) => t), + } + + const Wrapper = () => { + return shallowMount(UserProfileOverview, { localVue, mocks }) + } + + describe('shallow Mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('has a user card', () => { + expect(wrapper.findComponent({ name: 'UserCard' }).exists()).toBeTruthy() + }) + + it('has a user data form', () => { + expect(wrapper.findComponent({ name: 'FormUserData' }).exists()).toBeTruthy() + }) + + it('has a user name form', () => { + expect(wrapper.findComponent({ name: 'FormUsername' }).exists()).toBeTruthy() + }) + + it('has a user password form', () => { + expect(wrapper.findComponent({ name: 'FormUserPasswort' }).exists()).toBeTruthy() + }) + }) +}) diff --git a/frontend/src/views/Pages/UserProfileOverview.vue b/frontend/src/views/Pages/UserProfileOverview.vue new file mode 100644 index 000000000..0708a2329 --- /dev/null +++ b/frontend/src/views/Pages/UserProfileOverview.vue @@ -0,0 +1,28 @@ + + + diff --git a/frontend/src/views/Pages/UserProfileTransactionList.vue b/frontend/src/views/Pages/UserProfileTransactionList.vue index 1b5b30f7b..f1896acc7 100644 --- a/frontend/src/views/Pages/UserProfileTransactionList.vue +++ b/frontend/src/views/Pages/UserProfileTransactionList.vue @@ -1,16 +1,18 @@