Merge branch 'master' into api_password_reset

This commit is contained in:
einhornimmond 2021-03-31 12:38:52 +02:00 committed by GitHub
commit d1667e0ba9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
126 changed files with 10270 additions and 12870 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
*.log
/node_modules/*
/node_modules/*
.vscode

View File

@ -4,8 +4,49 @@ All notable changes to this project will be documented in this file. Dates are d
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
#### [0.9.4](https://github.com/gradido/gradido/compare/0.9.3...0.9.4)
- Build on run [`#103`](https://github.com/gradido/gradido/pull/103)
- update debug docker to use dependencies container pushed to docker hub [`1f002f4`](https://github.com/gradido/gradido/commit/1f002f4ed0b12d4b2bf63efceabe546d0c5b58ea)
- removed email tasks complete [`8a143be`](https://github.com/gradido/gradido/commit/8a143be8423d7bd894d4f512848895df8b9694b0)
- build login-server on docker-compose up in a docker volume so it rebuild only neccessary parts if some c++ files have changed [`0da5279`](https://github.com/gradido/gradido/commit/0da527917523530186e6effe63dc001fc99bd3e3)
#### [0.9.3](https://github.com/gradido/gradido/compare/0.9.2...0.9.3)
> 30 March 2021
- new version 0.9.3 [`#110`](https://github.com/gradido/gradido/pull/110)
- feat: Frontend tests for Content Footer [`#102`](https://github.com/gradido/gradido/pull/102)
- add check session state json function and doc [`#96`](https://github.com/gradido/gradido/pull/96)
- activity page stap 2 [`#86`](https://github.com/gradido/gradido/pull/86)
- qrcode scanner fixed, datum in activitäten fixed, sprache not null fixed [`#88`](https://github.com/gradido/gradido/pull/88)
- add additional docker container which is running skeema on startup to… [`#83`](https://github.com/gradido/gradido/pull/83)
- New fix up frontend for presentation [`#85`](https://github.com/gradido/gradido/pull/85)
- feat: Tougher eslint rules [`#77`](https://github.com/gradido/gradido/pull/77)
- feat: improve translations [`#81`](https://github.com/gradido/gradido/pull/81)
- use_correct_send_api [`#80`](https://github.com/gradido/gradido/pull/80)
- fix bug with access rights [`#78`](https://github.com/gradido/gradido/pull/78)
- make response.html better accessible [`#75`](https://github.com/gradido/gradido/pull/75)
- feat: Lokalize Validation Messages [`#67`](https://github.com/gradido/gradido/pull/67)
- feat: Localize links to gradito.net [`#74`](https://github.com/gradido/gradido/pull/74)
- fix-padding [`#73`](https://github.com/gradido/gradido/pull/73)
- Correctly use transactions API in frontend [`#69`](https://github.com/gradido/gradido/pull/69)
- Qr code scanner [`#72`](https://github.com/gradido/gradido/pull/72)
- Login fail message [`#71`](https://github.com/gradido/gradido/pull/71)
- Setup unit tests for frontend [`#55`](https://github.com/gradido/gradido/pull/55)
- Update doc [`#63`](https://github.com/gradido/gradido/pull/63)
- Add Feature in user search old frontend because Support has requested the feature long ago [`#56`](https://github.com/gradido/gradido/pull/56)
- sprache angepasst, for login, pwd, sigin [`#54`](https://github.com/gradido/gradido/pull/54)
- Improve workflows [`#53`](https://github.com/gradido/gradido/pull/53)
- setup eslint with tougher rules [`1f13507`](https://github.com/gradido/gradido/commit/1f13507eacfd93c2248fb841de5f481c9eb1e6bd)
- semicolon rule implemented [`6762a02`](https://github.com/gradido/gradido/commit/6762a028f2a3e4f2713b26bed81029defe686ad7)
- dev meeting, bernd [`a99de7f`](https://github.com/gradido/gradido/commit/a99de7f5d1f7557c0877eae565aa4263d65aaaf3)
#### [0.9.2](https://github.com/gradido/gradido/compare/0.9.1...0.9.2)
> 18 March 2021
- v0.9.2 [`#51`](https://github.com/gradido/gradido/pull/51)
- Reload after login fixed [`#50`](https://github.com/gradido/gradido/pull/50)
- Monorepo login server [`#48`](https://github.com/gradido/gradido/pull/48)
- Stage0 [`#3`](https://github.com/gradido/gradido/pull/3)

View File

@ -1,17 +1,17 @@
FROM phpdockerio/php74-fpm
# 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 clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
WORKDIR /var/www/cakephp
RUN mkdir logs && mkdir tmp && chmod 777 logs && chmod 777 tmp
COPY ./community_server/ .
COPY ./configs/community_server/app.php ./config/
RUN composer update
RUN composer dump-autoload
FROM phpdockerio/php74-fpm
# 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 clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
WORKDIR /var/www/cakephp
RUN mkdir logs && mkdir tmp && chmod 777 logs && chmod 777 tmp
COPY ./community_server/ .
COPY ./configs/community_server/app.php ./config/
RUN composer update
RUN composer dump-autoload

View File

@ -1,25 +1,25 @@
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;

View File

@ -1,88 +1,88 @@
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/png png;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
image/svg+xml svg svgz;
image/webp webp;
application/font-woff woff;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.wap.wmlc wmlc;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx;
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/png png;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
image/svg+xml svg svgz;
image/webp webp;
application/font-woff woff;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.wap.wmlc wmlc;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx;
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}

View File

@ -1,86 +1,86 @@
server {
listen 80 ;
listen [::]:80;
server_name 0.0.0.0;
#include /etc/nginx/common/protect.conf;
#include /etc/nginx/common/protect_add_header.conf;
#include /etc/nginx/common/ssl.conf;
root /usr/share/nginx/html/webroot;
index index.php;
location ~* \.(png|jpg|ico|webp)\$ {
expires 30d;
}
location ~* \.(js|css) {
# expires 1d;
expires 1d;
}
location ~ \.php\$ {
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Check that the PHP script exists before passing it
try_files $fastcgi_script_name =404;
# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
include fastcgi.conf;
#fastcgi_pass unix:/run/php/php7.3-fpm.sock;
fastcgi_pass 127.0.0.1:9000;
}
location ~ /\.ht {
deny all;
}
location /account {
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass \$http_upgrade;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$remote_addr;
proxy_set_header Host \$host;
rewrite /account/(.*) /\$1 break;
#proxy_next_upstream error timeout invalid_header http_502 non_idempotent;
proxy_pass http://login-server:1200;
proxy_redirect off;
}
location /login_api {
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass \$http_upgrade;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$remote_addr;
proxy_set_header Host \$host;
rewrite /login_api/(.*) /\$1 break;
proxy_pass http://login-server:1201;
proxy_redirect off;
}
location / {
try_files \$uri \$uri/ /index.php?\$args;
}
# access_log /var/log/nginx/access.log main;
server {
listen 80 ;
listen [::]:80;
server_name 0.0.0.0;
#include /etc/nginx/common/protect.conf;
#include /etc/nginx/common/protect_add_header.conf;
#include /etc/nginx/common/ssl.conf;
root /usr/share/nginx/html/webroot;
index index.php;
location ~* \.(png|jpg|ico|webp)\$ {
expires 30d;
}
location ~* \.(js|css) {
# expires 1d;
expires 1d;
}
location ~ \.php\$ {
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Check that the PHP script exists before passing it
try_files $fastcgi_script_name =404;
# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
include fastcgi.conf;
#fastcgi_pass unix:/run/php/php7.3-fpm.sock;
fastcgi_pass 127.0.0.1:9000;
}
location ~ /\.ht {
deny all;
}
location /account {
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass \$http_upgrade;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$remote_addr;
proxy_set_header Host \$host;
rewrite /account/(.*) /\$1 break;
#proxy_next_upstream error timeout invalid_header http_502 non_idempotent;
proxy_pass http://login-server:1200;
proxy_redirect off;
}
location /login_api {
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass \$http_upgrade;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$remote_addr;
proxy_set_header Host \$host;
rewrite /login_api/(.*) /\$1 break;
proxy_pass http://login-server:1201;
proxy_redirect off;
}
location / {
try_files \$uri \$uri/ /index.php?\$args;
}
# access_log /var/log/nginx/access.log main;
}

View File

@ -1,8 +1,8 @@
CREATE TABLE `community_profiles` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`state_user_id` int(10) unsigned NOT NULL,
`profile_img` longblob,
`profile_desc` varchar(2000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `state_user_id` (`state_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `community_profiles` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`state_user_id` int(10) unsigned NOT NULL,
`profile_img` longblob,
`profile_desc` varchar(2000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `state_user_id` (`state_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@ -1,71 +1,71 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace App\Controller\Component;
use Cake\Controller\Component;
use Cake\Http\Client;
use Cake\Core\Configure;
use Datto\JsonRpc\Client as JsonRpcClient;
//App\Controller\Component\ComponentRegistry
class JsonRpcRequestClientComponent extends Component
{
var $rpcClient = null;
public function __construct($registry, array $config = array()) {
parent::__construct($registry, $config);
$this->rpcClient = new JsonRpcClient();
}
// @param id: if id = 0 call rand for it
public function request($method, $params = [], $id = 0)
{
if(0 == $id) {
$id = random_int(1, 12000);
}
$this->rpcClient->query($id, $method, $params);
$message = $this->rpcClient->encode();
return $this->sendRequest($message);
// message: {"jsonrpc":"2.0","method":"add","params":[1,2],"id":1}
}
public function sendRequest($message) {
$http = new Client();
$response = $http->post($this->getGradidoNodeUrl(), $message, ['type' => 'json']);
$responseStatus = $response->getStatusCode();
if($responseStatus != 200) {
return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response status code isn\'t 200', 'details' => $responseStatus];
}
//$responseType = $response->getType();
//if($responseType != 'application/json') {
// return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t json', 'details' => $responseType];
// }
$json = $response->getJson();
if($json == null) {
//$responseType = $response->getType();
return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t valid json'];
}
return $json;
//return ['state' => 'success', 'data' => $json];
}
static public function getGradidoNodeUrl()
{
$gradidoNode = Configure::read('GradidoNode');
return $gradidoNode['host'] . ':' . $gradidoNode['port'];
}
}
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace App\Controller\Component;
use Cake\Controller\Component;
use Cake\Http\Client;
use Cake\Core\Configure;
use Datto\JsonRpc\Client as JsonRpcClient;
//App\Controller\Component\ComponentRegistry
class JsonRpcRequestClientComponent extends Component
{
var $rpcClient = null;
public function __construct($registry, array $config = array()) {
parent::__construct($registry, $config);
$this->rpcClient = new JsonRpcClient();
}
// @param id: if id = 0 call rand for it
public function request($method, $params = [], $id = 0)
{
if(0 == $id) {
$id = random_int(1, 12000);
}
$this->rpcClient->query($id, $method, $params);
$message = $this->rpcClient->encode();
return $this->sendRequest($message);
// message: {"jsonrpc":"2.0","method":"add","params":[1,2],"id":1}
}
public function sendRequest($message) {
$http = new Client();
$response = $http->post($this->getGradidoNodeUrl(), $message, ['type' => 'json']);
$responseStatus = $response->getStatusCode();
if($responseStatus != 200) {
return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response status code isn\'t 200', 'details' => $responseStatus];
}
//$responseType = $response->getType();
//if($responseType != 'application/json') {
// return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t json', 'details' => $responseType];
// }
$json = $response->getJson();
if($json == null) {
//$responseType = $response->getType();
return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t valid json'];
}
return $json;
//return ['state' => 'success', 'data' => $json];
}
static public function getGradidoNodeUrl()
{
$gradidoNode = Configure::read('GradidoNode');
return $gradidoNode['host'] . ':' . $gradidoNode['port'];
}
}

View File

@ -39,32 +39,143 @@ class StateBalancesController extends AppController
$this->set(compact('stateBalances'));
}
private function updateBalances($state_user_id)
private function updateBalances($stateUserId)
{
$state_balances = $this->StateBalances->find('all')->where(['state_user_id' => $state_user_id]);
if($state_balances->count() == 1) {
$stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
$state_user_transactions = $stateUserTransactionsTable
$stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
$transactionsTable = TableRegistry::getTableLocator()->get('Transactions');
// info: cakephp use lazy loading, query will be executed later only if needed
$state_balances = $this->StateBalances->find('all')->where(['state_user_id' => $stateUserId]);
$state_user_transactions = $stateUserTransactionsTable
->find('all')
->where(['state_user_id' => $state_user_id])
->where(['state_user_id' => $stateUserId])
->order(['transaction_id ASC'])
->contain(['']);
if($state_user_transactions->count() == 0){
return;
}
$last_state_user_transaction = $state_user_transactions->last();
$last_transaction = $this->StateBalance->newEntity();
$last_transaction->amount = $last_state_user_transaction->balance;
$last_transaction->record_date = $last_state_user_transaction->balance_date;
// if entrys are nearly the same, we don't need doing anything
if(abs($last_transaction->decay - $state_balances->decay) < 100) {
return;
}
foreach($state_user_transactions as $state_user_transaction) {
}
->contain(false);
if(!$state_user_transactions) {
//debug($state_user_transactions);
return true;
}
// first: decide what todo
$create_state_balance = false;
$recalculate_state_user_transactions_balance = false;
$clear_state_balance = false;
$update_state_balance = false;
if($state_balances->count() == 0) {
$create_state_balance = true;
}
if($state_balances->count() > 1) {
$clear_state_balance = true;
$create_state_balance = true;
}
if($state_balances->count() == 1) {
if($state_user_transactions->count() == 0){
$clear_state_balance = true;
} else {
$last_state_user_transaction = $state_user_transactions->last();
$last_transaction = $this->StateBalances->newEntity();
$last_transaction->amount = $last_state_user_transaction->balance;
$last_transaction->record_date = $last_state_user_transaction->balance_date;
// if entrys are nearly the same, we don't need doing anything
if(abs($last_transaction->decay - $state_balances->first()->decay) > 100) {
$recalculate_state_user_transactions_balance = true;
$update_state_balance = true;
}
}
}
if(!$recalculate_state_user_transactions_balance) {
$last_state_user_transaction = $state_user_transactions->last();
if($last_state_user_transaction->balance <= 0) {
$recalculate_state_user_transactions_balance = true;
if(!$create_state_balance) {
$update_state_balance = true;
}
}
}
// second: do what is needed
if($clear_state_balance) {
$this->StateBalances->deleteAll(['state_user_id' => $stateUserId]);
}
$transaction_ids = [];
if($recalculate_state_user_transactions_balance) {
$state_user_transactions_array = $state_user_transactions->toArray();
foreach($state_user_transactions_array as $i => $state_user_transaction) {
$transaction_ids[$state_user_transaction->transaction_id] = $i;
}
$transactions = $transactionsTable
->find('all')
->where(['id IN' => array_keys($transaction_ids)])
->contain(['TransactionCreations', 'TransactionSendCoins']);
$balance_cursor = $this->StateBalances->newEntity();
$i = 0;
foreach($transactions as $transaction) {
if($transaction->transaction_type_id > 2) {
continue;
}
$amount_date = null;
$amount = 0;
if($transaction->transaction_type_id == 1) {
$temp = $transaction->transaction_creations[0];
$balance_temp = $this->StateBalances->newEntity();
$balance_temp->amount = $temp->amount;
$balance_temp->record_date = $temp->target_date;
$amount = $balance_temp->partDecay($transaction->received);
$amount_date = $transaction->received;
//$amount_date =
} else if($transaction->transaction_type_id == 2) {
$temp = $transaction->transaction_send_coins[0];
$amount = intval($temp->amount);
// reverse if sender
if($stateUserId == $temp->state_user_id) {
$amount *= -1.0;
}
$amount_date = $transaction->received;
}
if($i == 0) {
$balance_cursor->amount = $amount;
} else {
$balance_cursor->amount = $balance_cursor->partDecay($amount_date) + $amount;
}
$balance_cursor->record_date = $amount_date;
$state_user_transaction_index = $transaction_ids[$transaction->id];
$state_user_transactions_array[$state_user_transaction_index]->balance = $balance_cursor->amount;
$state_user_transactions_array[$state_user_transaction_index]->balance_date = $balance_cursor->record_date;
$i++;
}
$results = $stateUserTransactionsTable->saveMany($state_user_transactions_array);
$errors = [];
foreach($results as $i => $result) {
if(!$result) {
$errors[$i] = $state_user_transactions_array[$i]->getErrors();
}
}
if(count($errors)) {
return ['success' => false, 'error' => 'error saving one ore more state user transactions', 'details' => $errors];
}
}
$state_balance = null;
if($update_state_balance) {
$state_balance = $state_balances->first();
}
else if($create_state_balance) {
$state_balance = $this->StateBalances->newEntity();
$state_balance->state_user_id = $stateUserId;
}
if($state_balance) {
$state_balance->amount = $state_user_transactions->last()->balance;
$state_balance->record_date = $state_user_transactions->last()->balance_date;
if(!$this->StateBalances->save($state_balance)) {
return ['success' => false, 'error' => 'error saving state balance', 'details' => $state_balance->getErrors()];
}
}
return true;
}
public function overview()
@ -82,7 +193,9 @@ class StateBalancesController extends AppController
if ($result !== true) {
return $result;
}
$user = $session->read('StateUser');
$this->updateBalances($user['id']);
// sendRequestGDT
// listPerEmailApi
@ -214,6 +327,7 @@ class StateBalancesController extends AppController
}
$session = $this->getRequest()->getSession();
$user = $session->read('StateUser');
$this->updateBalances($user['id']);
$public_key_bin = hex2bin($user['public_hex']);
$stateUserQuery = $this->StateBalances->StateUsers

View File

@ -69,14 +69,14 @@ class StateUsersController extends AppController
$this->set(compact('stateUsers'));
}
public function listIdentHashes()
/*public function listIdentHashes()
{
$stateUsers = $this->StateUsers->find('all')->toArray();
foreach ($stateUsers as $i => $user) {
$stateUsers[$i]->identHash = TransactionCreation::DRMakeStringHash($user->email);
}
$this->set('stateUsers', $stateUsers);
}
}*/
public function search()
{

View File

@ -54,12 +54,12 @@ class TransactionCreationsController extends AppController
];
$transactionCreations = $this->paginate($this->TransactionCreations);
$identHashes = [];
foreach ($transactionCreations as $creation) {
/*foreach ($transactionCreations as $creation) {
$identHash = TransactionCreation::DRMakeStringHash($creation->state_user->email);
$identHashes[$creation->state_user->id] = $identHash;
}
}*/
$this->set(compact('transactionCreations', 'identHashes'));
//$this->set(compact('transactionCreations', 'identHashes'));
}
/**
@ -125,7 +125,7 @@ class TransactionCreationsController extends AppController
if (count($receiverProposal) > $receiverIndex) {
$pubKeyHex = $receiverProposal[$receiverIndex]['key'];
$identHash = TransactionCreation::DRMakeStringHash($receiverProposal[$receiverIndex]['email']);
//$identHash = TransactionCreation::DRMakeStringHash($receiverProposal[$receiverIndex]['email']);
}
$builderResult = TransactionCreation::build(
$amountCent,
@ -369,7 +369,20 @@ class TransactionCreationsController extends AppController
$pendings[$id] = $localAmountCent;
}
$pubKeyHex = bin2hex(stream_get_contents($receiverUser->public_key));
$identHash = TransactionCreation::DRMakeStringHash($receiverUser->email);
$requestAnswear = $this->JsonRequestClient->sendRequest(json_encode([
'session_id' => $session->read('session_id'),
'email' => $receiverUser->email,
'ask' => ['user.identHash']
]), '/getUserInfos');
$identHash = 0;
if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) {
$identHash = $requestAnswear['data']['userData']['identHash'];
} else {
$this->Flash->error(__('Error by requesting LoginServer, please try again'));
}
//$identHash = TransactionCreation::DRMakeStringHash($receiverUser->email);
$localTargetDateFrozen = FrozenDate::now();
$localTargetDateFrozen = $localTargetDateFrozen
->year($localTargetDate['year'])

View File

@ -57,7 +57,8 @@ class StateBalance extends Entity
if($decay_duration === 0) {
return $this->amount;
}
return $this->amount * pow(0.99999997802044727, $decay_duration);
return $this->amount;
//return $this->amount * pow(0.99999997802044727, $decay_duration);
}
public function partDecay($target_date)
@ -67,7 +68,8 @@ class StateBalance extends Entity
if($decay_duration <= 0) {
return $this->amount;
}
return $this->amount * pow(0.99999997802044727, $decay_duration);
return 0;
//return $this->amount * pow(0.99999997802044727, $decay_duration);
}
public function decayDuration($target_date)

View File

@ -22,9 +22,9 @@ class Key extends \Google\Protobuf\Internal\Message
* Optional. Data for populating the Message object.
*
* @type string $ed25519
* ed25519 signature (libsodium default)
* ed25519 signature (libsodium default)
* @type string $ed25519_ref10
* ed25519 ref10 signature
* ed25519 ref10 signature
* }
*/
public function __construct($data = NULL) {
@ -33,7 +33,7 @@ class Key extends \Google\Protobuf\Internal\Message
}
/**
* ed25519 signature (libsodium default)
* ed25519 signature (libsodium default)
*
* Generated from protobuf field <code>bytes ed25519 = 2;</code>
* @return string
@ -44,7 +44,7 @@ class Key extends \Google\Protobuf\Internal\Message
}
/**
* ed25519 signature (libsodium default)
* ed25519 signature (libsodium default)
*
* Generated from protobuf field <code>bytes ed25519 = 2;</code>
* @param string $var
@ -59,7 +59,7 @@ class Key extends \Google\Protobuf\Internal\Message
}
/**
* ed25519 ref10 signature
* ed25519 ref10 signature
*
* Generated from protobuf field <code>bytes ed25519_ref10 = 3;</code>
* @return string
@ -70,7 +70,7 @@ class Key extends \Google\Protobuf\Internal\Message
}
/**
* ed25519 ref10 signature
* ed25519 ref10 signature
*
* Generated from protobuf field <code>bytes ed25519_ref10 = 3;</code>
* @param string $var

View File

@ -22,7 +22,7 @@ class SenderAmount extends \Google\Protobuf\Internal\Message
*/
private $amount = 0;
/**
* sender balance after transaction, including perishability
* sender balance after transaction, including perishability
*
* Generated from protobuf field <code>sint64 senderFinalBalance = 3;</code>
*/
@ -37,7 +37,7 @@ class SenderAmount extends \Google\Protobuf\Internal\Message
* @type string $ed25519_sender_pubkey
* @type int|string $amount
* @type int|string $senderFinalBalance
* sender balance after transaction, including perishability
* sender balance after transaction, including perishability
* }
*/
public function __construct($data = NULL) {
@ -90,7 +90,7 @@ class SenderAmount extends \Google\Protobuf\Internal\Message
}
/**
* sender balance after transaction, including perishability
* sender balance after transaction, including perishability
*
* Generated from protobuf field <code>sint64 senderFinalBalance = 3;</code>
* @return int|string
@ -101,7 +101,7 @@ class SenderAmount extends \Google\Protobuf\Internal\Message
}
/**
* sender balance after transaction, including perishability
* sender balance after transaction, including perishability
*
* Generated from protobuf field <code>sint64 senderFinalBalance = 3;</code>
* @param int|string $var

View File

@ -14,7 +14,7 @@ use Google\Protobuf\Internal\GPBUtil;
class SignatureMap extends \Google\Protobuf\Internal\Message
{
/**
* Each signature pair corresponds to a unique Key required to sign the transaction.
* Each signature pair corresponds to a unique Key required to sign the transaction.
*
* Generated from protobuf field <code>repeated .model.messages.gradido.SignaturePair sigPair = 1;</code>
*/
@ -27,7 +27,7 @@ class SignatureMap extends \Google\Protobuf\Internal\Message
* 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.
* Each signature pair corresponds to a unique Key required to sign the transaction.
* }
*/
public function __construct($data = NULL) {
@ -36,7 +36,7 @@ class SignatureMap extends \Google\Protobuf\Internal\Message
}
/**
* Each signature pair corresponds to a unique Key required to sign the transaction.
* Each signature pair corresponds to a unique Key required to sign the transaction.
*
* Generated from protobuf field <code>repeated .model.messages.gradido.SignaturePair sigPair = 1;</code>
* @return \Google\Protobuf\Internal\RepeatedField
@ -47,7 +47,7 @@ class SignatureMap extends \Google\Protobuf\Internal\Message
}
/**
* Each signature pair corresponds to a unique Key required to sign the transaction.
* Each signature pair corresponds to a unique Key required to sign the transaction.
*
* Generated from protobuf field <code>repeated .model.messages.gradido.SignaturePair sigPair = 1;</code>
* @param \Model\Messages\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $var

View File

@ -27,9 +27,9 @@ class SignaturePair extends \Google\Protobuf\Internal\Message
*
* @type string $pubKey
* @type string $ed25519
* ed25519 signature (libsodium default)
* ed25519 signature (libsodium default)
* @type string $ed25519_ref10
* ed25519 ref10 signature
* ed25519 ref10 signature
* }
*/
public function __construct($data = NULL) {
@ -60,7 +60,7 @@ class SignaturePair extends \Google\Protobuf\Internal\Message
}
/**
* ed25519 signature (libsodium default)
* ed25519 signature (libsodium default)
*
* Generated from protobuf field <code>bytes ed25519 = 2;</code>
* @return string
@ -71,7 +71,7 @@ class SignaturePair extends \Google\Protobuf\Internal\Message
}
/**
* ed25519 signature (libsodium default)
* ed25519 signature (libsodium default)
*
* Generated from protobuf field <code>bytes ed25519 = 2;</code>
* @param string $var
@ -86,7 +86,7 @@ class SignaturePair extends \Google\Protobuf\Internal\Message
}
/**
* ed25519 ref10 signature
* ed25519 ref10 signature
*
* Generated from protobuf field <code>bytes ed25519_ref10 = 3;</code>
* @return string
@ -97,7 +97,7 @@ class SignaturePair extends \Google\Protobuf\Internal\Message
}
/**
* ed25519 ref10 signature
* ed25519 ref10 signature
*
* Generated from protobuf field <code>bytes ed25519_ref10 = 3;</code>
* @param string $var

View File

@ -9,7 +9,7 @@ use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* need signature from this group and from parent (if it isn't zero)
* need signature from this group and from parent (if it isn't zero)
*
* Generated from protobuf message <code>model.messages.gradido.StateCreateGroup</code>
*/

View File

@ -9,7 +9,7 @@ use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* need signature from this group and from both parents (if it isn't zero)
* need signature from this group and from both parents (if it isn't zero)
*
* Generated from protobuf message <code>model.messages.gradido.StateGroupChangeParent</code>
*/

View File

@ -16,13 +16,13 @@ use Google\Protobuf\Internal\GPBUtil;
class Timestamp extends \Google\Protobuf\Internal\Message
{
/**
* Number of complete seconds since the start of the epoch
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
*/
private $seconds = 0;
/**
* Number of nanoseconds since the start of the last second
* Number of nanoseconds since the start of the last second
*
* Generated from protobuf field <code>int32 nanos = 2;</code>
*/
@ -35,9 +35,9 @@ class Timestamp extends \Google\Protobuf\Internal\Message
* Optional. Data for populating the Message object.
*
* @type int|string $seconds
* Number of complete seconds since the start of the epoch
* Number of complete seconds since the start of the epoch
* @type int $nanos
* Number of nanoseconds since the start of the last second
* Number of nanoseconds since the start of the last second
* }
*/
public function __construct($data = NULL) {
@ -46,7 +46,7 @@ class Timestamp extends \Google\Protobuf\Internal\Message
}
/**
* Number of complete seconds since the start of the epoch
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
* @return int|string
@ -57,7 +57,7 @@ class Timestamp extends \Google\Protobuf\Internal\Message
}
/**
* Number of complete seconds since the start of the epoch
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
* @param int|string $var
@ -72,7 +72,7 @@ class Timestamp extends \Google\Protobuf\Internal\Message
}
/**
* Number of nanoseconds since the start of the last second
* Number of nanoseconds since the start of the last second
*
* Generated from protobuf field <code>int32 nanos = 2;</code>
* @return int
@ -83,7 +83,7 @@ class Timestamp extends \Google\Protobuf\Internal\Message
}
/**
* Number of nanoseconds since the start of the last second
* Number of nanoseconds since the start of the last second
*
* Generated from protobuf field <code>int32 nanos = 2;</code>
* @param int $var

View File

@ -16,7 +16,7 @@ use Google\Protobuf\Internal\GPBUtil;
class TimestampSeconds extends \Google\Protobuf\Internal\Message
{
/**
* Number of complete seconds since the start of the epoch
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
*/
@ -29,7 +29,7 @@ class TimestampSeconds extends \Google\Protobuf\Internal\Message
* Optional. Data for populating the Message object.
*
* @type int|string $seconds
* Number of complete seconds since the start of the epoch
* Number of complete seconds since the start of the epoch
* }
*/
public function __construct($data = NULL) {
@ -38,7 +38,7 @@ class TimestampSeconds extends \Google\Protobuf\Internal\Message
}
/**
* Number of complete seconds since the start of the epoch
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
* @return int|string
@ -49,7 +49,7 @@ class TimestampSeconds extends \Google\Protobuf\Internal\Message
}
/**
* Number of complete seconds since the start of the epoch
* Number of complete seconds since the start of the epoch
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
* @param int|string $var

View File

@ -9,27 +9,27 @@ use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* need signature from group admin or
* percent of group users another than the receiver
* need signature from group admin or
* percent of group users another than the receiver
*
* Generated from protobuf message <code>model.messages.gradido.TransactionCreation</code>
*/
class TransactionCreation extends \Google\Protobuf\Internal\Message
{
/**
* 40 Byte
* 40 Byte
*
* Generated from protobuf field <code>.model.messages.gradido.ReceiverAmount receiverAmount = 1;</code>
*/
private $receiverAmount = null;
/**
* 4 Byte
* 4 Byte
*
* Generated from protobuf field <code>sint32 ident_hash = 2;</code>
*/
private $ident_hash = 0;
/**
* 8 Byte
* 8 Byte
*
* Generated from protobuf field <code>.model.messages.gradido.TimestampSeconds target_date = 3;</code>
*/
@ -42,11 +42,11 @@ class TransactionCreation extends \Google\Protobuf\Internal\Message
* Optional. Data for populating the Message object.
*
* @type \Model\Messages\Gradido\ReceiverAmount $receiverAmount
* 40 Byte
* 40 Byte
* @type int $ident_hash
* 4 Byte
* 4 Byte
* @type \Model\Messages\Gradido\TimestampSeconds $target_date
* 8 Byte
* 8 Byte
* }
*/
public function __construct($data = NULL) {
@ -55,7 +55,7 @@ class TransactionCreation extends \Google\Protobuf\Internal\Message
}
/**
* 40 Byte
* 40 Byte
*
* Generated from protobuf field <code>.model.messages.gradido.ReceiverAmount receiverAmount = 1;</code>
* @return \Model\Messages\Gradido\ReceiverAmount
@ -66,7 +66,7 @@ class TransactionCreation extends \Google\Protobuf\Internal\Message
}
/**
* 40 Byte
* 40 Byte
*
* Generated from protobuf field <code>.model.messages.gradido.ReceiverAmount receiverAmount = 1;</code>
* @param \Model\Messages\Gradido\ReceiverAmount $var
@ -81,7 +81,7 @@ class TransactionCreation extends \Google\Protobuf\Internal\Message
}
/**
* 4 Byte
* 4 Byte
*
* Generated from protobuf field <code>sint32 ident_hash = 2;</code>
* @return int
@ -92,7 +92,7 @@ class TransactionCreation extends \Google\Protobuf\Internal\Message
}
/**
* 4 Byte
* 4 Byte
*
* Generated from protobuf field <code>sint32 ident_hash = 2;</code>
* @param int $var
@ -107,7 +107,7 @@ class TransactionCreation extends \Google\Protobuf\Internal\Message
}
/**
* 8 Byte
* 8 Byte
*
* Generated from protobuf field <code>.model.messages.gradido.TimestampSeconds target_date = 3;</code>
* @return \Model\Messages\Gradido\TimestampSeconds
@ -118,7 +118,7 @@ class TransactionCreation extends \Google\Protobuf\Internal\Message
}
/**
* 8 Byte
* 8 Byte
*
* Generated from protobuf field <code>.model.messages.gradido.TimestampSeconds target_date = 3;</code>
* @param \Model\Messages\Gradido\TimestampSeconds $var

View File

@ -1,269 +1,269 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace Model\Transactions;
//use Model\Messages\Gradido\Transaction;
//use Model\Messages\Gradido\TransactionBody;
use Cake\ORM\TableRegistry;
use Cake\Datasource\ConnectionManager;
class Transaction extends TransactionBase {
private $mProtoTransaction = null;
private $mTransactionBody = null;
public function __construct($base64Data)
{
//$transactionBin = base64_decode($base64Data, true);
//if($transactionBin == false) {
//sodium_base64_VARIANT_URLSAFE_NO_PADDING
if(is_a($base64Data, '\Model\Messages\Gradido\Transaction')) {
$this->mProtoTransaction = $base64Data;
$this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes());
return;
}
try {
$transactionBin = sodium_base642bin($base64Data, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
} catch(\SodiumException $e) {
//$this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data);
//return;
$transactionBin = base64_decode($base64Data, true);
if($transactionBin == false) {
$this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data);
return;
}
}
//*/}
if($transactionBin == false) {
//$this->addError('base64 decode failed');
$this->addError('Transaction', 'base64 decode error: ' . $base64Data);
} else {
//var_dump($transactionBin);
$this->mProtoTransaction = new \Model\Messages\Gradido\Transaction();
try {
$this->mProtoTransaction->mergeFromString($transactionBin);
//var_dump($this->mProtoTransaction);
// cannot catch Exception with cakePHP, I don't know why
} catch(\Google\Protobuf\Internal\GPBDecodeException $e) {
//var_dump($e);
$this->addError('Transaction', $e->getMessage());
return;
}//*/
//echo 'serialize to json: <br>';
//echo $this->mProtoTransaction->serializeToJsonString();
//echo "body bytes: <br>";
//var_dump($this->mProtoTransaction->getBodyBytes());
//echo "<br>end body bytes<br>";
$this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes());
}
}
static public function build(\Model\Messages\Gradido\TransactionBody $transactionBody, $senderKeyPair)
{
$protoTransaction = new \Model\Messages\Gradido\Transaction();
$recevied = new \Model\Messages\Gradido\TimestampSeconds();
$recevied->setSeconds(time());
$protoTransaction->setReceived($recevied);
$bodyBytes = $transactionBody->serializeToString();
$sigMap = SignatureMap::build($bodyBytes, [$senderKeyPair]);
$protoTransaction->setSigMap($sigMap->getProto());
$protoTransaction->setBodyBytes($bodyBytes);
return $protoTransaction;
}
public function getTransactionBody() {
return $this->mTransactionBody;
}
public function getFirstPublic() {
$sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
return $sigPairs[0]->getPubKey();
}
public function getId() {
return $this->mProtoTransaction->getId();
}
public function validate() {
$sigMap = $this->mProtoTransaction->getSigMap();
if(!$sigMap) {
$this->addError('Transaction', 'signature map is zero');
return false;
}
//var_dump($sigMap);
//die();
$sigPairs = $sigMap->getSigPair();
$bodyBytes = $this->mProtoTransaction->getBodyBytes();
if(!$sigPairs || count($sigPairs) < 1) {
$this->addError('Transaction::validate', 'no signature found');
return false;
}
// check signature(s)
foreach($sigPairs as $sigPair) {
//echo 'sig Pair: '; var_dump($sigPair); echo "<br>";
$pubkey = $sigPair->getPubKey();
$signature = $sigPair->getEd25519();
//echo "verify bodybytes: <br>" . bin2hex($bodyBytes) . '<br>';
if (!\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) {
$this->addError('Transaction::validate', 'signature for key ' . bin2hex($pubkey) . ' isn\'t valid ' );
return false;
}
}
if(!$this->mTransactionBody->validate($sigPairs)) {
$this->addErrors($this->mTransactionBody->getErrors());
return false;
}
return true;
}
public function save()
{
$connection = ConnectionManager::get('default');
$connection->begin();
//id transaction_id signature pubkey
if (!$this->mTransactionBody->save($this->getFirstPublic(), $this->mProtoTransaction->getSigMap())) {
$this->addErrors($this->mTransactionBody->getErrors());
$connection->rollback();
return false;
}
// save transaction signatures
$transactionsSignaturesTable = TableRegistry::getTableLocator()->get('transaction_signatures');
$transactionId = $this->mTransactionBody->getTransactionID();
//signature pubkey
$sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
//echo "sigPairs: "; var_dump($sigPairs);
$signatureEntitys = [];
foreach($sigPairs as $sigPair) {
$signatureEntity = $transactionsSignaturesTable->newEntity();
$signatureEntity->transaction_id = $transactionId;
$signatureEntity->signature = $sigPair->getEd25519();
$signatureEntity->pubkey = $sigPair->getPubKey();
array_push($signatureEntitys, $signatureEntity);
}
//debug($signatureEntitys);
if(!$transactionsSignaturesTable->saveMany($signatureEntitys)) {
foreach($signatureEntitys as $entity) {
$errors = $entity->getErrors();
if(!$errors && count($errors) > 0) {
$pubkeyHex = bin2hex($entity->pubkey);
$this->addError('Transaction::save', 'error saving signature for pubkey: ' . $pubkeyHex . ', with errors: ' . json_encode($errors) );
}
}
$connection->rollback();
return false;
}
$connection->commit();
$this->mTransactionBody->getSpecificTransaction()->sendNotificationEmail($this->mTransactionBody->getMemo());
return true;
}
static public function fromTable($id)
{
$transactionsTable = TableRegistry::getTableLocator()->get('transactions');
$transactionEntry = $transactionsTable
->find('all')
->where(['id' => $id])
->contain([
'TransactionCreations',
'TransactionSendCoins',
'TransactionSignatures'])
->first();
//var_dump($transactionEntry->toArray());
$protoTransaction = new \Model\Messages\Gradido\Transaction();
$protoTransaction->setId($transactionEntry->id);
$recevied = new \Model\Messages\Gradido\TimestampSeconds();
$recevied->setSeconds($transactionEntry->received->getTimestamp());
$protoTransaction->setReceived($recevied);
$sigMap = SignatureMap::fromEntity($transactionEntry->transaction_signatures);
$protoTransaction->setSigMap($sigMap->getProto());
//echo "sig map: check<br>";
$protoTransaction->setTxHash(stream_get_contents($transactionEntry->tx_hash));
$body = TransactionBody::fromEntity($transactionEntry->memo, $transactionEntry);
if(is_array($body)) {
return ['state' => 'error', 'msg' => 'error creating body transaction', 'details' => $body];
}
// validate signatures
$sigPairs = $sigMap->getProto()->getSigPair();
if(!$sigPairs || count($sigPairs) < 1) {
return ['state' => 'error', 'msg' => 'error no signatures found'];
}
//echo "verify bodybytes: <br>" . bin2hex($bodyBytes) . '<br>';
$created = new \Model\Messages\Gradido\TimestampSeconds();
$created->setSeconds($recevied->getSeconds());
$body->setCreated($created);
$bodyBytes = $body->serializeToString();
$createTrys = 0;
$createRight = false;
// check signature(s) and
// try to get created field of TransactionBody right, because it wasn't saved
foreach($sigPairs as $sigPair) {
//echo 'sig Pair: '; var_dump($sigPair); echo "<br>";
$pubkey = $sigPair->getPubKey();
$signature = $sigPair->getEd25519();
if(!$createRight) {
while($createTrys < 500) {
if(\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) {
$createRight = true;
break;
} else {
$createTrys++;
$created->setSeconds($created->getSeconds() - 1);
//$body->setCreated($created);
$bodyBytes = $body->serializeToString();
}
}
}
if (!\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) {
return ['state' => 'error', 'msg' => 'signature for key ' . bin2hex($pubkey) . ' isn\'t valid '];
}
}
$protoTransaction->setBodyBytes($bodyBytes);
return $protoTransaction;
}
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace Model\Transactions;
//use Model\Messages\Gradido\Transaction;
//use Model\Messages\Gradido\TransactionBody;
use Cake\ORM\TableRegistry;
use Cake\Datasource\ConnectionManager;
class Transaction extends TransactionBase {
private $mProtoTransaction = null;
private $mTransactionBody = null;
public function __construct($base64Data)
{
//$transactionBin = base64_decode($base64Data, true);
//if($transactionBin == false) {
//sodium_base64_VARIANT_URLSAFE_NO_PADDING
if(is_a($base64Data, '\Model\Messages\Gradido\Transaction')) {
$this->mProtoTransaction = $base64Data;
$this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes());
return;
}
try {
$transactionBin = sodium_base642bin($base64Data, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
} catch(\SodiumException $e) {
//$this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data);
//return;
$transactionBin = base64_decode($base64Data, true);
if($transactionBin == false) {
$this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data);
return;
}
}
//*/}
if($transactionBin == false) {
//$this->addError('base64 decode failed');
$this->addError('Transaction', 'base64 decode error: ' . $base64Data);
} else {
//var_dump($transactionBin);
$this->mProtoTransaction = new \Model\Messages\Gradido\Transaction();
try {
$this->mProtoTransaction->mergeFromString($transactionBin);
//var_dump($this->mProtoTransaction);
// cannot catch Exception with cakePHP, I don't know why
} catch(\Google\Protobuf\Internal\GPBDecodeException $e) {
//var_dump($e);
$this->addError('Transaction', $e->getMessage());
return;
}//*/
//echo 'serialize to json: <br>';
//echo $this->mProtoTransaction->serializeToJsonString();
//echo "body bytes: <br>";
//var_dump($this->mProtoTransaction->getBodyBytes());
//echo "<br>end body bytes<br>";
$this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes());
}
}
static public function build(\Model\Messages\Gradido\TransactionBody $transactionBody, $senderKeyPair)
{
$protoTransaction = new \Model\Messages\Gradido\Transaction();
$recevied = new \Model\Messages\Gradido\TimestampSeconds();
$recevied->setSeconds(time());
$protoTransaction->setReceived($recevied);
$bodyBytes = $transactionBody->serializeToString();
$sigMap = SignatureMap::build($bodyBytes, [$senderKeyPair]);
$protoTransaction->setSigMap($sigMap->getProto());
$protoTransaction->setBodyBytes($bodyBytes);
return $protoTransaction;
}
public function getTransactionBody() {
return $this->mTransactionBody;
}
public function getFirstPublic() {
$sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
return $sigPairs[0]->getPubKey();
}
public function getId() {
return $this->mProtoTransaction->getId();
}
public function validate() {
$sigMap = $this->mProtoTransaction->getSigMap();
if(!$sigMap) {
$this->addError('Transaction', 'signature map is zero');
return false;
}
//var_dump($sigMap);
//die();
$sigPairs = $sigMap->getSigPair();
$bodyBytes = $this->mProtoTransaction->getBodyBytes();
if(!$sigPairs || count($sigPairs) < 1) {
$this->addError('Transaction::validate', 'no signature found');
return false;
}
// check signature(s)
foreach($sigPairs as $sigPair) {
//echo 'sig Pair: '; var_dump($sigPair); echo "<br>";
$pubkey = $sigPair->getPubKey();
$signature = $sigPair->getEd25519();
//echo "verify bodybytes: <br>" . bin2hex($bodyBytes) . '<br>';
if (!\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) {
$this->addError('Transaction::validate', 'signature for key ' . bin2hex($pubkey) . ' isn\'t valid ' );
return false;
}
}
if(!$this->mTransactionBody->validate($sigPairs)) {
$this->addErrors($this->mTransactionBody->getErrors());
return false;
}
return true;
}
public function save()
{
$connection = ConnectionManager::get('default');
$connection->begin();
//id transaction_id signature pubkey
if (!$this->mTransactionBody->save($this->getFirstPublic(), $this->mProtoTransaction->getSigMap())) {
$this->addErrors($this->mTransactionBody->getErrors());
$connection->rollback();
return false;
}
// save transaction signatures
$transactionsSignaturesTable = TableRegistry::getTableLocator()->get('transaction_signatures');
$transactionId = $this->mTransactionBody->getTransactionID();
//signature pubkey
$sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
//echo "sigPairs: "; var_dump($sigPairs);
$signatureEntitys = [];
foreach($sigPairs as $sigPair) {
$signatureEntity = $transactionsSignaturesTable->newEntity();
$signatureEntity->transaction_id = $transactionId;
$signatureEntity->signature = $sigPair->getEd25519();
$signatureEntity->pubkey = $sigPair->getPubKey();
array_push($signatureEntitys, $signatureEntity);
}
//debug($signatureEntitys);
if(!$transactionsSignaturesTable->saveMany($signatureEntitys)) {
foreach($signatureEntitys as $entity) {
$errors = $entity->getErrors();
if(!$errors && count($errors) > 0) {
$pubkeyHex = bin2hex($entity->pubkey);
$this->addError('Transaction::save', 'error saving signature for pubkey: ' . $pubkeyHex . ', with errors: ' . json_encode($errors) );
}
}
$connection->rollback();
return false;
}
$connection->commit();
$this->mTransactionBody->getSpecificTransaction()->sendNotificationEmail($this->mTransactionBody->getMemo());
return true;
}
static public function fromTable($id)
{
$transactionsTable = TableRegistry::getTableLocator()->get('transactions');
$transactionEntry = $transactionsTable
->find('all')
->where(['id' => $id])
->contain([
'TransactionCreations',
'TransactionSendCoins',
'TransactionSignatures'])
->first();
//var_dump($transactionEntry->toArray());
$protoTransaction = new \Model\Messages\Gradido\Transaction();
$protoTransaction->setId($transactionEntry->id);
$recevied = new \Model\Messages\Gradido\TimestampSeconds();
$recevied->setSeconds($transactionEntry->received->getTimestamp());
$protoTransaction->setReceived($recevied);
$sigMap = SignatureMap::fromEntity($transactionEntry->transaction_signatures);
$protoTransaction->setSigMap($sigMap->getProto());
//echo "sig map: check<br>";
$protoTransaction->setTxHash(stream_get_contents($transactionEntry->tx_hash));
$body = TransactionBody::fromEntity($transactionEntry->memo, $transactionEntry);
if(is_array($body)) {
return ['state' => 'error', 'msg' => 'error creating body transaction', 'details' => $body];
}
// validate signatures
$sigPairs = $sigMap->getProto()->getSigPair();
if(!$sigPairs || count($sigPairs) < 1) {
return ['state' => 'error', 'msg' => 'error no signatures found'];
}
//echo "verify bodybytes: <br>" . bin2hex($bodyBytes) . '<br>';
$created = new \Model\Messages\Gradido\TimestampSeconds();
$created->setSeconds($recevied->getSeconds());
$body->setCreated($created);
$bodyBytes = $body->serializeToString();
$createTrys = 0;
$createRight = false;
// check signature(s) and
// try to get created field of TransactionBody right, because it wasn't saved
foreach($sigPairs as $sigPair) {
//echo 'sig Pair: '; var_dump($sigPair); echo "<br>";
$pubkey = $sigPair->getPubKey();
$signature = $sigPair->getEd25519();
if(!$createRight) {
while($createTrys < 500) {
if(\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) {
$createRight = true;
break;
} else {
$createTrys++;
$created->setSeconds($created->getSeconds() - 1);
//$body->setCreated($created);
$bodyBytes = $body->serializeToString();
}
}
}
if (!\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) {
return ['state' => 'error', 'msg' => 'signature for key ' . bin2hex($pubkey) . ' isn\'t valid '];
}
}
$protoTransaction->setBodyBytes($bodyBytes);
return $protoTransaction;
}
}

View File

@ -1,122 +1,122 @@
<?php
namespace Model\Transactions;
use Cake\ORM\TableRegistry;
class TransactionBase {
private $errors = [];
static $tables = [];
public function getErrors() {
return $this->errors;
}
public function addError($functionName, $errorName) {
array_push($this->errors, [$functionName => $errorName]);
}
public function addErrors($errors) {
$this->errors = array_merge($this->errors, $errors);
}
public function hasErrors() {
return count($this->errors) > 0;
}
public static function getTable($tableName) {
if(!isset(self::$tables[$tableName])) {
self::$tables[$tableName] = TableRegistry::getTableLocator()->get($tableName);
}
return self::$tables[$tableName];
}
protected function getStateUserId($publicKey) {
$stateUsersTable = self::getTable('state_users');
$stateUser = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $publicKey])->first();
if($stateUser) {
return $stateUser->id;
}
// create new entry
$stateUserEntity = $stateUsersTable->newEntity();
$stateUserEntity->public_key = $publicKey;
if($stateUsersTable->save($stateUserEntity)) {
return $stateUserEntity->id;
} else {
$this->addError('TransactionBase::getStateUserId', 'error saving new state user with error: ' . json_encode($stateUserEntity->getErrors()));
}
return NULL;
}
protected function getStateUser($id) {
$stateUsersTable = self::getTable('state_users');
$stateUser = $stateUsersTable->get($id);
if($stateUser) {
return $stateUser;
}
return NULL;
}
protected function updateStateBalance($stateUserId, $addAmountCent, $recordDate) {
$finalBalance = 0;
$stateBalancesTable = self::getTable('stateBalances');
$stateBalanceQuery = $stateBalancesTable
->find('all')
->select(['amount', 'id'])
->contain(false)
->where(['state_user_id' => $stateUserId]);//->first();
//debug($stateBalanceQuery);
if($stateBalanceQuery->count() > 0) {
$stateBalanceEntry = $stateBalanceQuery->first();
$stateBalanceEntry->amount = $stateBalanceEntry->partDecay($recordDate) + $addAmountCent;
$stateBalanceEntry->amount += $addAmountCent;
} else {
$stateBalanceEntry = $stateBalancesTable->newEntity();
$stateBalanceEntry->state_user_id = $stateUserId;
$stateBalanceEntry->amount = $addAmountCent;
}
$stateBalanceEntry->record_date = $recordDate;
$finalBalance = $stateBalanceEntry->amount;
//echo "\ntry to save: "; var_dump($stateBalanceEntry); echo "\n";
if(!$stateBalancesTable->save($stateBalanceEntry)) {
$errors = $stateBalanceEntry->getErrors();
$this->addError('TransactionBase::updateStateBalance', 'error saving state balance with: ' . json_encode($errors));
return false;
}
return $finalBalance;
}
protected function addStateUserTransaction($stateUserId, $transactionId, $transactionTypeId, $balance) {
$stateUserTransactionTable = self::getTable('state_user_transactions');
$stateUserTransactions = $stateUserTransactionTable
->find('all')
->where(['state_user_id' => $stateUserId])
->order(['transaction_id DESC']);
if($stateUserTransactions->count() > 0) {
$stateBalanceTable = self::getTable('state_balances');
$balance_entity = $stateBalanceTable->newEntity();
$balance_entity->amount = $stateUserTransactions->first()->balance;
$balance_entity->record_date = $stateUserTransactions->first()->balance_date;
$balance = $balance_entity->decay + $balance;
}
$entity = $stateUserTransactionTable->newEntity();
$entity->state_user_id = $stateUserId;
$entity->transaction_id = $transactionId;
$entity->transaction_type_id = $transactionTypeId;
$entity->balance = $balance;
if(!$stateUserTransactionTable->save($entity)) {
$errors = $entity->getErrors();
$this->addError('TransactionBase::addStateUserTransaction', 'error saving state user balance with: ' . json_encode($errors));
return false;
}
return true;
}
<?php
namespace Model\Transactions;
use Cake\ORM\TableRegistry;
class TransactionBase {
private $errors = [];
static $tables = [];
public function getErrors() {
return $this->errors;
}
public function addError($functionName, $errorName) {
array_push($this->errors, [$functionName => $errorName]);
}
public function addErrors($errors) {
$this->errors = array_merge($this->errors, $errors);
}
public function hasErrors() {
return count($this->errors) > 0;
}
public static function getTable($tableName) {
if(!isset(self::$tables[$tableName])) {
self::$tables[$tableName] = TableRegistry::getTableLocator()->get($tableName);
}
return self::$tables[$tableName];
}
protected function getStateUserId($publicKey) {
$stateUsersTable = self::getTable('state_users');
$stateUser = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $publicKey])->first();
if($stateUser) {
return $stateUser->id;
}
// create new entry
$stateUserEntity = $stateUsersTable->newEntity();
$stateUserEntity->public_key = $publicKey;
if($stateUsersTable->save($stateUserEntity)) {
return $stateUserEntity->id;
} else {
$this->addError('TransactionBase::getStateUserId', 'error saving new state user with error: ' . json_encode($stateUserEntity->getErrors()));
}
return NULL;
}
protected function getStateUser($id) {
$stateUsersTable = self::getTable('state_users');
$stateUser = $stateUsersTable->get($id);
if($stateUser) {
return $stateUser;
}
return NULL;
}
protected function updateStateBalance($stateUserId, $addAmountCent, $recordDate) {
$finalBalance = 0;
$stateBalancesTable = self::getTable('stateBalances');
$stateBalanceQuery = $stateBalancesTable
->find('all')
->select(['amount', 'id'])
->contain(false)
->where(['state_user_id' => $stateUserId]);//->first();
//debug($stateBalanceQuery);
if($stateBalanceQuery->count() > 0) {
$stateBalanceEntry = $stateBalanceQuery->first();
$stateBalanceEntry->amount = $stateBalanceEntry->partDecay($recordDate) + $addAmountCent;
$stateBalanceEntry->amount += $addAmountCent;
} else {
$stateBalanceEntry = $stateBalancesTable->newEntity();
$stateBalanceEntry->state_user_id = $stateUserId;
$stateBalanceEntry->amount = $addAmountCent;
}
$stateBalanceEntry->record_date = $recordDate;
$finalBalance = $stateBalanceEntry->amount;
//echo "\ntry to save: "; var_dump($stateBalanceEntry); echo "\n";
if(!$stateBalancesTable->save($stateBalanceEntry)) {
$errors = $stateBalanceEntry->getErrors();
$this->addError('TransactionBase::updateStateBalance', 'error saving state balance with: ' . json_encode($errors));
return false;
}
return $finalBalance;
}
protected function addStateUserTransaction($stateUserId, $transactionId, $transactionTypeId, $balance) {
$stateUserTransactionTable = self::getTable('state_user_transactions');
$stateUserTransactions = $stateUserTransactionTable
->find('all')
->where(['state_user_id' => $stateUserId])
->order(['transaction_id DESC']);
if($stateUserTransactions->count() > 0) {
$stateBalanceTable = self::getTable('state_balances');
$balance_entity = $stateBalanceTable->newEntity();
$balance_entity->amount = $stateUserTransactions->first()->balance;
$balance_entity->record_date = $stateUserTransactions->first()->balance_date;
$balance = $balance_entity->decay + $balance;
}
$entity = $stateUserTransactionTable->newEntity();
$entity->state_user_id = $stateUserId;
$entity->transaction_id = $transactionId;
$entity->transaction_type_id = $transactionTypeId;
$entity->balance = $balance;
if(!$stateUserTransactionTable->save($entity)) {
$errors = $entity->getErrors();
$this->addError('TransactionBase::addStateUserTransaction', 'error saving state user balance with: ' . json_encode($errors));
return false;
}
return true;
}
}

View File

@ -63,24 +63,6 @@ class TransactionCreation extends TransactionBase {
return ['state' => 'success', 'transactionBody' => $transactionBody];
}
static protected function DRHashRotateLeft( $hash, $rotateBy )
{
return ($hash<<$rotateBy)|($hash>>(32-$rotateBy));
}
static public function DRMakeStringHash($str)
{
$ret = 0;
if( $str )
{
for ($i=0; $i < strlen($str); $i++)
{
$ret = TransactionCreation::DRHashRotateLeft($ret, 7) + ord($str{$i});
}
}
return $ret;
}
public function getAmount() {
return $this->protoTransactionCreation->getReceiverAmount()->getAmount();
@ -272,7 +254,7 @@ class TransactionCreation extends TransactionBase {
->setSubject(__('Gradido Schöpfung erhalten'))
->send();
} catch(Exception $e) {
$this->addError('TransactionCreation::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage());
// $this->addError('TransactionCreation::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage());
return false;
}
return true;
@ -303,7 +285,7 @@ class TransactionCreation extends TransactionBase {
// intval
//$protoCreation->setIdentHash(intval($identHashBytes));
$protoCreation->setIdentHash(self::DRMakeStringHash($stateUser->email));
//$protoCreation->setIdentHash(self::DRMakeStringHash($stateUser->email));
return new TransactionCreation($protoCreation);
}
}

View File

@ -75,7 +75,8 @@ class TransactionTransfer extends TransactionBase {
foreach($sigPairs as $sigPair) {
//echo 'sig Pair: '; var_dump($sigPair); echo "<br>";
$pubkey = bin2hex($sigPair->getPubKey());
$hash = TransactionCreation::DRMakeStringHash($pubkey);
//$hash = TransactionCreation::DRMakeStringHash($pubkey);
$hash = $pubkey;
if(!isset($sigPubHexs[$hash])) {
$sigPubHexs[$hash] = [$pubkey];
} else {
@ -100,7 +101,8 @@ class TransactionTransfer extends TransactionBase {
return false;
}
// check if signature exist for sender
$hash = TransactionCreation::DRMakeStringHash($senderPublicHex);
//$hash = TransactionCreation::DRMakeStringHash($senderPublicHex);
$hash = $senderPublicHex;
if(!isset($sigPubHexs[$hash]) || in_array($senderPublicHex, $sigPubHexs[$hash]) === FALSE) {
$this->addError($functionName, 'missing signature for sender');
return false;
@ -253,7 +255,7 @@ class TransactionTransfer extends TransactionBase {
->setSubject(__('Gradidos erhalten'))
->send();
} catch(Exception $e) {
$this->addError('TransactionTransfer::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage());
//$this->addError('TransactionTransfer::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage());
return false;
}
return true;

View File

@ -1,149 +1,149 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
$this->assign('title', __('Kontoübersicht'));
$header = '<h1>' . __('Aktueller Kontostand: ') . '</h1>' .
'<h1>' . $this->element('printGradido', ['number' => $balance]) . '</h1>';
if($gdtSum > 0) {
$header .= '<h1>'.$this->Html->link(
$this->element('printGDT', ['number' => $gdtSum]),
['action' => 'overview_gdt'],
['escape' => false]
).'</h1>';
}
$this->assign('header', $header);
//var_dump($transactions);
?>
<?php if($transactionExecutingCount > 0) : ?>
<div id="transaction-execute-display" class="">
</div>
<?php endif; ?>
<div class="content-list">
<p class="content-list-title">Überweisungen</p>
<div class="content-list-table">
<div class="row">
<div class="cell header-cell c4"><?= __('Absender') . ' / ' . ('Empfänger') ?></div>
<div class="cell header-cell c0"><?= __('Verwendungszweck') ?></div>
<div class="cell header-cell c4"><?= __('Datum') ?></div>
<div class="cell header-cell c3"><?= __('Betrag') ?></div>
<div class="cell header-cell c2" title="<?= __('Transaktions Nr.') ?>"><?= __('Nr') ?></div>
</div>
<?php foreach($transactions as $transaction):
$send = $transaction['type'] == 'send';
$balance = $transaction['balance'];
$memoShort = $transaction['memo'];
if(strlen($memoShort) > 30) {
$memoShort = substr($memoShort, 0, 30) . '...';
}
$cellColorClass = 'success-color';
if($send) {
$balance = -$balance;
$cellColorClass = 'alert-color';
} else if($transaction['type'] == 'creation') {
$cellColorClass = 'orange-color';
}
?>
<div class="row">
<div class="cell c4">
<?= $this->Html->image('50x50.png', ['class' => 'profile-img', 'alt' => 'profile image']) ?>
<div>
<?php if(isset($transaction['email']) && $transaction['email'] != ''): ?>
<a href="mailto:<?= $transaction['email'] ?>" title="<?= $transaction['email'] ?>">
<small class="tx-email"><?= $transaction['name'] ?></small>
</a>
<?php else : ?>
<small class="tx-email"><?= $transaction['name'] ?></small>
<?php endif; ?>
<!-- noch ungeklärt - icon ist nicht aligned -->
<div class="cell-icon <?= $cellColorClass ?>">
<?php if($transaction['type'] == 'creation') : ?>
<i class="material-icons-outlined orange-color">redeem</i>
<!-- insights / redeem -->
<?= __('Geschöpft')?>
<?php elseif($transaction['type'] == 'send') : ?>
<i class="material-icons-outlined">arrow_back</i>
<?= __('Gesendet') ?>
<?php elseif($transaction['type'] == 'receive') : ?>
<i class="material-icons-outlined">arrow_forward</i>
<?= __('Empfangen') ?>
<?php endif; ?>
</div>
</div>
</div>
<div class="cell c0" data-toggle="tooltip" data-placement="bottom" title="<?= $transaction['memo'] ?>">
<?php if(strlen($transaction['memo']) > 30): ?>
<?= substr($memoShort, 0, 30) . '...' ?>
<?php else : ?>
<?= $transaction['memo'] ?>
<?php endif;?>
</div>
<div class="cell c4"><?= $transaction['date']->nice() ?></div>
<div class="cell c3"><?= $this->element('printGradido', ['number' => $balance]) ?></div>
<div class="cell c2">
<?= $transaction['transaction_id'] ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<!--<a class="border-top px-3 py-2 d-block text-gray" href="#"><small class="font-weight-medium"><i class="mdi mdi-chevron-down mr-2"></i>View All Order History</small></a>-->
<!--?= $this->Html->css(['gdt.css']) ?-->
<?php if($transactionExecutingCount > 0) : ?>
<script type="text/javascript">
//function getJson(basisUrl, method, successFunction, errorFunction, timeoutFunction)
g_transactionExecutionCount = <?= $transactionExecutingCount ?>;
function updateTransactionExecutingDisplay(count) {
var display = document.getElementById('transaction-execute-display');
display.innerHTML = count + " ";
if(count == 1) {
display.innerHTML += "<?= __('Laufende Transaktion') ?>";
} else {
display.innerHTML += "<?= __('Laufende Transaktionen') ?>";
}
display.innerHTML += '&nbsp;<div class="spinner-border text-light spinner-border-sm" role="status"><span class="sr-only">Loading...</span></div>';
}
function checkTransactionExecuting() {
getJson('<?= $this->Url->build(["controller" => "JsonRequestHandler"]);?>', 'getRunningUserTasks',
// success
function(json) {
if(json.state === 'success') {
var newCount = 0;
if(json.data.runningTasks["sign transaction"] != undefined) {
newCount = json.data.runningTasks["sign transaction"];
}
if(newCount != g_transactionExecutionCount) {
g_transactionExecutionCount = newCount;
location.reload();
//updateTransactionExecutingDisplay(g_transactionExecutionCount);
} else {
setTimeout(checkTransactionExecuting, 100);
}
}
},
// error
function(e) {
},
// timeout
function(e) {
}
)
}
(function(document, window, domIsReady, undefined) {
domIsReady(function() {
updateTransactionExecutingDisplay(g_transactionExecutionCount);
setTimeout(checkTransactionExecuting, 100);
//setInterval(checkTransactionExecuting, 100);
});
})(document, window, domIsReady);
</script>
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
$this->assign('title', __('Kontoübersicht'));
$header = '<h1>' . __('Aktueller Kontostand: ') . '</h1>' .
'<h1>' . $this->element('printGradido', ['number' => $balance]) . '</h1>';
if($gdtSum > 0) {
$header .= '<h1>'.$this->Html->link(
$this->element('printGDT', ['number' => $gdtSum]),
['action' => 'overview_gdt'],
['escape' => false]
).'</h1>';
}
$this->assign('header', $header);
//var_dump($transactions);
?>
<?php if($transactionExecutingCount > 0) : ?>
<div id="transaction-execute-display" class="">
</div>
<?php endif; ?>
<div class="content-list">
<p class="content-list-title">Überweisungen</p>
<div class="content-list-table">
<div class="row">
<div class="cell header-cell c4"><?= __('Absender') . ' / ' . ('Empfänger') ?></div>
<div class="cell header-cell c0"><?= __('Verwendungszweck') ?></div>
<div class="cell header-cell c4"><?= __('Datum') ?></div>
<div class="cell header-cell c3"><?= __('Betrag') ?></div>
<div class="cell header-cell c2" title="<?= __('Transaktions Nr.') ?>"><?= __('Nr') ?></div>
</div>
<?php foreach($transactions as $transaction):
$send = $transaction['type'] == 'send';
$balance = $transaction['balance'];
$memoShort = $transaction['memo'];
if(strlen($memoShort) > 30) {
$memoShort = substr($memoShort, 0, 30) . '...';
}
$cellColorClass = 'success-color';
if($send) {
$balance = -$balance;
$cellColorClass = 'alert-color';
} else if($transaction['type'] == 'creation') {
$cellColorClass = 'orange-color';
}
?>
<div class="row">
<div class="cell c4">
<?= $this->Html->image('50x50.png', ['class' => 'profile-img', 'alt' => 'profile image']) ?>
<div>
<?php if(isset($transaction['email']) && $transaction['email'] != ''): ?>
<a href="mailto:<?= $transaction['email'] ?>" title="<?= $transaction['email'] ?>">
<small class="tx-email"><?= $transaction['name'] ?></small>
</a>
<?php else : ?>
<small class="tx-email"><?= $transaction['name'] ?></small>
<?php endif; ?>
<!-- noch ungeklärt - icon ist nicht aligned -->
<div class="cell-icon <?= $cellColorClass ?>">
<?php if($transaction['type'] == 'creation') : ?>
<i class="material-icons-outlined orange-color">redeem</i>
<!-- insights / redeem -->
<?= __('Geschöpft')?>
<?php elseif($transaction['type'] == 'send') : ?>
<i class="material-icons-outlined">arrow_back</i>
<?= __('Gesendet') ?>
<?php elseif($transaction['type'] == 'receive') : ?>
<i class="material-icons-outlined">arrow_forward</i>
<?= __('Empfangen') ?>
<?php endif; ?>
</div>
</div>
</div>
<div class="cell c0" data-toggle="tooltip" data-placement="bottom" title="<?= $transaction['memo'] ?>">
<?php if(strlen($transaction['memo']) > 30): ?>
<?= substr($memoShort, 0, 30) . '...' ?>
<?php else : ?>
<?= $transaction['memo'] ?>
<?php endif;?>
</div>
<div class="cell c4"><?= $transaction['date']->nice() ?></div>
<div class="cell c3"><?= $this->element('printGradido', ['number' => $balance]) ?></div>
<div class="cell c2">
<?= $transaction['transaction_id'] ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<!--<a class="border-top px-3 py-2 d-block text-gray" href="#"><small class="font-weight-medium"><i class="mdi mdi-chevron-down mr-2"></i>View All Order History</small></a>-->
<!--?= $this->Html->css(['gdt.css']) ?-->
<?php if($transactionExecutingCount > 0) : ?>
<script type="text/javascript">
//function getJson(basisUrl, method, successFunction, errorFunction, timeoutFunction)
g_transactionExecutionCount = <?= $transactionExecutingCount ?>;
function updateTransactionExecutingDisplay(count) {
var display = document.getElementById('transaction-execute-display');
display.innerHTML = count + " ";
if(count == 1) {
display.innerHTML += "<?= __('Laufende Transaktion') ?>";
} else {
display.innerHTML += "<?= __('Laufende Transaktionen') ?>";
}
display.innerHTML += '&nbsp;<div class="spinner-border text-light spinner-border-sm" role="status"><span class="sr-only">Loading...</span></div>';
}
function checkTransactionExecuting() {
getJson('<?= $this->Url->build(["controller" => "JsonRequestHandler"]);?>', 'getRunningUserTasks',
// success
function(json) {
if(json.state === 'success') {
var newCount = 0;
if(json.data.runningTasks["sign transaction"] != undefined) {
newCount = json.data.runningTasks["sign transaction"];
}
if(newCount != g_transactionExecutionCount) {
g_transactionExecutionCount = newCount;
location.reload();
//updateTransactionExecutingDisplay(g_transactionExecutionCount);
} else {
setTimeout(checkTransactionExecuting, 100);
}
}
},
// error
function(e) {
},
// timeout
function(e) {
}
)
}
(function(document, window, domIsReady, undefined) {
domIsReady(function() {
updateTransactionExecutingDisplay(g_transactionExecutionCount);
setTimeout(checkTransactionExecuting, 100);
//setInterval(checkTransactionExecuting, 100);
});
})(document, window, domIsReady);
</script>
<?php endif; ?>

View File

@ -1,29 +1,29 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
?>
<div class="grd_container_small">
<table>
<thead>
<tr>
<th>first name</th><th>last name</th><th>email</th><th>identHash</th><th>Public key hex
</tr>
</thead>
<tbody>
<?php foreach($stateUsers as $user) :?>
<tr>
<td><?= $user->first_name ?></td>
<td><?= $user->last_name ?></td>
<td><?= $user->email ?></td>
<td><?= $user->identHash ?></td>
<td><?= bin2hex(stream_get_contents($user->public_key)) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
?>
<div class="grd_container_small">
<table>
<thead>
<tr>
<th>first name</th><th>last name</th><th>email</th><th>identHash</th><th>Public key hex
</tr>
</thead>
<tbody>
<?php foreach($stateUsers as $user) :?>
<tr>
<td><?= $user->first_name ?></td>
<td><?= $user->last_name ?></td>
<td><?= $user->email ?></td>
<td><?= $user->identHash ?></td>
<td><?= bin2hex(stream_get_contents($user->public_key)) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

View File

@ -1,31 +1,31 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
$address_options = [];//__('Selbst eingeben:')];
foreach($receiverProposal as $i => $receiver) {
//var_dump($receiver);
array_push($address_options, [
'text' => $receiver['name'],
'value' => $i+1,
'title' => $receiver['key']
]);
}
$this->assign('title', __('Schöpfungstransaktion'));
?>
<div class="grd_container_small">
<?= $this->Form->create($creationForm) ?>
<fieldset>
<?= $this->Form->control('memo'); ?>
<?= $this->Form->control('amount'); ?>
<?= $this->Form->control('receiver', ['options' => $address_options]); ?>
<!--<?= $this->Form->control('receiver_pubkey_hex', []) ?>-->
</fieldset>
<?= $this->Form->button(__('Transaktion(en) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?>
<?= $this->Form->button(__('Weitere Transaktion erstellen'), ['name' => 'add', 'class' => 'grd-form-bn grd_clickable grd-width-200']) ?>
<?= $this->Form->end() ?>
</div>
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
$address_options = [];//__('Selbst eingeben:')];
foreach($receiverProposal as $i => $receiver) {
//var_dump($receiver);
array_push($address_options, [
'text' => $receiver['name'],
'value' => $i+1,
'title' => $receiver['key']
]);
}
$this->assign('title', __('Schöpfungstransaktion'));
?>
<div class="grd_container_small">
<?= $this->Form->create($creationForm) ?>
<fieldset>
<?= $this->Form->control('memo'); ?>
<?= $this->Form->control('amount'); ?>
<?= $this->Form->control('receiver', ['options' => $address_options]); ?>
<!--<?= $this->Form->control('receiver_pubkey_hex', []) ?>-->
</fieldset>
<?= $this->Form->button(__('Transaktion(en) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?>
<?= $this->Form->button(__('Weitere Transaktion erstellen'), ['name' => 'add', 'class' => 'grd-form-bn grd_clickable grd-width-200']) ?>
<?= $this->Form->end() ?>
</div>

View File

@ -1,46 +1,46 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
?>
<div class="transactions form large-9 medium-8 columns content">
<h1>Synchronize state_user_transactions with transactions</h1>
<p>transactions count: <?= $count1 ?></p>
<p>state_user_transaction count: <?= $count2 ?></p>
<p>Missing count: <?= count($missing_transactions); ?></p>
<p>First 10 Missing ids: </p>
<p><?php
foreach($missing_transactions as $i => $id) {
if($i > 10) break;
if($i > 0) echo ', ';
echo $id['id'];
} ?></p>
<?php if(isset($entities) && isset($results)) : ?>
<h2>Synchronize errors: </h2>
<ul>
<?php
$succeed = 0;
//var_dump($results);
if($results) :
foreach($results as $i => $result) :
if(false != $result) {
$succeed++;
continue;
}
?>
<li>Error saving entity: <?= json_encode($entities[$i]) ?> with error: <?= json_encode($entities[$i]->getErrors()) ?></li>
<?php endforeach; ?>
<?php endif; ?>
<li><success>Succeed: <?= $succeed ?></success></li>
</ul>
<?php endif; ?>
<?= $this->Form->create() ?>
<?= $this->Form->button(__('Synchronize')) ?>
<?= $this->Form->end() ?>
</div>
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
?>
<div class="transactions form large-9 medium-8 columns content">
<h1>Synchronize state_user_transactions with transactions</h1>
<p>transactions count: <?= $count1 ?></p>
<p>state_user_transaction count: <?= $count2 ?></p>
<p>Missing count: <?= count($missing_transactions); ?></p>
<p>First 10 Missing ids: </p>
<p><?php
foreach($missing_transactions as $i => $id) {
if($i > 10) break;
if($i > 0) echo ', ';
echo $id['id'];
} ?></p>
<?php if(isset($entities) && isset($results)) : ?>
<h2>Synchronize errors: </h2>
<ul>
<?php
$succeed = 0;
//var_dump($results);
if($results) :
foreach($results as $i => $result) :
if(false != $result) {
$succeed++;
continue;
}
?>
<li>Error saving entity: <?= json_encode($entities[$i]) ?> with error: <?= json_encode($entities[$i]->getErrors()) ?></li>
<?php endforeach; ?>
<?php endif; ?>
<li><success>Succeed: <?= $succeed ?></success></li>
</ul>
<?php endif; ?>
<?= $this->Form->create() ?>
<?= $this->Form->button(__('Synchronize')) ?>
<?= $this->Form->end() ?>
</div>

View File

@ -1,46 +1,46 @@
<?php
namespace App\Test\TestCase\Controller;
use App\Controller\AppController;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
/**
* App\Controller\DashboardController Test Case
*
* @uses \App\Controller\DashboardController
*/
class AppControllerTest extends TestCase
{
use IntegrationTestTrait;
/**
* Fixtures
*
* @var array
*/
public $fixtures = [
'app.StateBalances'
];
public function setUp()
{
parent::setUp();
}
/**
* Test initialize method
*
* @return void
*/
public function testInitialize()
{
$this->session(['StateUser.id' => 1]);
$this->get('/');
$this->assertSession(1200, 'StateUser.balance');
//$this->markTestIncomplete('Not implemented yet.');
}
}
<?php
namespace App\Test\TestCase\Controller;
use App\Controller\AppController;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
/**
* App\Controller\DashboardController Test Case
*
* @uses \App\Controller\DashboardController
*/
class AppControllerTest extends TestCase
{
use IntegrationTestTrait;
/**
* Fixtures
*
* @var array
*/
public $fixtures = [
'app.StateBalances'
];
public function setUp()
{
parent::setUp();
}
/**
* Test initialize method
*
* @return void
*/
public function testInitialize()
{
$this->session(['StateUser.id' => 1]);
$this->get('/');
$this->assertSession(1200, 'StateUser.balance');
//$this->markTestIncomplete('Not implemented yet.');
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,408 +1,408 @@
<?php
use Cake\Cache\Engine\FileEngine;
use Cake\Database\Connection;
use Cake\Database\Driver\Mysql;
use Cake\Error\ExceptionRenderer;
use Cake\Log\Engine\FileLog;
use Cake\Mailer\Transport\MailTransport;
return [
/**
* Debug Level:
*
* Production Mode:
* false: No error messages, errors, or warnings shown.
*
* Development Mode:
* true: Errors and warnings shown.
*/
'debug' => filter_var(env('DEBUG', true), FILTER_VALIDATE_BOOLEAN),
/**
* Configure basic information about the application.
*
* - namespace - The namespace to find app classes under.
* - defaultLocale - The default locale for translation, formatting currencies and numbers, date and time.
* - encoding - The encoding used for HTML + database connections.
* - base - The base directory the app resides in. If false this
* will be auto detected.
* - dir - Name of app directory.
* - webroot - The webroot directory.
* - wwwRoot - The file path to webroot.
* - baseUrl - To configure CakePHP to *not* use mod_rewrite and to
* use CakePHP pretty URLs, remove these .htaccess
* files:
* /.htaccess
* /webroot/.htaccess
* And uncomment the baseUrl key below.
* - fullBaseUrl - A base URL to use for absolute links. When set to false (default)
* CakePHP generates required value based on `HTTP_HOST` environment variable.
* However, you can define it manually to optimize performance or if you
* are concerned about people manipulating the `Host` header.
* - imageBaseUrl - Web path to the public images directory under webroot.
* - cssBaseUrl - Web path to the public css directory under webroot.
* - jsBaseUrl - Web path to the public js directory under webroot.
* - paths - Configure paths for non class based resources. Supports the
* `plugins`, `templates`, `locales` subkeys, which allow the definition of
* paths for plugins, view templates and locale files respectively.
*/
'App' => [
'namespace' => 'App',
'encoding' => env('APP_ENCODING', 'UTF-8'),
'defaultLocale' => env('APP_DEFAULT_LOCALE', 'en_US'),
'defaultTimezone' => env('APP_DEFAULT_TIMEZONE', 'UTC'),
'base' => false,
'dir' => 'src',
'webroot' => 'webroot',
'wwwRoot' => WWW_ROOT,
//'baseUrl' => env('SCRIPT_NAME'),
'fullBaseUrl' => false,
'imageBaseUrl' => 'img/',
'cssBaseUrl' => 'css/',
'jsBaseUrl' => 'js/',
'paths' => [
'plugins' => [ROOT . DS . 'plugins' . DS],
'templates' => [APP . 'Template' . DS],
'locales' => [APP . 'Locale' . DS],
],
],
/**
* Security and encryption configuration
*
* - salt - A random string used in security hashing methods.
* The salt value is also used as the encryption key.
* You should treat it as extremely sensitive data.
*/
'Security' => [
'salt' => env('SECURITY_SALT', '7ddf685a27d997ef36e51bdd626e7fc6b50a3abfb2971e8e59974d421116a150'),
],
/**
* Apply timestamps with the last modified time to static assets (js, css, images).
* Will append a querystring parameter containing the time the file was modified.
* This is useful for busting browser caches.
*
* Set to true to apply timestamps when debug is true. Set to 'force' to always
* enable timestamping regardless of debug value.
*/
'Asset' => [
//'timestamp' => true,
// 'cacheTime' => '+1 year'
],
/**
* Configure the cache adapters.
*/
'Cache' => [
'default' => [
'className' => FileEngine::class,
'path' => CACHE,
'url' => env('CACHE_DEFAULT_URL', null),
],
/**
* Configure the cache used for general framework caching.
* Translation cache files are stored with this configuration.
* Duration will be set to '+2 minutes' in bootstrap.php when debug = true
* If you set 'className' => 'Null' core cache will be disabled.
*/
'_cake_core_' => [
'className' => FileEngine::class,
'prefix' => 'myapp_cake_core_',
'path' => CACHE . 'persistent/',
'serialize' => true,
'duration' => '+1 years',
'url' => env('CACHE_CAKECORE_URL', null),
],
/**
* Configure the cache for model and datasource caches. This cache
* configuration is used to store schema descriptions, and table listings
* in connections.
* Duration will be set to '+2 minutes' in bootstrap.php when debug = true
*/
'_cake_model_' => [
'className' => FileEngine::class,
'prefix' => 'myapp_cake_model_',
'path' => CACHE . 'models/',
'serialize' => true,
'duration' => '+1 years',
'url' => env('CACHE_CAKEMODEL_URL', null),
],
/**
* Configure the cache for routes. The cached routes collection is built the
* first time the routes are processed via `config/routes.php`.
* Duration will be set to '+2 seconds' in bootstrap.php when debug = true
*/
'_cake_routes_' => [
'className' => FileEngine::class,
'prefix' => 'myapp_cake_routes_',
'path' => CACHE,
'serialize' => true,
'duration' => '+1 years',
'url' => env('CACHE_CAKEROUTES_URL', null),
],
],
/**
* Configure the Error and Exception handlers used by your application.
*
* By default errors are displayed using Debugger, when debug is true and logged
* by Cake\Log\Log when debug is false.
*
* In CLI environments exceptions will be printed to stderr with a backtrace.
* In web environments an HTML page will be displayed for the exception.
* With debug true, framework errors like Missing Controller will be displayed.
* When debug is false, framework errors will be coerced into generic HTTP errors.
*
* Options:
*
* - `errorLevel` - int - The level of errors you are interested in capturing.
* - `trace` - boolean - Whether or not backtraces should be included in
* logged errors/exceptions.
* - `log` - boolean - Whether or not you want exceptions logged.
* - `exceptionRenderer` - string - The class responsible for rendering
* uncaught exceptions. If you choose a custom class you should place
* the file for that class in src/Error. This class needs to implement a
* render method.
* - `skipLog` - array - List of exceptions to skip for logging. Exceptions that
* extend one of the listed exceptions will also be skipped for logging.
* E.g.:
* `'skipLog' => ['Cake\Http\Exception\NotFoundException', 'Cake\Http\Exception\UnauthorizedException']`
* - `extraFatalErrorMemory` - int - The number of megabytes to increase
* the memory limit by when a fatal error is encountered. This allows
* breathing room to complete logging or error handling.
*/
'Error' => [
'errorLevel' => E_ALL,
'exceptionRenderer' => ExceptionRenderer::class,
'skipLog' => [],
'log' => true,
'trace' => true,
],
/**
* Email configuration.
*
* By defining transports separately from delivery profiles you can easily
* re-use transport configuration across multiple profiles.
*
* You can specify multiple configurations for production, development and
* testing.
*
* Each transport needs a `className`. Valid options are as follows:
*
* Mail - Send using PHP mail function
* Smtp - Send using SMTP
* Debug - Do not send the email, just return the result
*
* You can add custom transports (or override existing transports) by adding the
* appropriate file to src/Mailer/Transport. Transports should be named
* 'YourTransport.php', where 'Your' is the name of the transport.
*/
'EmailTransport' => [
'default' => [
'className' => MailTransport::class,
/*
* The following keys are used in SMTP transports:
*/
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
'username' => null,
'password' => null,
'client' => null,
'tls' => null,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],
/**
* Email delivery profiles
*
* Delivery profiles allow you to predefine various properties about email
* messages from your application and give the settings a name. This saves
* duplication across your application and makes maintenance and development
* easier. Each profile accepts a number of keys. See `Cake\Mailer\Email`
* for more information.
*/
'Email' => [
'default' => [
'transport' => 'default',
'from' => 'you@localhost',
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
],
],
/**
* Connection information used by the ORM to connect
* to your application's datastores.
*
* ### Notes
* - Drivers include Mysql Postgres Sqlite Sqlserver
* See vendor\cakephp\cakephp\src\Database\Driver for complete list
* - Do not use periods in database name - it may lead to error.
* See https://github.com/cakephp/cakephp/issues/6471 for details.
* - 'encoding' is recommended to be set to full UTF-8 4-Byte support.
* E.g set it to 'utf8mb4' in MariaDB and MySQL and 'utf8' for any
* other RDBMS.
*/
'Datasources' => [
'default' => [
'className' => Connection::class,
'driver' => Mysql::class,
'persistent' => false,
'host' => 'mariadb',
/*
* CakePHP will use the default DB port based on the driver selected
* MySQL on MAMP uses port 8889, MAMP users will want to uncomment
* the following line and set the port accordingly
*/
//'port' => 'non_standard_port_number',
'username' => 'root',
'password' => '',
'database' => 'gradido_community',
/*
* You do not need to set this flag to use full utf-8 encoding (internal default since CakePHP 3.6).
*/
//'encoding' => 'utf8mb4',
'timezone' => 'UTC',
'flags' => [],
'cacheMetadata' => true,
'log' => false,
/**
* Set identifier quoting to true if you are using reserved words or
* special characters in your table or column names. Enabling this
* setting will result in queries built using the Query Builder having
* identifiers quoted when creating SQL. It should be noted that this
* decreases performance because each query needs to be traversed and
* manipulated before being executed.
*/
'quoteIdentifiers' => false,
/**
* During development, if using MySQL < 5.6, uncommenting the
* following line could boost the speed at which schema metadata is
* fetched from the database. It can also be set directly with the
* mysql configuration directive 'innodb_stats_on_metadata = 0'
* which is the recommended value in production environments
*/
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
'url' => env('DATABASE_URL', null),
],
/**
* The test connection is used during the test suite.
*/
'test' => [
'className' => Connection::class,
'driver' => Mysql::class,
'persistent' => false,
'host' => 'localhost',
//'port' => 'non_standard_port_number',
'username' => 'my_app',
'password' => 'secret',
'database' => 'test_myapp',
//'encoding' => 'utf8mb4',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
'url' => env('DATABASE_TEST_URL', null),
],
],
/**
* Configures logging options
*/
'Log' => [
'debug' => [
'className' => FileLog::class,
'path' => LOGS,
'file' => 'debug',
'url' => env('LOG_DEBUG_URL', null),
'scopes' => false,
'levels' => ['notice', 'info', 'debug'],
],
'error' => [
'className' => FileLog::class,
'path' => LOGS,
'file' => 'error',
'url' => env('LOG_ERROR_URL', null),
'scopes' => false,
'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
],
// To enable this dedicated query log, you need set your datasource's log flag to true
'queries' => [
'className' => FileLog::class,
'path' => LOGS,
'file' => 'queries',
'url' => env('LOG_QUERIES_URL', null),
'scopes' => ['queriesLog'],
],
],
/**
* Session configuration.
*
* Contains an array of settings to use for session configuration. The
* `defaults` key is used to define a default preset to use for sessions, any
* settings declared here will override the settings of the default config.
*
* ## Options
*
* - `cookie` - The name of the cookie to use. Defaults to 'CAKEPHP'. Avoid using `.` in cookie names,
* as PHP will drop sessions from cookies with `.` in the name.
* - `cookiePath` - The url path for which session cookie is set. Maps to the
* `session.cookie_path` php.ini config. Defaults to base path of app.
* - `timeout` - The time in minutes the session should be valid for.
* Pass 0 to disable checking timeout.
* Please note that php.ini's session.gc_maxlifetime must be equal to or greater
* than the largest Session['timeout'] in all served websites for it to have the
* desired effect.
* - `defaults` - The default configuration set to use as a basis for your session.
* There are four built-in options: php, cake, cache, database.
* - `handler` - Can be used to enable a custom session handler. Expects an
* array with at least the `engine` key, being the name of the Session engine
* class to use for managing the session. CakePHP bundles the `CacheSession`
* and `DatabaseSession` engines.
* - `ini` - An associative array of additional ini values to set.
*
* The built-in `defaults` options are:
*
* - 'php' - Uses settings defined in your php.ini.
* - 'cake' - Saves session files in CakePHP's /tmp directory.
* - 'database' - Uses CakePHP's database sessions.
* - 'cache' - Use the Cache class to save sessions.
*
* To define a custom session handler, save it at src/Network/Session/<name>.php.
* Make sure the class implements PHP's `SessionHandlerInterface` and set
* Session.handler to <name>
*
* To use database sessions, load the SQL file located at config/schema/sessions.sql
*/
'Session' => [
'defaults' => 'php',
],
// Gradido specific configuration
// Login Server ip and port
'LoginServer' => [
'host' => 'http://login-server',
'port' => 1201
],
'API' => [
'allowedCaller' => ['login-server']
],
'ServerAdminEmail' => 'info@gradido.net',
'noReplyEmail' => 'no-reply@gradido.net',
'disableEmail' => true,
'GroupNode' => false
];
<?php
use Cake\Cache\Engine\FileEngine;
use Cake\Database\Connection;
use Cake\Database\Driver\Mysql;
use Cake\Error\ExceptionRenderer;
use Cake\Log\Engine\FileLog;
use Cake\Mailer\Transport\MailTransport;
return [
/**
* Debug Level:
*
* Production Mode:
* false: No error messages, errors, or warnings shown.
*
* Development Mode:
* true: Errors and warnings shown.
*/
'debug' => filter_var(env('DEBUG', true), FILTER_VALIDATE_BOOLEAN),
/**
* Configure basic information about the application.
*
* - namespace - The namespace to find app classes under.
* - defaultLocale - The default locale for translation, formatting currencies and numbers, date and time.
* - encoding - The encoding used for HTML + database connections.
* - base - The base directory the app resides in. If false this
* will be auto detected.
* - dir - Name of app directory.
* - webroot - The webroot directory.
* - wwwRoot - The file path to webroot.
* - baseUrl - To configure CakePHP to *not* use mod_rewrite and to
* use CakePHP pretty URLs, remove these .htaccess
* files:
* /.htaccess
* /webroot/.htaccess
* And uncomment the baseUrl key below.
* - fullBaseUrl - A base URL to use for absolute links. When set to false (default)
* CakePHP generates required value based on `HTTP_HOST` environment variable.
* However, you can define it manually to optimize performance or if you
* are concerned about people manipulating the `Host` header.
* - imageBaseUrl - Web path to the public images directory under webroot.
* - cssBaseUrl - Web path to the public css directory under webroot.
* - jsBaseUrl - Web path to the public js directory under webroot.
* - paths - Configure paths for non class based resources. Supports the
* `plugins`, `templates`, `locales` subkeys, which allow the definition of
* paths for plugins, view templates and locale files respectively.
*/
'App' => [
'namespace' => 'App',
'encoding' => env('APP_ENCODING', 'UTF-8'),
'defaultLocale' => env('APP_DEFAULT_LOCALE', 'en_US'),
'defaultTimezone' => env('APP_DEFAULT_TIMEZONE', 'UTC'),
'base' => false,
'dir' => 'src',
'webroot' => 'webroot',
'wwwRoot' => WWW_ROOT,
//'baseUrl' => env('SCRIPT_NAME'),
'fullBaseUrl' => false,
'imageBaseUrl' => 'img/',
'cssBaseUrl' => 'css/',
'jsBaseUrl' => 'js/',
'paths' => [
'plugins' => [ROOT . DS . 'plugins' . DS],
'templates' => [APP . 'Template' . DS],
'locales' => [APP . 'Locale' . DS],
],
],
/**
* Security and encryption configuration
*
* - salt - A random string used in security hashing methods.
* The salt value is also used as the encryption key.
* You should treat it as extremely sensitive data.
*/
'Security' => [
'salt' => env('SECURITY_SALT', '7ddf685a27d997ef36e51bdd626e7fc6b50a3abfb2971e8e59974d421116a150'),
],
/**
* Apply timestamps with the last modified time to static assets (js, css, images).
* Will append a querystring parameter containing the time the file was modified.
* This is useful for busting browser caches.
*
* Set to true to apply timestamps when debug is true. Set to 'force' to always
* enable timestamping regardless of debug value.
*/
'Asset' => [
//'timestamp' => true,
// 'cacheTime' => '+1 year'
],
/**
* Configure the cache adapters.
*/
'Cache' => [
'default' => [
'className' => FileEngine::class,
'path' => CACHE,
'url' => env('CACHE_DEFAULT_URL', null),
],
/**
* Configure the cache used for general framework caching.
* Translation cache files are stored with this configuration.
* Duration will be set to '+2 minutes' in bootstrap.php when debug = true
* If you set 'className' => 'Null' core cache will be disabled.
*/
'_cake_core_' => [
'className' => FileEngine::class,
'prefix' => 'myapp_cake_core_',
'path' => CACHE . 'persistent/',
'serialize' => true,
'duration' => '+1 years',
'url' => env('CACHE_CAKECORE_URL', null),
],
/**
* Configure the cache for model and datasource caches. This cache
* configuration is used to store schema descriptions, and table listings
* in connections.
* Duration will be set to '+2 minutes' in bootstrap.php when debug = true
*/
'_cake_model_' => [
'className' => FileEngine::class,
'prefix' => 'myapp_cake_model_',
'path' => CACHE . 'models/',
'serialize' => true,
'duration' => '+1 years',
'url' => env('CACHE_CAKEMODEL_URL', null),
],
/**
* Configure the cache for routes. The cached routes collection is built the
* first time the routes are processed via `config/routes.php`.
* Duration will be set to '+2 seconds' in bootstrap.php when debug = true
*/
'_cake_routes_' => [
'className' => FileEngine::class,
'prefix' => 'myapp_cake_routes_',
'path' => CACHE,
'serialize' => true,
'duration' => '+1 years',
'url' => env('CACHE_CAKEROUTES_URL', null),
],
],
/**
* Configure the Error and Exception handlers used by your application.
*
* By default errors are displayed using Debugger, when debug is true and logged
* by Cake\Log\Log when debug is false.
*
* In CLI environments exceptions will be printed to stderr with a backtrace.
* In web environments an HTML page will be displayed for the exception.
* With debug true, framework errors like Missing Controller will be displayed.
* When debug is false, framework errors will be coerced into generic HTTP errors.
*
* Options:
*
* - `errorLevel` - int - The level of errors you are interested in capturing.
* - `trace` - boolean - Whether or not backtraces should be included in
* logged errors/exceptions.
* - `log` - boolean - Whether or not you want exceptions logged.
* - `exceptionRenderer` - string - The class responsible for rendering
* uncaught exceptions. If you choose a custom class you should place
* the file for that class in src/Error. This class needs to implement a
* render method.
* - `skipLog` - array - List of exceptions to skip for logging. Exceptions that
* extend one of the listed exceptions will also be skipped for logging.
* E.g.:
* `'skipLog' => ['Cake\Http\Exception\NotFoundException', 'Cake\Http\Exception\UnauthorizedException']`
* - `extraFatalErrorMemory` - int - The number of megabytes to increase
* the memory limit by when a fatal error is encountered. This allows
* breathing room to complete logging or error handling.
*/
'Error' => [
'errorLevel' => E_ALL,
'exceptionRenderer' => ExceptionRenderer::class,
'skipLog' => [],
'log' => true,
'trace' => true,
],
/**
* Email configuration.
*
* By defining transports separately from delivery profiles you can easily
* re-use transport configuration across multiple profiles.
*
* You can specify multiple configurations for production, development and
* testing.
*
* Each transport needs a `className`. Valid options are as follows:
*
* Mail - Send using PHP mail function
* Smtp - Send using SMTP
* Debug - Do not send the email, just return the result
*
* You can add custom transports (or override existing transports) by adding the
* appropriate file to src/Mailer/Transport. Transports should be named
* 'YourTransport.php', where 'Your' is the name of the transport.
*/
'EmailTransport' => [
'default' => [
'className' => MailTransport::class,
/*
* The following keys are used in SMTP transports:
*/
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
'username' => null,
'password' => null,
'client' => null,
'tls' => null,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],
/**
* Email delivery profiles
*
* Delivery profiles allow you to predefine various properties about email
* messages from your application and give the settings a name. This saves
* duplication across your application and makes maintenance and development
* easier. Each profile accepts a number of keys. See `Cake\Mailer\Email`
* for more information.
*/
'Email' => [
'default' => [
'transport' => 'default',
'from' => 'you@localhost',
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
],
],
/**
* Connection information used by the ORM to connect
* to your application's datastores.
*
* ### Notes
* - Drivers include Mysql Postgres Sqlite Sqlserver
* See vendor\cakephp\cakephp\src\Database\Driver for complete list
* - Do not use periods in database name - it may lead to error.
* See https://github.com/cakephp/cakephp/issues/6471 for details.
* - 'encoding' is recommended to be set to full UTF-8 4-Byte support.
* E.g set it to 'utf8mb4' in MariaDB and MySQL and 'utf8' for any
* other RDBMS.
*/
'Datasources' => [
'default' => [
'className' => Connection::class,
'driver' => Mysql::class,
'persistent' => false,
'host' => 'mariadb',
/*
* CakePHP will use the default DB port based on the driver selected
* MySQL on MAMP uses port 8889, MAMP users will want to uncomment
* the following line and set the port accordingly
*/
//'port' => 'non_standard_port_number',
'username' => 'root',
'password' => '',
'database' => 'gradido_community',
/*
* You do not need to set this flag to use full utf-8 encoding (internal default since CakePHP 3.6).
*/
//'encoding' => 'utf8mb4',
'timezone' => 'UTC',
'flags' => [],
'cacheMetadata' => true,
'log' => false,
/**
* Set identifier quoting to true if you are using reserved words or
* special characters in your table or column names. Enabling this
* setting will result in queries built using the Query Builder having
* identifiers quoted when creating SQL. It should be noted that this
* decreases performance because each query needs to be traversed and
* manipulated before being executed.
*/
'quoteIdentifiers' => false,
/**
* During development, if using MySQL < 5.6, uncommenting the
* following line could boost the speed at which schema metadata is
* fetched from the database. It can also be set directly with the
* mysql configuration directive 'innodb_stats_on_metadata = 0'
* which is the recommended value in production environments
*/
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
'url' => env('DATABASE_URL', null),
],
/**
* The test connection is used during the test suite.
*/
'test' => [
'className' => Connection::class,
'driver' => Mysql::class,
'persistent' => false,
'host' => 'localhost',
//'port' => 'non_standard_port_number',
'username' => 'my_app',
'password' => 'secret',
'database' => 'test_myapp',
//'encoding' => 'utf8mb4',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
'url' => env('DATABASE_TEST_URL', null),
],
],
/**
* Configures logging options
*/
'Log' => [
'debug' => [
'className' => FileLog::class,
'path' => LOGS,
'file' => 'debug',
'url' => env('LOG_DEBUG_URL', null),
'scopes' => false,
'levels' => ['notice', 'info', 'debug'],
],
'error' => [
'className' => FileLog::class,
'path' => LOGS,
'file' => 'error',
'url' => env('LOG_ERROR_URL', null),
'scopes' => false,
'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
],
// To enable this dedicated query log, you need set your datasource's log flag to true
'queries' => [
'className' => FileLog::class,
'path' => LOGS,
'file' => 'queries',
'url' => env('LOG_QUERIES_URL', null),
'scopes' => ['queriesLog'],
],
],
/**
* Session configuration.
*
* Contains an array of settings to use for session configuration. The
* `defaults` key is used to define a default preset to use for sessions, any
* settings declared here will override the settings of the default config.
*
* ## Options
*
* - `cookie` - The name of the cookie to use. Defaults to 'CAKEPHP'. Avoid using `.` in cookie names,
* as PHP will drop sessions from cookies with `.` in the name.
* - `cookiePath` - The url path for which session cookie is set. Maps to the
* `session.cookie_path` php.ini config. Defaults to base path of app.
* - `timeout` - The time in minutes the session should be valid for.
* Pass 0 to disable checking timeout.
* Please note that php.ini's session.gc_maxlifetime must be equal to or greater
* than the largest Session['timeout'] in all served websites for it to have the
* desired effect.
* - `defaults` - The default configuration set to use as a basis for your session.
* There are four built-in options: php, cake, cache, database.
* - `handler` - Can be used to enable a custom session handler. Expects an
* array with at least the `engine` key, being the name of the Session engine
* class to use for managing the session. CakePHP bundles the `CacheSession`
* and `DatabaseSession` engines.
* - `ini` - An associative array of additional ini values to set.
*
* The built-in `defaults` options are:
*
* - 'php' - Uses settings defined in your php.ini.
* - 'cake' - Saves session files in CakePHP's /tmp directory.
* - 'database' - Uses CakePHP's database sessions.
* - 'cache' - Use the Cache class to save sessions.
*
* To define a custom session handler, save it at src/Network/Session/<name>.php.
* Make sure the class implements PHP's `SessionHandlerInterface` and set
* Session.handler to <name>
*
* To use database sessions, load the SQL file located at config/schema/sessions.sql
*/
'Session' => [
'defaults' => 'php',
],
// Gradido specific configuration
// Login Server ip and port
'LoginServer' => [
'host' => 'http://login-server',
'port' => 1201
],
'API' => [
'allowedCaller' => ['login-server']
],
'ServerAdminEmail' => 'info@gradido.net',
'noReplyEmail' => 'no-reply@gradido.net',
'disableEmail' => true,
'GroupNode' => false
];

View File

@ -51,4 +51,6 @@ 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

View File

@ -1,20 +1,20 @@
worker_count = 2
io_worker_count = 1
data_root_folder = /opt/instance/.gradido
hedera_mirror_endpoint = hcs.testnet.mirrornode.hedera.com:5600
sibling_node_file = /opt/instance/.gradido/sibling_nodes.txt
#group_requests_endpoint = 0.0.0.0:13701
#record_requests_endpoint = 0.0.0.0:13702
#manage_network_requests_endpoint = 0.0.0.0:13703
grpc_endpoint = 0.0.0.0:13701
json_rpc_port = 13702
# larger value, larger batch, less concurrency
blockchain_append_batch_size = 1000
#blochchain_init_batch_size = 1000
#block_record_outbound_batch_size = 100
general_batch_size = 1000
group_register_topic_id = 0.0.79574
topic_reset_allowed = 1
worker_count = 2
io_worker_count = 1
data_root_folder = /opt/instance/.gradido
hedera_mirror_endpoint = hcs.testnet.mirrornode.hedera.com:5600
sibling_node_file = /opt/instance/.gradido/sibling_nodes.txt
#group_requests_endpoint = 0.0.0.0:13701
#record_requests_endpoint = 0.0.0.0:13702
#manage_network_requests_endpoint = 0.0.0.0:13703
grpc_endpoint = 0.0.0.0:13701
json_rpc_port = 13702
# larger value, larger batch, less concurrency
blockchain_append_batch_size = 1000
#blochchain_init_batch_size = 1000
#block_record_outbound_batch_size = 100
general_batch_size = 1000
group_register_topic_id = 0.0.79574
topic_reset_allowed = 1

View File

@ -38,6 +38,10 @@ services:
## NGINX ################################################
#########################################################
nginx:
depends_on:
- frontend
- community-server
- login-server
volumes:
- ./logs:/var/log/nginx
@ -74,4 +78,5 @@ services:
volumes:
frontend_node_modules:
conan:
conan:

View File

@ -1,138 +1,138 @@
# This file defines the production settings. It is overwritten by docker-compose.override.yml,
# which defines the development settings. The override.yml is loaded by default. Therefore it
# is required to explicitly define if you want an production build:
# > docker-compose -f docker-compose.yml up
version: "3.4"
services:
########################################################
# FRONTEND #############################################
########################################################
frontend:
image: gradido/frontend:latest
build:
context: ./frontend
target: production
networks:
- external-net
depends_on:
- nginx
ports:
- 8080:8080
environment:
# Envs used in Dockerfile
# - DOCKER_WORKDIR="/app"
# - PORT="8080"
- BUILD_DATE
- BUILD_VERSION
- BUILD_COMMIT
- NODE_ENV="production"
# Application only envs
#- HOST=0.0.0.0 # This is nuxt specific, alternative value is HOST=webapp
#env_file:
# - ./frontend/.env
#########################################################
## MARIADB ##############################################
#########################################################
mariadb:
build:
context: .
dockerfile: ./mariadb/Dockerfile
target: mariadb_server
container_name: mariadb
environment:
- MARIADB_ALLOW_EMPTY_PASSWORD=1
- MARIADB_USER=root
networks:
- internal-net
ports:
- 3306:3306
volumes:
- db_vol:/var/lib/mysql
#########################################################
## LOGIN SERVER #########################################
#########################################################
login-server:
build:
context: ./login_server/
target: login_server
container_name: login-server
depends_on:
- mariadb
networks:
- internal-net
ports:
- 1200:1200
- 1201:1201
volumes:
- ./configs/login_server:/etc/grd_login
#########################################################
## NGINX ################################################
#########################################################
## nginx, connect login-server and community-server together (and php-fpm to community-server)
nginx:
build:
context: .
dockerfile: ./nginx/Dockerfile
container_name: nginx
networks:
- external-net
- internal-net
depends_on:
- community-server
- login-server
ports:
- 80:80
#########################################################
## COMMUNITY SERVER (cakephp with php-fpm) ##############
#########################################################
community-server:
build:
context: .
dockerfile: ./community_server/Dockerfile
container_name: community-server
environment:
- DB_PASSWORD=''
- DB_USER='root'
- DB_DATABASE='gradido_community'
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
#########################################################
## GRADIDO NODE v1 ######################################
#########################################################
# gradido-node:
# build:
# context: .
# dockerfile: ./gn/docker/deprecated-hedera-node/Dockerfile
# volumes:
# - ${GN_INSTANCE_FOLDER}:/opt/instance
# container_name: ${GN_CONTAINER_NAME}
#########################################################
## GRADIDO NODE test ###################################
#########################################################
# gradido-node-test:
# build:
# context: .
# dockerfile: ./gn/docker/deprecated-hedera-node/Dockerfile
# container_name: gn-test
# working_dir: /opt/gn/build
# command: ["./unit_tests"]
networks:
external-net:
internal-net:
internal: true
volumes:
db_vol:
# This file defines the production settings. It is overwritten by docker-compose.override.yml,
# which defines the development settings. The override.yml is loaded by default. Therefore it
# is required to explicitly define if you want an production build:
# > docker-compose -f docker-compose.yml up
version: "3.4"
services:
########################################################
# FRONTEND #############################################
########################################################
frontend:
image: gradido/frontend:latest
build:
context: ./frontend
target: production
networks:
- external-net
depends_on:
- nginx
ports:
- 8080:8080
environment:
# Envs used in Dockerfile
# - DOCKER_WORKDIR="/app"
# - PORT="8080"
- BUILD_DATE
- BUILD_VERSION
- BUILD_COMMIT
- NODE_ENV="production"
# Application only envs
#- HOST=0.0.0.0 # This is nuxt specific, alternative value is HOST=webapp
#env_file:
# - ./frontend/.env
#########################################################
## MARIADB ##############################################
#########################################################
mariadb:
build:
context: .
dockerfile: ./mariadb/Dockerfile
target: mariadb_server
container_name: mariadb
environment:
- MARIADB_ALLOW_EMPTY_PASSWORD=1
- MARIADB_USER=root
networks:
- internal-net
ports:
- 3306:3306
volumes:
- db_vol:/var/lib/mysql
#########################################################
## LOGIN SERVER #########################################
#########################################################
login-server:
build:
context: ./login_server/
target: login_server
container_name: login-server
depends_on:
- mariadb
networks:
- internal-net
ports:
- 1200:1200
- 1201:1201
volumes:
- ./configs/login_server:/etc/grd_login
#########################################################
## NGINX ################################################
#########################################################
## nginx, connect login-server and community-server together (and php-fpm to community-server)
nginx:
build:
context: .
dockerfile: ./nginx/Dockerfile
container_name: nginx
networks:
- external-net
- internal-net
depends_on:
- community-server
- login-server
ports:
- 80:80
#########################################################
## COMMUNITY SERVER (cakephp with php-fpm) ##############
#########################################################
community-server:
build:
context: .
dockerfile: ./community_server/Dockerfile
container_name: community-server
environment:
- DB_PASSWORD=''
- DB_USER='root'
- DB_DATABASE='gradido_community'
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
#########################################################
## GRADIDO NODE v1 ######################################
#########################################################
# gradido-node:
# build:
# context: .
# dockerfile: ./gn/docker/deprecated-hedera-node/Dockerfile
# volumes:
# - ${GN_INSTANCE_FOLDER}:/opt/instance
# container_name: ${GN_CONTAINER_NAME}
#########################################################
## GRADIDO NODE test ###################################
#########################################################
# gradido-node-test:
# build:
# context: .
# dockerfile: ./gn/docker/deprecated-hedera-node/Dockerfile
# container_name: gn-test
# working_dir: /opt/gn/build
# command: ["./unit_tests"]
networks:
external-net:
internal-net:
internal: true
volumes:
db_vol:

View File

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

View File

@ -277,7 +277,7 @@ return with "state":"error" and additional "msg" if error occured (no email send
Check if transactions on login-server for user are processed
GET http://localhost/login_api/getRunningUserTasks?email=max.musterman%40gmail.de
# OR
**OR**
POST http://localhost/login_api/getRunningUserTasks
```json
{"email":"max.musterman@gmail.de"}

View File

@ -1,22 +0,0 @@
{
"presets": [
[
"@babel/preset-env"
]
],
"env": {
"test": {
"plugins": ["require-context-hook"],
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "10"
}
}
]
]
}
}
}

View File

@ -1,3 +1,4 @@
LOGIN_API_URL=http://localhost/login_api/
COMMUNITY_API_STATE_BALANCE_URL=http://localhost/state-balances/
COMMUNITY_API_TRANSACTION_CREATION_URL=http://localhost/transaction-creations/
COMMUNITY_API_TRANSACTION_CREATION_URL=http://localhost/transaction-creations/
VUE_PATH=/vue

21
frontend/DEV-README.md Normal file
View File

@ -0,0 +1,21 @@
DEV README von Alex
default Page:
´´´
<template>
<div>default</div>
</template>
<script>
export default {
name: 'default',
data() {
return {}
},
methods: {},
watch: {},
}
</script>
´´´

View File

@ -1,5 +1,5 @@
module.exports = {
presets: ['@vue/app'],
presets: ['@babel/preset-env'],
plugins: [
[
'component',

View File

@ -10,16 +10,15 @@ module.exports = {
coverageReporters: ['lcov'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
'\\.(css|less)$': 'identity-obj-proxy',
},
transform: {
'^.+\\.vue$': 'vue-jest',
// '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.(js|jsx)?$': 'babel-jest',
'^.+\\.vue$': '<rootDir>/node_modules/vue-jest',
'^.+\\.(js|jsx)?$': '<rootDir>/node_modules/babel-jest',
},
//setupFiles: [
// "<rootDir>/test/registerContext.js"
//],
setupFiles: ['<rootDir>/test/testSetup.js'],
testMatch: ['**/?(*.)+(spec|test).js?(x)'],
// snapshotSerializers: ['jest-serializer-vue'],
transformIgnorePatterns: ['<rootDir>/node_modules/'],
preset: '@vue/cli-plugin-unit-jest',
}

View File

@ -1,6 +1,6 @@
{
"name": "bootstrap-vue-gradido-wallet",
"version": "0.9.2",
"version": "0.9.4",
"private": true,
"scripts": {
"start": "node server.js",
@ -12,11 +12,16 @@
"test": "jest"
},
"dependencies": {
"@babel/core": "^7.13.13",
"@babel/node": "^7.13.13",
"@babel/preset-env": "^7.13.12",
"@vue/cli-plugin-unit-jest": "^4.5.12",
"@vue/test-utils": "^1.1.3",
"axios": "^0.21.1",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^26.6.3",
"babel-plugin-require-context-hook": "^1.0.0",
"babel-preset-vue": "^2.0.2",
"bootstrap": "4.3.1",
"bootstrap-vue": "^2.5.0",
"chart.js": "^2.9.3",
@ -41,6 +46,7 @@
"flatpickr": "^4.5.7",
"fuse.js": "^3.2.0",
"google-maps": "^3.2.1",
"identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3",
"nouislider": "^12.1.0",
"particles-bg-vue": "1.2.3",

View File

@ -32,6 +32,13 @@ export default {
components: {
ParticlesBg,
},
data() {
return {
session_id: null,
email: '',
language: 'en',
}
},
created() {
//console.log('xx', $cookies.get('gdd_lang'))
//console.log('%cWillkommen bei Gradido %cgreen text', 'font-weight:bold', 'color: green')

View File

@ -60,43 +60,33 @@
"title": "Danke!",
"subtitle": "Wir haben dir eine eMail gesendet."
},
"overview":{
"overview":{
"account_overview":"Kontoübersicht",
"since_last_month": "seid letzten Monat",
"send_gradido":"Gradido versenden",
"add_work":"neuer Gemeinschaftsbeitrag"
},
"navbar" : {
"my-profil":"Mein Profil",
"settings":"Einstellungen",
"activity":"Aktivität",
"support":"Support"
},
"sidebar" : {
"community":"Gemeinschaft",
"members_area":"Mitgliederbereich",
"membership":"Mitgliedschaft",
"language":"Sprachen"
},
"landing1" : {
"explore": "Erkunden Sie Gradido",
"text": "Gesundes Geld für eine gesunde Welt — Das Gradido-Modell kann weltweiten Wohlstand und Frieden schaffen",
"link": "Seiten erkunden"
},
"404" : {
"ooops" : "Ooops!",
"text" : "Seite nicht gefunden. Aber keine Sorge, wir haben noch viele andere Seiten zum Erkunden",
"back" : "Zurück zur Übersicht!"
}
},
"admin": {
"site": {
"overview": {
"created": "Schöpfen",
"transience" : "Transience",
"exchanged": "Exchanged",
"members" : "Members"
}
},
"navbar" : {
"my-profil":"Mein Profil",
"settings":"Einstellungen",
"activity":"Aktivität",
"support":"Support"
},
"sidebar" : {
"community":"Gemeinschaft",
"members_area":"Mitgliederbereich",
"membership":"Mitgliedschaft",
"language":"Sprachen"
},
"landing1" : {
"explore": "Erkunden Sie Gradido",
"text": "Gesundes Geld für eine gesunde Welt — Das Gradido-Modell kann weltweiten Wohlstand und Frieden schaffen",
"link": "Seiten erkunden"
},
"404" : {
"ooops" : "Ooops!",
"text" : "Seite nicht gefunden. Aber keine Sorge, wir haben noch viele andere Seiten zum Erkunden",
"back" : "Zurück zur Übersicht!"
}
},
"nav": {

View File

@ -90,16 +90,6 @@
"back" : "Back to dashboard!"
}
},
"admin": {
"site": {
"overview": {
"creation": "Creation",
"transience" : "Transience",
"exchanged": "Exchanged",
"members" : "Members"
}
}
},
"nav": {
"features": "Features"
}

View File

@ -1,8 +1,7 @@
import DashboardLayout from '@/views/Layout/DashboardLayout.vue'
import DashboardLayout from '@/views/Layout/DashboardLayout_gdd.vue'
import AuthLayoutGDD from '@/views/Layout/AuthLayout_gdd.vue'
import AuthLayout from '@/views/Layout/AuthLayout.vue'
// import NotFound from '@/views/NotFoundPage.vue'
import NotFound from '@/views/NotFoundPage.vue'
const routes = [
{
@ -63,22 +62,7 @@ const routes = [
},
],
},
,
{
path: '/',
redirect: 'AdminOverview',
component: AuthLayout,
children: [
{
path: '/AdminOverview',
name: 'Adminübersicht',
component: () => import('../views/AdminOverview.vue'),
meta: {
requiresAuth: true,
},
},
],
},
{ path: '*', component: NotFound },
]
export default routes

View File

@ -1,33 +0,0 @@
import Vue from 'vue'
import Router from 'vue-router'
import DashboardLayout from '../views/Starter/SampleLayout.vue'
import Starter from '../views/Starter/SamplePage.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'home',
redirect: '/dashboard',
component: DashboardLayout,
children: [
{
path: 'dashboard',
name: 'dashboard',
components: { default: Starter },
},
],
},
],
scrollBehavior: (to, from, savedPosition) => {
if (savedPosition) {
return savedPosition
}
if (to.hash) {
return { selector: to.hash }
}
return { x: 0, y: 0 }
},
})

View File

@ -8,28 +8,16 @@ import communityAPI from '../apis/communityAPI'
export const store = new Vuex.Store({
state: {
session_id: null,
email: null,
email: '',
language: 'en',
sizeDE: 'normal',
sizeGB: 'big',
loginfail: false,
row_form: true,
row_check: false,
row_thx: false,
user: {
name: '',
balance: 0,
balance_gdt: 0,
},
ajaxCreateData: {
session_id: '',
email: '',
amount: 0,
target_date: '',
memo: '',
auto_sign: true,
},
transactions: [],
modals: false,
optionAxios: {
headers: {
@ -39,11 +27,7 @@ export const store = new Vuex.Store({
},
},
},
getters: {
//isLoggedIn: (state /*, getters */) => {
// return state.session_id !== null;
//}
},
getters: {},
// Syncronous mutation of the state
mutations: {
language: (state, language) => {
@ -78,10 +62,6 @@ export const store = new Vuex.Store({
//console.log('mutation: user_balance_gdt')
state.user.balance_gdt = balance / 10000
},
transactions: (state, transactions) => {
//console.log('mutation: transactions')
state.transactions = transactions
},
},
// Asyncronous actions - used for api calls
actions: {
@ -129,7 +109,6 @@ export const store = new Vuex.Store({
},
logout: async ({ commit, state }) => {
//console.log('action: logout')
// Are we actually logged in?
if (state.session_id) {
const result = await loginAPI.logout(state.session_id)
// The result can be error, but thats ok with us
@ -142,39 +121,11 @@ export const store = new Vuex.Store({
$cookies.remove('gdd_lang')
router.push('/Login')
},
ajaxCreate: async ({ dispatch, state }) => {
//console.log('action: ajaxCreate')
state.ajaxCreateData.amount = state.ajaxCreateData.amount * 10000
const result = await communityAPI.send(
state.session_id,
state.ajaxCreateData.email,
state.ajaxCreateData.amount,
state.ajaxCreateData.memo,
)
return result
//console.log(result)
},
ajaxListTransactions: async ({ commit, dispatch, state }) => {
// console.log('action: ajaxListTransactions', state.session_id)
// const result = await communityAPI.transactions(state.session_id)
},
accountBalance: async ({ commit, dispatch, state }) => {
//console.log('action: accountBalance')
// console.log('action: dispatch', dispatch)
// console.log('action: state.session_id', state.session_id)
// console.log(" action: $cookies.get('gdd_session_id') ", $cookies.get("gdd_session_id") )
// commit('session_id', $cookies.get("gdd_session_id"))
// commit('email', $cookies.get("gdd_u"))
const result = await communityAPI.balance($cookies.get('gdd_session_id'))
//console.log("accountBalance result", result)
//console.log("aresult.result.data.balance", result.result.data.balance)
if (result.success) {
commit('user_balance', result.result.data.balance)
} else {
//console.log('action accountBalance to logout start')
dispatch('logout')
}
},

View File

@ -1,399 +0,0 @@
<template>
<div>
<base-header class="pb-6 pb-8 pt-5 pt-md-8">
<b-row>
<b-col xl="3" md="6">
<stats-card
:title="$t('admin.site.overview.creation')"
type="gradient-red"
sub-title="350,897"
icon="ni ni-active-40"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">3.48%</span>
<span class="text-nowrap">
{{ $t('site.overview.since_last_month') }}
</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
:title="$t('admin.site.overview.transience')"
type="gradient-orange"
sub-title="2,356"
icon="ni ni-chart-pie-35"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">12.18%</span>
<span class="text-nowrap">
{{ $t('site.overview.since_last_month') }}
</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
:title="$t('admin.site.overview.exchanged')"
type="gradient-green"
sub-title="924"
icon="ni ni-money-coins"
class="mb-4"
>
<template slot="footer">
<span class="text-danger mr-2">5.72%</span>
<span class="text-nowrap">
{{ $t('site.overview.since_last_month') }}
</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
:title="$t('admin.site.overview.members')"
type="gradient-info"
sub-title="49,65%"
icon="ni ni-chart-bar-32"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">54.8%</span>
<span class="text-nowrap">
{{ $t('site.overview.since_last_month') }}
</span>
</template>
</stats-card>
</b-col>
</b-row>
</base-header>
<!--Charts-->
<b-container fluid class="mt--7">
<b-row>
<b-col xl="8" class="mb-5 mb-xl-0">
<card type="default" header-classes="bg-transparent">
<b-row align-v="center" slot="header">
<b-col>
<h6 class="text-light text-uppercase ls-1 mb-1">Charts</h6>
<h5 class="h3 mb-0">Geschöpft</h5>
</b-col>
<b-col>
<b-nav class="nav-pills justify-content-end">
<b-nav-item
class="mr-2 mr-md-0"
:active="bigLineChart.activeIndex === 0"
link-classes="py-2 px-1"
@click.prevent="initBigChart(0)"
>
<span class="d-none d-md-block">geschöpft</span>
<span class="d-md-none">M</span>
</b-nav-item>
<b-nav-item
link-classes="py-2 px-1"
:active="bigLineChart.activeIndex === 1"
@click.prevent="initBigChart(1)"
>
<span class="d-none d-md-block">geteilt</span>
<span class="d-md-none">W</span>
</b-nav-item>
<b-nav-item
link-classes="py-2 px-1"
:active="bigLineChart.activeIndex === 2"
@click.prevent="initBigChart(2)"
>
<span class="d-none d-md-block">vergangen</span>
<span class="d-md-none">W</span>
</b-nav-item>
<b-nav-item
link-classes="py-2 px-1"
:active="bigLineChart.activeIndex === 3"
@click.prevent="initBigChart(3)"
>
<span class="d-none d-md-block">mitglieder</span>
<span class="d-md-none">W</span>
</b-nav-item>
</b-nav>
</b-col>
</b-row>
<line-chart
:height="350"
ref="bigChart"
:chart-data="bigLineChart.chartData"
:extra-options="bigLineChart.extraOptions"
></line-chart>
</card>
</b-col>
<b-col xl="4" class="mb-5 mb-xl-0">
<card header-classes="bg-transparent">
<b-row align-v="center" slot="header">
<b-col>
<h6 class="text-uppercase text-muted ls-1 mb-1">Community</h6>
<h5 class="h3 mb-0">Neue Einträge</h5>
</b-col>
</b-row>
<bar-chart :height="350" ref="barChart" :chart-data="redBarChart.chartData"></bar-chart>
</card>
</b-col>
</b-row>
<!-- End charts-->
<br />
<br />
<br />
<!--Tables User Search && New User-->
<admin-user-search />
<br />
<br />
<br />
<admin-user-creation />
<br />
<b-card-header>
<hr />
<h3>Admin Participation List</h3>
<small>/public/json-example/admin_card_statistic.json</small>
<p>
{{ cardstatistic }}
</p>
</b-card-header>
<b-card-header>
<hr />
<h3>Admin Charts Statistic</h3>
<small>/public/json-example/admin_charts_statistic.json</small>
<p>
{{ chartsstatistic }}
</p>
</b-card-header>
<b-card-header>
<hr />
<h3>Admin Community Statistic</h3>
<small>/public/json-example/admin_community_statistic.json</small>
<p>
{{ communitystatistic }}
</p>
</b-card-header>
<b-card-header>
<hr />
<h3>Admin User List</h3>
<small>/public/json-example/admin_userlist.json</small>
<p>
{{ userlist }}
</p>
</b-card-header>
<b-card-header>
<hr />
<h3>Admin Transaction List</h3>
<small>/public/json-example/admin_transaction_list.json</small>
<p>
{{ transactionlist }}
</p>
<hr />
</b-card-header>
<b-card-header>
<h3>Admin Transience List</h3>
<small>/public/json-example/admin_transience_list.json</small>
<p>
{{ transiencelist }}
</p>
</b-card-header>
<!--End tables-->
</b-container>
</div>
</template>
<script>
// Charts
import * as chartConfigs from '@/components/Charts/config'
import LineChart from '@/components/Charts/LineChart'
import BarChart from '@/components/Charts/BarChart'
// Components
import BaseProgress from '@/components/BaseProgress'
import StatsCard from '@/components/Cards/StatsCard'
import SearchUser from '@/components/SearchUser'
// Tables
import PageVisitsTable from './Dashboard/PageVisitsTable'
import AdminUserSearch from './AdminOverview/AdminUserSearch'
import AdminUserCreation from './AdminOverview/AdminUserCreation'
import axios from 'axios'
export default {
components: {
LineChart,
BarChart,
//BaseProgress,
StatsCard,
//PageVisitsTable,
AdminUserSearch,
AdminUserCreation,
//SearchUser
},
data() {
return {
statisticdata: [],
cardstatistic: [],
chartsstatistic: [],
communitystatistic: [],
userlist: [],
transactionlist: [],
transiencelist: [],
filter: '',
items: [
{ id: 1, first_name: 'Mikkel', last_name: 'Hansen', age: 54 },
{ id: 2, first_name: 'Kasper', last_name: 'Hvidt', age: 42 },
{ id: 3, first_name: 'Lasse', last_name: 'Boesen', age: 39 },
{ id: 4, first_name: 'Kasper', last_name: 'Hansen', age: 62 },
{ id: 5, first_name: 'Mads', last_name: 'Mikkelsen', age: 31 },
],
bigLineChart: {
allData: [
[0, 20, 10, 30, 15, 40, 20, 60, 60],
[0, 20, 5, 25, 10, 30, 35, 60, 40],
[0, 2, 5, 7, 10, 30, 15, 9, 10],
[0, 2, 5, 7, 10, 14, 29, 78, 120],
],
activeIndex: 0,
chartData: {
datasets: [
{
label: 'Performance',
data: [0, 20, 10, 30, 15, 40, 20, 60, 60],
},
],
labels: ['May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
},
extraOptions: chartConfigs.blueChartOptions,
},
redBarChart: {
chartData: {
labels: ['Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
datasets: [
{
label: 'Sales',
data: [25, 20, 30, 22, 17, 29],
},
],
},
extraOptions: chartConfigs.blueChartOptions,
},
}
},
methods: {
TransienceList() {
axios.get('/json-example/admin_transience_list.json').then(
(d) => {
//console.log(d);
this.transiencelist = d.data
},
(error) => {
//console.log(error)
},
)
},
TransactionList() {
axios.get('/json-example/admin_transaction_list.json').then(
(d) => {
//console.log(d);
this.transactionlist = d.data
},
(error) => {
//console.log(error)
},
)
},
UserList() {
axios.get('/json-example/admin_userlist.json').then(
(d) => {
//console.log(d);
this.userlist = d.data
},
(error) => {
//console.log(error)
},
)
},
CommunityStatistic() {
axios.get('/json-example/admin_community_statistic.json').then(
(d) => {
//console.log(d);
this.communitystatistic = d.data
},
(error) => {
//console.log(error)
},
)
},
ChartsStatistic() {
axios.get('/json-example/admin_charts_statistic.json').then(
(d) => {
//console.log(d);
this.chartsstatistic = d.data
},
(error) => {
//console.log(error)
},
)
},
CardStatistic() {
axios.get('/json-example/admin_card_statistic.json').then(
(d) => {
//console.log(d);
this.cardstatistic = d.data
},
(error) => {
//console.log(error)
},
)
},
StatisticDatas() {
axios.get('/json-example/admin_statisticdatas.json').then(
(d) => {
//console.log(d);
this.userdata = d.data
},
(error) => {
//console.log(error)
},
)
},
initBigChart(index) {
let chartData = {
datasets: [
{
label: 'Performance',
data: this.bigLineChart.allData[index],
},
],
labels: ['May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
}
this.bigLineChart.chartData = chartData
this.bigLineChart.activeIndex = index
},
},
mounted() {
this.initBigChart(0)
this.TransienceList()
this.TransactionList()
this.UserList()
this.CommunityStatistic()
this.ChartsStatistic()
this.CardStatistic()
},
}
</script>
<style>
.el-table .cell {
padding-left: 0px;
padding-right: 0px;
}
</style>

View File

@ -1,347 +0,0 @@
<template>
<div>
<b-card-header>Gradido Schüpfung</b-card-header>
<!--Tables-->
<b-row class="mt-5">
<b-col xl="8" class="mb-5 mb-xl-0">
<vue-good-table
:columns="columns"
:rows="rows"
max-height="370px"
:fixed-header="true"
:line-numbers="false"
styleClass="vgt-table"
theme="nocturnal"
@on-row-click="onRowClick"
@on-search="onSearch"
:search-options="{
enabled: true,
skipDiacritics: true,
searchFn: mySearchFn,
placeholder: 'durchsuche die tabelle',
}"
:pagination-options="{
enabled: true,
mode: 'pages',
}"
>
<div slot="table-actions">Einträge suchen .</div>
</vue-good-table>
</b-col>
<b-col xl="4" class="mb-5 mb-xl-0">
<b-card body-class="p-0" header-class="border-0">
<template v-slot:header>
<b-row align-v="center">
<b-col>
<h3 class="mb-0"></h3>
</b-col>
<b-col class="text-right">
<a href="#!" class="btn btn-sm btn-primary">speichern</a>
</b-col>
</b-row>
</template>
<b-card-body>
<p>{{ creation.createdAt }}</p>
<p>{{ creation.group }}</p>
<p>{{ creation.id }}</p>
<p>{{ creation.name }}</p>
<p>{{ creation.originalIndex }}</p>
<p>{{ creation.text }}</p>
<p>{{ creation.vgt_id }}</p>
</b-card-body>
</b-card>
</b-col>
</b-row>
<!--End tables-->
</div>
</template>
<script>
export default {
name: 'admin-user-creation',
data() {
return {
creation: {
createdAt: '',
group: '',
id: '',
name: '',
originalIndex: '',
text: '',
vgt_id: '',
},
columns: [
{
label: 'Name',
field: 'name',
},
{
label: 'Gruppe',
field: 'group',
type: 'group',
},
{
label: 'eingereicht',
field: 'createdAt',
type: 'date',
dateInputFormat: 'yyyy-MM-dd',
dateOutputFormat: 'dd.MM.yyyy',
},
{
label: 'Text',
field: 'text',
type: 'text',
},
],
rows: [
{
id: 1,
createdAt: '2021-01-25',
name: 'Sellora',
group: 'gruppe1',
text: 'aASDASdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 2,
createdAt: '2021-01-31',
name: 'Jane',
group: 'gruppe14',
text: 'WQadCXhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 3,
createdAt: '2021-01-30',
name: 'Susan',
group: 'gruppe31',
text: 'IaYXCYdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 4,
createdAt: '2020-01-11',
name: 'Chris',
group: 'gruppe12',
text: 'TZadhhCYXCda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 5,
createdAt: '2020-12-21',
name: 'Dan',
group: 'gruppe11',
text: 'Wad3323hhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 6,
createdAt: '2020-12-31',
name: 'zBohn',
group: 'gruppe71',
text: 'Tadh hD da hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 7,
createdAt: '2020-12-31',
name: 'xyTellohn',
group: 'gruppe31',
text: 'Fad AD31 hhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 8,
createdAt: '2021-01-25',
name: 'uSellora',
group: 'gruppe1',
text: 'aASDASdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 9,
createdAt: '2021-01-31',
name: 'yJane',
group: 'gruppe14',
text: '55 55 55 WQadCXhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 10,
createdAt: '2021-01-20',
name: 'kSusan',
group: 'gruppe31',
text: 'IaYXCYdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 11,
createdAt: '2021-01-25',
name: 'qSellora',
group: 'gruppe12',
text: 'aASDASdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 12,
createdAt: '2021-01-31',
name: 'fJane',
group: 'gruppe15',
text: 'WQadCXhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 13,
createdAt: '2021-01-38',
name: 'aSusan',
group: 'gruppe1',
text: 'asssss IaYXCYdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 14,
createdAt: '2020-01-11',
name: 'uChris',
group: 'gruppe12',
text: 'TZadhhCYXCda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 15,
createdAt: '2020-12-21',
name: 'tzDan',
group: 'gruppe11',
text: 'Wad33 23hhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 16,
createdAt: '2020-12-31',
name: 'fBohn',
group: 'gruppe71',
text: '3f Tadh hD da hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 17,
createdAt: '2020-12-31',
name: 'aEsau',
group: 'gruppe15',
text: '2324 adhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 18,
createdAt: '2021-01-25',
name: 'gSellora',
group: 'gruppe1',
text: '5h aASDASdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 19,
createdAt: '2021-01-31',
name: 'sJane',
group: 'gruppe14',
text: 'as sdsd WQadCXhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 20,
createdAt: '2021-01-30',
name: 'oSusan',
group: 'gruppe31',
text: 'sd IaYXCYdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 21,
createdAt: '2021-01-25',
name: 'Sellora',
group: 'gruppe1',
text: '3 aASDASdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 22,
createdAt: '2021-01-13',
name: 'rtJane',
group: 'gruppe14',
text: 'q WQadCXhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 23,
createdAt: '2021-01-16',
name: 'rSusan',
group: 'gruppe31',
text: 'Iare YXCYdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 24,
createdAt: '2020-01-15',
name: 'sChris',
group: 'gruppe12',
text: '43 TZad hhCYXCda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 25,
createdAt: '2020-12-14',
name: 'dDan',
group: 'gruppe11',
text: 'aas aWad3323hhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 26,
createdAt: '2020-12-13',
name: 'fBohn',
group: 'gruppe71',
text: 'Ta adh hD da hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 27,
createdAt: '2020-12-12',
name: 'gTellohn',
group: 'gruppe31',
text: '55 Fad AD31 hhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 28,
createdAt: '2021-01-12',
name: 'zSellora',
group: 'gruppe1',
text: 'e q raASDASdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 29,
createdAt: '2021-01-12',
name: 'uJane',
group: 'gruppe14',
text: 'erW QadCXhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
{
id: 30,
createdAt: '2021-01-11',
name: 'iSusan',
group: 'gruppe31',
text: '3IaYXCYdhhda hkahkh hakdh kaks hkadhk kdhkasdh kdhkhka dka dhakhdk',
},
],
}
},
methods: {
onRowClick(params) {
/*
console.log('onRowClick', params.row.createdAt)
console.log('onRowClick', params.row.group)
console.log('onRowClick', params.row.id)
console.log('onRowClick', params.row.name)
console.log('onRowClick', params.row.originalIndex)
console.log('onRowClick', params.row.text)
console.log('onRowClick', params.row.vgt_id)
*/
this.creation.createdAt = params.row.createdAt
this.creation.group = params.row.group
this.creation.id = params.row.id
this.creation.name = params.row.name
this.creation.originalIndex = params.row.originalIndex
this.creation.text = params.row.text
this.creation.vgt_id = params.row.vgt_id
// params.row - row object
// params.pageIndex - index of this row on the current page.
// params.selected - if selection is enabled this argument
// indicates selected or not
// params.event - click event
},
onSearch(params) {
//console.log('onSearch', params)
// params.searchTerm - term being searched for
// params.rowCount - number of rows that match search
},
mySearchFn(params) {
//console.log("mySearchFn", params)
},
},
}
</script>

View File

@ -1,261 +0,0 @@
<template>
<div>
<b-card-header>User</b-card-header>
<!--Tables-->
<b-row class="mt-5">
<b-col xl="8" class="mb-5 mb-xl-0">
<vue-good-table
:columns="columns"
:rows="rows"
max-height="470px"
:fixed-header="true"
:line-numbers="false"
styleClass="vgt-table striped condensed"
theme="nocturnal"
@on-row-click="onRowClick"
@on-search="onSearch"
:search-options="{
enabled: true,
skipDiacritics: true,
searchFn: mySearchFn,
placeholder: 'durchsuche die tabelle',
}"
:pagination-options="{
enabled: true,
mode: 'pages',
}"
>
<div slot="table-actions">Mitglieder suchen .</div>
</vue-good-table>
</b-col>
<b-col xl="4" class="mb-5 mb-xl-0">
<!-- card neues mitglied -->
<b-card v-if="showNewUser" body-class="p-0" header-class="border-0">
<template v-slot:header>
<b-row align-v="center">
<b-col>
<h3 class="mb-0">Neues Mitglied anlegen</h3>
</b-col>
<b-col class="text-right">
<a href="#!" class="btn btn-sm btn-primary">speichern</a>
</b-col>
</b-row>
</template>
<b-card-body>
<form>
<b-row class="">
<label class="col-md-3 col-form-label form-control-label">Name</label>
<b-col md="10">
<base-input placeholder="Jon Snow"></base-input>
</b-col>
</b-row>
<b-row class="">
<label for="example-email-input" class="col-md-3 col-form-label form-control-label">
Email
</label>
<b-col md="10">
<base-input
type="email"
placeholder="gradido@example.com"
id="example-email-input0"
/>
</b-col>
</b-row>
<b-row class="">
<label class="col-md-3 col-form-label form-control-label">Gruppe</label>
<b-col md="10">
<base-input placeholder="Gruppe"></base-input>
</b-col>
</b-row>
</form>
</b-card-body>
</b-card>
<!-- card mitglied bearbeiten -->
<b-card v-else body-class="p-0" header-class="border-0">
<template v-slot:header>
<b-row align-v="center">
<b-col>
<h3 class="mb-0">Mitglied Daten</h3>
</b-col>
<b-col class="text-right">
<a href="#!" @click="showNewUser = true" class="btn btn-sm btn-warning">
schliesen
</a>
</b-col>
</b-row>
</template>
<b-card-body>
<img
style="width: 147px"
src="https://demos.creative-tim.com/argon-dashboard-pro/assets/img/theme/team-4.jpg"
/>
<form>
<b-row class="">
<label class="col-md-3 col-form-label form-control-label">Name</label>
<b-col md="10">
<base-input placeholder="name"></base-input>
</b-col>
</b-row>
<b-row class="">
<label for="example-email-input" class="col-md-3 col-form-label form-control-label">
Email
</label>
<b-col md="10">
<base-input
type="email"
autocomplete="username email"
placeholder="agradido@example.com"
id="example-email-input1"
/>
</b-col>
</b-row>
<b-row class="">
<label class="col-md-3 col-form-label form-control-label">Gruppe</label>
<b-col md="10">
<base-input placeholder="Gruppe"></base-input>
</b-col>
</b-row>
</form>
</b-card-body>
</b-card>
</b-col>
</b-row>
</div>
</template>
<script>
export default {
name: 'admin-user-search',
data() {
return {
showNewUser: true,
formSetUser: {
name: '',
email: '',
group: '',
},
formGetUser: {
name: '',
email: '',
group: '',
},
columns: [
{
label: 'Name',
field: 'name',
},
{
label: 'E-Mail',
field: 'email',
type: 'email',
},
{
label: 'Mitglied seid',
field: 'createdAt',
type: 'date',
dateInputFormat: 'yyyy-MM-dd',
dateOutputFormat: 'dd.MM.yyyy',
},
{
label: 'Gruppe',
field: 'group',
type: 'group',
},
],
rows: [
{
id: 1,
name: 'John',
email: 'temail@tutanota.com',
createdAt: '1976-10-25',
group: 'gruppe1',
},
{
id: 2,
name: 'Jane',
email: 'temail@tutanota.com',
createdAt: '2011-10-31',
group: 'gruppe2',
},
{
id: 3,
name: 'Susan',
email: 'temail@tutanota.com',
createdAt: '2011-10-30',
group: 'gruppe4',
},
{
id: 4,
name: 'Chris',
email: 'temail@tutanota.com',
createdAt: '2011-10-11',
group: 'gruppe3',
},
{
id: 5,
name: 'Dan',
email: 'temail@tutanota.com',
createdAt: '2011-10-21',
group: 'gruppe1',
},
{
id: 6,
name: 'Bohn',
email: 'temail@tutanota.com',
createdAt: '2011-10-31',
group: 'gruppe2',
},
{
id: 7,
name: 'Tellohn',
email: 'temail@tutanota.com',
createdAt: '2009-10-31',
group: 'gruppe2',
},
{
id: 7,
name: 'Tellohn',
email: 'temail@tutanota.com',
createdAt: '2009-10-31',
group: 'gruppe5',
},
],
}
},
methods: {
onRowClick(params) {
//console.log(params.row)
this.showNewUser = false
// params.row - row object
// params.pageIndex - index of this row on the current page.
// params.selected - if selection is enabled this argument
// indicates selected or not
// params.event - click event
},
onSearch(params) {
//console.log(params)
// params.searchTerm - term being searched for
// params.rowCount - number of rows that match search
},
mySearchFn(params) {
//console.log(params)
},
validateEmail(value) {
if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value)) {
this.msg['email'] = ''
} else {
this.msg['email'] = 'Invalid Email Address'
}
},
},
watch: {
mail(value) {
// binding this to the data value in the email input
this.email = value
this.validateEmail(value)
},
},
}
</script>

View File

@ -1,14 +0,0 @@
<template>
<div>default</div>
</template>
<script>
export default {
name: 'default',
data() {
return {}
},
methods: {},
watch: {},
}
</script>

View File

@ -1,215 +0,0 @@
<template>
<div>
<base-header class="pb-6 pb-8 pt-5 pt-md-8">
<!-- Card stats -->
<b-row>
<b-col xl="3" md="6">
<stats-card
title="Total traffic"
type="gradient-red"
sub-title="350,897"
icon="ni ni-active-40"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">3.48%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
title="Total traffic"
type="gradient-orange"
sub-title="2,356"
icon="ni ni-chart-pie-35"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">12.18%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
title="Sales"
type="gradient-green"
sub-title="924"
icon="ni ni-money-coins"
class="mb-4"
>
<template slot="footer">
<span class="text-danger mr-2">5.72%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
title="Performance"
type="gradient-info"
sub-title="49,65%"
icon="ni ni-chart-bar-32"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">54.8%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
</b-row>
</base-header>
<!--Charts-->
<b-container fluid class="mt--7">
<b-row>
<b-col xl="8" class="mb-5 mb-xl-0">
<card type="default" header-classes="bg-transparent">
<b-row align-v="center" slot="header">
<b-col>
<h6 class="text-light text-uppercase ls-1 mb-1">Overview</h6>
<h5 class="h3 mb-0">Sales value</h5>
</b-col>
<b-col>
<b-nav class="nav-pills justify-content-end">
<b-nav-item
class="mr-2 mr-md-0"
:active="bigLineChart.activeIndex === 0"
link-classes="py-2 px-3"
@click.prevent="initBigChart(0)"
>
<span class="d-none d-md-block">Month</span>
<span class="d-md-none">M</span>
</b-nav-item>
<b-nav-item
link-classes="py-2 px-3"
:active="bigLineChart.activeIndex === 1"
@click.prevent="initBigChart(1)"
>
<span class="d-none d-md-block">Week</span>
<span class="d-md-none">W</span>
</b-nav-item>
</b-nav>
</b-col>
</b-row>
<line-chart
:height="350"
ref="bigChart"
:chart-data="bigLineChart.chartData"
:extra-options="bigLineChart.extraOptions"
></line-chart>
</card>
</b-col>
<b-col xl="4" class="mb-5 mb-xl-0">
<card header-classes="bg-transparent">
<b-row align-v="center" slot="header">
<b-col>
<h6 class="text-uppercase text-muted ls-1 mb-1">Performance</h6>
<h5 class="h3 mb-0">Total orders</h5>
</b-col>
</b-row>
<bar-chart :height="350" ref="barChart" :chart-data="redBarChart.chartData"></bar-chart>
</card>
</b-col>
</b-row>
<!-- End charts-->
<!--Tables-->
<b-row class="mt-5">
<b-col xl="8" class="mb-5 mb-xl-0">
<page-visits-table></page-visits-table>
</b-col>
<b-col xl="4" class="mb-5 mb-xl-0">
<social-traffic-table></social-traffic-table>
</b-col>
</b-row>
<!--End tables-->
</b-container>
</div>
</template>
<script>
// Charts
import * as chartConfigs from '@/components/Charts/config'
import LineChart from '@/components/Charts/LineChart'
import BarChart from '@/components/Charts/BarChart'
// Components
import BaseProgress from '@/components/BaseProgress'
import StatsCard from '@/components/Cards/StatsCard'
// Tables
import SocialTrafficTable from './Dashboard/SocialTrafficTable'
import PageVisitsTable from './Dashboard/PageVisitsTable'
export default {
components: {
LineChart,
BarChart,
//BaseProgress,
StatsCard,
PageVisitsTable,
SocialTrafficTable,
},
data() {
return {
bigLineChart: {
allData: [
[0, 20, 10, 30, 15, 40, 20, 60, 60],
[0, 20, 5, 25, 10, 30, 15, 40, 40],
],
activeIndex: 0,
chartData: {
datasets: [
{
label: 'Performance',
data: [0, 20, 10, 30, 15, 40, 20, 60, 60],
},
],
labels: ['May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
},
extraOptions: chartConfigs.blueChartOptions,
},
redBarChart: {
chartData: {
labels: ['Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
datasets: [
{
label: 'Sales',
data: [25, 20, 30, 22, 17, 29],
},
],
},
extraOptions: chartConfigs.blueChartOptions,
},
}
},
methods: {
initBigChart(index) {
let chartData = {
datasets: [
{
label: 'Performance',
data: this.bigLineChart.allData[index],
},
],
labels: ['May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
}
this.bigLineChart.chartData = chartData
this.bigLineChart.activeIndex = index
},
},
mounted() {
this.initBigChart(0)
},
}
</script>
<style>
.el-table .cell {
padding-left: 0px;
padding-right: 0px;
}
</style>

View File

@ -1,150 +0,0 @@
<template>
<div>
<!--Tables-->
<b-row class="mt-5">
<b-col xl="8" class="mb-5 mb-xl-0">
<vue-good-table
:columns="columns"
:rows="rows"
max-height="370px"
:fixed-header="true"
:line-numbers="true"
@on-row-click="onRowClick"
@on-search="onSearch"
:search-options="{
enabled: true,
skipDiacritics: true,
searchFn: mySearchFn,
placeholder: 'durchsuche die tabelle',
externalQuery: searchQuery,
}"
:pagination-options="{
enabled: true,
mode: 'pages',
}"
>
<div slot="table-actions">Mitglieder suchen .</div>
</vue-good-table>
</b-col>
<b-col xl="4" class="mb-5 mb-xl-0">
<social-traffic-table></social-traffic-table>
</b-col>
</b-row>
<!--End tables-->
</div>
</template>
<script>
import SocialTrafficTable from './SocialTrafficTable'
export default {
name: 'my-component',
components: {
SocialTrafficTable,
},
data() {
return {
columns: [
{
label: 'Name',
field: 'name',
},
{
label: 'Alter',
field: 'age',
type: 'number',
},
{
label: 'Mitglied seid',
field: 'createdAt',
type: 'date',
dateInputFormat: 'yyyy-MM-dd',
dateOutputFormat: 'dd.MM.yyyy',
},
{
label: 'Prozent',
field: 'score',
type: 'percentage',
},
],
rows: [
{
id: 1,
name: 'John',
age: 20,
createdAt: '1976-10-25',
score: 0.03343,
},
{
id: 2,
name: 'Jane',
age: 24,
createdAt: '2011-10-31',
score: 0.03343,
},
{
id: 3,
name: 'Susan',
age: 16,
createdAt: '2011-10-30',
score: 0.03343,
},
{
id: 4,
name: 'Chris',
age: 55,
createdAt: '2011-10-11',
score: 0.03343,
},
{
id: 5,
name: 'Dan',
age: 40,
createdAt: '2011-10-21',
score: 0.03343,
},
{
id: 6,
name: 'Bohn',
age: 70,
createdAt: '2011-10-31',
score: 0.03343,
},
{
id: 7,
name: 'Tellohn',
age: 56,
createdAt: '2009-10-31',
score: 0.13343,
},
{
id: 7,
name: 'Tellohn',
age: 56,
createdAt: '2009-10-31',
score: 0.03343,
},
],
}
},
methods: {
onRowClick(params) {
//console.log(params)
// params.row - row object
// params.pageIndex - index of this row on the current page.
// params.selected - if selection is enabled this argument
// indicates selected or not
// params.event - click event
},
onSearch(params) {
//console.log(params)
// params.searchTerm - term being searched for
// params.rowCount - number of rows that match search
},
mySearchFn(params) {
//console.log(params)
},
},
}
</script>

View File

@ -1,80 +0,0 @@
<template>
<b-card body-class="p-0" header-class="border-0">
<template v-slot:header>
<b-row align-v="center">
<b-col>
<h3 class="mb-0">Page visits</h3>
</b-col>
<b-col class="text-right">
<a href="#!" class="btn btn-sm btn-primary">See all</a>
</b-col>
</b-row>
</template>
<el-table class="table-responsive table" :data="tableData" header-row-class-name="thead-light">
<el-table-column label="Page name" min-width="130px" prop="page">
<template v-slot="{ row }">
<div class="font-weight-600">{{ row.page }}</div>
</template>
</el-table-column>
<el-table-column label="Visitors" min-width="70px" prop="visitors"></el-table-column>
<el-table-column label="Unique users" min-width="90px" prop="unique"></el-table-column>
<el-table-column label="Bounce rate" min-width="90px" prop="bounceRate">
<template v-slot="{ row }">
{{ row.bounceRate }}
</template>
</el-table-column>
</el-table>
</b-card>
</template>
<script>
import { Table, TableColumn, DropdownMenu, DropdownItem, Dropdown } from 'element-ui'
export default {
name: 'page-visits-table',
components: {
[Table.name]: Table,
[TableColumn.name]: TableColumn,
[Dropdown.name]: Dropdown,
[DropdownItem.name]: DropdownItem,
[DropdownMenu.name]: DropdownMenu,
},
data() {
return {
tableData: [
{
page: '/argon/',
visitors: '4,569',
unique: '340',
bounceRate: '46,53%',
},
{
page: '/argon/index.html',
visitors: '3,985',
unique: '319',
bounceRate: '46,53%',
},
{
page: '/argon/charts.html',
visitors: '3,513',
unique: '294',
bounceRate: '36,49%',
},
{
page: '/argon/tables.html',
visitors: '2,050',
unique: '147',
bounceRate: '50,87%',
},
{
page: '/argon/profile.html',
visitors: '1,795',
unique: '190',
bounceRate: '46,53%',
},
],
}
},
}
</script>
<style></style>

View File

@ -1,85 +0,0 @@
<template>
<b-card body-class="p-0" header-class="border-0">
<template v-slot:header>
<b-row align-v="center">
<b-col>
<h3 class="mb-0">Social traffic</h3>
</b-col>
<b-col class="text-right">
<base-button size="sm" type="primary">See all</base-button>
</b-col>
</b-row>
</template>
<el-table class="table-responsive table" :data="tableData" header-row-class-name="thead-light">
<el-table-column label="Referral" min-width="115px" prop="name">
<template v-slot="{ row }">
<div class="font-weight-600">{{ row.name }}</div>
</template>
</el-table-column>
<el-table-column label="Visitors" min-width="110px" prop="visitors"></el-table-column>
<el-table-column min-width="220px" prop="progress">
<template v-slot="{ row }">
<div class="d-flex align-items-center">
<span class="mr-2">{{ row.progress }}%</span>
<base-progress :type="row.progressType" :value="row.progress" />
</div>
</template>
</el-table-column>
</el-table>
</b-card>
</template>
<script>
import { BaseProgress } from '@/components'
import { Table, TableColumn, DropdownMenu, DropdownItem, Dropdown } from 'element-ui'
export default {
name: 'social-traffic-table',
components: {
BaseProgress,
[Table.name]: Table,
[TableColumn.name]: TableColumn,
[Dropdown.name]: Dropdown,
[DropdownItem.name]: DropdownItem,
[DropdownMenu.name]: DropdownMenu,
},
data() {
return {
tableData: [
{
name: 'Facebook',
visitors: '1,480',
progress: 60,
progressType: 'gradient-danger',
},
{
name: 'LinkedIn',
visitors: '5,480',
progress: 70,
progressType: 'gradient-success',
},
{
name: 'Google',
visitors: '4,807',
progress: 80,
progressType: 'gradient-primary',
},
{
name: 'Instagram',
visitors: '3,678',
progress: 75,
progressType: 'gradient-info',
},
{
name: 'Twitter',
visitors: '2,645',
progress: 30,
progressType: 'gradient-warning',
},
],
}
},
}
</script>
<style></style>

View File

@ -1,169 +0,0 @@
<template>
<div>
<base-header class="pb-6 pb-8 pt-5 pt-md-8 bg-gradient-success">
<!-- Card stats -->
<b-row>
<b-col xl="3" md="6">
<stats-card
title="Total traffic"
type="gradient-red"
sub-title="350,897"
icon="ni ni-active-40"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">3.48%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
title="Total traffic"
type="gradient-orange"
sub-title="2,356"
icon="ni ni-chart-pie-35"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">12.18%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
title="Sales"
type="gradient-green"
sub-title="924"
icon="ni ni-money-coins"
class="mb-4"
>
<template slot="footer">
<span class="text-danger mr-2">5.72%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
title="Performance"
type="gradient-info"
sub-title="49,65%"
icon="ni ni-chart-bar-32"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">54.8%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
</b-row>
</base-header>
<b-container fluid class="mt--7">
<b-row>
<b-col>
<b-card no-body class="border-0">
<div id="map-custom" class="map-canvas" style="height: 600px"></div>
</b-card>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
import { API_KEY } from './Maps/API_KEY'
import GoogleMapsLoader from 'google-maps'
GoogleMapsLoader.KEY = API_KEY
export default {
methods: {
initMap(google) {
let map,
lat = 40.748817,
lng = -73.985428,
color = '#5e72e4'
map = document.getElementById('map-custom')
let myLatlng = new google.maps.LatLng(lat, lng)
let mapOptions = {
zoom: 12,
scrollwheel: false,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
styles: [
{
featureType: 'administrative',
elementType: 'labels.text.fill',
stylers: [{ color: '#444444' }],
},
{
featureType: 'landscape',
elementType: 'all',
stylers: [{ color: '#f2f2f2' }],
},
{
featureType: 'poi',
elementType: 'all',
stylers: [{ visibility: 'off' }],
},
{
featureType: 'road',
elementType: 'all',
stylers: [{ saturation: -100 }, { lightness: 45 }],
},
{
featureType: 'road.highway',
elementType: 'all',
stylers: [{ visibility: 'simplified' }],
},
{
featureType: 'road.arterial',
elementType: 'labels.icon',
stylers: [{ visibility: 'off' }],
},
{
featureType: 'transit',
elementType: 'all',
stylers: [{ visibility: 'off' }],
},
{
featureType: 'water',
elementType: 'all',
stylers: [{ color: color }, { visibility: 'on' }],
},
],
}
map = new google.maps.Map(map, mapOptions)
let marker = new google.maps.Marker({
position: myLatlng,
map: map,
animation: google.maps.Animation.DROP,
title: 'Hello World!',
})
let contentString =
'<div class="info-window-content"><h2>Argon Dashboard PRO</h2>' +
'<p>A beautiful premium dashboard for Bootstrap 4.</p></div>'
let infowindow = new google.maps.InfoWindow({
content: contentString,
})
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker)
})
},
},
mounted() {
GoogleMapsLoader.load((google) => {
this.initMap(google)
})
},
}
</script>

File diff suppressed because it is too large Load Diff

View File

@ -2,25 +2,20 @@
<div>
<base-header class="pb-6 pb-8 pt-5 pt-md-8 bg-transparent"></base-header>
<b-container fluid class="mt--7">
<gdd-status />
<gdd-status :row_form="row_form" />
<br />
<gdd-send />
<gdd-send
:row_form="row_form"
:row_check="row_check"
:row_thx="row_thx"
@change-rows="setRows"
/>
<hr />
<gdd-table />
<!-- <hr>
<div>
<gdd-add-work-2 />
</div>
<br> -->
<!--
<div>
<gdd-add-work />
</div>
<br>
-->
<!-- <div>
<gdd-work-table />
</div> -->
<gdd-table
:row_form="row_form"
:transactions="transactions"
@change-transactions="setTransactions"
/>
</b-container>
</div>
</template>
@ -28,21 +23,35 @@
import GddStatus from './KontoOverview/GddStatus.vue'
import GddSend from './KontoOverview/GddSend.vue'
import GddTable from './KontoOverview/GddTable.vue'
// import GddAddWork2 from './KontoOverview/GddAddWork2.vue';
// import GddWorkTable from './KontoOverview/GddWorkTable.vue';
export default {
name: 'Overview',
data() {
return {
row_form: true,
row_check: false,
row_thx: false,
transactions: [],
}
},
components: {
GddStatus,
GddSend,
GddTable,
//GddAddWork2,
//GddWorkTable
},
created() {
this.$store.dispatch('accountBalance', $cookies.get('gdd_session_id'))
},
methods: {
setRows(rows) {
this.row_form = rows.row_form
this.row_check = rows.row_check
this.row_thx = rows.row_thx
},
setTransactions(transactions) {
this.transactions = transactions
},
},
}
</script>

View File

@ -8,8 +8,8 @@
<b-form-input
type="number"
size="lg"
placeholder="0"
style="font-size: xx-large; padding-left: 20px"
placeholder="23"
style="font-size: xx-large; padding-left: 5px"
/>
</base-input>
<base-input label="Datum / Zeitraum">
@ -17,7 +17,7 @@
class="form-control"
v-model="date"
:config="config"
style="font-size: x-large; padding-left: 20px"
style="font-size: 0.5em; padding-left: 5px"
></flat-pickr>
</base-input>
</b-col>

View File

@ -1,6 +1,6 @@
<template>
<div>
<b-row v-show="$store.state.row_form">
<b-row v-show="row_form">
<b-col xl="12" md="12">
<b-alert variant="warning" show dismissible>
<strong>Achtung!</strong>
@ -140,28 +140,28 @@
</b-card>
</b-col>
</b-row>
<b-row v-show="$store.state.row_check">
<b-row v-show="row_check">
<b-col>
<div class="display-4 p-4">Bestätige deine Zahlung. Prüfe bitte nochmal alle Daten!</div>
<b-list-group>
<b-list-group-item active>Meine Zahlung</b-list-group-item>
<b-list-group-item class="d-flex justify-content-between align-items-center">
{{ $store.state.ajaxCreateData.email }}
{{ ajaxCreateData.email }}
<b-badge variant="primary" pill>Empfänger</b-badge>
</b-list-group-item>
<b-list-group-item class="d-flex justify-content-between align-items-center">
{{ $store.state.ajaxCreateData.amount }} GDD
{{ ajaxCreateData.amount }} GDD
<b-badge variant="primary" pill>Betrag</b-badge>
</b-list-group-item>
<b-list-group-item class="d-flex justify-content-between align-items-center">
{{ $store.state.ajaxCreateData.memo }}
{{ ajaxCreateData.memo }}
<b-badge variant="primary" pill>Nachricht</b-badge>
</b-list-group-item>
<b-list-group-item class="d-flex justify-content-between align-items-center">
{{ $moment($store.state.ajaxCreateData.target_date).format('DD.MM.YYYY - HH:mm:ss') }}
{{ $moment(ajaxCreateData.target_date).format('DD.MM.YYYY - HH:mm:ss') }}
<b-badge variant="primary" pill>Datum</b-badge>
</b-list-group-item>
</b-list-group>
@ -174,7 +174,7 @@
</b-row>
</b-col>
</b-row>
<b-row v-show="$store.state.row_thx">
<b-row v-show="row_thx">
<b-col>
<div class="display-1 p-4">
Danke
@ -192,6 +192,7 @@
<script>
import { QrcodeStream, QrcodeDropZone } from 'vue-qrcode-reader'
import { BIcon } from 'bootstrap-vue'
import communityAPI from '../../apis/communityAPI.js'
export default {
name: 'GddSent',
@ -200,6 +201,11 @@ export default {
QrcodeDropZone,
BIcon,
},
props: {
row_form: { type: Boolean, default: true },
row_check: { type: Boolean, default: false },
row_thx: { type: Boolean, default: false },
},
data() {
return {
scan: false,
@ -210,48 +216,53 @@ export default {
amount: '',
memo: '',
},
ajaxCreateData: {
email: '',
amount: 0,
target_date: '',
memo: '',
auto_sign: true,
},
send: false,
}
},
computed: {
state() {
return this.name.length >= 4
},
invalidFeedback() {
if (this.name.length > 0) {
return 'Geben Sie mindestens 4 Zeichen ein.'
}
return 'Bitte geben Sie eine GDD Adresse ein.'
},
},
computed: {},
methods: {
async onDecode(decodedString) {
//console.log('onDecode JSON.parse(decodedString)', JSON.parse(decodedString))
const arr = JSON.parse(decodedString)
//console.log('qr-email', arr[0].email)
//console.log('qr-amount', arr[0].amount)
this.form.email = arr[0].email
this.form.amount = arr[0].amount
this.scan = false
},
async onSubmit() {
//event.preventDefault()
//console.log("onSubmit", this.form)
this.$store.state.ajaxCreateData.session_id = this.$cookies.get('gdd_session_id')
this.$store.state.ajaxCreateData.email = this.form.email
this.$store.state.ajaxCreateData.amount = this.form.amount
this.$store.state.ajaxCreateData.memo = this.form.memo
this.$store.state.ajaxCreateData.target_date = Date.now()
this.ajaxCreateData.email = this.form.email
this.ajaxCreateData.amount = this.form.amount
this.ajaxCreateData.target_date = Date.now()
this.ajaxCreateData.memo = this.form.memo
this.$store.state.row_form = false
this.$store.state.row_check = true
this.$store.state.row_thx = false
this.$emit('change-rows', { row_form: false, row_check: true, row_thx: false })
},
sendTransaction() {
this.$store.dispatch('ajaxCreate')
this.$store.state.row_form = false
this.$store.state.row_check = false
this.$store.state.row_thx = true
async sendTransaction() {
this.ajaxCreateData.amount = this.ajaxCreateData.amount * 10000
const result = await communityAPI.send(
this.$store.state.session_id,
this.ajaxCreateData.email,
this.ajaxCreateData.amount,
this.ajaxCreateData.memo,
)
// console.log(result)
if (result.success) {
// console.log('send success')
this.$emit('change-rows', { row_form: false, row_check: false, row_thx: true })
} else {
// console.log('send error')
alert('error')
this.$emit('change-rows', { row_form: true, row_check: false, row_thx: false })
}
},
onReset(event) {
event.preventDefault()
@ -261,9 +272,7 @@ export default {
this.$nextTick(() => {
this.show = true
})
this.$store.state.row_form = true
this.$store.state.row_check = false
this.$store.state.row_thx = false
this.$emit('change-rows', { row_form: true, row_check: false, row_thx: false })
},
},
}

View File

@ -1,6 +1,6 @@
<template>
<div>
<b-row v-show="$store.state.row_form">
<b-row v-show="this.row_form">
<b-col xl="6" md="6">
<stats-card
type="gradient-red"
@ -28,5 +28,8 @@
<script>
export default {
name: 'GddStatus',
props: {
row_form: { type: Boolean, default: true },
},
}
</script>

View File

@ -1,6 +1,6 @@
<template>
<div>
<b-list-group v-show="$store.state.row_form">
<b-list-group v-show="this.row_form">
<b-list-group-item
v-for="item in filteredItems"
:key="item.id"
@ -90,6 +90,9 @@ import communityAPI from '../../apis/communityAPI'
export default {
name: 'GddTable',
props: {
row_form: { type: Boolean, default: true },
},
data() {
return {
form: [],

View File

@ -1,14 +0,0 @@
<template>
<div>default</div>
</template>
<script>
export default {
name: 'default',
data() {
return {}
},
methods: {},
watch: {},
}
</script>

View File

@ -1,178 +0,0 @@
<template>
<div>
<!-- Header -->
<div class="header bg-gradient-info py-7 py-lg-8 pt-lg-9">
<b-container>
<div class="header-body text-center mb-7">
<p class="h1">GRADIDO</p>
<p class="h4">Wallet</p>
<!-- <b-row class="justify-content-center">
<b-col xl="5" lg="6" md="6" class="px-5">
<h1 class="text-light">Landing Gradido</h1>
<br>
<router-link to="/overview" class="font-weight-bold text-white mt-5"> LoginUser</router-link>
<br><br>
<router-link to="/AdminOverview" class="font-weight-bold text-white mt-5"> Login Admin</router-link>
<br><br>
<router-link to="/register" class="font-weight-bold text-white mt-5"> Register</router-link>
</b-col>
</b-row> -->
<hr />
<p class="lead">Anmelden</p>
<b-row class="justify-content-center">
<b-col xl="5" lg="6" md="6" class="px-5">
<form @submit.prevent="login">
<b-row class="form-group">
<label
for="example-email-input"
class="col-md-2 col-form-label form-control-label"
>
Email
</label>
<b-col md="10">
<base-input
type="email"
autocomplete="username email"
placeholder="argon@example.com"
v-model="lemail"
/>
</b-col>
</b-row>
<b-row class="form-group">
<label
for="example-password-input"
class="col-md-2 col-form-label form-control-label"
>
Password
</label>
<b-col md="10">
<base-input
type="password"
autocomplete="current-password"
placeholder="password"
v-model="lpwd"
/>
</b-col>
</b-row>
<b-button block type="submit">Anmelden</b-button>
</form>
</b-col>
</b-row>
<hr />
<p class="lead">neues Mitglied anlegen</p>
<b-row class="justify-content-center">
<b-col xl="5" lg="6" md="6" class="px-5">
<form>
<b-row class="form-group">
<label class="col-md-2 col-form-label form-control-label">Vorname</label>
<b-col md="10">
<base-input placeholder="Jon " v-model="rfname"></base-input>
</b-col>
</b-row>
<b-row class="form-group">
<label class="col-md-2 col-form-label form-control-label">Nachname</label>
<b-col md="10">
<base-input placeholder=" Snow" v-model="rlname"></base-input>
</b-col>
</b-row>
<b-row class="form-group">
<label
for="example-email-input"
class="col-md-2 col-form-label form-control-label"
>
Email
</label>
<b-col md="10">
<base-input
type="email"
autocomplete="username email"
placeholder="argon@example.com"
v-model="remail"
/>
</b-col>
</b-row>
<b-row class="form-group">
<label
for="example-password-input"
class="col-md-2 col-form-label form-control-label"
>
Password
</label>
<b-col md="10">
<base-input
type="password"
autocomplete="current-password"
placeholder="password"
v-model="rpwd"
/>
</b-col>
</b-row>
</form>
<b-button block type="submit" @click="createUser()">Anmelden</b-button>
</b-col>
</b-row>
</div>
</b-container>
<div class="separator separator-bottom separator-skew zindex-100">
<svg
x="0"
y="0"
viewBox="0 0 2560 100"
preserveAspectRatio="none"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<polygon class="fill-default" points="2560 0 2560 100 0 100"></polygon>
</svg>
</div>
</div>
<!-- Page content -->
</div>
</template>
<script>
// Components
export default {
name: 'Landing',
data() {
return {
lemail: '',
lpwd: '',
rfname: '',
rlname: '',
remail: '',
rpwd: '',
}
},
methods: {
login() {
//if (this.lemail !== '' || this.lpwd !== '') { // TODO this should be done via form validation
this.$store.dispatch('login', {
email: this.lemail,
password: this.lpwd,
})
//}
},
createUser() {
this.$store.dispatch('createUser', {
email: this.remail,
first_name: this.rfname,
last_name: this.rlname,
password: this.rpwd,
})
},
loginAsAdmin() {
//console.log('app.vue admin login(): ' + this.$store.state.is_admin)
this.modals = false
this.$store.commit('loginAsAdmin')
this.$router.push('/AdminOverview')
},
},
}
</script>

View File

@ -1,114 +0,0 @@
<template>
<div class="wrapper">
<notifications></notifications>
<side-bar>
<template slot="links">
<sidebar-item
:link="{
name: 'Kontoübersicht',
path: '/overview',
icon: 'ni ni-tv-2 text-primary',
}"
></sidebar-item>
<sidebar-item
:link="{
name: 'User Profile',
path: '/profile',
icon: 'ni ni-single-02 text-yellow',
}"
></sidebar-item>
<sidebar-item
:link="{
name: 'Login',
path: '/login',
icon: 'ni ni-key-25 text-info',
}"
></sidebar-item>
<sidebar-item
:link="{
name: 'Register',
path: '/register',
icon: 'ni ni-circle-08 text-pink',
}"
></sidebar-item>
</template>
<template slot="links-after">
<hr class="my-3" />
<h6 class="navbar-heading p-0 text-muted">Community</h6>
<b-nav class="navbar-nav mb-md-3">
<b-nav-item href="https://gradido.net/de/" target="_blank">
<i class="ni ni-spaceship"></i>
<b-nav-text class="p-0">GRADIDO.net</b-nav-text>
</b-nav-item>
<b-nav-item href="https://elopage.com/s/gradido/sign_in">
<i class="ni ni-palette"></i>
<b-nav-text class="p-0">Mitgliederbereich</b-nav-text>
</b-nav-item>
<b-nav-item href="https://gradido.net/de/memberships/">
<i class="ni ni-ui-04"></i>
<b-nav-text class="p-0">Mitgliedschaft</b-nav-text>
</b-nav-item>
</b-nav>
</template>
</side-bar>
<div class="main-content">
<dashboard-navbar :type="$route.meta.navbarType"></dashboard-navbar>
<div @click="$sidebar.displaySidebar(false)">
<fade-transition :duration="200" origin="center top" mode="out-in">
<!-- your content here -->
<router-view></router-view>
</fade-transition>
</div>
<content-footer v-if="!$route.meta.hideFooter"></content-footer>
</div>
</div>
</template>
<script>
/* eslint-disable no-new */
import PerfectScrollbar from 'perfect-scrollbar'
import 'perfect-scrollbar/css/perfect-scrollbar.css'
function hasElement(className) {
return document.getElementsByClassName(className).length > 0
}
function initScrollbar(className) {
if (hasElement(className)) {
new PerfectScrollbar(`.${className}`)
} else {
// try to init it later in case this component is loaded async
setTimeout(() => {
initScrollbar(className)
}, 100)
}
}
import DashboardNavbar from './DashboardNavbar.vue'
import ContentFooter from './ContentFooter.vue'
import DashboardContent from './Content.vue'
import { FadeTransition } from 'vue2-transitions'
export default {
components: {
DashboardNavbar,
ContentFooter,
//DashboardContent,
FadeTransition,
},
methods: {
initScrollbar() {
let isWindows = navigator.platform.startsWith('Win')
if (isWindows) {
initScrollbar('sidenav')
}
},
},
mounted() {
this.initScrollbar()
},
}
</script>
<style lang="scss"></style>

View File

@ -1,173 +0,0 @@
<template>
<div class="main-content bg-default">
<base-nav
v-model="showMenu"
:transparent="true"
menu-classes="justify-content-end"
class="navbar-horizontal navbar-main navbar-top navbar-dark"
expand="lg"
>
<div slot="brand" class="navbar-wrapper">
<b-navbar-brand to="/overview">
<img src="img/brand/white.png" />
</b-navbar-brand>
</div>
<template>
<div class="navbar-collapse-header">
<b-row>
<b-col cols="6" class="collapse-brand">
<router-link to="/overview">
<img src="img/brand/green.png" />
</router-link>
</b-col>
<b-col cols="6" class="collapse-close">
<button type="button" class="navbar-toggler" @click="showMenu = false">
<span></span>
<span></span>
</button>
</b-col>
</b-row>
</div>
</template>
</base-nav>
<div class="main-content">
<zoom-center-transition :duration="pageTransitionDuration" mode="out-in">
<router-view></router-view>
</zoom-center-transition>
</div>
<footer class="py-5" id="footer-main">
<b-container>
<b-row align-v="center" class="justify-content-xl-between">
<b-col xl="6">
<div class="copyright text-center text-xl-left text-muted">
© {{ year }}
<a href="https://gradido.net/" class="font-weight-bold ml-1" target="_blank">
Gradido-Akademie
</a>
</div>
</b-col>
<b-col xl="6" class="col-xl-6">
<b-nav class="nav-footer justify-content-center justify-content-lg-end">
<b-nav-item ref="https://www.creative-tim.com" target="_blank">Gradido</b-nav-item>
<b-nav-item href="https://www.creative-tim.com/presentation" target="_blank">
Impressum
</b-nav-item>
<b-nav-item href="http://blog.creative-tim.com" target="_blank">
Datenschutzerklärung
</b-nav-item>
</b-nav>
</b-col>
</b-row>
</b-container>
</footer>
</div>
</template>
<script>
import { BaseNav } from '@/components'
import { ZoomCenterTransition } from 'vue2-transitions'
export default {
components: {
BaseNav,
ZoomCenterTransition,
},
props: {
backgroundColor: {
type: String,
default: 'black',
},
},
data() {
return {
showMenu: false,
menuTransitionDuration: 250,
pageTransitionDuration: 200,
year: new Date().getFullYear(),
pageClass: 'login-page',
}
},
computed: {
title() {
return `${this.$route.name} Page`
},
},
methods: {
toggleNavbar() {
document.body.classList.toggle('nav-open')
this.showMenu = !this.showMenu
},
closeMenu() {
document.body.classList.remove('nav-open')
this.showMenu = false
},
setBackgroundColor() {
document.body.classList.add('bg-default')
},
removeBackgroundColor() {
document.body.classList.remove('bg-default')
},
updateBackground() {
if (!this.$route.meta.noBodyBackground) {
this.setBackgroundColor()
} else {
this.removeBackgroundColor()
}
},
},
beforeDestroy() {
this.removeBackgroundColor()
},
beforeRouteUpdate(to, from, next) {
// Close the mobile menu first then transition to next page
if (this.showMenu) {
this.closeMenu()
setTimeout(() => {
next()
}, this.menuTransitionDuration)
} else {
next()
}
},
watch: {
$route: {
immediate: true,
handler: function () {
this.updateBackground()
},
},
},
}
</script>
<style lang="scss">
$scaleSize: 0.8;
@keyframes zoomIn8 {
from {
opacity: 0;
transform: scale3d($scaleSize, $scaleSize, $scaleSize);
}
100% {
opacity: 1;
}
}
.main-content .zoomIn {
animation-name: zoomIn8;
}
@keyframes zoomOut8 {
from {
opacity: 1;
}
to {
opacity: 0;
transform: scale3d($scaleSize, $scaleSize, $scaleSize);
}
}
.main-content .zoomOut {
animation-name: zoomOut8;
}
</style>

View File

@ -0,0 +1,104 @@
import { mount } from '@vue/test-utils'
import ContentFooter from './ContentFooter'
const localVue = global.localVue
describe('ContentFooter', () => {
let wrapper
let mocks = {
$i18n: {
locale: 'en',
},
$t: jest.fn((t) => t),
}
const Wrapper = () => {
return mount(ContentFooter, { localVue, mocks })
}
describe('mount', () => {
beforeEach(() => {
wrapper = Wrapper()
})
it('renders the content footer', () => {
expect(wrapper.find('footer.footer').exists()).toBeTruthy()
})
describe('copyright', () => {
it('shows the copyright', () => {
expect(wrapper.find('div.copyright').exists()).toBeTruthy()
})
it('renders the copyright year', () => {
expect(wrapper.find('div.copyright').text()).toMatch(/©\s*2[0-9]{3,3}\s+/)
})
it('renders a link to Gradido-Akademie', () => {
expect(wrapper.find('div.copyright').find('a').text()).toEqual('Gradido-Akademie')
})
it('links to the login page when clicked on copyright', () => {
expect(wrapper.find('div.copyright').find('a').attributes('href')).toEqual('#/Login')
})
})
describe('links to gradido.net', () => {
it('has a link to the gradido.net', () => {
expect(wrapper.findAll('a.nav-link').at(0).text()).toEqual('Gradido')
})
it('links to the https://gradido.net/en when locale is en', () => {
expect(wrapper.findAll('a.nav-link').at(0).attributes('href')).toEqual(
'https://gradido.net/en',
)
})
it('has a link to the legal notice', () => {
expect(wrapper.findAll('a.nav-link').at(1).text()).toEqual('imprint')
})
it('links to the https://gradido.net/en/impressum when locale is en', () => {
expect(wrapper.findAll('a.nav-link').at(1).attributes('href')).toEqual(
'https://gradido.net/en/impressum/',
)
})
it('has a link to the privacy policy', () => {
expect(wrapper.findAll('a.nav-link').at(2).text()).toEqual('privacy_policy')
})
it('links to the https://gradido.net/en/datenschutz when locale is en', () => {
expect(wrapper.findAll('a.nav-link').at(2).attributes('href')).toEqual(
'https://gradido.net/en/datenschutz/',
)
})
describe('links are localized', () => {
beforeEach(() => {
mocks.$i18n.locale = 'de'
})
it('links to the https://gradido.net/de when locale is de', () => {
expect(wrapper.findAll('a.nav-link').at(0).attributes('href')).toEqual(
'https://gradido.net/de',
)
})
it('links to the https://gradido.net/de/impressum when locale is de', () => {
expect(wrapper.findAll('a.nav-link').at(1).attributes('href')).toEqual(
'https://gradido.net/de/impressum/',
)
})
it('links to the https://gradido.net/de/datenschutz when locale is de', () => {
expect(wrapper.findAll('a.nav-link').at(2).attributes('href')).toEqual(
'https://gradido.net/de/datenschutz/',
)
})
})
})
})
})

View File

@ -4,7 +4,7 @@
<b-col>
<div class="copyright text-center text-lg-center text-muted">
© {{ year }}
<a href="#!" to="/login" class="font-weight-bold ml-1">Gradido-Akademie</a>
<a href="#/Login" class="font-weight-bold ml-1">Gradido-Akademie</a>
</div>
</b-col>
</b-row>

View File

@ -1 +0,0 @@
export const API_KEY = 'YOUR_API_KEY'

View File

@ -1,14 +1,10 @@
<template>
<div>
<!-- Header -->
<div class="header bg-gradient-info py-7 py-lg-8 pt-lg-9">
<div class="header py-1 py-lg-1 pt-lg-3">
<b-container>xx</b-container>
<b-container>
<div class="header-body text-center mb-7">
<b-row class="justify-content-center">
<b-col xl="5" lg="6" md="6" class="px-5">
<h1 class="text-light">{{ $t('site.404.text') }}</h1>
</b-col>
</b-row>
<div class="header-body text-center mb-3">
<a href="/login" to="/login">
<div class="container">
<div class="row">
@ -1189,38 +1185,7 @@
</a>
</div>
</b-container>
<div class="separator separator-bottom separator-skew zindex-100">
<svg
x="0"
y="0"
viewBox="0 0 2560 100"
preserveAspectRatio="none"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<polygon class="fill-default" points="2560 0 2560 100 0 100"></polygon>
</svg>
</div>
</div>
<!-- Page content -->
<section class="py-6">
<b-container>
<b-row align-v="center" class="row-grid">
<b-col md="6">
<b-img src="img/theme/landing-1.png" fluid />
</b-col>
<b-col md="6">
<div class="pr-md-5">
<h1 class="text-light">{{ $t('site.landing1.explore') }}</h1>
<p class="text-light">{{ $t('site.landing1.text') }}</p>
<router-link to="/overview" class="font-weight-bold text-warning mt-5">
{{ $t('site.landing1.link') }}
</router-link>
</div>
</b-col>
</b-row>
</b-container>
</section>
</div>
</template>
@ -1252,11 +1217,6 @@ export default {
}
</script>
<style>
body {
background-color: #141019;
background: radial-gradient(at 50% -20%, #047006, #f5f9f7) fixed;
}
#handboy {
animation: swing ease-in-out 1.3s infinite alternate;
transform-origin: 98% 98%;

View File

@ -1,115 +0,0 @@
<template>
<div>
<base-header class="pb-6 pb-8 pt-5 pt-md-8 bg-gradient-success">
<!-- Card stats -->
<b-row>
<b-col xl="3" md="6">
<stats-card
title="Total traffic"
type="gradient-red"
sub-title="350,897"
icon="ni ni-active-40"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">3.48%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
title="Total traffic"
type="gradient-orange"
sub-title="2,356"
icon="ni ni-chart-pie-35"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">12.18%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
title="Sales"
type="gradient-green"
sub-title="924"
icon="ni ni-money-coins"
class="mb-4"
>
<template slot="footer">
<span class="text-danger mr-2">5.72%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
<b-col xl="3" md="6">
<stats-card
title="Performance"
type="gradient-info"
sub-title="49,65%"
icon="ni ni-chart-bar-32"
class="mb-4"
>
<template slot="footer">
<span class="text-success mr-2">54.8%</span>
<span class="text-nowrap">Since last month</span>
</template>
</stats-card>
</b-col>
</b-row>
</base-header>
<b-container fluid class="mt--7">
<b-row>
<b-col>
<light-table />
</b-col>
</b-row>
<div class="mt-5"></div>
<dark-table></dark-table>
</b-container>
</div>
</template>
<script>
import { Dropdown, DropdownItem, DropdownMenu, Table, TableColumn } from 'element-ui'
import projects from './Tables/projects'
import users from './Tables/users'
import LightTable from './Tables/RegularTables/LightTable'
import DarkTable from './Tables/RegularTables/DarkTable'
export default {
components: {
LightTable,
DarkTable,
[Dropdown.name]: Dropdown,
[DropdownItem.name]: DropdownItem,
[DropdownMenu.name]: DropdownMenu,
[Table.name]: Table,
[TableColumn.name]: TableColumn,
},
data() {
return {
projects,
users,
}
},
}
</script>
<style>
.el-table.table-dark {
background-color: #172b4d;
color: #f8f9fe;
}
.el-table.table-dark th,
.el-table.table-dark tr {
background-color: #172b4d;
}
.el-table.table-dark td,
.el-table.table-dark th.is-leaf {
border-bottom: none;
}
</style>

View File

@ -1,105 +0,0 @@
<template>
<b-card no-body class="bg-default shadow">
<b-card-header class="bg-transparent border-0">
<h3 class="mb-0 text-white">Dark table</h3>
</b-card-header>
<el-table
class="table-responsive table table-dark"
header-row-class-name="thead-dark"
:data="projects"
>
<el-table-column label="Project" min-width="310px" prop="name">
<template v-slot="{ row }">
<b-media no-body class="align-items-center">
<a href="#" class="mr-3">
<b-img class="avatar" rounded="circle" alt="Image placeholder" :src="row.img" />
</a>
<b-media-body>
<span class="font-weight-600 name mb-0 text-sm">
{{ row.title }}
</span>
</b-media-body>
</b-media>
</template>
</el-table-column>
<el-table-column label="Budget" prop="budget" min-width="140px"></el-table-column>
<el-table-column label="Status" min-width="170px" prop="status">
<template v-slot="{ row }">
<badge class="badge-dot mr-4">
<i :class="`bg-${row.statusType}`"></i>
<span class="status" :class="`text-${row.statusType}`">
{{ row.status }}
</span>
</badge>
</template>
</el-table-column>
<el-table-column label="Users" min-width="190px">
<div class="avatar-group">
<a
href="#"
class="avatar avatar-sm rounded-circle"
data-toggle="tooltip"
data-original-title="Ryan Tompson"
>
<img alt="Image placeholder" src="img/theme/team-1.jpg" />
</a>
<a
href="#"
class="avatar avatar-sm rounded-circle"
data-toggle="tooltip"
data-original-title="Romina Hadid"
>
<img alt="Image placeholder" src="img/theme/team-2.jpg" />
</a>
<a
href="#"
class="avatar avatar-sm rounded-circle"
data-toggle="tooltip"
data-original-title="Alexander Smith"
>
<img alt="Image placeholder" src="img/theme/team-3.jpg" />
</a>
<a
href="#"
class="avatar avatar-sm rounded-circle"
data-toggle="tooltip"
data-original-title="Jessica Doe"
>
<img alt="Image placeholder" src="img/theme/team-4.jpg" />
</a>
</div>
</el-table-column>
<el-table-column label="Completion" prop="completion" min-width="240px">
<template v-slot="{ row }">
<div class="d-flex align-items-center">
<span class="completion mr-2">{{ row.completion }}%</span>
<div>
<base-progress :type="row.statusType" :value="row.completion" />
</div>
</div>
</template>
</el-table-column>
</el-table>
</b-card>
</template>
<script>
import projects from './../projects'
import { Table, TableColumn } from 'element-ui'
export default {
name: 'light-table',
components: {
[Table.name]: Table,
[TableColumn.name]: TableColumn,
},
data() {
return {
projects,
currentPage: 1,
}
},
}
</script>

View File

@ -1,105 +0,0 @@
<template>
<b-card no-body>
<b-card-header class="border-0">
<h3 class="mb-0">Light table</h3>
</b-card-header>
<el-table class="table-responsive table" header-row-class-name="thead-light" :data="projects">
<el-table-column label="Project" min-width="310px" prop="name">
<template v-slot="{ row }">
<b-media no-body class="align-items-center">
<a href="#" class="avatar rounded-circle mr-3">
<img alt="Image placeholder" :src="row.img" />
</a>
<b-media-body>
<span class="font-weight-600 name mb-0 text-sm">
{{ row.title }}
</span>
</b-media-body>
</b-media>
</template>
</el-table-column>
<el-table-column label="Budget" prop="budget" min-width="140px"></el-table-column>
<el-table-column label="Status" min-width="170px" prop="status">
<template v-slot="{ row }">
<badge class="badge-dot mr-4" type="">
<i :class="`bg-${row.statusType}`"></i>
<span class="status" :class="`text-${row.statusType}`">
{{ row.status }}
</span>
</badge>
</template>
</el-table-column>
<el-table-column label="Users" min-width="190px">
<div class="avatar-group">
<a
href="#"
class="avatar avatar-sm rounded-circle"
data-toggle="tooltip"
data-original-title="Ryan Tompson"
>
<img alt="Image placeholder" src="img/theme/team-1.jpg" />
</a>
<a
href="#"
class="avatar avatar-sm rounded-circle"
data-toggle="tooltip"
data-original-title="Romina Hadid"
>
<img alt="Image placeholder" src="img/theme/team-2.jpg" />
</a>
<a
href="#"
class="avatar avatar-sm rounded-circle"
data-toggle="tooltip"
data-original-title="Alexander Smith"
>
<img alt="Image placeholder" src="img/theme/team-3.jpg" />
</a>
<a
href="#"
class="avatar avatar-sm rounded-circle"
data-toggle="tooltip"
data-original-title="Jessica Doe"
>
<img alt="Image placeholder" src="img/theme/team-4.jpg" />
</a>
</div>
</el-table-column>
<el-table-column label="Completion" prop="completion" min-width="240px">
<template v-slot="{ row }">
<div class="d-flex align-items-center">
<span class="completion mr-2">{{ row.completion }}%</span>
<div>
<base-progress :type="row.statusType" :value="row.completion" />
</div>
</div>
</template>
</el-table-column>
</el-table>
<b-card-footer class="py-4 d-flex justify-content-end">
<base-pagination v-model="currentPage" :per-page="10" :total="50"></base-pagination>
</b-card-footer>
</b-card>
</template>
<script>
import projects from './../projects'
import { Table, TableColumn } from 'element-ui'
export default {
name: 'light-table',
components: {
[Table.name]: Table,
[TableColumn.name]: TableColumn,
},
data() {
return {
projects,
currentPage: 1,
}
},
}
</script>

View File

@ -1,74 +0,0 @@
export default [
{
img: 'img/theme/bootstrap.jpg',
title: 'Argon Design System',
budget: '$2500 USD',
status: 'pending',
statusType: 'warning',
completion: 60,
},
{
img: 'img/theme/angular.jpg',
title: 'Angular Now UI Kit PRO',
budget: '$1800 USD',
status: 'completed',
statusType: 'success',
completion: 100,
},
{
img: 'img/theme/sketch.jpg',
title: 'Black Dashboard',
budget: '$3150 USD',
status: 'delayed',
statusType: 'danger',
completion: 72,
},
{
img: 'img/theme/react.jpg',
title: 'React Material Dashboard',
budget: '$4400 USD',
status: 'on schedule',
statusType: 'info',
completion: 90,
},
{
img: 'img/theme/vue.jpg',
title: 'Vue Paper UI Kit PRO',
budget: '$2200 USD',
status: 'completed',
statusType: 'success',
completion: 100,
},
{
img: 'img/theme/bootstrap.jpg',
title: 'Argon Design System',
budget: '$2500 USD',
status: 'pending',
statusType: 'warning',
completion: 60,
},
{
img: 'img/theme/angular.jpg',
title: 'Angular Now UI Kit PRO',
budget: '$1800 USD',
status: 'completed',
statusType: 'success',
completion: 100,
},
{
img: 'img/theme/sketch.jpg',
title: 'Black Dashboard',
budget: '$3150 USD',
status: 'delayed',
statusType: 'danger',
completion: 72,
},
{
img: 'img/theme/vue.jpg',
title: 'Vue Paper UI Kit PRO',
budget: '$2200 USD',
status: 'completed',
statusType: 'success',
completion: 100,
},
]

View File

@ -1,42 +0,0 @@
export default [
{
id: 1,
name: 'John Michael',
image: 'img/theme/team-1.jpg',
createdAt: '10/09/2018',
product: 'Argon Dashboard PRO',
active: true,
},
{
id: 2,
name: 'Alexandra Smith',
image: 'img/theme/team-2.jpg',
createdAt: '08/09/2018',
product: 'Argon Design System',
active: false,
},
{
id: 3,
name: 'Samantha Ivy',
image: 'img/theme/team-3.jpg',
createdAt: '30/08/2018',
product: 'Black Dashboard',
active: false,
},
{
id: 4,
name: 'John Michael',
image: 'img/theme/team-1.jpg',
createdAt: '10/09/2018',
product: 'Argon Dashboard PRO',
active: true,
},
{
id: 5,
name: 'Alexandra Smith',
image: 'img/theme/team-2.jpg',
createdAt: '30/09/2018',
product: 'Vue Argon Dashboard',
active: true,
},
]

View File

@ -1,14 +0,0 @@
<template>
<div>default</div>
</template>
<script>
export default {
name: 'default',
data() {
return {}
},
methods: {},
watch: {},
}
</script>

View File

@ -0,0 +1,8 @@
import { createLocalVue } from '@vue/test-utils'
import ElementUI from 'element-ui'
import BootstrapVue from 'bootstrap-vue'
global.localVue = createLocalVue()
global.localVue.use(ElementUI)
global.localVue.use(BootstrapVue)

View File

@ -4,6 +4,12 @@ const dotenv = require('dotenv-webpack')
function resolveSrc(_path) {
return path.join(__dirname, _path)
}
let vue_path = process.env.VUE_PATH
if (vue_path == undefined) {
vue_path = ''
}
// vue.config.js
module.exports = {
pluginOptions: {
@ -15,6 +21,7 @@ module.exports = {
},
},
lintOnSave: true,
publicPath: vue_path + '/',
configureWebpack: {
// Set up all the aliases we use in our app.
resolve: {
@ -28,4 +35,5 @@ module.exports = {
// Enable CSS source maps.
sourceMap: process.env.NODE_ENV !== 'production',
},
outputDir: path.resolve(__dirname, './dist' + vue_path),
}

File diff suppressed because it is too large Load Diff

View File

@ -1,177 +1,177 @@
cmake_minimum_required(VERSION 3.0)
project(Gradido_LoginServer C CXX)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin" )
SET ( CMAKE_CXX_FLAGS "-std=c++17" )
include_directories(
"dependencies"
"dependencies/tinf/src/"
"dependencies/iroha-ed25519/include"
"dependencies/mariadb-connector-c/include"
"dependencies/mariadb-connector-c/build/include"
"dependencies/spirit-po/include"
"src/cpp/proto"
#"dependencies/mariadb-connector-c/build/include"
#"dependencies/mariadb-connector-c/include"
#"import/mariadb/include"
)
FILE(GLOB CONTROLLER "src/cpp/controller/*.cpp" "src/cpp/controller/*.h")
FILE(GLOB TINF "dependencies/tinf/src/*.c" "dependencies/tinf/src/*.h")
FILE(GLOB HTTPInterface "src/cpp/HTTPInterface/*.h" "src/cpp/HTTPInterface/*.cpp")
FILE(GLOB JSONInterface "src/cpp/JSONInterface/*.h" "src/cpp/JSONInterface/*.cpp")
FILE(GLOB TASKS "src/cpp/tasks/*.cpp" "src/cpp/tasks/*.h")
FILE(GLOB SINGLETON_MANAGER "src/cpp/SingletonManager/*.h" "src/cpp/SingletonManager/*.cpp")
FILE(GLOB LIB_SRC "src/cpp/lib/*.h" "src/cpp/lib/*.cpp")
FILE(GLOB MODEL "src/cpp/model/*.h" "src/cpp/model/*.cpp")
FILE(GLOB MODEL_TABLE "src/cpp/model/table/*.h" "src/cpp/model/table/*.cpp")
FILE(GLOB MODEL_EMAIL "src/cpp/model/email/*.h" "src/cpp/model/email/*.cpp")
FILE(GLOB CRYPTO "src/cpp/Crypto/*.h" "src/cpp/Crypto/*.cpp")
FILE(GLOB MAIN "src/cpp/*.cpp" "src/cpp/*.c" "src/cpp/*.h")
FILE(GLOB MYSQL "src/cpp/MySQL/*.cpp" "src/cpp/MySQL/*.h" "src/cpp/MySQL/Poco/*.h")
FILE(GLOB PROTO_GRADIDO "src/cpp/proto/gradido/*.cc" "src/cpp/proto/gradido/*.h")
FILE(GLOB PROTO_HEDERA "src/cpp/proto/hedera/*.cc" "src/cpp/proto/hedera/*.h")
# used only for test project
FILE(GLOB TEST "src/cpp/test/*.cpp" "src/cpp/test/*.h")
FILE(GLOB TEST_CRYPTO "src/cpp/test/crypto/*.cpp" "src/cpp/test/crypto/*.h")
FILE(GLOB TEST_MODEL "src/cpp/test/model/*.cpp" "src/cpp/test/model/*.h")
FILE(GLOB TEST_MODEL_TABLE "src/cpp/test/model/table/*.cpp" "src/cpp/test/model/table/*.h")
FILE(GLOB TEST_CONTROLLER "src/cpp/test/controller/*.cpp" "src/cpp/test/controller/*.h")
SET(LOCAL_SRCS
${CONTROLLER} ${TINF} ${MAIN} ${HTTPInterface}
${JSONInterface} ${CRYPTO} ${MODEL} ${MODEL_TABLE} ${MODEL_EMAIL}
${SINGLETON_MANAGER} ${LIB_SRC} ${MYSQL} ${TASKS}
${PROTO_GRADIDO} ${PROTO_HEDERA}
)
SET(LOCAL_TEST_SRC
${TEST} ${TEST_CRYPTO} ${TEST_MODEL} ${TEST_MODEL_TABLE} ${TEST_CONTROLLER}
)
aux_source_directory("src/cpp" LOCAL_SRCS)
if(MSVC)
# src
source_group("controller" FILES ${CONTROLLER})
source_group("proto\\gradido" FILES ${PROTO_GRADIDO})
source_group("proto\\hedera" FILES ${PROTO_HEDERA})
source_group("tinf" FILES ${TINF})
source_group("Crypto" FILES ${CRYPTO})
source_group("tasks" FILES ${TASKS})
source_group("model\\table" FILES ${MODEL_TABLE})
source_group("model\\email" FILES ${MODEL_EMAIL})
source_group("model" FILES ${MODEL})
source_group("mysql" FILES ${MYSQL})
source_group("SingletonManager" FILES ${SINGLETON_MANAGER})
source_group("lib" FILES ${LIB_SRC})
source_group("HTTP-Interface" FILES ${HTTPInterface})
source_group("Json-Interface" FILES ${JSONInterface})
source_group("Test\\crypto" FILES ${TEST_CRYPTO})
source_group("Test\\model\\table" FILES ${TEST_MODEL_TABLE})
source_group("Test\\model" FILES ${TEST_MODEL})
source_group("Test\\controller" FILES ${TEST_CONTROLLER})
source_group("Test" FILES ${TEST})
endif(MSVC)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
#add_subdirectory("dependencies/curl")
#add_subdirectory("dependencies/mariadb-connector-c")
add_executable(Gradido_LoginServer ${LOCAL_SRCS})
#SUBDIRS("src/test")
if(WIN32)
find_library(MYSQL_LIBRARIES mariadbclient.lib PATHS "dependencies/mariadb-connector-c/build/libmariadb/Release" REQUIRED)
#find_library(MYSQL_LIBRARIES_DEBUG mariadbclient.lib PATHS "import/mariadb/lib/debug")
find_library(COMPILED_MARIADB_CLIENT_DEBUG mariadbclient PATHS "dependencies/mariadb-connector-c/build/libmariadb/Debug" REQUIRED)
find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build/Debug" REQUIRED)
set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include")
#set(POCO_DEBUG_PATH "I:/FremdCode/C++/poco/win64/lib/Debug")
#find_library(POCO_DEBUG_FOUNDATION PocoFoundationd PocoFoundation PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_DATA PocoDatad PocoData PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_NET PocoNetd PocoNet PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_NET_SSL PocoNetSSLd PocoNetSSL PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_UTIL PocoUtild PocoUtil PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_CRYPTO PocoCryptod PocoCrypto PATHS ${POCO_DEBUG_PATH} REQUIRED)
#set(POCO_DEBUG_LIBS ${POCO_DEBUG_FOUNDATION} ${POCO_DEBUG_UTIL} ${POCO_DEBUG_DATA} ${POCO_DEBUG_NET} ${POCO_DEBUG_NET_SSL} ${POCO_DEBUG_CRYPTO})
#include_directories(
# "I:/FremdCode/C++/poco/Foundation/include"
# "I:/FremdCode/C++/poco/Data/include"
# "I:/FremdCode/C++/poco/Net/include"
#"I:/FremdCode/C++/poco/NetSSL_Win/include"
# "I:/FremdCode/C++/poco/NetSSL_OpenSSL/include"
# "I:/FremdCode/C++/poco/Crypto/include"
# "I:/FremdCode/C++/poco/Util/include"
# "I:/FremdCode/C++/ssl/include"
#)
set(CMAKE_CXX_FLAGS "/MP /EHsc")
#set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3")
#set(CMAKE_CXX_FLAGS_RELEASE "-O3")
else()
find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build" REQUIRED)
# set vars for mariadb cmake files
set(INSTALL_BINDIR "bin")
set(INSTALL_PLUGINDIR "bin")
add_subdirectory("dependencies/mariadb-connector-c")
include_directories(
"dependencies/mariadb-connector-c/include"
"build/dependencies/mariadb-connector-c/include"
)
endif()
target_link_libraries(Gradido_LoginServer ${CONAN_LIBS} ${IROHA_ED25519})
if(WIN32)
TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi)
TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi)
else()
target_link_libraries(Gradido_LoginServer libmariadb -pthread)
endif()
# install
if(UNIX)
install(TARGETS Gradido_LoginServer RUNTIME DESTINATION /usr/local/bin)
#install(FILES lib/libmariadb /usr/local/lib)
install(FILES DESTINATION lib COMPONENT libmariadb)
install(DIRECTORY src/LOCALE DESTINATION /etc/grd_login/
FILES_MATCHING PATTERN "*.po(t)")
endif(UNIX)
enable_testing()
# ---------------------- Test -----------------------------------------
#project(Gradido_LoginServer_Test C CXX)
#_TEST_BUILD
add_executable(Gradido_LoginServer_Test ${LOCAL_SRCS} ${LOCAL_TEST_SRC})
target_compile_definitions(Gradido_LoginServer_Test PUBLIC "_TEST_BUILD")
target_link_libraries(Gradido_LoginServer_Test ${CONAN_LIBS} ${IROHA_ED25519})
if(WIN32)
TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test optimized ${MYSQL_LIBRARIES} Shlwapi)
TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi)
else()
target_link_libraries(Gradido_LoginServer_Test libmariadb -pthread)
endif()
add_test(NAME main COMMAND Gradido_LoginServer_Test)
cmake_minimum_required(VERSION 3.0)
project(Gradido_LoginServer C CXX)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin" )
SET ( CMAKE_CXX_FLAGS "-std=c++17" )
include_directories(
"dependencies"
"dependencies/tinf/src/"
"dependencies/iroha-ed25519/include"
"dependencies/mariadb-connector-c/include"
"dependencies/mariadb-connector-c/build/include"
"dependencies/spirit-po/include"
"src/cpp/proto"
#"dependencies/mariadb-connector-c/build/include"
#"dependencies/mariadb-connector-c/include"
#"import/mariadb/include"
)
FILE(GLOB CONTROLLER "src/cpp/controller/*.cpp" "src/cpp/controller/*.h")
FILE(GLOB TINF "dependencies/tinf/src/*.c" "dependencies/tinf/src/*.h")
FILE(GLOB HTTPInterface "src/cpp/HTTPInterface/*.h" "src/cpp/HTTPInterface/*.cpp")
FILE(GLOB JSONInterface "src/cpp/JSONInterface/*.h" "src/cpp/JSONInterface/*.cpp")
FILE(GLOB TASKS "src/cpp/tasks/*.cpp" "src/cpp/tasks/*.h")
FILE(GLOB SINGLETON_MANAGER "src/cpp/SingletonManager/*.h" "src/cpp/SingletonManager/*.cpp")
FILE(GLOB LIB_SRC "src/cpp/lib/*.h" "src/cpp/lib/*.cpp")
FILE(GLOB MODEL "src/cpp/model/*.h" "src/cpp/model/*.cpp")
FILE(GLOB MODEL_TABLE "src/cpp/model/table/*.h" "src/cpp/model/table/*.cpp")
FILE(GLOB MODEL_EMAIL "src/cpp/model/email/*.h" "src/cpp/model/email/*.cpp")
FILE(GLOB CRYPTO "src/cpp/Crypto/*.h" "src/cpp/Crypto/*.cpp")
FILE(GLOB MAIN "src/cpp/*.cpp" "src/cpp/*.c" "src/cpp/*.h")
FILE(GLOB MYSQL "src/cpp/MySQL/*.cpp" "src/cpp/MySQL/*.h" "src/cpp/MySQL/Poco/*.h")
FILE(GLOB PROTO_GRADIDO "src/cpp/proto/gradido/*.cc" "src/cpp/proto/gradido/*.h")
FILE(GLOB PROTO_HEDERA "src/cpp/proto/hedera/*.cc" "src/cpp/proto/hedera/*.h")
# used only for test project
FILE(GLOB TEST "src/cpp/test/*.cpp" "src/cpp/test/*.h")
FILE(GLOB TEST_CRYPTO "src/cpp/test/crypto/*.cpp" "src/cpp/test/crypto/*.h")
FILE(GLOB TEST_MODEL "src/cpp/test/model/*.cpp" "src/cpp/test/model/*.h")
FILE(GLOB TEST_MODEL_TABLE "src/cpp/test/model/table/*.cpp" "src/cpp/test/model/table/*.h")
FILE(GLOB TEST_CONTROLLER "src/cpp/test/controller/*.cpp" "src/cpp/test/controller/*.h")
SET(LOCAL_SRCS
${CONTROLLER} ${TINF} ${MAIN} ${HTTPInterface}
${JSONInterface} ${CRYPTO} ${MODEL} ${MODEL_TABLE} ${MODEL_EMAIL}
${SINGLETON_MANAGER} ${LIB_SRC} ${MYSQL} ${TASKS}
${PROTO_GRADIDO} ${PROTO_HEDERA}
)
SET(LOCAL_TEST_SRC
${TEST} ${TEST_CRYPTO} ${TEST_MODEL} ${TEST_MODEL_TABLE} ${TEST_CONTROLLER}
)
aux_source_directory("src/cpp" LOCAL_SRCS)
if(MSVC)
# src
source_group("controller" FILES ${CONTROLLER})
source_group("proto\\gradido" FILES ${PROTO_GRADIDO})
source_group("proto\\hedera" FILES ${PROTO_HEDERA})
source_group("tinf" FILES ${TINF})
source_group("Crypto" FILES ${CRYPTO})
source_group("tasks" FILES ${TASKS})
source_group("model\\table" FILES ${MODEL_TABLE})
source_group("model\\email" FILES ${MODEL_EMAIL})
source_group("model" FILES ${MODEL})
source_group("mysql" FILES ${MYSQL})
source_group("SingletonManager" FILES ${SINGLETON_MANAGER})
source_group("lib" FILES ${LIB_SRC})
source_group("HTTP-Interface" FILES ${HTTPInterface})
source_group("Json-Interface" FILES ${JSONInterface})
source_group("Test\\crypto" FILES ${TEST_CRYPTO})
source_group("Test\\model\\table" FILES ${TEST_MODEL_TABLE})
source_group("Test\\model" FILES ${TEST_MODEL})
source_group("Test\\controller" FILES ${TEST_CONTROLLER})
source_group("Test" FILES ${TEST})
endif(MSVC)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
#add_subdirectory("dependencies/curl")
#add_subdirectory("dependencies/mariadb-connector-c")
add_executable(Gradido_LoginServer ${LOCAL_SRCS})
#SUBDIRS("src/test")
if(WIN32)
find_library(MYSQL_LIBRARIES mariadbclient.lib PATHS "dependencies/mariadb-connector-c/build/libmariadb/Release" REQUIRED)
#find_library(MYSQL_LIBRARIES_DEBUG mariadbclient.lib PATHS "import/mariadb/lib/debug")
find_library(COMPILED_MARIADB_CLIENT_DEBUG mariadbclient PATHS "dependencies/mariadb-connector-c/build/libmariadb/Debug" REQUIRED)
find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build/Debug" REQUIRED)
set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include")
#set(POCO_DEBUG_PATH "I:/FremdCode/C++/poco/win64/lib/Debug")
#find_library(POCO_DEBUG_FOUNDATION PocoFoundationd PocoFoundation PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_DATA PocoDatad PocoData PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_NET PocoNetd PocoNet PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_NET_SSL PocoNetSSLd PocoNetSSL PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_UTIL PocoUtild PocoUtil PATHS ${POCO_DEBUG_PATH} REQUIRED)
#find_library(POCO_DEBUG_CRYPTO PocoCryptod PocoCrypto PATHS ${POCO_DEBUG_PATH} REQUIRED)
#set(POCO_DEBUG_LIBS ${POCO_DEBUG_FOUNDATION} ${POCO_DEBUG_UTIL} ${POCO_DEBUG_DATA} ${POCO_DEBUG_NET} ${POCO_DEBUG_NET_SSL} ${POCO_DEBUG_CRYPTO})
#include_directories(
# "I:/FremdCode/C++/poco/Foundation/include"
# "I:/FremdCode/C++/poco/Data/include"
# "I:/FremdCode/C++/poco/Net/include"
#"I:/FremdCode/C++/poco/NetSSL_Win/include"
# "I:/FremdCode/C++/poco/NetSSL_OpenSSL/include"
# "I:/FremdCode/C++/poco/Crypto/include"
# "I:/FremdCode/C++/poco/Util/include"
# "I:/FremdCode/C++/ssl/include"
#)
set(CMAKE_CXX_FLAGS "/MP /EHsc")
#set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3")
#set(CMAKE_CXX_FLAGS_RELEASE "-O3")
else()
find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build" REQUIRED)
# set vars for mariadb cmake files
set(INSTALL_BINDIR "bin")
set(INSTALL_PLUGINDIR "bin")
add_subdirectory("dependencies/mariadb-connector-c")
include_directories(
"dependencies/mariadb-connector-c/include"
"build/dependencies/mariadb-connector-c/include"
)
endif()
target_link_libraries(Gradido_LoginServer ${CONAN_LIBS} ${IROHA_ED25519})
if(WIN32)
TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi)
TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi)
else()
target_link_libraries(Gradido_LoginServer libmariadb -pthread)
endif()
# install
if(UNIX)
install(TARGETS Gradido_LoginServer RUNTIME DESTINATION /usr/local/bin)
#install(FILES lib/libmariadb /usr/local/lib)
install(FILES DESTINATION lib COMPONENT libmariadb)
install(DIRECTORY src/LOCALE DESTINATION /etc/grd_login/
FILES_MATCHING PATTERN "*.po(t)")
endif(UNIX)
enable_testing()
# ---------------------- Test -----------------------------------------
#project(Gradido_LoginServer_Test C CXX)
#_TEST_BUILD
add_executable(Gradido_LoginServer_Test ${LOCAL_SRCS} ${LOCAL_TEST_SRC})
target_compile_definitions(Gradido_LoginServer_Test PUBLIC "_TEST_BUILD")
target_link_libraries(Gradido_LoginServer_Test ${CONAN_LIBS} ${IROHA_ED25519})
if(WIN32)
TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test optimized ${MYSQL_LIBRARIES} Shlwapi)
TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi)
else()
target_link_libraries(Gradido_LoginServer_Test libmariadb -pthread)
endif()
add_test(NAME main COMMAND Gradido_LoginServer_Test)

View File

@ -1,18 +1,3 @@
#########################################################################################################
# Build protoc
#########################################################################################################
FROM gcc:7.5 as protoc_build
RUN git clone --recurse-submodules https://github.com/protocolbuffers/protobuf.git
WORKDIR /protobuf
RUN git checkout v3.9.1
RUN ./autogen.sh
RUN ./configure --enable-static=yes
RUN make -j$(grep processor /proc/cpuinfo | wc -l)
RUN make check
CMD ["./protobuf"]
#########################################################################################################
# Build release
#########################################################################################################
@ -22,11 +7,10 @@ ENV DOCKER_WORKDIR="/code"
USER root
COPY --from=protoc_build /protobuf/src/.libs/protoc /usr/bin/
COPY --from=protoc_build /protobuf/src/.libs/libprotobuf.so.20.0.1 /usr/lib/libprotobuf.so.20
COPY --from=protoc_build /protobuf/src/.libs/libprotoc.so.20.0.1 /usr/lib/libprotoc.so.20
COPY --from=protoc_build /protobuf/src/google/protobuf/*.proto /usr/include/google/protobuf/
COPY --from=protoc_build /protobuf/src/google/protobuf/*.h /usr/include/google/protobuf/
COPY --from=unicorny/protoc:3.9.1 /usr/bin/protoc /usr/bin/
COPY --from=unicorny/protoc:3.9.1 /usr/lib/libprotobuf.so.20 /usr/lib/libprotobuf.so.20
COPY --from=unicorny/protoc:3.9.1 /usr/lib/libprotoc.so.20 /usr/lib/libprotoc.so.20
COPY --from=unicorny/protoc:3.9.1 /usr/include/google/protobuf/* /usr/include/google/protobuf/
RUN mkdir -p ${DOCKER_WORKDIR}
@ -40,7 +24,7 @@ RUN cd dependencies/iroha-ed25519 && \
mkdir build && \
cd build && \
cmake .. -DEDIMPL=ref10 -DHASH=sha2_sphlib -DRANDOM=bcryptgen -DBUILD=STATIC && \
make -j$(grep processor /proc/cpuinfo | wc -l)
make -j$(nproc)
RUN cd dependencies/mariadb-connector-c && \
mkdir build && \
@ -56,7 +40,7 @@ RUN mkdir build && \
cd build && \
conan install .. --build=missing && \
cmake .. && \
make -j$(grep processor /proc/cpuinfo | wc -l) Gradido_LoginServer
make -j$(nproc) Gradido_LoginServer
CMD ["./code"]

View File

@ -1,132 +1,67 @@
#########################################################################################################
# Build protoc
#########################################################################################################
FROM gcc:7.5 as protoc_build
RUN git clone --recurse-submodules https://github.com/protocolbuffers/protobuf.git
WORKDIR /protobuf
RUN git checkout v3.9.1
RUN ./autogen.sh
RUN ./configure --enable-static=yes
RUN make -j$(grep processor /proc/cpuinfo | wc -l)
RUN make check
CMD ["./protobuf"]
#########################################################################################################
# debug build preparation
#########################################################################################################
From conanio/gcc7 as debug_preparation
ENV DOCKER_WORKDIR="/code"
USER root
COPY --from=protoc_build /protobuf/src/.libs/protoc /usr/bin/
COPY --from=protoc_build /protobuf/src/.libs/libprotobuf.so.20.0.1 /usr/lib/libprotobuf.so.20
COPY --from=protoc_build /protobuf/src/.libs/libprotoc.so.20.0.1 /usr/lib/libprotoc.so.20
COPY --from=protoc_build /protobuf/src/google/protobuf/*.proto /usr/include/google/protobuf/
COPY --from=protoc_build /protobuf/src/google/protobuf/*.h /usr/include/google/protobuf/
#VOLUME /root/.conan
RUN mkdir -p ${DOCKER_WORKDIR}
WORKDIR ${DOCKER_WORKDIR}
COPY ./dependencies ./dependencies
COPY ./conanfile.txt ./conanfile.txt
RUN ls -la
RUN cd dependencies/iroha-ed25519 && \
ls -la && \
mkdir build && \
cd build && \
cmake .. -DCMAKE_BUILD_TYPE=Debug -DEDIMPL=ref10 -DHASH=sha2_sphlib -DRANDOM=bcryptgen -DBUILD=STATIC && \
make -j$(grep processor /proc/cpuinfo | wc -l)
RUN cd dependencies/mariadb-connector-c && \
mkdir build && \
cd build && \
cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_SSL=OFF ..
#RUN chmod +x compile_proto.sh
#RUN chmod +x compile_pot.sh
#RUN ls -la
#RUN ./compile_pot.sh
#RUN ./compile_proto.sh
RUN mkdir build && \
cd build && \
conan install .. --build=missing -s build_type=Debug
#########################################################################################################
# Build debug
#########################################################################################################
From debug_preparation as debug
ENV DOCKER_WORKDIR="/code"
USER root
#VOLUME /root/.conan
RUN apt-get update && \
apt-get install -y --no-install-recommends gdb && \
apt-get autoclean && \
apt-get autoremove && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
#COPY --from=protoc_build /protobuf/src/.libs/libprotobuf.so.20.0.1 /usr/lib/libprotobuf.so.20
#COPY --from=protoc_build /protobuf/src/google/protobuf/*.h /usr/include/google/protobuf/
#COPY --from=debug_preparation /code /code
#COPY --from=debug_preparation /home/conan /home/conan
#RUN ls -la /home/conan/.conan
COPY . .
WORKDIR ${DOCKER_WORKDIR}
#RUN ls -la
#RUN cat build/conanbuildinfo.cmake
RUN chmod +x compile_proto.sh
RUN chmod +x compile_pot.sh
#RUN ls -la
RUN ./compile_pot.sh
RUN ./compile_proto.sh
RUN cd build && \
cmake -DCMAKE_BUILD_TYPE=Debug .. && \
make -j$(grep processor /proc/cpuinfo | wc -l)
#########################################################################################################
# run debug
#########################################################################################################
FROM ubuntu:latest as login_server_debug
WORKDIR "/usr/bin"
#RUN apt-get update && \
# apt-get install -y --no-install-recommends gdb && \
# apt-get autoclean && \
# apt-get autoremove && \
# apt-get clean && \
# rm -rf /var/lib/apt/lists/*
VOLUME /var/log/grd_login
COPY --from=debug /code/build/bin/Gradido_LoginServer /usr/bin/
COPY --from=debug /code/build/lib/libmariadb.so.3 /usr/lib/
#COPY start_after_mysql.sh .
RUN chmod +x /usr/bin/Gradido_LoginServer
EXPOSE 1200
EXPOSE 1201
#ENTRYPOINT ["/usr/bin/Gradido_LoginServer"]
# Wait on mariadb to started
#CMD ["sleep 5", "/usr/bin/Gradido_LoginServer"]
#RUN chmod +x ./start_after_mysql.sh
#ENTRYPOINT ["/usr/bin/Gradido_LoginServer"]
#CMD gdb -ex=r Gradido_LoginServer
CMD Gradido_LoginServer
#########################################################################################################
# Build debug
#########################################################################################################
From gradido/login_dependencies:stage1 as debug
ENV DOCKER_WORKDIR="/code"
USER root
#VOLUME /root/.conan
#RUN apt-get update && \
# apt-get install -y --no-install-recommends gdb && \
# apt-get autoclean && \
# apt-get autoremove && \
# apt-get clean && \
# rm -rf /var/lib/apt/lists/*
#COPY --from=protoc_build /protobuf/src/.libs/libprotobuf.so.20.0.1 /usr/lib/libprotobuf.so.20
#COPY --from=protoc_build /protobuf/src/google/protobuf/*.h /usr/include/google/protobuf/
#COPY --from=debug_preparation /code /code
#COPY --from=debug_preparation /home/conan /home/conan
#RUN ls -la /home/conan/.conan
WORKDIR ${DOCKER_WORKDIR}
COPY . .
#RUN ls -la
#RUN cat build/conanbuildinfo.cmake
RUN chmod +x compile_proto.sh
RUN chmod +x compile_pot.sh
#RUN ls -la
RUN ./compile_pot.sh
RUN ./compile_proto.sh
#########################################################################################################
# run debug
#########################################################################################################
FROM debug as login_server_debug
ENV DOCKER_WORKDIR="/code"
#RUN apt-get update && \
# apt-get install -y --no-install-recommends gdb && \
# apt-get autoclean && \
# apt-get autoremove && \
# apt-get clean && \
# rm -rf /var/lib/apt/lists/*
VOLUME /var/log/grd_login
VOLUME /code/src
EXPOSE 1200
EXPOSE 1201
WORKDIR ${DOCKER_WORKDIR}
RUN chmod +x ./Dockerfiles/build_and_run.sh
#ENTRYPOINT ["/usr/bin/Gradido_LoginServer"]
# Wait on mariadb to started
#CMD ["sleep 5", "/usr/bin/Gradido_LoginServer"]
#RUN chmod +x ./start_after_mysql.sh
#ENTRYPOINT ["/usr/bin/Gradido_LoginServer"]
#CMD gdb -ex=r Gradido_LoginServer
CMD ./Dockerfiles/build_and_run.sh

View File

@ -0,0 +1,46 @@
#########################################################################################################
# debug build preparation
#########################################################################################################
From conanio/gcc7 as debug_preparation
ENV DOCKER_WORKDIR="/code"
USER root
COPY --from=gradido/protoc:3.9.1 /usr/bin/protoc /usr/bin/
COPY --from=gradido/protoc:3.9.1 /usr/lib/libprotobuf.so.20 /usr/lib/libprotobuf.so.20
COPY --from=gradido/protoc:3.9.1 /usr/lib/libprotoc.so.20 /usr/lib/libprotoc.so.20
COPY --from=gradido/protoc:3.9.1 /usr/include/google/protobuf/* /usr/include/google/protobuf/
#VOLUME /root/.conan
RUN mkdir -p ${DOCKER_WORKDIR}
WORKDIR ${DOCKER_WORKDIR}
COPY ./dependencies ./dependencies
COPY ./conanfile.txt ./conanfile.txt
RUN ls -la
RUN cd dependencies/iroha-ed25519 && \
ls -la && \
mkdir build && \
cd build && \
cmake .. -DCMAKE_BUILD_TYPE=Debug -DEDIMPL=ref10 -DHASH=sha2_sphlib -DRANDOM=bcryptgen -DBUILD=STATIC && \
make -j$(nproc)
RUN cd dependencies/mariadb-connector-c && \
mkdir build && \
cd build && \
cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_SSL=OFF ..
#RUN chmod +x compile_proto.sh
#RUN chmod +x compile_pot.sh
#RUN ls -la
#RUN ./compile_pot.sh
#RUN ./compile_proto.sh
RUN mkdir build && \
cd build && \
conan install .. --build=missing -s build_type=Debug

View File

@ -0,0 +1,30 @@
#########################################################################################################
# Build protoc
#########################################################################################################
FROM gcc:7.5 as protoc3.9.1_build
RUN git clone --recurse-submodules https://github.com/protocolbuffers/protobuf.git
WORKDIR /protobuf
RUN git checkout v3.9.1
RUN ./autogen.sh
RUN ./configure --enable-static=yes
RUN make -j$(nproc)
#RUN make check
CMD ["./protobuf"]
#########################################################################################################
# Store protoc
#########################################################################################################
FROM alpine:3.10 as protoc
COPY --from=protoc3.9.1_build /protobuf/src/.libs/protoc /usr/bin/
COPY --from=protoc3.9.1_build /protobuf/src/.libs/libprotobuf.so.20.0.1 /usr/lib/libprotobuf.so.20
COPY --from=protoc3.9.1_build /protobuf/src/.libs/libprotoc.so.20.0.1 /usr/lib/libprotoc.so.20
COPY --from=protoc3.9.1_build /protobuf/src/google/protobuf/*.proto /usr/include/google/protobuf/
COPY --from=protoc3.9.1_build /protobuf/src/google/protobuf/*.h /usr/include/google/protobuf/
## build with:
# docker build . -f Dockefile.protoc -t gradido/protoc:3.9.1
## upload (login to docker hub on shell before):
# docker push gradido/protoc:3.9.1

View File

@ -0,0 +1,9 @@
#!/bin/bash
cp build/conan* build_vol/
cd build_vol
cmake -DCMAKE_BUILD_TYPE=Debug ..
make -j$(nproc) Gradido_LoginServer
echo "building done"
chmod +x ./bin/Gradido_LoginServer
./bin/Gradido_LoginServer

View File

@ -1,16 +1,16 @@
CREATE TABLE `users` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`email` varchar(191) NOT NULL,
`first_name` varchar(150) NOT NULL,
`last_name` varchar(255) DEFAULT '',
`password` bigint unsigned DEFAULT 0,
`pubkey` binary(32) DEFAULT NULL,
`privkey` binary(80) DEFAULT NULL,
`created` datetime NOT NULL DEFAULT current_timestamp(),
`email_checked` tinyint NOT NULL DEFAULT 0,
`passphrase_shown` tinyint NOT NULL DEFAULT 0,
`language` varchar(4) NOT NULL DEFAULT 'de',
`disabled` BOOLEAN NULL DEFAULT FALSE,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `users` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`email` varchar(191) NOT NULL,
`first_name` varchar(150) NOT NULL,
`last_name` varchar(255) DEFAULT '',
`password` bigint unsigned DEFAULT 0,
`pubkey` binary(32) DEFAULT NULL,
`privkey` binary(80) DEFAULT NULL,
`created` datetime NOT NULL DEFAULT current_timestamp(),
`email_checked` tinyint NOT NULL DEFAULT 0,
`passphrase_shown` tinyint NOT NULL DEFAULT 0,
`language` varchar(4) NOT NULL DEFAULT 'de',
`disabled` BOOLEAN NULL DEFAULT FALSE,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@ -1,267 +1,267 @@
#include "Gradido_LoginServer.h"
#include "ServerConfig.h"
#include "HTTPInterface/PageRequestHandlerFactory.h"
#include "JSONInterface/JsonRequestHandlerFactory.h"
#include "lib/Profiler.h"
#include "SingletonManager/ConnectionManager.h"
#include "SingletonManager/SessionManager.h"
#include "SingletonManager/EmailManager.h"
#include "controller/User.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Environment.h"
#include "Poco/Logger.h"
#include "Poco/Path.h"
#include "Poco/AsyncChannel.h"
#include "Poco/SimpleFileChannel.h"
#include "Poco/ConsoleChannel.h"
#include "Poco/SplitterChannel.h"
#include "MySQL/Poco/Connector.h"
#include <sodium.h>
Gradido_LoginServer::Gradido_LoginServer()
: _helpRequested(false)
{
}
Gradido_LoginServer::~Gradido_LoginServer()
{
}
void Gradido_LoginServer::initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void Gradido_LoginServer::uninitialize()
{
ServerApplication::uninitialize();
}
void Gradido_LoginServer::defineOptions(Poco::Util::OptionSet& options)
{
ServerApplication::defineOptions(options);
/*options.addOption(
Poco::Util::Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false));*/
options.addOption(
Poco::Util::Option("config", "c", "use non default config file (default is /etc/grd_login.properties)", false)
.repeatable(false)
.argument("Gradido_LoginServer.properties", true)
.callback(Poco::Util::OptionCallback<Gradido_LoginServer>(this, &Gradido_LoginServer::handleOption)));
}
void Gradido_LoginServer::handleOption(const std::string& name, const std::string& value)
{
//printf("handle option: %s with value: %s\n", name.data(), value.data());
if (name == "config") {
mConfigPath = value;
return;
}
ServerApplication::handleOption(name, value);
if (name == "help") _helpRequested = true;
}
void Gradido_LoginServer::displayHelp()
{
Poco::Util::HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("Gradido Login Server");
helpFormatter.format(std::cout);
}
void Gradido_LoginServer::createConsoleFileAsyncLogger(std::string name, std::string filePath)
{
Poco::AutoPtr<Poco::ConsoleChannel> logConsoleChannel(new Poco::ConsoleChannel);
Poco::AutoPtr<Poco::SimpleFileChannel> logFileChannel(new Poco::SimpleFileChannel(filePath));
logFileChannel->setProperty("rotation", "500 K");
Poco::AutoPtr<Poco::SplitterChannel> logSplitter(new Poco::SplitterChannel);
logSplitter->addChannel(logConsoleChannel);
logSplitter->addChannel(logFileChannel);
Poco::AutoPtr<Poco::AsyncChannel> logAsyncChannel(new Poco::AsyncChannel(logSplitter));
Poco::Logger& log = Poco::Logger::get(name);
log.setChannel(logAsyncChannel);
log.setLevel("information");
}
int Gradido_LoginServer::main(const std::vector<std::string>& args)
{
Profiler usedTime;
if (_helpRequested)
{
displayHelp();
}
else
{
// ********** logging ************************************
std::string log_Path = "/var/log/grd_login/";
//#ifdef _WIN32
#if defined(_WIN32) || defined(_WIN64)
log_Path = "./";
#endif
// init speed logger
Poco::AutoPtr<Poco::SimpleFileChannel> speedLogFileChannel(new Poco::SimpleFileChannel(log_Path + "speedLog.txt"));
/*
The optional log file rotation mode:
never: no rotation (default)
<n>: rotate if file size exceeds <n> bytes
<n> K: rotate if file size exceeds <n> Kilobytes
<n> M: rotate if file size exceeds <n> Megabytes
*/
speedLogFileChannel->setProperty("rotation", "500 K");
Poco::AutoPtr<Poco::AsyncChannel> speedLogAsyncChannel(new Poco::AsyncChannel(speedLogFileChannel));
Poco::Logger& speedLogger = Poco::Logger::get("SpeedLog");
speedLogger.setChannel(speedLogAsyncChannel);
speedLogger.setLevel("information");
// logging for request handling
createConsoleFileAsyncLogger("requestLog", log_Path + "requestLog.txt");
// error logging
createConsoleFileAsyncLogger("errorLog", log_Path + "errorLog.txt");
Poco::Logger& errorLog = Poco::Logger::get("errorLog");
createConsoleFileAsyncLogger("emailLog", log_Path + "emailLog.txt");
// *************** load from config ********************************************
std::string cfg_Path = Poco::Path::config() + "grd_login/grd_login.properties";
if (mConfigPath != "") {
cfg_Path = mConfigPath;
}
try {
loadConfiguration(cfg_Path);
}
catch (Poco::Exception& ex) {
errorLog.error("error loading config: %s from path: %s", ex.displayText(), cfg_Path);
}
unsigned short port = (unsigned short)config().getInt("HTTPServer.port", 9980);
unsigned short json_port = (unsigned short)config().getInt("JSONServer.port", 1201);
//printf("show mnemonic list: \n");
//printf(ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER].getCompleteWordList().data());
if (!ServerConfig::initServerCrypto(config())) {
//printf("[Gradido_LoginServer::%s] error init server crypto\n", __FUNCTION__);
errorLog.error("[Gradido_LoginServer::main] error init server crypto");
return Application::EXIT_CONFIG;
}
// first check time for crypto
auto testUser = new User("email@google.de", "Max", "Mustermann");
Profiler timeUsed;
testUser->validatePwd("haz27Newpassword", nullptr);
ServerConfig::g_FakeLoginSleepTime = (int)std::round(timeUsed.millis());
delete testUser;
Poco::Int64 i1 = randombytes_random();
Poco::Int64 i2 = randombytes_random();
ServerConfig::g_ServerKeySeed->put(1, i1 | (i2 << 8));
ServerConfig::initEMailAccount(config());
EmailManager::getInstance()->init(config());
// start cpu scheduler
uint8_t worker_count = Poco::Environment::processorCount() * 2;
ServerConfig::g_CPUScheduler = new UniLib::controller::CPUSheduler(worker_count, "Default Worker");
ServerConfig::g_CryptoCPUScheduler = new UniLib::controller::CPUSheduler(2, "Crypto Worker");
// load up connection configs
// register MySQL connector
Poco::Data::MySQL::Connector::registerConnector();
//Poco::Data::MySQL::Connector::KEY;
auto conn = ConnectionManager::getInstance();
//conn->setConnection()
//printf("try connect login server mysql db\n");
try {
conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER);
}
catch (Poco::Exception& ex) {
// maybe we in docker environment and db needs some time to start up
// let's wait 10 seconds
int count = 10;
while (count > 0) {
printf("\rwait on mysql/mariadb %d seconds...", count);
count--;
Poco::Thread::sleep(1000);
}
conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER);
}
//printf("try connect php server mysql \n");
//conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_PHP_SERVER);
SessionManager::getInstance()->init();
// put urandom on linux servers
//srand();
Poco::Net::initializeSSL();
if(!ServerConfig::initSSLClientContext()) {
//printf("[Gradido_LoginServer::%s] error init server SSL Client\n", __FUNCTION__);
errorLog.error("[Gradido_LoginServer::main] error init server SSL Client\n");
return Application::EXIT_CONFIG;
}
// schedule email verification resend
controller::User::checkIfVerificationEmailsShouldBeResend(ServerConfig::g_CronJobsTimer);
// HTTP Interface Server
// set-up a server socket
Poco::Net::ServerSocket svs(port);
// set-up a HTTPServer instance
Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool();
Poco::Net::HTTPServer srv(new PageRequestHandlerFactory, svs, new Poco::Net::HTTPServerParams);
ServerConfig::g_ServerKeySeed->put(7, 918276611);
// start the HTTPServer
srv.start();
// JSON Interface Server
Poco::Net::ServerSocket json_svs(json_port);
Poco::Net::HTTPServer json_srv(new JsonRequestHandlerFactory, json_svs, new Poco::Net::HTTPServerParams);
// start the json server
json_srv.start();
printf("[Gradido_LoginServer::main] started in %s\n", usedTime.string().data());
// wait for CTRL-C or kill
waitForTerminationRequest();
// Stop the HTTPServer
srv.stop();
// Stop the json server
json_srv.stop();
ServerConfig::unload();
Poco::Net::uninitializeSSL();
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
}
return Application::EXIT_OK;
}
#include "Gradido_LoginServer.h"
#include "ServerConfig.h"
#include "HTTPInterface/PageRequestHandlerFactory.h"
#include "JSONInterface/JsonRequestHandlerFactory.h"
#include "lib/Profiler.h"
#include "SingletonManager/ConnectionManager.h"
#include "SingletonManager/SessionManager.h"
#include "SingletonManager/EmailManager.h"
#include "controller/User.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Environment.h"
#include "Poco/Logger.h"
#include "Poco/Path.h"
#include "Poco/AsyncChannel.h"
#include "Poco/SimpleFileChannel.h"
#include "Poco/ConsoleChannel.h"
#include "Poco/SplitterChannel.h"
#include "MySQL/Poco/Connector.h"
#include <sodium.h>
Gradido_LoginServer::Gradido_LoginServer()
: _helpRequested(false)
{
}
Gradido_LoginServer::~Gradido_LoginServer()
{
}
void Gradido_LoginServer::initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void Gradido_LoginServer::uninitialize()
{
ServerApplication::uninitialize();
}
void Gradido_LoginServer::defineOptions(Poco::Util::OptionSet& options)
{
ServerApplication::defineOptions(options);
/*options.addOption(
Poco::Util::Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false));*/
options.addOption(
Poco::Util::Option("config", "c", "use non default config file (default is /etc/grd_login.properties)", false)
.repeatable(false)
.argument("Gradido_LoginServer.properties", true)
.callback(Poco::Util::OptionCallback<Gradido_LoginServer>(this, &Gradido_LoginServer::handleOption)));
}
void Gradido_LoginServer::handleOption(const std::string& name, const std::string& value)
{
//printf("handle option: %s with value: %s\n", name.data(), value.data());
if (name == "config") {
mConfigPath = value;
return;
}
ServerApplication::handleOption(name, value);
if (name == "help") _helpRequested = true;
}
void Gradido_LoginServer::displayHelp()
{
Poco::Util::HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("Gradido Login Server");
helpFormatter.format(std::cout);
}
void Gradido_LoginServer::createConsoleFileAsyncLogger(std::string name, std::string filePath)
{
Poco::AutoPtr<Poco::ConsoleChannel> logConsoleChannel(new Poco::ConsoleChannel);
Poco::AutoPtr<Poco::SimpleFileChannel> logFileChannel(new Poco::SimpleFileChannel(filePath));
logFileChannel->setProperty("rotation", "500 K");
Poco::AutoPtr<Poco::SplitterChannel> logSplitter(new Poco::SplitterChannel);
logSplitter->addChannel(logConsoleChannel);
logSplitter->addChannel(logFileChannel);
Poco::AutoPtr<Poco::AsyncChannel> logAsyncChannel(new Poco::AsyncChannel(logSplitter));
Poco::Logger& log = Poco::Logger::get(name);
log.setChannel(logAsyncChannel);
log.setLevel("information");
}
int Gradido_LoginServer::main(const std::vector<std::string>& args)
{
Profiler usedTime;
if (_helpRequested)
{
displayHelp();
}
else
{
// ********** logging ************************************
std::string log_Path = "/var/log/grd_login/";
//#ifdef _WIN32
#if defined(_WIN32) || defined(_WIN64)
log_Path = "./";
#endif
// init speed logger
Poco::AutoPtr<Poco::SimpleFileChannel> speedLogFileChannel(new Poco::SimpleFileChannel(log_Path + "speedLog.txt"));
/*
The optional log file rotation mode:
never: no rotation (default)
<n>: rotate if file size exceeds <n> bytes
<n> K: rotate if file size exceeds <n> Kilobytes
<n> M: rotate if file size exceeds <n> Megabytes
*/
speedLogFileChannel->setProperty("rotation", "500 K");
Poco::AutoPtr<Poco::AsyncChannel> speedLogAsyncChannel(new Poco::AsyncChannel(speedLogFileChannel));
Poco::Logger& speedLogger = Poco::Logger::get("SpeedLog");
speedLogger.setChannel(speedLogAsyncChannel);
speedLogger.setLevel("information");
// logging for request handling
createConsoleFileAsyncLogger("requestLog", log_Path + "requestLog.txt");
// error logging
createConsoleFileAsyncLogger("errorLog", log_Path + "errorLog.txt");
Poco::Logger& errorLog = Poco::Logger::get("errorLog");
createConsoleFileAsyncLogger("emailLog", log_Path + "emailLog.txt");
// *************** load from config ********************************************
std::string cfg_Path = Poco::Path::config() + "grd_login/grd_login.properties";
if (mConfigPath != "") {
cfg_Path = mConfigPath;
}
try {
loadConfiguration(cfg_Path);
}
catch (Poco::Exception& ex) {
errorLog.error("error loading config: %s from path: %s", ex.displayText(), cfg_Path);
}
unsigned short port = (unsigned short)config().getInt("HTTPServer.port", 9980);
unsigned short json_port = (unsigned short)config().getInt("JSONServer.port", 1201);
//printf("show mnemonic list: \n");
//printf(ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER].getCompleteWordList().data());
if (!ServerConfig::initServerCrypto(config())) {
//printf("[Gradido_LoginServer::%s] error init server crypto\n", __FUNCTION__);
errorLog.error("[Gradido_LoginServer::main] error init server crypto");
return Application::EXIT_CONFIG;
}
// first check time for crypto
auto testUser = new User("email@google.de", "Max", "Mustermann");
Profiler timeUsed;
testUser->validatePwd("haz27Newpassword", nullptr);
ServerConfig::g_FakeLoginSleepTime = (int)std::round(timeUsed.millis());
delete testUser;
Poco::Int64 i1 = randombytes_random();
Poco::Int64 i2 = randombytes_random();
ServerConfig::g_ServerKeySeed->put(1, i1 | (i2 << 8));
ServerConfig::initEMailAccount(config());
EmailManager::getInstance()->init(config());
// start cpu scheduler
uint8_t worker_count = Poco::Environment::processorCount() * 2;
ServerConfig::g_CPUScheduler = new UniLib::controller::CPUSheduler(worker_count, "Default Worker");
ServerConfig::g_CryptoCPUScheduler = new UniLib::controller::CPUSheduler(2, "Crypto Worker");
// load up connection configs
// register MySQL connector
Poco::Data::MySQL::Connector::registerConnector();
//Poco::Data::MySQL::Connector::KEY;
auto conn = ConnectionManager::getInstance();
//conn->setConnection()
//printf("try connect login server mysql db\n");
try {
conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER);
}
catch (Poco::Exception& ex) {
// maybe we in docker environment and db needs some time to start up
// let's wait 10 seconds
int count = 10;
while (count > 0) {
printf("\rwait on mysql/mariadb %d seconds...", count);
count--;
Poco::Thread::sleep(1000);
}
conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER);
}
//printf("try connect php server mysql \n");
//conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_PHP_SERVER);
SessionManager::getInstance()->init();
// put urandom on linux servers
//srand();
Poco::Net::initializeSSL();
if(!ServerConfig::initSSLClientContext()) {
//printf("[Gradido_LoginServer::%s] error init server SSL Client\n", __FUNCTION__);
errorLog.error("[Gradido_LoginServer::main] error init server SSL Client\n");
return Application::EXIT_CONFIG;
}
// schedule email verification resend
controller::User::checkIfVerificationEmailsShouldBeResend(ServerConfig::g_CronJobsTimer);
// HTTP Interface Server
// set-up a server socket
Poco::Net::ServerSocket svs(port);
// set-up a HTTPServer instance
Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool();
Poco::Net::HTTPServer srv(new PageRequestHandlerFactory, svs, new Poco::Net::HTTPServerParams);
ServerConfig::g_ServerKeySeed->put(7, 918276611);
// start the HTTPServer
srv.start();
// JSON Interface Server
Poco::Net::ServerSocket json_svs(json_port);
Poco::Net::HTTPServer json_srv(new JsonRequestHandlerFactory, json_svs, new Poco::Net::HTTPServerParams);
// start the json server
json_srv.start();
printf("[Gradido_LoginServer::main] started in %s\n", usedTime.string().data());
// wait for CTRL-C or kill
waitForTerminationRequest();
// Stop the HTTPServer
srv.stop();
// Stop the json server
json_srv.stop();
ServerConfig::unload();
Poco::Net::uninitializeSSL();
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
}
return Application::EXIT_OK;
}

View File

@ -1,42 +1,42 @@
#ifndef Gradido_LoginServer_INCLUDED
#define Gradido_LoginServer_INCLUDED
#include "Poco/Util/ServerApplication.h"
class Gradido_LoginServer : public Poco::Util::ServerApplication
{
/// The main application class.
///
/// This class handles command-line arguments and
/// configuration files.
/// Start the Gradido_LoginServer executable with the help
/// option (/help on Windows, --help on Unix) for
/// the available command line options.
///
public:
Gradido_LoginServer();
~Gradido_LoginServer();
protected:
void initialize(Application& self);
void uninitialize();
void defineOptions(Poco::Util::OptionSet& options);
void handleOption(const std::string& name, const std::string& value);
void displayHelp();
int main(const std::vector<std::string>& args);
void createConsoleFileAsyncLogger(std::string name, std::string filePath);
private:
bool _helpRequested;
std::string mConfigPath;
};
#endif //Gradido_LoginServer_INCLUDED
#ifndef Gradido_LoginServer_INCLUDED
#define Gradido_LoginServer_INCLUDED
#include "Poco/Util/ServerApplication.h"
class Gradido_LoginServer : public Poco::Util::ServerApplication
{
/// The main application class.
///
/// This class handles command-line arguments and
/// configuration files.
/// Start the Gradido_LoginServer executable with the help
/// option (/help on Windows, --help on Unix) for
/// the available command line options.
///
public:
Gradido_LoginServer();
~Gradido_LoginServer();
protected:
void initialize(Application& self);
void uninitialize();
void defineOptions(Poco::Util::OptionSet& options);
void handleOption(const std::string& name, const std::string& value);
void displayHelp();
int main(const std::vector<std::string>& args);
void createConsoleFileAsyncLogger(std::string name, std::string filePath);
private:
bool _helpRequested;
std::string mConfigPath;
};
#endif //Gradido_LoginServer_INCLUDED

View File

@ -11,16 +11,15 @@ using namespace Poco::Data::Keywords;
#include "../SingletonManager/ConnectionManager.h"
#include "../SingletonManager/ErrorManager.h"
#include "../SingletonManager/SessionManager.h"
#include "../SingletonManager/EmailManager.h"
#include "../ServerConfig.h"
#include "../tasks/PrepareEmailTask.h"
#include "../tasks/SendEmailTask.h"
#include "../controller/EmailVerificationCode.h"
#include "../model/table/ElopageBuy.h"
#include "../lib/DataTypeConverter.h"
void ElopageWebhook::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
@ -277,22 +276,9 @@ int HandleElopageRequestTask::run()
saveElopageBuy->scheduleTask(saveElopageBuy);
// check product id
Poco::UInt64 product_id = 0;
try {
product_id = stoull(mRequestData.get("product[id]", "0"));
}
catch (const std::invalid_argument& ia) {
std::cerr << __FUNCTION__ << "Invalid argument: " << ia.what() << '\n';
}
catch (const std::out_of_range& oor) {
std::cerr << __FUNCTION__ << "Out of Range error: " << oor.what() << '\n';
}
catch (const std::logic_error & ler) {
std::cerr << __FUNCTION__ << "Logical error: " << ler.what() << '\n';
}
catch (...) {
std::cerr << __FUNCTION__ << "Unknown error" << '\n';
}
unsigned long long product_id = 0;
DataTypeConverter::strToInt(mRequestData.get("product[id]", "0"), product_id);
std::string order_id = mRequestData.get("order_id", "");
auto param_error_order_id = new ParamError("HandleElopageRequestTask", "order_id", order_id.data());
@ -380,56 +366,16 @@ int HandleElopageRequestTask::run()
sendErrorsAsEmail();
return -4;
}
auto em = EmailManager::getInstance();
if (emailVerification->getModel()->insertIntoDB(false)) {
int noEMail = 0;
DataTypeConverter::strToInt(mRequestData.get("noEmail", "0"), noEMail);
// write email verification code into db
UniLib::controller::TaskPtr saveEmailVerificationCode(new model::table::ModelInsertTask(emailVerification->getModel(), true));
saveEmailVerificationCode->scheduleTask(saveEmailVerificationCode);
int noEMail = 0;
std::string noEmailString = mRequestData.get("noEmail", "0");
try {
noEMail = stoi(noEmailString);
}
catch (const std::invalid_argument& ia) {
std::cerr << __FUNCTION__ << " Invalid argument: " << ia.what() << ", str: " << noEmailString << '\n';
}
catch (const std::out_of_range& oor) {
std::cerr << __FUNCTION__ << " Out of Range error: " << oor.what() << '\n';
}
catch (const std::logic_error & ler) {
std::cerr << __FUNCTION__ << " Logical error: " << ler.what() << '\n';
}
catch (...) {
std::cerr << __FUNCTION__ << " Unknown error" << '\n';
if (noEMail != 1) {
em->addEmail(new model::Email(emailVerification, newUser, model::EMAIL_USER_VERIFICATION_CODE));
}
}
if (noEMail != 1) {
// send email to user
/*auto message = new Poco::Net::MailMessage;
message->addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, mEmail));
message->setSubject("Gradido: E-Mail Verification");
std::stringstream ss;
ss << "Hallo " << mFirstName << " " << mLastName << "," << std::endl << std::endl;
ss << "Du oder jemand anderes hat sich soeben mit dieser E-Mail Adresse bei Gradido registriert. " << std::endl;
ss << "Wenn du es warst, klicke bitte auf den Link: " << ServerConfig::g_serverPath << "/checkEmail/" << emailVerification->getModel()->getCode() << std::endl;
//ss << "oder kopiere den Code: " << mEmailVerificationCode << " selbst dort hinein." << std::endl;
ss << "oder kopiere den obigen Link in Dein Browserfenster." << std::endl;
ss << std::endl;
ss << "Mit freundlichen " << u8"Grüßen" << std::endl;
ss << "Dario, Gradido Server Admin" << std::endl;
message->addContent(new Poco::Net::StringPartSource(ss.str()));
*/
//UniLib::controller::TaskPtr sendEmail(new SendEmailTask(message, ServerConfig::g_CPUScheduler, 1));
//Email(AutoPtr<controller::EmailVerificationCode> emailVerification, AutoPtr<controller::User> user, EmailType type);
UniLib::controller::TaskPtr sendEmail(new SendEmailTask(new model::Email(emailVerification, newUser, model::EMAIL_USER_VERIFICATION_CODE), ServerConfig::g_CPUScheduler, 1));
//sendEmail->setParentTaskPtrInArray(prepareEmail, 0);
sendEmail->setParentTaskPtrInArray(saveEmailVerificationCode, 0);
sendEmail->scheduleTask(sendEmail);
}
}
// if errors occured, send via email

View File

@ -1,365 +1,365 @@
#include "LoginPage.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTMLForm.h"
#include "Poco/DeflatingStream.h"
#line 7 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
#include "../gettext.h"
#include "Poco/Net/HTTPCookie.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Logger.h"
#include "../SingletonManager/SessionManager.h"
#include "../SingletonManager/LanguageManager.h"
#include "../SingletonManager/ErrorManager.h"
#line 1 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
#include "../ServerConfig.h"
LoginPage::LoginPage(Session* arg):
SessionHTTPRequestHandler(arg)
{
}
void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
response.setChunkedTransferEncoding(true);
response.setContentType("text/html");
bool _compressResponse(request.hasToken("Accept-Encoding", "gzip"));
if (_compressResponse) response.set("Content-Encoding", "gzip");
Poco::Net::HTMLForm form(request, request.stream());
#line 18 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
const char* pageName = "Login";
auto sm = SessionManager::getInstance();
auto lm = LanguageManager::getInstance();
auto em = ErrorManager::getInstance();
auto lang = chooseLanguage(request);
//printf("choose language return: %d\n", lang);
auto langCatalog = lm->getFreeCatalog(lang);
std::string presetEmail("");
if(mSession && mSession->getUser()) {
presetEmail = mSession->getUser()->getEmail();
}
if(!form.empty()) {
bool langUpdatedByBtn = false;
auto langBtn = form.get("lang", "");
if(langBtn != "") {
langUpdatedByBtn = true;
}
/*
auto langInput = form.get("lang", "");
auto updatedLang = LANG_NULL;
if(langBtn != "") {
updatedLang = chooseLanguage(request, langBtn);
langUpdatedByBtn = true;
} else if(langInput != "") {
updatedLang = chooseLanguage(request, langInput);
}
if(updatedLang != LANG_NULL && updatedLang != lang) {
lang = updatedLang;
langCatalog = lm->getFreeCatalog(lang);
}
*/
auto email = form.get("login-email", "");
auto password = form.get("login-password", "");
if(email != "" && password != "") {
//auto session = sm->getSession(request);
//if(!mSession) mSession = sm->findByEmail(email);
if(!mSession) {
mSession = sm->getNewSession();
mSession->setLanguageCatalog(langCatalog);
// get language
// first check url, second check language header
// for debugging client ip
auto client_host = request.clientAddress().host();
//auto client_ip = request.clientAddress();
// X-Real-IP forwarded ip from nginx config
auto client_host_string = request.get("X-Real-IP", client_host.toString());
std::string clientIpString = "client ip: ";
client_host = Poco::Net::IPAddress(client_host_string);
clientIpString += client_host_string;
Poco::Logger::get("requestLog").information(clientIpString);
// debugging end
mSession->setClientIp(client_host);
response.addCookie(mSession->getLoginCookie());
} else {
langCatalog = mSession->getLanguageCatalog();
}
UserStates user_state;
try {
user_state = mSession->loadUser(email, password);
} catch (Poco::Exception& ex) {
addError(new ParamError("login", "exception by calling loadUser: ", ex.displayText()));
sendErrorsAsEmail();
addError(new Error("Error", "Intern Server error, please try again later"));
}
auto user = mSession->getNewUser();
if(user_state >= USER_LOADED_FROM_DB && !user.isNull() && !user->getModel()->getPublicKey()) {
if(mSession->generateKeys(true, true)) {
user_state = USER_COMPLETE;
if(user->getModel()->isDisabled()) {
user_state = USER_DISABLED;
}
}
} else {
//printf("pubkey exist: %p\n",user->getModel()->getPublicKey());
}
getErrors(mSession);
auto uri_start = request.serverParams().getServerName();
auto lastExternReferer = mSession->getLastReferer();
printf("user_state: %d\n", user_state);
switch(user_state) {
case USER_EMPTY:
case USER_PASSWORD_INCORRECT:
addError(new Error(langCatalog->gettext("Login"), langCatalog->gettext("E-Mail or password isn't right, please try again!")), false);
if(mSession) {
getErrors(mSession);
sm->releaseSession(mSession);
}
sm->deleteLoginCookies(request, response);
break;
case USER_PASSWORD_ENCRYPTION_IN_PROCESS:
addError(new Error(langCatalog->gettext("Passwort"), langCatalog->gettext("Passwort wird noch berechnet, bitte versuche es in etwa 1 Minute erneut.")), false);
break;
case USER_KEYS_DONT_MATCH:
addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Error in saved data, the server admin will look at it.")));
break;
case USER_DISABLED:
addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Benutzer ist deaktiviert, kein Login möglich!")));
if(mSession) {
getErrors(mSession);
sm->releaseSession(mSession);
}
sm->deleteLoginCookies(request, response);
break;
case USER_NO_PRIVATE_KEY:
case USER_COMPLETE:
case USER_EMAIL_NOT_ACTIVATED:
auto referer = request.find("Referer");
std::string refererString;
if (referer != request.end()) {
refererString = referer->second;
}
if(lastExternReferer != "") {
//printf("redirect to: %s\n", lastExternReferer.data());
response.redirect(lastExternReferer);
} else if(refererString != "" &&
refererString.find("login") == std::string::npos &&
refererString.find("logout") == std::string::npos &&
refererString.find("user_delete") == std::string::npos &&
refererString != ServerConfig::g_serverPath + request.getURI()) {
std::string uri = request.getURI();
printf("request uri: %s, redirect to: %s\n", uri.data(), refererString.data());
response.redirect(refererString);
} else {
//printf("redirect to: %s\n", ServerConfig::g_php_serverPath.data());
response.redirect(ServerConfig::g_php_serverPath + "/");
}
return;
}
} else if(!langUpdatedByBtn) {
addError(new Error(langCatalog->gettext("Login"), langCatalog->gettext("Username and password are needed!")), false);
}
} else {
// on enter login page with empty form
//auto session = sm->getSession(request);
// remove old cookies and session if exist
if(mSession) {
getErrors(mSession);
sm->releaseSession(mSession);
}
sm->deleteLoginCookies(request, response);
}
#line 3 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
bool withMaterialIcons = false;
std::ostream& _responseStream = response.send();
Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1);
std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream;
responseStream << "\n";
// begin include header.cpsp
responseStream << "\n";
responseStream << "<!DOCTYPE html>\n";
responseStream << "<html>\n";
responseStream << "<head>\n";
responseStream << "<meta charset=\"UTF-8\">\n";
responseStream << "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n";
responseStream << "<title>Gradido Login Server: ";
#line 11 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( pageName );
responseStream << "</title>\n";
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"";
#line 12 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "css/main.css\">\n";
#line 13 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
if(withMaterialIcons) { responseStream << "\n";
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"";
#line 14 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "css/materialdesignicons.min.css\">\n";
#line 15 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
} responseStream << "\n";
responseStream << "</head>\n";
responseStream << "<body>\n";
responseStream << " <div class=\"layout\">\n";
responseStream << " <div class=\"center-form-single\">\n";
responseStream << " <div class=\"center-form-header\">\n";
responseStream << " <a href=\"";
#line 21 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "\" class=\"center-logo\">\n";
responseStream << " <picture>\n";
responseStream << " <source srcset=\"";
#line 23 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.webp\" type=\"image/webp\">\n";
responseStream << " <source srcset=\"";
#line 24 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.png\" type=\"image/png\">\n";
responseStream << " <img src=\"";
#line 25 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.png\" alt=\"logo\" />\n";
responseStream << " </picture>\n";
responseStream << " </a>\n";
responseStream << " </div>";
// end include header.cpsp
responseStream << "\n";
#line 175 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( getErrorsHtml() );
responseStream << "\n";
responseStream << "<!--<input type=\"hidden\" name=\"lang\" value=\"";
#line 176 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( LanguageManager::keyForLanguage(lang) );
responseStream << "\">-->\n";
responseStream << "<div class=\"center-form-container\">\n";
responseStream << " ";
// begin include flags.cpsp
responseStream << "<div class=\"center-form-selectors\">\n";
responseStream << "<form method=\"GET\" action=\"\">\n";
responseStream << "\t<button id=\"flag-england\" name=\"lang\" value=\"en\" title=\"English\" type=\"submit\" ";
#line 3 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
if(lang != LANG_EN) { responseStream << "class=\"flag-btn\"";
#line 3 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
}
else { responseStream << "class=\"flag-btn\" disabled";
#line 4 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
} responseStream << ">\n";
responseStream << "\t <span class=\"flag flag-england\"></span>\n";
responseStream << "\t</button>\n";
responseStream << "\t<button id=\"flag-germany\" name=\"lang\" value=\"de\" title=\"Deutsch\" type=\"submit\" ";
#line 7 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
if(lang != LANG_DE) { responseStream << "class=\"flag-btn\"";
#line 7 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
}
else { responseStream << "class=\"flag-btn\" disabled";
#line 8 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
} responseStream << ">\n";
responseStream << "\t <span class=\"flag flag-germany\"></span>\n";
responseStream << "\t</button>\n";
responseStream << "</form>\n";
responseStream << "</div>";
// end include flags.cpsp
responseStream << "\n";
responseStream << " <div class=\"center-form-form\">\n";
responseStream << "\t\t<form action=\"";
#line 180 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/\" method=\"POST\">\n";
responseStream << "\t\t\t<input class=\"form-control\" type=\"text\" name=\"login-email\" placeholder=\"";
#line 181 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("E-Mail") );
responseStream << "\" value=\"";
#line 181 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( presetEmail );
responseStream << "\"/>\n";
responseStream << "\t\t\t<input class=\"form-control\" type=\"password\" name=\"login-password\" placeholder=\"";
#line 182 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("Password") );
responseStream << "\" />\n";
responseStream << "\t\t <button type=\"submit\" name=\"submit\" class=\"center-form-submit form-button\">";
#line 183 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext(" Login ") );
responseStream << "</button>\n";
responseStream << "\t\t</form>\n";
responseStream << " </div>\n";
responseStream << " <div class=\"center-form-bottom\">\n";
responseStream << " <div class=\"signup-link\">\n";
responseStream << "\t <p>";
#line 188 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("You haven't any account yet? Please follow the link to create one.") );
responseStream << "</p>\n";
responseStream << "\t <a href=\"https://elopage.com/s/gradido/registration-de/payment?locale=de\">\n";
responseStream << "\t\t\t";
#line 190 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("Create New Account") );
responseStream << "\n";
responseStream << "\t\t </a>\n";
responseStream << "\t </div>\n";
responseStream << "\t\t<div class=\"reset-pwd-link\">\n";
responseStream << "\t\t\t<a href=\"";
#line 194 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/resetPassword\">";
#line 194 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("Passwort vergessen") );
responseStream << "</a>\n";
responseStream << "\t\t</div>\n";
responseStream << "\t</div>\n";
responseStream << "</div>\n";
responseStream << "<p>&nbsp;</p>\n";
responseStream << "<div class=\"container\">\n";
responseStream << "\t<a href=\"https://docs.google.com/document/d/1jZp-DiiMPI9ZPNXmjsvOQ1BtnfDFfx8BX7CDmA8KKjY/edit?usp=sharing\" target=\"_blank\">Zum Whitepaper</a>\n";
responseStream << "\t<br>\n";
responseStream << "\t<br>\n";
responseStream << "\t<a href=\"https://docs.google.com/document/d/1kcX1guOi6tDgnFHD9tf7fB_MneKTx-0nHJxzdN8ygNs/edit?usp=sharing\" target=\"_blank\">To the Whitepaper</a>\n";
responseStream << "</div>\n";
// begin include footer.cpsp
responseStream << " <div class=\"center-bottom\">\n";
responseStream << " <p>Copyright © Gradido 2020</p>\n";
responseStream << " </div>\n";
responseStream << " </div>\n";
responseStream << " <div class=\"bottomleft\">\n";
responseStream << " ";
#line 6 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\footer.cpsp"
responseStream << ( mTimeProfiler.string() );
responseStream << "\n";
responseStream << " </div>\n";
responseStream << " <div class=\"bottomright\">\n";
responseStream << " <p>Login Server in Entwicklung</p>\n";
responseStream << " <p>Alpha ";
#line 10 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\footer.cpsp"
responseStream << ( ServerConfig::g_versionString );
responseStream << "</p>\n";
responseStream << " </div>\n";
responseStream << " </div>\n";
responseStream << "</body>\n";
responseStream << "\n";
responseStream << "</html>";
// end include footer.cpsp
if (_compressResponse) _gzipStream.close();
}
#include "LoginPage.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTMLForm.h"
#include "Poco/DeflatingStream.h"
#line 7 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
#include "../gettext.h"
#include "Poco/Net/HTTPCookie.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Logger.h"
#include "../SingletonManager/SessionManager.h"
#include "../SingletonManager/LanguageManager.h"
#include "../SingletonManager/ErrorManager.h"
#line 1 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
#include "../ServerConfig.h"
LoginPage::LoginPage(Session* arg):
SessionHTTPRequestHandler(arg)
{
}
void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
response.setChunkedTransferEncoding(true);
response.setContentType("text/html");
bool _compressResponse(request.hasToken("Accept-Encoding", "gzip"));
if (_compressResponse) response.set("Content-Encoding", "gzip");
Poco::Net::HTMLForm form(request, request.stream());
#line 18 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
const char* pageName = "Login";
auto sm = SessionManager::getInstance();
auto lm = LanguageManager::getInstance();
auto em = ErrorManager::getInstance();
auto lang = chooseLanguage(request);
//printf("choose language return: %d\n", lang);
auto langCatalog = lm->getFreeCatalog(lang);
std::string presetEmail("");
if(mSession && mSession->getUser()) {
presetEmail = mSession->getUser()->getEmail();
}
if(!form.empty()) {
bool langUpdatedByBtn = false;
auto langBtn = form.get("lang", "");
if(langBtn != "") {
langUpdatedByBtn = true;
}
/*
auto langInput = form.get("lang", "");
auto updatedLang = LANG_NULL;
if(langBtn != "") {
updatedLang = chooseLanguage(request, langBtn);
langUpdatedByBtn = true;
} else if(langInput != "") {
updatedLang = chooseLanguage(request, langInput);
}
if(updatedLang != LANG_NULL && updatedLang != lang) {
lang = updatedLang;
langCatalog = lm->getFreeCatalog(lang);
}
*/
auto email = form.get("login-email", "");
auto password = form.get("login-password", "");
if(email != "" && password != "") {
//auto session = sm->getSession(request);
//if(!mSession) mSession = sm->findByEmail(email);
if(!mSession) {
mSession = sm->getNewSession();
mSession->setLanguageCatalog(langCatalog);
// get language
// first check url, second check language header
// for debugging client ip
auto client_host = request.clientAddress().host();
//auto client_ip = request.clientAddress();
// X-Real-IP forwarded ip from nginx config
auto client_host_string = request.get("X-Real-IP", client_host.toString());
std::string clientIpString = "client ip: ";
client_host = Poco::Net::IPAddress(client_host_string);
clientIpString += client_host_string;
Poco::Logger::get("requestLog").information(clientIpString);
// debugging end
mSession->setClientIp(client_host);
response.addCookie(mSession->getLoginCookie());
} else {
langCatalog = mSession->getLanguageCatalog();
}
UserStates user_state;
try {
user_state = mSession->loadUser(email, password);
} catch (Poco::Exception& ex) {
addError(new ParamError("login", "exception by calling loadUser: ", ex.displayText()));
sendErrorsAsEmail();
addError(new Error("Error", "Intern Server error, please try again later"));
}
auto user = mSession->getNewUser();
if(user_state >= USER_LOADED_FROM_DB && !user.isNull() && !user->getModel()->getPublicKey()) {
if(mSession->generateKeys(true, true)) {
user_state = USER_COMPLETE;
if(user->getModel()->isDisabled()) {
user_state = USER_DISABLED;
}
}
} else {
//printf("pubkey exist: %p\n",user->getModel()->getPublicKey());
}
getErrors(mSession);
auto uri_start = request.serverParams().getServerName();
auto lastExternReferer = mSession->getLastReferer();
printf("user_state: %d\n", user_state);
switch(user_state) {
case USER_EMPTY:
case USER_PASSWORD_INCORRECT:
addError(new Error(langCatalog->gettext("Login"), langCatalog->gettext("E-Mail or password isn't right, please try again!")), false);
if(mSession) {
getErrors(mSession);
sm->releaseSession(mSession);
}
sm->deleteLoginCookies(request, response);
break;
case USER_PASSWORD_ENCRYPTION_IN_PROCESS:
addError(new Error(langCatalog->gettext("Passwort"), langCatalog->gettext("Passwort wird noch berechnet, bitte versuche es in etwa 1 Minute erneut.")), false);
break;
case USER_KEYS_DONT_MATCH:
addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Error in saved data, the server admin will look at it.")));
break;
case USER_DISABLED:
addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Benutzer ist deaktiviert, kein Login möglich!")));
if(mSession) {
getErrors(mSession);
sm->releaseSession(mSession);
}
sm->deleteLoginCookies(request, response);
break;
case USER_NO_PRIVATE_KEY:
case USER_COMPLETE:
case USER_EMAIL_NOT_ACTIVATED:
auto referer = request.find("Referer");
std::string refererString;
if (referer != request.end()) {
refererString = referer->second;
}
if(lastExternReferer != "") {
//printf("redirect to: %s\n", lastExternReferer.data());
response.redirect(lastExternReferer);
} else if(refererString != "" &&
refererString.find("login") == std::string::npos &&
refererString.find("logout") == std::string::npos &&
refererString.find("user_delete") == std::string::npos &&
refererString != ServerConfig::g_serverPath + request.getURI()) {
std::string uri = request.getURI();
printf("request uri: %s, redirect to: %s\n", uri.data(), refererString.data());
response.redirect(refererString);
} else {
//printf("redirect to: %s\n", ServerConfig::g_php_serverPath.data());
response.redirect(ServerConfig::g_php_serverPath + "/");
}
return;
}
} else if(!langUpdatedByBtn) {
addError(new Error(langCatalog->gettext("Login"), langCatalog->gettext("Username and password are needed!")), false);
}
} else {
// on enter login page with empty form
//auto session = sm->getSession(request);
// remove old cookies and session if exist
if(mSession) {
getErrors(mSession);
sm->releaseSession(mSession);
}
sm->deleteLoginCookies(request, response);
}
#line 3 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
bool withMaterialIcons = false;
std::ostream& _responseStream = response.send();
Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1);
std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream;
responseStream << "\n";
// begin include header.cpsp
responseStream << "\n";
responseStream << "<!DOCTYPE html>\n";
responseStream << "<html>\n";
responseStream << "<head>\n";
responseStream << "<meta charset=\"UTF-8\">\n";
responseStream << "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n";
responseStream << "<title>Gradido Login Server: ";
#line 11 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( pageName );
responseStream << "</title>\n";
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"";
#line 12 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "css/main.css\">\n";
#line 13 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
if(withMaterialIcons) { responseStream << "\n";
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"";
#line 14 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "css/materialdesignicons.min.css\">\n";
#line 15 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
} responseStream << "\n";
responseStream << "</head>\n";
responseStream << "<body>\n";
responseStream << " <div class=\"layout\">\n";
responseStream << " <div class=\"center-form-single\">\n";
responseStream << " <div class=\"center-form-header\">\n";
responseStream << " <a href=\"";
#line 21 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "\" class=\"center-logo\">\n";
responseStream << " <picture>\n";
responseStream << " <source srcset=\"";
#line 23 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.webp\" type=\"image/webp\">\n";
responseStream << " <source srcset=\"";
#line 24 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.png\" type=\"image/png\">\n";
responseStream << " <img src=\"";
#line 25 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.png\" alt=\"logo\" />\n";
responseStream << " </picture>\n";
responseStream << " </a>\n";
responseStream << " </div>";
// end include header.cpsp
responseStream << "\n";
#line 175 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( getErrorsHtml() );
responseStream << "\n";
responseStream << "<!--<input type=\"hidden\" name=\"lang\" value=\"";
#line 176 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( LanguageManager::keyForLanguage(lang) );
responseStream << "\">-->\n";
responseStream << "<div class=\"center-form-container\">\n";
responseStream << " ";
// begin include flags.cpsp
responseStream << "<div class=\"center-form-selectors\">\n";
responseStream << "<form method=\"GET\" action=\"\">\n";
responseStream << "\t<button id=\"flag-england\" name=\"lang\" value=\"en\" title=\"English\" type=\"submit\" ";
#line 3 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
if(lang != LANG_EN) { responseStream << "class=\"flag-btn\"";
#line 3 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
}
else { responseStream << "class=\"flag-btn\" disabled";
#line 4 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
} responseStream << ">\n";
responseStream << "\t <span class=\"flag flag-england\"></span>\n";
responseStream << "\t</button>\n";
responseStream << "\t<button id=\"flag-germany\" name=\"lang\" value=\"de\" title=\"Deutsch\" type=\"submit\" ";
#line 7 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
if(lang != LANG_DE) { responseStream << "class=\"flag-btn\"";
#line 7 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
}
else { responseStream << "class=\"flag-btn\" disabled";
#line 8 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\flags.cpsp"
} responseStream << ">\n";
responseStream << "\t <span class=\"flag flag-germany\"></span>\n";
responseStream << "\t</button>\n";
responseStream << "</form>\n";
responseStream << "</div>";
// end include flags.cpsp
responseStream << "\n";
responseStream << " <div class=\"center-form-form\">\n";
responseStream << "\t\t<form action=\"";
#line 180 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/\" method=\"POST\">\n";
responseStream << "\t\t\t<input class=\"form-control\" type=\"text\" name=\"login-email\" placeholder=\"";
#line 181 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("E-Mail") );
responseStream << "\" value=\"";
#line 181 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( presetEmail );
responseStream << "\"/>\n";
responseStream << "\t\t\t<input class=\"form-control\" type=\"password\" name=\"login-password\" placeholder=\"";
#line 182 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("Password") );
responseStream << "\" />\n";
responseStream << "\t\t <button type=\"submit\" name=\"submit\" class=\"center-form-submit form-button\">";
#line 183 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext(" Login ") );
responseStream << "</button>\n";
responseStream << "\t\t</form>\n";
responseStream << " </div>\n";
responseStream << " <div class=\"center-form-bottom\">\n";
responseStream << " <div class=\"signup-link\">\n";
responseStream << "\t <p>";
#line 188 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("You haven't any account yet? Please follow the link to create one.") );
responseStream << "</p>\n";
responseStream << "\t <a href=\"https://elopage.com/s/gradido/registration-de/payment?locale=de\">\n";
responseStream << "\t\t\t";
#line 190 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("Create New Account") );
responseStream << "\n";
responseStream << "\t\t </a>\n";
responseStream << "\t </div>\n";
responseStream << "\t\t<div class=\"reset-pwd-link\">\n";
responseStream << "\t\t\t<a href=\"";
#line 194 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/resetPassword\">";
#line 194 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("Passwort vergessen") );
responseStream << "</a>\n";
responseStream << "\t\t</div>\n";
responseStream << "\t</div>\n";
responseStream << "</div>\n";
responseStream << "<p>&nbsp;</p>\n";
responseStream << "<div class=\"container\">\n";
responseStream << "\t<a href=\"https://docs.google.com/document/d/1jZp-DiiMPI9ZPNXmjsvOQ1BtnfDFfx8BX7CDmA8KKjY/edit?usp=sharing\" target=\"_blank\">Zum Whitepaper</a>\n";
responseStream << "\t<br>\n";
responseStream << "\t<br>\n";
responseStream << "\t<a href=\"https://docs.google.com/document/d/1kcX1guOi6tDgnFHD9tf7fB_MneKTx-0nHJxzdN8ygNs/edit?usp=sharing\" target=\"_blank\">To the Whitepaper</a>\n";
responseStream << "</div>\n";
// begin include footer.cpsp
responseStream << " <div class=\"center-bottom\">\n";
responseStream << " <p>Copyright © Gradido 2020</p>\n";
responseStream << " </div>\n";
responseStream << " </div>\n";
responseStream << " <div class=\"bottomleft\">\n";
responseStream << " ";
#line 6 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\footer.cpsp"
responseStream << ( mTimeProfiler.string() );
responseStream << "\n";
responseStream << " </div>\n";
responseStream << " <div class=\"bottomright\">\n";
responseStream << " <p>Login Server in Entwicklung</p>\n";
responseStream << " <p>Alpha ";
#line 10 "F:\\Gradido\\gradido_local\\login_server\\src\\cpsp\\footer.cpsp"
responseStream << ( ServerConfig::g_versionString );
responseStream << "</p>\n";
responseStream << " </div>\n";
responseStream << " </div>\n";
responseStream << "</body>\n";
responseStream << "\n";
responseStream << "</html>";
// end include footer.cpsp
if (_compressResponse) _gzipStream.close();
}

View File

@ -1,20 +1,20 @@
#ifndef LoginPage_INCLUDED
#define LoginPage_INCLUDED
#include "Poco/Net/HTTPRequestHandler.h"
#include "SessionHTTPRequestHandler.h"
class LoginPage: public SessionHTTPRequestHandler
{
public:
LoginPage(Session*);
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);
};
#endif // LoginPage_INCLUDED
#ifndef LoginPage_INCLUDED
#define LoginPage_INCLUDED
#include "Poco/Net/HTTPRequestHandler.h"
#include "SessionHTTPRequestHandler.h"
class LoginPage: public SessionHTTPRequestHandler
{
public:
LoginPage(Session*);
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);
};
#endif // LoginPage_INCLUDED

View File

@ -1,108 +1,108 @@
#include "JsonCreateUser.h"
#include "../model/email/Email.h"
#include "../controller/User.h"
#include "../controller/EmailVerificationCode.h"
#include "../SingletonManager/EmailManager.h"
#include "../SingletonManager/SessionManager.h"
#include "../tasks/AuthenticatedEncryptionCreateKeyTask.h"
Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params)
{
std::string email;
std::string first_name;
std::string last_name;
std::string password;
bool login_after_register = false;
int emailType;
auto em = EmailManager::getInstance();
auto sm = SessionManager::getInstance();
// if is json object
if (params.type() == typeid(Poco::JSON::Object::Ptr)) {
Poco::JSON::Object::Ptr paramJsonObject = params.extract<Poco::JSON::Object::Ptr>();
/// Throws a RangeException if the value does not fit
/// into the result variable.
/// Throws a NotImplementedException if conversion is
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
try {
paramJsonObject->get("email").convert(email);
paramJsonObject->get("first_name").convert(first_name);
paramJsonObject->get("last_name").convert(last_name);
paramJsonObject->get("emailType").convert(emailType);
if ((ServerConfig::g_AllowUnsecureFlags & ServerConfig::UNSECURE_PASSWORD_REQUESTS)) {
paramJsonObject->get("password").convert(password);
}
if (!paramJsonObject->isNull("login_after_register")) {
paramJsonObject->get("login_after_register").convert(login_after_register);
}
}
catch (Poco::Exception& ex) {
return stateError("json exception", ex.displayText());
}
}
else {
return stateError("parameter format unknown");
}
auto user = controller::User::create();
if (user->load(email) > 0) {
return customStateError("exist", "user already exist");
}
if (password.size()) {
ErrorList errors;
if (!sm->checkPwdValidation(password, &errors)) {
Poco::JSON::Object* result = new Poco::JSON::Object;
result->set("state", "error");
result->set("msg", errors.getLastError()->getString(false));
if (errors.errorCount()) {
result->set("details", errors.getLastError()->getString(false));
}
return result;
}
}
// create user
user = controller::User::create(email, first_name, last_name);
auto userModel = user->getModel();
Session* session = nullptr;
if (!userModel->insertIntoDB(true)) {
userModel->sendErrorsAsEmail();
return stateError("insert user failed");
}
if (password.size()) {
session = sm->getNewSession();
session->setUser(user);
session->generateKeys(true, true);
session->setClientIp(mClientIP);
// calculate encryption key, could need some time, will save encrypted privkey to db
UniLib::controller::TaskPtr create_authenticated_encrypten_key = new AuthenticatedEncryptionCreateKeyTask(user, password);
create_authenticated_encrypten_key->scheduleTask(create_authenticated_encrypten_key);
}
auto emailOptIn = controller::EmailVerificationCode::create(userModel->getID(), model::table::EMAIL_OPT_IN_REGISTER);
auto emailOptInModel = emailOptIn->getModel();
if (!emailOptInModel->insertIntoDB(false)) {
emailOptInModel->sendErrorsAsEmail();
return stateError("insert emailOptIn failed");
}
em->addEmail(new model::Email(emailOptIn, user, model::Email::convertTypeFromInt(emailType)));
if (login_after_register && session) {
Poco::JSON::Object* result = stateSuccess();
result->set("session_id", session->getHandle());
return result;
}
return stateSuccess();
#include "JsonCreateUser.h"
#include "../model/email/Email.h"
#include "../controller/User.h"
#include "../controller/EmailVerificationCode.h"
#include "../SingletonManager/EmailManager.h"
#include "../SingletonManager/SessionManager.h"
#include "../tasks/AuthenticatedEncryptionCreateKeyTask.h"
Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params)
{
std::string email;
std::string first_name;
std::string last_name;
std::string password;
bool login_after_register = false;
int emailType;
auto em = EmailManager::getInstance();
auto sm = SessionManager::getInstance();
// if is json object
if (params.type() == typeid(Poco::JSON::Object::Ptr)) {
Poco::JSON::Object::Ptr paramJsonObject = params.extract<Poco::JSON::Object::Ptr>();
/// Throws a RangeException if the value does not fit
/// into the result variable.
/// Throws a NotImplementedException if conversion is
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
try {
paramJsonObject->get("email").convert(email);
paramJsonObject->get("first_name").convert(first_name);
paramJsonObject->get("last_name").convert(last_name);
paramJsonObject->get("emailType").convert(emailType);
if ((ServerConfig::g_AllowUnsecureFlags & ServerConfig::UNSECURE_PASSWORD_REQUESTS)) {
paramJsonObject->get("password").convert(password);
}
if (!paramJsonObject->isNull("login_after_register")) {
paramJsonObject->get("login_after_register").convert(login_after_register);
}
}
catch (Poco::Exception& ex) {
return stateError("json exception", ex.displayText());
}
}
else {
return stateError("parameter format unknown");
}
auto user = controller::User::create();
if (user->load(email) > 0) {
return customStateError("exist", "user already exist");
}
if (password.size()) {
ErrorList errors;
if (!sm->checkPwdValidation(password, &errors)) {
Poco::JSON::Object* result = new Poco::JSON::Object;
result->set("state", "error");
result->set("msg", errors.getLastError()->getString(false));
if (errors.errorCount()) {
result->set("details", errors.getLastError()->getString(false));
}
return result;
}
}
// create user
user = controller::User::create(email, first_name, last_name);
auto userModel = user->getModel();
Session* session = nullptr;
if (!userModel->insertIntoDB(true)) {
userModel->sendErrorsAsEmail();
return stateError("insert user failed");
}
if (password.size()) {
session = sm->getNewSession();
session->setUser(user);
session->generateKeys(true, true);
session->setClientIp(mClientIP);
// calculate encryption key, could need some time, will save encrypted privkey to db
UniLib::controller::TaskPtr create_authenticated_encrypten_key = new AuthenticatedEncryptionCreateKeyTask(user, password);
create_authenticated_encrypten_key->scheduleTask(create_authenticated_encrypten_key);
}
auto emailOptIn = controller::EmailVerificationCode::create(userModel->getID(), model::table::EMAIL_OPT_IN_REGISTER);
auto emailOptInModel = emailOptIn->getModel();
if (!emailOptInModel->insertIntoDB(false)) {
emailOptInModel->sendErrorsAsEmail();
return stateError("insert emailOptIn failed");
}
em->addEmail(new model::Email(emailOptIn, user, model::Email::convertTypeFromInt(emailType)));
if (login_after_register && session) {
Poco::JSON::Object* result = stateSuccess();
result->set("session_id", session->getHandle());
return result;
}
return stateSuccess();
}

View File

@ -1,144 +1,144 @@
#include "JsonGetUserInfos.h"
#include "../lib/DataTypeConverter.h"
#include "../SingletonManager/SessionManager.h"
#include "../controller/User.h"
#include "../controller/EmailVerificationCode.h"
#include "../ServerConfig.h"
Poco::UInt64 JsonGetUserInfos::readOrCreateEmailVerificationCode(int user_id, model::table::EmailOptInType type)
{
try {
auto emailVerificationCode = controller::EmailVerificationCode::load(user_id, type);
if (!emailVerificationCode) {
emailVerificationCode = controller::EmailVerificationCode::create(user_id, type);
UniLib::controller::TaskPtr insert = new model::table::ModelInsertTask(emailVerificationCode->getModel(), false);
insert->scheduleTask(insert);
}
return emailVerificationCode->getModel()->getCode();
}
catch (Poco::Exception& ex) {
ErrorList errors;
//printf("exception: %s\n", ex.displayText().data());
errors.addError(new ParamError("JsonGetUserInfos::readOrCreateEmailVerificationCode", "exception: ", ex.displayText()));
errors.sendErrorsAsEmail();
}
return 0;
}
Poco::JSON::Object* JsonGetUserInfos::handle(Poco::Dynamic::Var params)
{
/*
'session_id' => $session_id,
'email' => $email,
'ask' => ['EmailOptIn.Register']
*/
// incoming
int session_id = 0;
std::string email;
Poco::JSON::Array::Ptr askArray;
auto sm = SessionManager::getInstance();
// if is json object
if (params.type() == typeid(Poco::JSON::Object::Ptr)) {
Poco::JSON::Object::Ptr paramJsonObject = params.extract<Poco::JSON::Object::Ptr>();
/// Throws a RangeException if the value does not fit
/// into the result variable.
/// Throws a NotImplementedException if conversion is
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
try {
paramJsonObject->get("email").convert(email);
paramJsonObject->get("session_id").convert(session_id);
askArray = paramJsonObject->getArray("ask");
}
catch (Poco::Exception& ex) {
return stateError("json exception", ex.displayText());
}
}
else {
return stateError("parameter format unknown");
}
if (!session_id) {
return stateError("session_id invalid");
}
if (askArray.isNull()) {
return stateError("ask is zero or not an array");
}
auto session = sm->getSession(session_id);
if (!session) {
return customStateError("not found", "session not found");
}
auto session_user = session->getNewUser();
auto session_user_model = session_user->getModel();
bool isAdmin = false;
bool emailBelongToUser = false;
if (model::table::ROLE_ADMIN == session_user_model->getRole()) {
isAdmin = true;
}
if (session_user_model->getEmail() == email) {
emailBelongToUser = true;
}
auto user = controller::User::create();
if (1 != user->load(email)) {
return customStateError("not found", "user not found");
}
auto user_model = user->getModel();
Poco::JSON::Object* result = new Poco::JSON::Object;
result->set("state", "success");
Poco::JSON::Array jsonErrorsArray;
Poco::JSON::Object jsonUser;
Poco::JSON::Object jsonServer;
for (auto it = askArray->begin(); it != askArray->end(); it++) {
auto parameter = *it;
std::string parameterString;
try {
parameter.convert(parameterString);
if (parameterString == "EmailVerificationCode.Register" && isAdmin && !emailBelongToUser) {
auto code = readOrCreateEmailVerificationCode(user_model->getID(), model::table::EMAIL_OPT_IN_REGISTER_DIRECT);
if (code) {
jsonUser.set("EmailVerificationCode.Register", std::to_string(code));
}
}
else if (parameterString == "loginServer.path") {
jsonServer.set("loginServer.path", ServerConfig::g_serverPath);
}
else if (parameterString == "user.pubkeyhex") {
jsonUser.set("pubkeyhex", user_model->getPublicKeyHex());
}
else if (parameterString == "user.first_name") {
jsonUser.set("first_name", user_model->getFirstName());
}
else if (parameterString == "user.last_name") {
jsonUser.set("last_name", user_model->getLastName());
}
else if (parameterString == "user.disabled") {
jsonUser.set("disabled", user_model->isDisabled());
}
else if (parameterString == "user.email_checked" && (isAdmin || emailBelongToUser)) {
jsonUser.set("email_checked", user_model->isEmailChecked());
}
else if (parameterString == "user.identHash") {
auto email = user_model->getEmail();
jsonUser.set("identHash", DRMakeStringHash(email.data(), email.size()));
}
}
catch (Poco::Exception& ex) {
jsonErrorsArray.add("ask parameter invalid");
}
}
result->set("errors", jsonErrorsArray);
result->set("userData", jsonUser);
result->set("server", jsonServer);
return result;
#include "JsonGetUserInfos.h"
#include "../lib/DataTypeConverter.h"
#include "../SingletonManager/SessionManager.h"
#include "../controller/User.h"
#include "../controller/EmailVerificationCode.h"
#include "../ServerConfig.h"
Poco::UInt64 JsonGetUserInfos::readOrCreateEmailVerificationCode(int user_id, model::table::EmailOptInType type)
{
try {
auto emailVerificationCode = controller::EmailVerificationCode::load(user_id, type);
if (!emailVerificationCode) {
emailVerificationCode = controller::EmailVerificationCode::create(user_id, type);
UniLib::controller::TaskPtr insert = new model::table::ModelInsertTask(emailVerificationCode->getModel(), false);
insert->scheduleTask(insert);
}
return emailVerificationCode->getModel()->getCode();
}
catch (Poco::Exception& ex) {
ErrorList errors;
//printf("exception: %s\n", ex.displayText().data());
errors.addError(new ParamError("JsonGetUserInfos::readOrCreateEmailVerificationCode", "exception: ", ex.displayText()));
errors.sendErrorsAsEmail();
}
return 0;
}
Poco::JSON::Object* JsonGetUserInfos::handle(Poco::Dynamic::Var params)
{
/*
'session_id' => $session_id,
'email' => $email,
'ask' => ['EmailOptIn.Register']
*/
// incoming
int session_id = 0;
std::string email;
Poco::JSON::Array::Ptr askArray;
auto sm = SessionManager::getInstance();
// if is json object
if (params.type() == typeid(Poco::JSON::Object::Ptr)) {
Poco::JSON::Object::Ptr paramJsonObject = params.extract<Poco::JSON::Object::Ptr>();
/// Throws a RangeException if the value does not fit
/// into the result variable.
/// Throws a NotImplementedException if conversion is
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
try {
paramJsonObject->get("email").convert(email);
paramJsonObject->get("session_id").convert(session_id);
askArray = paramJsonObject->getArray("ask");
}
catch (Poco::Exception& ex) {
return stateError("json exception", ex.displayText());
}
}
else {
return stateError("parameter format unknown");
}
if (!session_id) {
return stateError("session_id invalid");
}
if (askArray.isNull()) {
return stateError("ask is zero or not an array");
}
auto session = sm->getSession(session_id);
if (!session) {
return customStateError("not found", "session not found");
}
auto session_user = session->getNewUser();
auto session_user_model = session_user->getModel();
bool isAdmin = false;
bool emailBelongToUser = false;
if (model::table::ROLE_ADMIN == session_user_model->getRole()) {
isAdmin = true;
}
if (session_user_model->getEmail() == email) {
emailBelongToUser = true;
}
auto user = controller::User::create();
if (1 != user->load(email)) {
return customStateError("not found", "user not found");
}
auto user_model = user->getModel();
Poco::JSON::Object* result = new Poco::JSON::Object;
result->set("state", "success");
Poco::JSON::Array jsonErrorsArray;
Poco::JSON::Object jsonUser;
Poco::JSON::Object jsonServer;
for (auto it = askArray->begin(); it != askArray->end(); it++) {
auto parameter = *it;
std::string parameterString;
try {
parameter.convert(parameterString);
if (parameterString == "EmailVerificationCode.Register" && isAdmin && !emailBelongToUser) {
auto code = readOrCreateEmailVerificationCode(user_model->getID(), model::table::EMAIL_OPT_IN_REGISTER_DIRECT);
if (code) {
jsonUser.set("EmailVerificationCode.Register", std::to_string(code));
}
}
else if (parameterString == "loginServer.path") {
jsonServer.set("loginServer.path", ServerConfig::g_serverPath);
}
else if (parameterString == "user.pubkeyhex") {
jsonUser.set("pubkeyhex", user_model->getPublicKeyHex());
}
else if (parameterString == "user.first_name") {
jsonUser.set("first_name", user_model->getFirstName());
}
else if (parameterString == "user.last_name") {
jsonUser.set("last_name", user_model->getLastName());
}
else if (parameterString == "user.disabled") {
jsonUser.set("disabled", user_model->isDisabled());
}
else if (parameterString == "user.email_checked" && (isAdmin || emailBelongToUser)) {
jsonUser.set("email_checked", user_model->isEmailChecked());
}
else if (parameterString == "user.identHash") {
auto email = user_model->getEmail();
jsonUser.set("identHash", DRMakeStringHash(email.data(), email.size()));
}
}
catch (Poco::Exception& ex) {
jsonErrorsArray.add("ask parameter invalid");
}
}
result->set("errors", jsonErrorsArray);
result->set("userData", jsonUser);
result->set("server", jsonServer);
return result;
}

View File

@ -1,44 +1,44 @@
#include "JsonLogout.h"
#include "../SingletonManager/SessionManager.h"
Poco::JSON::Object* JsonLogout::handle(Poco::Dynamic::Var params)
{
auto sm = SessionManager::getInstance();
int session_id = 0;
// if is json object
if (params.type() == typeid(Poco::JSON::Object::Ptr)) {
Poco::JSON::Object::Ptr paramJsonObject = params.extract<Poco::JSON::Object::Ptr>();
/// Throws a RangeException if the value does not fit
/// into the result variable.
/// Throws a NotImplementedException if conversion is
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
try {
paramJsonObject->get("session_id").convert(session_id);
}
catch (Poco::Exception& ex) {
return stateError("json exception", ex.displayText());
}
}
else {
return stateError("parameter format unknown");
}
auto session = sm->getSession(session_id);
if (!session) {
return stateError("session not found", std::to_string(session_id));
}
if (sm->releaseSession(session_id)) {
return stateSuccess();
}
return stateError("error by releasing session");
#include "JsonLogout.h"
#include "../SingletonManager/SessionManager.h"
Poco::JSON::Object* JsonLogout::handle(Poco::Dynamic::Var params)
{
auto sm = SessionManager::getInstance();
int session_id = 0;
// if is json object
if (params.type() == typeid(Poco::JSON::Object::Ptr)) {
Poco::JSON::Object::Ptr paramJsonObject = params.extract<Poco::JSON::Object::Ptr>();
/// Throws a RangeException if the value does not fit
/// into the result variable.
/// Throws a NotImplementedException if conversion is
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
try {
paramJsonObject->get("session_id").convert(session_id);
}
catch (Poco::Exception& ex) {
return stateError("json exception", ex.displayText());
}
}
else {
return stateError("parameter format unknown");
}
auto session = sm->getSession(session_id);
if (!session) {
return stateError("session not found", std::to_string(session_id));
}
if (sm->releaseSession(session_id)) {
return stateSuccess();
}
return stateError("error by releasing session");
}

View File

@ -1,18 +1,18 @@
#ifndef __JSON_INTERFACE_JSON_LOGOUT_
#define __JSON_INTERFACE_JSON_LOGOUT_
#include "JsonRequestHandler.h"
class JsonLogout : public JsonRequestHandler
{
public:
JsonLogout(Poco::Net::IPAddress ip) : mClientIP(ip) {}
Poco::JSON::Object* handle(Poco::Dynamic::Var params);
protected:
Poco::Net::IPAddress mClientIP;
};
#ifndef __JSON_INTERFACE_JSON_LOGOUT_
#define __JSON_INTERFACE_JSON_LOGOUT_
#include "JsonRequestHandler.h"
class JsonLogout : public JsonRequestHandler
{
public:
JsonLogout(Poco::Net::IPAddress ip) : mClientIP(ip) {}
Poco::JSON::Object* handle(Poco::Dynamic::Var params);
protected:
Poco::Net::IPAddress mClientIP;
};
#endif // __JSON_INTERFACE_JSON_LOGOUT_

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