This commit is contained in:
ogerly 2021-03-31 13:53:49 +02:00
commit c50e4daf36
116 changed files with 8738 additions and 12573 deletions

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

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

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

@ -1,51 +1,56 @@
HTTPServer.port = 1200
JSONServer.port = 1201
Gradido.group_id = 1
crypto.server_admin_public = f909a866baec97c5460b8d7a93b72d3d4d20cc45d9f15d78bd83944eb9286b7f
crypto.server_key = a51ef8ac7ef1abf162fb7a65261acd7a
# TODO auto-generate in docker build step
crypto.app_secret = 21ffbbc616fe
# Server admin Passphrase
# nerve execute merit pool talk hockey basic win cargo spin disagree ethics swear price purchase say clutch decrease slow half forest reform cheese able
#
phpServer.url = http://localhost/
phpServer.host = nginx
loginServer.path = http://localhost/account
loginServer.default_locale = de
loginServer.db.host = mariadb
loginServer.db.name = gradido_login
loginServer.db.user = root
loginServer.db.password =
loginServer.db.port = 3306
email.disable = true
#email.username =
#email.sender =
#email.admin_receiver =
#email.password =
#email.smtp.url =
#email.smtp.port =
# binary is default, for debugging also json is possible
#hedera.consensus.message_format = json
# TESTNET or MAINNET, TESTNET is default
hedera.nettype = TESTNET
# server setup types: test, staging or production
ServerSetupType=test
# Session timeout in minutes
#
session.timeout = 15
# Disabling security features for faster develop and testing
unsecure.allow_passwort_via_json_request = 1
unsecure.allow_auto_sign_transactions = 1
unsecure.allow_cors_all = 1
# default disable, passwords must contain a number, a lower character, a high character, special character, and be at least 8 characters long
unsecure.allow_all_passwords = 1
HTTPServer.port = 1200
JSONServer.port = 1201
Gradido.group_id = 1
crypto.server_admin_public = f909a866baec97c5460b8d7a93b72d3d4d20cc45d9f15d78bd83944eb9286b7f
crypto.server_key = a51ef8ac7ef1abf162fb7a65261acd7a
# TODO auto-generate in docker build step
crypto.app_secret = 21ffbbc616fe
# Server admin Passphrase
# nerve execute merit pool talk hockey basic win cargo spin disagree ethics swear price purchase say clutch decrease slow half forest reform cheese able
#
phpServer.url = http://localhost/
phpServer.host = nginx
loginServer.path = http://localhost/account
loginServer.default_locale = de
loginServer.db.host = mariadb
loginServer.db.name = gradido_login
loginServer.db.user = root
loginServer.db.password =
loginServer.db.port = 3306
frontend.checkEmailPath = http://localhost/account/checkEmail
email.disable = true
#email.username =
#email.sender =
#email.admin_receiver =
#email.password =
#email.smtp.url =
#email.smtp.port =
# binary is default, for debugging also json is possible
#hedera.consensus.message_format = json
# TESTNET or MAINNET, TESTNET is default
hedera.nettype = TESTNET
# server setup types: test, staging or production
ServerSetupType=test
# Session timeout in minutes
#
session.timeout = 15
# Disabling security features for faster develop and testing
unsecure.allow_passwort_via_json_request = 1
unsecure.allow_auto_sign_transactions = 1
unsecure.allow_cors_all = 1
# default disable, passwords must contain a number, a lower character, a high character, special character, and be at least 8 characters long
unsecure.allow_all_passwords = 1

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

@ -1,136 +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
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

@ -98,6 +98,7 @@ Update password can only be used if in Login-Server config:
```ini
unsecure.allow_passwort_via_json_request = 1
```
is set
POST http://localhost/login_api/updateUserInfos
```json
@ -207,16 +208,76 @@ return
- registerDirect: code generated by register for check email
- register: code generated by auto-register via elopage for check email
- info can contain additional info strings
- user hasn't password: if user hasn't set a password yet (for example if he was registered via elopage)
- email already activated: if email was already checked
- "user hasn't password": if user hasn't set a password yet (for example if he was registered via elopage)
- "email already activated": if email was already checked
- session_id: session_id for new session
## Send Emails
Let send Login-Server Password reset E-Mail to User
Can be also used for admin interface to resend email verification code
POST http://localhost/login_api/sendEmail
```json
{"email": "max.musterman@gmail.de", "email_text":7, "email_verification_code_type":"resetPassword" }
```
also valid:
```json
{"email": "max.musterman@gmail.de", "email_text":"user reset Password", "email_verification_code_type":"resetPassword" }
```
or:
```json
{"session_id": -127182, "email": "max.musterman@gmail.de", "email_text":5, "email_verification_code_type":"register" }
```
- session_id: not needed for resetPassword emails
- email_type: choose which email text should be used (number or string can be used)
- "email user verification code" (2): default text used when new user has registered
- "email user verification code resend" (3): text used when user hasn't activated his account 7 days after register
- "email user verification code resend after long time" (4): text used when user hasn't activated his account more than 7 days after register
- "email admin user verification code" (5): used if admin trigger sending the email with email verification code
- "email admin user verification code resend" (6): used if admin trigger sending the email with email verification code again
- "user reset Password" (7): used for reset password email text
- "email custom tex" (8): used if custom email text should be used (than email_custom_text and email_custom_subject must also be filled)
- email_verification_code_type
- resetPassword: for password resets, will be deleted immediately, is a only one use code, can be used without session_id
- registerDirect: code generated by register for check email, can only be used by admins for another user
- register: code generated by auto-register via elopage for check email, can only be used by admins for another user
- email_custom_text (optional): can be used to send email with custom text
placeholder for email text, will be replaced
- [first_name] first name
- [last_name] last name
- [duration] time span since user has created account (ex.: 10 Days) with largest unit, day is last unit
- [link] login-server checkEmail link with email verification code (ex.: http://localhost/account/checkEmail/382738273892983)
- [code] email verification code if you like to use your one link
- email_custom_subject (optional): for custom email the subject
return
```json
{"state":"success"}
```
if everything is okay
return
```json
{"state":"warning", "msg":"email already sended"}
```
if emails was successfully sended but was already sended in past also.
return with "state":"error" and additional "msg" if error occured (no email sended):
- "email already send less than a hour before": User has already get a password reset email and haven't used the link yet
- "not supported email type": with "email_verification_code_type":"resetPassword" only email type 7 or 8 allowed
- "admin needed": only admins can send email verification emails because this emails normally sended out automaticly
- "invalid email": if email wasn't found in db
- "invalid session": if session wasn't found (only checked if session_id is set and != 0)
- "invalid email type": could not parse email type
- "invalid verification code type": could not parse email verification code type
- "json exception": error parsing input json, more infos can be found in details
## Check Running Transactions / password encryption
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"}

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

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

@ -7,12 +7,30 @@ const EMAIL_TYPE = {
ADMIN: 5, // if user was registered by an admin
}
const apiGet = async (url) => {
try {
const result = await axios.get(url)
if (result.status !== 200) {
throw new Error('HTTP Status Error ' + result.status)
}
if (result.data.state !== 'success') {
throw new Error(result.data.msg)
}
return { success: true, result }
} catch (error) {
return { success: false, result: error }
}
}
const apiPost = async (url, payload) => {
try {
const result = await axios.post(url, payload)
if (result.status !== 200) {
throw new Error('HTTP Status Error ' + result.status)
}
if (result.data.state === 'warning') {
return { success: true, result: error }
}
if (result.data.state !== 'success') {
throw new Error(result.data.msg)
}

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

@ -13,23 +13,11 @@ export const store = new Vuex.Store({
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,45 +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,
)
console.log(result)
if (result.success) {
console.log('send success')
} else {
console.log('send error')
}
return 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

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

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

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

@ -8,10 +8,10 @@ ENV DOCKER_WORKDIR="/code"
USER root
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/
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

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

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

View File

@ -139,3 +139,15 @@ Poco::JSON::Object* JsonRequestHandler::customStateError(const char* state, cons
return result;
}
Poco::JSON::Object* JsonRequestHandler::stateWarning(const char* msg, std::string details/* = ""*/)
{
Poco::JSON::Object* result = new Poco::JSON::Object;
result->set("state", "warning");
result->set("msg", msg);
if (details != "") {
result->set("details", details);
}
return result;
}

View File

@ -22,6 +22,7 @@ protected:
static Poco::JSON::Object* stateError(const char* msg, std::string details = "");
static Poco::JSON::Object* customStateError(const char* state, const char* msg, std::string details = "");
static Poco::JSON::Object* stateSuccess();
static Poco::JSON::Object* stateWarning(const char* msg, std::string details = "");
};

View File

@ -1,3 +1,4 @@
#include "JsonRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerRequest.h"
@ -13,10 +14,13 @@
#include "JsonGetRunningUserTasks.h"
#include "JsonGetUsers.h"
#include "JsonLoginViaEmailVerificationCode.h"
#include "JsonLogout.h"
#include "JsonSendEmail.h"
#include "JsonAdminEmailVerificationResend.h"
#include "JsonGetUserInfos.h"
#include "JsonUpdateUserInfos.h"
#include "JsonUnsecureLogin.h"
#include "JsonLogout.h"
JsonRequestHandlerFactory::JsonRequestHandlerFactory()
: mRemoveGETParameters("^/([a-zA-Z0-9_-]*)"), mLogging(Poco::Logger::get("requestLog"))
@ -75,8 +79,12 @@ Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(c
else if (url_first_part == "/loginViaEmailVerificationCode") {
return new JsonLoginViaEmailVerificationCode(client_host);
}
else if (url_first_part == "/sendEmail") {
return new JsonSendEmail;
}
else if (url_first_part == "/logout") {
return new JsonLogout(client_host);
}
return new JsonUnknown;
}

View File

@ -0,0 +1,149 @@
#include "JsonSendEmail.h"
#include "Poco/URI.h"
#include "../SingletonManager/SessionManager.h"
#include "../SingletonManager/EmailManager.h"
#include "../SingletonManager/LanguageManager.h"
#include "../controller/User.h"
#include "../controller/EmailVerificationCode.h"
#include "../lib/DataTypeConverter.h"
Poco::JSON::Object* JsonSendEmail::handle(Poco::Dynamic::Var params)
{
int session_id = 0;
std::string email;
model::EmailType emailType = model::EMAIL_DEFAULT;
model::table::EmailOptInType emailVerificationCodeType;
std::string emailCustomText;
std::string emailCustomSubject;
std::string languageCode;
std::string email_verification_code_type_string;
std::string email_type_string;
int email_type_int = 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 {
if (paramJsonObject->has("session_id")) {
paramJsonObject->get("session_id").convert(session_id);
}
if (paramJsonObject->has("email_custom_text")) {
paramJsonObject->get("email_custom_text").convert(emailCustomText);
}
if (paramJsonObject->has("email_custom_subject")) {
paramJsonObject->get("email_custom_subject").convert(emailCustomSubject);
}
if (paramJsonObject->has("language")) {
paramJsonObject->get("language").convert(languageCode);
}
paramJsonObject->get("email").convert(email);
paramJsonObject->get("email_verification_code_type").convert(email_verification_code_type_string);
auto email_text = paramJsonObject->get("email_text");
if (email_text.isString()) {
email_text.convert(email_type_string);
}
else if (email_text.isInteger()) {
email_text.convert(email_type_int);
}
}
catch (Poco::Exception& ex) {
return stateError("json exception", ex.displayText());
}
}
// convert types into enum
if (email_type_int > 0 && email_type_int < model::EMAIL_MAX) {
emailType = (model::EmailType)email_type_int;
}
else if (email_type_string != "") {
emailType = model::Email::emailType(email_type_string);
}
emailVerificationCodeType = model::table::EmailOptIn::stringToType(email_verification_code_type_string);
if (model::table::EMAIL_OPT_IN_EMPTY == emailVerificationCodeType) {
return stateError("invalid verification code type");
}
switch (emailType) {
case model::EMAIL_DEFAULT:
case model::EMAIL_ERROR:
case model::EMAIL_MAX: return stateError("invalid email type");
}
if (0 == session_id &&
(model::table::EMAIL_OPT_IN_REGISTER == emailVerificationCodeType || model::table::EMAIL_OPT_IN_REGISTER_DIRECT == emailVerificationCodeType)
){
return stateError("login needed");
}
auto sm = SessionManager::getInstance();
auto em = EmailManager::getInstance();
auto lm = LanguageManager::getInstance();
Session* session = nullptr;
if (session_id != 0) {
session = sm->getSession(session_id);
if (nullptr == session) {
return stateError("invalid session");
}
}
auto receiver_user = controller::User::create();
if (1 != receiver_user->load(email)) {
return stateError("invalid email");
}
auto receiver_user_id = receiver_user->getModel()->getID();
if (emailVerificationCodeType == model::table::EMAIL_OPT_IN_RESET_PASSWORD)
{
session = sm->getNewSession();
if (emailType == model::EMAIL_USER_RESET_PASSWORD) {
auto r = session->sendResetPasswordEmail(receiver_user, false);
if (1 == r) {
return stateWarning("email already sended");
}
else if (2 == r) {
return stateError("email already send less than a hour before");
}
}
else if (emailType == model::EMAIL_CUSTOM_TEXT) {
auto email_verification_code_object = controller::EmailVerificationCode::loadOrCreate(receiver_user_id, model::table::EMAIL_OPT_IN_RESET_PASSWORD);
auto email = new model::Email(email_verification_code_object, receiver_user, emailCustomText, emailCustomSubject);
em->addEmail(email);
}
else {
return stateError("not supported email type");
}
return stateSuccess();
}
else
{
if (session->getNewUser()->getModel()->getRole() != model::table::ROLE_ADMIN) {
return stateError("admin needed");
}
auto email_verification_code_object = controller::EmailVerificationCode::loadOrCreate(receiver_user_id, emailVerificationCodeType);
model::Email* email = nullptr;
if (emailType == model::EMAIL_CUSTOM_TEXT) {
email = new model::Email(email_verification_code_object, receiver_user, emailCustomText, emailCustomSubject);
}
else {
email = new model::Email(email_verification_code_object, receiver_user, emailType);
}
em->addEmail(email);
return stateSuccess();
}
}

View File

@ -0,0 +1,16 @@
#ifndef __JSON_SEND_EMAIL_H
#define __JSON_SEND_EMAIL_H
#include "JsonRequestHandler.h"
class JsonSendEmail : public JsonRequestHandler
{
public:
Poco::JSON::Object* handle(Poco::Dynamic::Var params);
protected:
};
#endif // __JSON_SEND_EMAIL_H

View File

@ -1,175 +1,175 @@
#include "JsonTransaction.h"
#include "Poco/URI.h"
#include "Poco/Dynamic/Struct.h"
#include "../SingletonManager/SessionManager.h"
#include "../ServerConfig.h"
Poco::JSON::Object* JsonTransaction::handle(Poco::Dynamic::Var params)
{
Poco::JSON::Object* result = new Poco::JSON::Object;
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>();
try {
/// 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.
paramJsonObject->get("session_id").convert(session_id);
auto sm = SessionManager::getInstance();
if (session_id != 0) {
auto session = sm->getSession(session_id);
if (!session) {
result->set("state", "error");
result->set("msg", "session not found");
return result;
}
int balance = 0;
if (!paramJsonObject->isNull("balance")) {
paramJsonObject->get("balance").convert(balance);
if (balance) {
auto u = session->getUser();
if (u) {
u->setBalance(balance);
}
auto nu = session->getNewUser();
if (!nu.isNull()) {
nu->setBalance(balance);
}
}
}
std::string transactionBase64String;
Poco::Dynamic::Var transaction_base64 = paramJsonObject->get("transaction_base64");
bool auto_sign = false;
auto auto_sign_json = paramJsonObject->get("auto_sign");
if (!auto_sign_json.isEmpty()) {
auto_sign_json.convert(auto_sign);
}
if (transaction_base64.isString()) {
paramJsonObject->get("transaction_base64").convert(transactionBase64String);
if (!session->startProcessingTransaction(transactionBase64String, auto_sign)) {
if (auto_sign) {
auto errorJson = session->getErrorsArray();
result->set("state", "error");
result->set("msg", "error processing transaction");
result->set("details", errorJson);
return result;
}
auto lastError = session->getLastError();
if (lastError) delete lastError;
result->set("state", "error");
result->set("msg", "already enlisted");
return result;
}
} else {
Poco::DynamicStruct ds = *paramJsonObject;
int alreadyEnlisted = 0;
for (int i = 0; i < ds["transaction_base64"].size(); i++) {
ds["transaction_base64"][i].convert(transactionBase64String);
if (!session->startProcessingTransaction(transactionBase64String, auto_sign)) {
auto lastError = session->getLastError();
if (lastError) delete lastError;
alreadyEnlisted++;
}
}
if (alreadyEnlisted > 0) {
result->set("state", "warning");
result->set("msg", std::to_string(alreadyEnlisted) + " already enlisted");
return result;
}
}
result->set("state", "success");
return result;
}
}
catch (Poco::Exception& ex) {
printf("[JsonTransaction::handle] try to use params as jsonObject: %s\n", ex.displayText().data());
result->set("state", "error");
result->set("msg", "json exception");
result->set("details", ex.displayText());
return result;
}
}
else if (params.isVector()) {
const Poco::URI::QueryParameters queryParams = params.extract<Poco::URI::QueryParameters>();
auto transactionIT = queryParams.begin();
for (auto it = queryParams.begin(); it != queryParams.end(); it++) {
if (it->first == "session_id") {
session_id = stoi(it->second);
//break;
}
else if (it->first == "transaction_base64") {
transactionIT = it;
}
}
if (session_id) {
auto sm = SessionManager::getInstance();
auto session = sm->getSession(session_id);
if (!session) {
result->set("state", "error");
result->set("msg", "session not found");
return result;
}
if (!session->startProcessingTransaction(transactionIT->second)) {
auto lastError = session->getLastError();
if (lastError) delete lastError;
result->set("state", "error");
result->set("msg", "already enlisted");
return result;
}
result->set("state", "success");
return result;
}
else {
result->set("state", "error");
result->set("msg", "session id not set");
return result;
}
}
else if (params.isStruct()) {
result->set("state", "error");
result->set("msg", "struct not implemented yet");
}
else if (params.isArray()) {
result->set("state", "error");
result->set("msg", "array not implemented yet");
}
else if (params.isList()) {
result->set("state", "error");
result->set("msg", "list not implemented yet");
}
else if (params.isString()) {
result->set("state", "error");
result->set("msg", "string not implemented yet");
}
else if (params.isDeque()) {
result->set("state", "error");
result->set("msg", "deque not implemented yet");
}
else {
result->set("state", "error");
result->set("msg", "format not implemented");
result->set("details", std::string(params.type().name()));
}
return result;
}
#include "JsonTransaction.h"
#include "Poco/URI.h"
#include "Poco/Dynamic/Struct.h"
#include "../SingletonManager/SessionManager.h"
#include "../ServerConfig.h"
Poco::JSON::Object* JsonTransaction::handle(Poco::Dynamic::Var params)
{
Poco::JSON::Object* result = new Poco::JSON::Object;
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>();
try {
/// 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.
paramJsonObject->get("session_id").convert(session_id);
auto sm = SessionManager::getInstance();
if (session_id != 0) {
auto session = sm->getSession(session_id);
if (!session) {
result->set("state", "error");
result->set("msg", "session not found");
return result;
}
int balance = 0;
if (!paramJsonObject->isNull("balance")) {
paramJsonObject->get("balance").convert(balance);
if (balance) {
auto u = session->getUser();
if (u) {
u->setBalance(balance);
}
auto nu = session->getNewUser();
if (!nu.isNull()) {
nu->setBalance(balance);
}
}
}
std::string transactionBase64String;
Poco::Dynamic::Var transaction_base64 = paramJsonObject->get("transaction_base64");
bool auto_sign = false;
auto auto_sign_json = paramJsonObject->get("auto_sign");
if (!auto_sign_json.isEmpty()) {
auto_sign_json.convert(auto_sign);
}
if (transaction_base64.isString()) {
paramJsonObject->get("transaction_base64").convert(transactionBase64String);
if (!session->startProcessingTransaction(transactionBase64String, auto_sign)) {
if (auto_sign) {
auto errorJson = session->getErrorsArray();
result->set("state", "error");
result->set("msg", "error processing transaction");
result->set("details", errorJson);
return result;
}
auto lastError = session->getLastError();
if (lastError) delete lastError;
result->set("state", "error");
result->set("msg", "already enlisted");
return result;
}
} else {
Poco::DynamicStruct ds = *paramJsonObject;
int alreadyEnlisted = 0;
for (int i = 0; i < ds["transaction_base64"].size(); i++) {
ds["transaction_base64"][i].convert(transactionBase64String);
if (!session->startProcessingTransaction(transactionBase64String, auto_sign)) {
auto lastError = session->getLastError();
if (lastError) delete lastError;
alreadyEnlisted++;
}
}
if (alreadyEnlisted > 0) {
result->set("state", "warning");
result->set("msg", std::to_string(alreadyEnlisted) + " already enlisted");
return result;
}
}
result->set("state", "success");
return result;
}
}
catch (Poco::Exception& ex) {
printf("[JsonTransaction::handle] try to use params as jsonObject: %s\n", ex.displayText().data());
result->set("state", "error");
result->set("msg", "json exception");
result->set("details", ex.displayText());
return result;
}
}
else if (params.isVector()) {
const Poco::URI::QueryParameters queryParams = params.extract<Poco::URI::QueryParameters>();
auto transactionIT = queryParams.begin();
for (auto it = queryParams.begin(); it != queryParams.end(); it++) {
if (it->first == "session_id") {
session_id = stoi(it->second);
//break;
}
else if (it->first == "transaction_base64") {
transactionIT = it;
}
}
if (session_id) {
auto sm = SessionManager::getInstance();
auto session = sm->getSession(session_id);
if (!session) {
result->set("state", "error");
result->set("msg", "session not found");
return result;
}
if (!session->startProcessingTransaction(transactionIT->second)) {
auto lastError = session->getLastError();
if (lastError) delete lastError;
result->set("state", "error");
result->set("msg", "already enlisted");
return result;
}
result->set("state", "success");
return result;
}
else {
result->set("state", "error");
result->set("msg", "session id not set");
return result;
}
}
else if (params.isStruct()) {
result->set("state", "error");
result->set("msg", "struct not implemented yet");
}
else if (params.isArray()) {
result->set("state", "error");
result->set("msg", "array not implemented yet");
}
else if (params.isList()) {
result->set("state", "error");
result->set("msg", "list not implemented yet");
}
else if (params.isString()) {
result->set("state", "error");
result->set("msg", "string not implemented yet");
}
else if (params.isDeque()) {
result->set("state", "error");
result->set("msg", "deque not implemented yet");
}
else {
result->set("state", "error");
result->set("msg", "format not implemented");
result->set("details", std::string(params.type().name()));
}
return result;
}

View File

@ -1,19 +1,19 @@
#ifndef __JSON_INTERFACE_JSON_TRANSACTION_
#define __JSON_INTERFACE_JSON_TRANSACTION_
#include "JsonRequestHandler.h"
class Session;
class JsonTransaction : public JsonRequestHandler
{
public:
Poco::JSON::Object* handle(Poco::Dynamic::Var params);
protected:
bool startProcessingTransaction(Session* session, const std::string& transactionBase64);
};
#ifndef __JSON_INTERFACE_JSON_TRANSACTION_
#define __JSON_INTERFACE_JSON_TRANSACTION_
#include "JsonRequestHandler.h"
class Session;
class JsonTransaction : public JsonRequestHandler
{
public:
Poco::JSON::Object* handle(Poco::Dynamic::Var params);
protected:
bool startProcessingTransaction(Session* session, const std::string& transactionBase64);
};
#endif // __JSON_INTERFACE_JSON_TRANSACTION_

View File

@ -68,7 +68,7 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
try {
if ( "User.first_name" == name) {
if ( "User.first_name" == name && value.size() > 0) {
if (!value.isString()) {
jsonErrorsArray.add("User.first_name isn't a string");
}
@ -77,7 +77,7 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
extractet_values++;
}
}
else if ("User.last_name" == name) {
else if ("User.last_name" == name && value.size() > 0) {
if (!value.isString()) {
jsonErrorsArray.add("User.last_name isn't a string");
}
@ -103,7 +103,7 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
jsonErrorsArray.add("User.disabled isn't a boolean or integer");
}
}
else if ("User.language" == name) {
else if ("User.language" == name && value.size() > 0) {
if (!value.isString()) {
jsonErrorsArray.add("User.language isn't a string");
}
@ -118,7 +118,7 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
}
}
}
else if ("User.password" == name && (ServerConfig::g_AllowUnsecureFlags & ServerConfig::UNSECURE_PASSWORD_REQUESTS) == ServerConfig::UNSECURE_PASSWORD_REQUESTS) {
else if ("User.password" == name && value.size() > 0 && (ServerConfig::g_AllowUnsecureFlags & ServerConfig::UNSECURE_PASSWORD_REQUESTS) == ServerConfig::UNSECURE_PASSWORD_REQUESTS) {
if (!value.isString()) {
jsonErrorsArray.add("User.password isn't string");
}

View File

@ -48,6 +48,7 @@ namespace ServerConfig {
Languages g_default_locale;
std::string g_php_serverPath;
std::string g_php_serverHost;
std::string g_frontend_checkEmailPath;
int g_phpServerPort;
Poco::Mutex g_TimeMutex;
int g_FakeLoginSleepTime = 820;
@ -210,7 +211,7 @@ namespace ServerConfig {
DISASM_FALSERET;
g_SessionTimeout = cfg.getInt("session.timeout", SESSION_TIMEOUT_DEFAULT);
g_serverPath = cfg.getString("loginServer.path", "");
g_serverPath = cfg.getString("loginServer.path", "http://localhost/account");
replaceZeroIPWithLocalhostIP(g_serverPath);
g_default_locale = LanguageManager::languageFromString(cfg.getString("loginServer.default_locale"));
g_serverPort = cfg.getInt("loginServer.port", 0);
@ -231,6 +232,8 @@ namespace ServerConfig {
if ("" != app_secret_string) {
g_CryptoAppSecret = DataTypeConverter::hexToBin(app_secret_string);
}
std::string defaultCheckEmailPath = g_serverPath + "/checkEmail";
g_frontend_checkEmailPath = cfg.getString("frontend.checkEmailPath", defaultCheckEmailPath);
//g_CryptoAppSecret
g_gRPCRelayServerFullURL = cfg.getString("grpc.server", "");

View File

@ -66,6 +66,7 @@ namespace ServerConfig {
extern Languages g_default_locale;
extern std::string g_php_serverPath;
extern std::string g_php_serverHost;
extern std::string g_frontend_checkEmailPath;
extern int g_phpServerPort;
extern Poco::Mutex g_TimeMutex;
extern int g_FakeLoginSleepTime;
@ -87,4 +88,5 @@ namespace ServerConfig {
void unload();
};
#endif //__GRADIDO_LOGIN_SERVER_SERVER_CONFIG__

File diff suppressed because it is too large Load Diff

View File

@ -67,6 +67,24 @@ namespace controller {
return nullptr;
}
Poco::AutoPtr<EmailVerificationCode> EmailVerificationCode::loadOrCreate(int user_id, model::table::EmailOptInType type)
{
model::table::EmailOptIn db;
std::vector<std::string> fields = { "user_id", "email_opt_in_type_id" };
std::vector<int> field_values = { user_id, (int)type };
auto results = db.loadFromDB<int, model::table::EmailOptInTuple>(fields, field_values);
if (results.size() > 0) {
return Poco::AutoPtr<EmailVerificationCode>(new EmailVerificationCode(new model::table::EmailOptIn(results[0])));
}
else {
auto result = create(user_id, type);
result->getModel()->insertIntoDB(false);
return result;
}
return nullptr;
}
std::vector<Poco::AutoPtr<EmailVerificationCode>> EmailVerificationCode::load(int user_id)
{
auto db = new model::table::EmailOptIn();
@ -102,8 +120,10 @@ namespace controller {
std::string EmailVerificationCode::getLink()
{
std::string link = ServerConfig::g_serverPath;
link += "/checkEmail/";
std::string link = ServerConfig::g_frontend_checkEmailPath;
if (link.data()[link.size() - 1] != '/') {
link += '/';
}
link += std::to_string(getModel()->getCode());
return link;
}

View File

@ -14,6 +14,8 @@ namespace controller {
static Poco::AutoPtr<EmailVerificationCode> create(int user_id, model::table::EmailOptInType type = model::table::EMAIL_OPT_IN_REGISTER);
static Poco::AutoPtr<EmailVerificationCode> create(model::table::EmailOptInType type = model::table::EMAIL_OPT_IN_REGISTER);
//! try to load code, create if not exist and save into db
static Poco::AutoPtr<EmailVerificationCode> loadOrCreate(int user_id, model::table::EmailOptInType type);
static Poco::AutoPtr<EmailVerificationCode> load(const Poco::UInt64& code);
static std::vector<Poco::AutoPtr<EmailVerificationCode>> load(int user_id);

View File

@ -1,63 +1,63 @@
/*!
*
* \author: einhornimmond
*
* \date: 07.03.19
*
* \brief: error data
*/
#ifndef DR_LUA_WEB_MODULE_ERROR_ERROR_H
#define DR_LUA_WEB_MODULE_ERROR_ERROR_H
#include <string>
#include <sstream>
class Error
{
public:
Error(const char* functionName, const char* message);
~Error();
const char* getFunctionName() { return mFunctionName.data(); }
const char* getMessage() { return mMessage.data(); }
virtual std::string getString(bool withNewline = true);
virtual std::string getHtmlString();
protected:
std::string mFunctionName;
std::string mMessage;
};
class ParamError : public Error
{
public:
ParamError(const char* functionName, const char* message, const char* param)
: Error(functionName, message), mParam(param) {}
ParamError(const char* functionName, const char* message, const std::string& param)
: Error(functionName, message), mParam(param) {}
ParamError(const char* functioName, const char* message, int param)
: Error(functioName, message) {
std::stringstream ss;
ss << param;
mParam = ss.str();
}
virtual std::string getString(bool withNewline = true);
virtual std::string getHtmlString();
protected:
std::string mParam;
};
class IErrorCollection
{
public:
virtual void addError(Error*, bool log = true) = 0;
};
#endif // DR_LUA_WEB_MODULE_ERROR_ERROR_H
/*!
*
* \author: einhornimmond
*
* \date: 07.03.19
*
* \brief: error data
*/
#ifndef DR_LUA_WEB_MODULE_ERROR_ERROR_H
#define DR_LUA_WEB_MODULE_ERROR_ERROR_H
#include <string>
#include <sstream>
class Error
{
public:
Error(const char* functionName, const char* message);
~Error();
const char* getFunctionName() { return mFunctionName.data(); }
const char* getMessage() { return mMessage.data(); }
virtual std::string getString(bool withNewline = true);
virtual std::string getHtmlString();
protected:
std::string mFunctionName;
std::string mMessage;
};
class ParamError : public Error
{
public:
ParamError(const char* functionName, const char* message, const char* param)
: Error(functionName, message), mParam(param) {}
ParamError(const char* functionName, const char* message, const std::string& param)
: Error(functionName, message), mParam(param) {}
ParamError(const char* functioName, const char* message, int param)
: Error(functioName, message) {
std::stringstream ss;
ss << param;
mParam = ss.str();
}
virtual std::string getString(bool withNewline = true);
virtual std::string getHtmlString();
protected:
std::string mParam;
};
class IErrorCollection
{
public:
virtual void addError(Error*, bool log = true) = 0;
};
#endif // DR_LUA_WEB_MODULE_ERROR_ERROR_H

View File

@ -1,201 +1,201 @@
#include "ErrorList.h"
#include "../ServerConfig.h"
//#include "Poco/Net/MailMessage.h"
#include "Poco/Net/MediaType.h"
#include "../SingletonManager/EmailManager.h"
SendErrorMessage::~SendErrorMessage()
{
if (mMessage) {
delete mMessage;
mMessage = nullptr;
}
}
int SendErrorMessage::run()
{
if (ServerConfig::g_disableEmail) return 0;
auto mailClientSession = new Poco::Net::SecureSMTPClientSession(ServerConfig::g_EmailAccount.url, ServerConfig::g_EmailAccount.port);
mailClientSession->login();
mailClientSession->startTLS(ServerConfig::g_SSL_CLient_Context);
mailClientSession->login(Poco::Net::SMTPClientSession::AUTH_LOGIN, ServerConfig::g_EmailAccount.username, ServerConfig::g_EmailAccount.password);
try {
mMessage->setSender(ServerConfig::g_EmailAccount.sender);
mailClientSession->sendMessage(*mMessage);
mailClientSession->close();
}
catch (Poco::Exception& exc) {
printf("[SendErrorMessage::%s] error sending error message to admin: %s\n",
__FUNCTION__, exc.displayText().data());
return -1;
}
return 0;
}
// ------------------------------------------------------------------------------------
ErrorList::ErrorList()
: mLogging(Poco::Logger::get("errorLog"))
{
}
ErrorList::~ErrorList()
{
while (mErrorStack.size() > 0) {
delete mErrorStack.top();
mErrorStack.pop();
}
}
void ErrorList::addError(Error* error, bool log/* = true */)
{
if (log) {
std::string dateTimeString = Poco::DateTimeFormatter::format(Poco::DateTime(), "%d.%m.%y %H:%M:%S");
mLogging.error("%s [ErrorList::addError] %s", dateTimeString, error->getString(false));
}
mErrorStack.push(error);
}
Error* ErrorList::getLastError()
{
if (mErrorStack.size() == 0) {
return nullptr;
}
Error* error = mErrorStack.top();
if (error) {
mErrorStack.pop();
}
return error;
}
void ErrorList::clearErrors()
{
while (mErrorStack.size()) {
auto error = mErrorStack.top();
if (error) {
delete error;
}
mErrorStack.pop();
}
}
int ErrorList::getErrors(ErrorList* send)
{
Error* error = nullptr;
int iCount = 0;
while (error = send->getLastError()) {
addError(error, false);
iCount++;
}
return iCount;
}
void ErrorList::printErrors()
{
while (mErrorStack.size() > 0) {
auto error = mErrorStack.top();
mErrorStack.pop();
printf(error->getString().data());
delete error;
}
}
std::vector<std::string> ErrorList::getErrorsArray()
{
std::vector<std::string> result;
result.reserve(mErrorStack.size());
while (mErrorStack.size() > 0) {
auto error = mErrorStack.top();
mErrorStack.pop();
//result->add(error->getString());
result.push_back(error->getString());
delete error;
}
return result;
}
std::string ErrorList::getErrorsHtml()
{
std::string res;
res = "<ul class='grd-no-style'>";
while (mErrorStack.size() > 0) {
auto error = mErrorStack.top();
mErrorStack.pop();
res += "<li class='grd-error'>";
res += error->getHtmlString();
res += "</li>";
delete error;
}
res += "</ul>";
return res;
}
std::string ErrorList::getErrorsHtmlNewFormat()
{
std::string html;
while (mErrorStack.size() > 0) {
auto error = std::unique_ptr<Error>(mErrorStack.top());
mErrorStack.pop();
html += "<div class=\"alert alert-error\" role=\"alert\">";
html += "<i class=\"material-icons-outlined\">report_problem</i>";
html += "<span>";
html += error->getHtmlString();
html += "</span>";
html += "</div>";
}
return html;
}
/*
<div class="alert alert-error" role="alert">
<i class="material-icons-outlined">report_problem</i>
<span>Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?</span>
</div>
*/
void ErrorList::sendErrorsAsEmail(std::string rawHtml/* = ""*/)
{
auto em = EmailManager::getInstance();
/*auto message = new Poco::Net::MailMessage();
message->setSender("gradido_loginServer@gradido.net");
message->addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, "***REMOVED***"));
message->setSubject("Error from Gradido Login Server");
*/
std::string content;
while (mErrorStack.size() > 0) {
auto error = mErrorStack.top();
mErrorStack.pop();
content += error->getString();
delete error;
}
auto email = new model::Email(content, model::EMAIL_ERROR);
//message->addContent(new Poco::Net::StringPartSource(content));
if (rawHtml != "") {
Poco::Net::MediaType mt("text", "html");
mt.setParameter("charset", "utf-8");
email->addContent(new Poco::Net::StringPartSource(rawHtml, mt.toString()));
}
em->addEmail(email);
//UniLib::controller::TaskPtr sendErrorMessageTask(new SendErrorMessage(message, ServerConfig::g_CPUScheduler));
//sendErrorMessageTask->scheduleTask(sendErrorMessageTask);
#include "ErrorList.h"
#include "../ServerConfig.h"
//#include "Poco/Net/MailMessage.h"
#include "Poco/Net/MediaType.h"
#include "../SingletonManager/EmailManager.h"
SendErrorMessage::~SendErrorMessage()
{
if (mMessage) {
delete mMessage;
mMessage = nullptr;
}
}
int SendErrorMessage::run()
{
if (ServerConfig::g_disableEmail) return 0;
auto mailClientSession = new Poco::Net::SecureSMTPClientSession(ServerConfig::g_EmailAccount.url, ServerConfig::g_EmailAccount.port);
mailClientSession->login();
mailClientSession->startTLS(ServerConfig::g_SSL_CLient_Context);
mailClientSession->login(Poco::Net::SMTPClientSession::AUTH_LOGIN, ServerConfig::g_EmailAccount.username, ServerConfig::g_EmailAccount.password);
try {
mMessage->setSender(ServerConfig::g_EmailAccount.sender);
mailClientSession->sendMessage(*mMessage);
mailClientSession->close();
}
catch (Poco::Exception& exc) {
printf("[SendErrorMessage::%s] error sending error message to admin: %s\n",
__FUNCTION__, exc.displayText().data());
return -1;
}
return 0;
}
// ------------------------------------------------------------------------------------
ErrorList::ErrorList()
: mLogging(Poco::Logger::get("errorLog"))
{
}
ErrorList::~ErrorList()
{
while (mErrorStack.size() > 0) {
delete mErrorStack.top();
mErrorStack.pop();
}
}
void ErrorList::addError(Error* error, bool log/* = true */)
{
if (log) {
std::string dateTimeString = Poco::DateTimeFormatter::format(Poco::DateTime(), "%d.%m.%y %H:%M:%S");
mLogging.error("%s [ErrorList::addError] %s", dateTimeString, error->getString(false));
}
mErrorStack.push(error);
}
Error* ErrorList::getLastError()
{
if (mErrorStack.size() == 0) {
return nullptr;
}
Error* error = mErrorStack.top();
if (error) {
mErrorStack.pop();
}
return error;
}
void ErrorList::clearErrors()
{
while (mErrorStack.size()) {
auto error = mErrorStack.top();
if (error) {
delete error;
}
mErrorStack.pop();
}
}
int ErrorList::getErrors(ErrorList* send)
{
Error* error = nullptr;
int iCount = 0;
while (error = send->getLastError()) {
addError(error, false);
iCount++;
}
return iCount;
}
void ErrorList::printErrors()
{
while (mErrorStack.size() > 0) {
auto error = mErrorStack.top();
mErrorStack.pop();
printf(error->getString().data());
delete error;
}
}
std::vector<std::string> ErrorList::getErrorsArray()
{
std::vector<std::string> result;
result.reserve(mErrorStack.size());
while (mErrorStack.size() > 0) {
auto error = mErrorStack.top();
mErrorStack.pop();
//result->add(error->getString());
result.push_back(error->getString());
delete error;
}
return result;
}
std::string ErrorList::getErrorsHtml()
{
std::string res;
res = "<ul class='grd-no-style'>";
while (mErrorStack.size() > 0) {
auto error = mErrorStack.top();
mErrorStack.pop();
res += "<li class='grd-error'>";
res += error->getHtmlString();
res += "</li>";
delete error;
}
res += "</ul>";
return res;
}
std::string ErrorList::getErrorsHtmlNewFormat()
{
std::string html;
while (mErrorStack.size() > 0) {
auto error = std::unique_ptr<Error>(mErrorStack.top());
mErrorStack.pop();
html += "<div class=\"alert alert-error\" role=\"alert\">";
html += "<i class=\"material-icons-outlined\">report_problem</i>";
html += "<span>";
html += error->getHtmlString();
html += "</span>";
html += "</div>";
}
return html;
}
/*
<div class="alert alert-error" role="alert">
<i class="material-icons-outlined">report_problem</i>
<span>Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?</span>
</div>
*/
void ErrorList::sendErrorsAsEmail(std::string rawHtml/* = ""*/)
{
auto em = EmailManager::getInstance();
/*auto message = new Poco::Net::MailMessage();
message->setSender("gradido_loginServer@gradido.net");
message->addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, "***REMOVED***"));
message->setSubject("Error from Gradido Login Server");
*/
std::string content;
while (mErrorStack.size() > 0) {
auto error = mErrorStack.top();
mErrorStack.pop();
content += error->getString();
delete error;
}
auto email = new model::Email(content, model::EMAIL_ERROR);
//message->addContent(new Poco::Net::StringPartSource(content));
if (rawHtml != "") {
Poco::Net::MediaType mt("text", "html");
mt.setParameter("charset", "utf-8");
email->addContent(new Poco::Net::StringPartSource(rawHtml, mt.toString()));
}
em->addEmail(email);
//UniLib::controller::TaskPtr sendErrorMessageTask(new SendErrorMessage(message, ServerConfig::g_CPUScheduler));
//sendErrorMessageTask->scheduleTask(sendErrorMessageTask);
}

View File

@ -1,76 +1,76 @@
/*!
*
* \author: einhornimmond
*
* \date: 07.03.19
*
* \brief: error
*/
#ifndef DR_LUA_WEB_MODULE_ERROR_ERROR_LIST_H
#define DR_LUA_WEB_MODULE_ERROR_ERROR_LIST_H
#include "Error.h"
#include <stack>
#include "../tasks/CPUTask.h"
#include "Poco/Net/SecureSMTPClientSession.h"
#include "Poco/Net/StringPartSource.h"
#include "Poco/Logger.h"
#include "Poco/JSON/Array.h"
class ErrorList : public IErrorCollection
{
public:
ErrorList();
~ErrorList();
// push error, error will be deleted in deconstructor
virtual void addError(Error* error, bool log = true);
// return error on top of stack, please delete after using
Error* getLastError();
inline size_t errorCount() { return mErrorStack.size(); }
// delete all errors
void clearErrors();
static int moveErrors(ErrorList* recv, ErrorList* send) {
return recv->getErrors(send);
}
int getErrors(ErrorList* send);
void printErrors();
std::string getErrorsHtml();
std::string getErrorsHtmlNewFormat();
std::vector<std::string> getErrorsArray();
void sendErrorsAsEmail(std::string rawHtml = "");
protected:
std::stack<Error*> mErrorStack;
// poco logging
Poco::Logger& mLogging;
};
class SendErrorMessage : public UniLib::controller::CPUTask
{
public:
SendErrorMessage(Poco::Net::MailMessage* message, UniLib::controller::CPUSheduler* scheduler)
: UniLib::controller::CPUTask(scheduler), mMessage(message) {}
~SendErrorMessage();
virtual int run();
const char* getResourceType() const { return "SendErrorMessage"; };
protected:
Poco::Net::MailMessage* mMessage;
};
#endif // DR_LUA_WEB_MODULE_ERROR_ERROR_LIST_H
/*!
*
* \author: einhornimmond
*
* \date: 07.03.19
*
* \brief: error
*/
#ifndef DR_LUA_WEB_MODULE_ERROR_ERROR_LIST_H
#define DR_LUA_WEB_MODULE_ERROR_ERROR_LIST_H
#include "Error.h"
#include <stack>
#include "../tasks/CPUTask.h"
#include "Poco/Net/SecureSMTPClientSession.h"
#include "Poco/Net/StringPartSource.h"
#include "Poco/Logger.h"
#include "Poco/JSON/Array.h"
class ErrorList : public IErrorCollection
{
public:
ErrorList();
~ErrorList();
// push error, error will be deleted in deconstructor
virtual void addError(Error* error, bool log = true);
// return error on top of stack, please delete after using
Error* getLastError();
inline size_t errorCount() { return mErrorStack.size(); }
// delete all errors
void clearErrors();
static int moveErrors(ErrorList* recv, ErrorList* send) {
return recv->getErrors(send);
}
int getErrors(ErrorList* send);
void printErrors();
std::string getErrorsHtml();
std::string getErrorsHtmlNewFormat();
std::vector<std::string> getErrorsArray();
void sendErrorsAsEmail(std::string rawHtml = "");
protected:
std::stack<Error*> mErrorStack;
// poco logging
Poco::Logger& mLogging;
};
class SendErrorMessage : public UniLib::controller::CPUTask
{
public:
SendErrorMessage(Poco::Net::MailMessage* message, UniLib::controller::CPUSheduler* scheduler)
: UniLib::controller::CPUTask(scheduler), mMessage(message) {}
~SendErrorMessage();
virtual int run();
const char* getResourceType() const { return "SendErrorMessage"; };
protected:
Poco::Net::MailMessage* mMessage;
};
#endif // DR_LUA_WEB_MODULE_ERROR_ERROR_LIST_H

View File

@ -1,57 +1,57 @@
#include "Gradido_LoginServer.h"
#include <sodium.h>
#include "proto/gradido/TransactionBody.pb.h"
#include "model/User.h"
#include "model/Session.h"
#include "lib/Profiler.h"
#include "ServerConfig.h"
#include "ImportantTests.h"
#include "model/table/User.h"
#include "model/table/EmailOptIn.h"
#include "Poco/DateTimeParser.h"
#ifndef _TEST_BUILD
int main(int argc, char** argv)
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (sodium_init() < 0) {
/* panic! the library couldn't be initialized, it is not safe to use */
printf("error initializing sodium, early exit\n");
return -1;
}
std::string dateTimeString = __DATE__;
//printf("Building date time string: %s\n", dateTimeString.data());
std::string formatString("%b %d %Y");
int timeZone = 0;
Poco::DateTime buildDateTime = Poco::DateTimeParser::parse(formatString, dateTimeString, timeZone);
ServerConfig::g_versionString = Poco::DateTimeFormatter::format(buildDateTime, "0.%y.%m.%d");
//ServerConfig::g_versionString = "0.20.KW13.02";
printf("Version: %s\n", ServerConfig::g_versionString.data());
printf("User size: %d Bytes, Session size: %d Bytes\n", sizeof(User), sizeof(Session));
printf("model sizes: User: %d Bytes, EmailOptIn: %d Bytes\n", sizeof(model::table::User), sizeof(model::table::EmailOptIn));
// load word lists
if (!ServerConfig::loadMnemonicWordLists()) {
//printf("[Gradido_LoginServer::%s] error loading mnemonic Word List\n", __FUNCTION__);
printf("[Gradido_LoginServer::main] error loading mnemonic Word List");
return -2;
}
if (!ImportantTests::passphraseGenerationAndTransformation()) {
printf("test passphrase generation and transformation failed\n");
return -3;
}
Gradido_LoginServer app;
app.setUnixOptions(true);
return app.run(argc, argv);
}
#include "Gradido_LoginServer.h"
#include <sodium.h>
#include "proto/gradido/TransactionBody.pb.h"
#include "model/User.h"
#include "model/Session.h"
#include "lib/Profiler.h"
#include "ServerConfig.h"
#include "ImportantTests.h"
#include "model/table/User.h"
#include "model/table/EmailOptIn.h"
#include "Poco/DateTimeParser.h"
#ifndef _TEST_BUILD
int main(int argc, char** argv)
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (sodium_init() < 0) {
/* panic! the library couldn't be initialized, it is not safe to use */
printf("error initializing sodium, early exit\n");
return -1;
}
std::string dateTimeString = __DATE__;
//printf("Building date time string: %s\n", dateTimeString.data());
std::string formatString("%b %d %Y");
int timeZone = 0;
Poco::DateTime buildDateTime = Poco::DateTimeParser::parse(formatString, dateTimeString, timeZone);
ServerConfig::g_versionString = Poco::DateTimeFormatter::format(buildDateTime, "0.%y.%m.%d");
//ServerConfig::g_versionString = "0.20.KW13.02";
printf("Version: %s\n", ServerConfig::g_versionString.data());
printf("User size: %d Bytes, Session size: %d Bytes\n", sizeof(User), sizeof(Session));
printf("model sizes: User: %d Bytes, EmailOptIn: %d Bytes\n", sizeof(model::table::User), sizeof(model::table::EmailOptIn));
// load word lists
if (!ServerConfig::loadMnemonicWordLists()) {
//printf("[Gradido_LoginServer::%s] error loading mnemonic Word List\n", __FUNCTION__);
printf("[Gradido_LoginServer::main] error loading mnemonic Word List");
return -2;
}
if (!ImportantTests::passphraseGenerationAndTransformation()) {
printf("test passphrase generation and transformation failed\n");
return -3;
}
Gradido_LoginServer app;
app.setUnixOptions(true);
return app.run(argc, argv);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,282 +1,282 @@
/*!
*
* \author: einhornimmond
*
* \date: 02.03.19
*
* \brief: store session data
*/
#ifndef DR_LUA_WEB_MODULE_SESSION_SESSION_H
#define DR_LUA_WEB_MODULE_SESSION_SESSION_H
#include "../lib/ErrorList.h"
#include "User.h"
#include "../controller/User.h"
#include "../lib/MultithreadContainer.h"
#include "../tasks/ProcessingTransaction.h"
#include "../SingletonManager/LanguageManager.h"
#include "../controller/EmailVerificationCode.h"
#include "Poco/Thread.h"
#include "Poco/Types.h"
#include "Poco/DateTime.h"
#include "Poco/Net/IPAddress.h"
#include "Poco/Net/HTTPCookie.h"
#include <mutex>
class WriteEmailVerification;
enum SessionStates {
SESSION_STATE_EMPTY,
SESSION_STATE_CRYPTO_KEY_GENERATED,
SESSION_STATE_USER_WRITTEN,
SESSION_STATE_EMAIL_VERIFICATION_WRITTEN,
SESSION_STATE_EMAIL_VERIFICATION_SEND,
SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED,
SESSION_STATE_PASSPHRASE_GENERATED,
SESSION_STATE_PASSPHRASE_SHOWN,
SESSION_STATE_PASSPHRASE_WRITTEN,
SESSION_STATE_KEY_PAIR_GENERATED,
SESSION_STATE_KEY_PAIR_WRITTEN,
SESSION_STATE_RESET_PASSWORD_REQUEST,
SESSION_STATE_RESET_PASSWORD_SUCCEED,
SESSION_STATE_COUNT
};
class SessionManager;
class UpdateUserPasswordPage;
class PassphrasePage;
class RepairDefectPassphrase;
class Session : public ErrorList, public UniLib::lib::MultithreadContainer
{
friend WriteEmailVerification;
friend SessionManager;
friend UpdateUserPasswordPage;
friend PassphrasePage;
friend RepairDefectPassphrase;
public:
Session(int handle);
~Session();
// get new model objects
Poco::AutoPtr<controller::EmailVerificationCode> getEmailVerificationCodeObject();
// set new model objects
inline void setUser(Poco::AutoPtr<controller::User> user) { mNewUser = user; }
inline Poco::AutoPtr<controller::User> getNewUser() { return mNewUser; }
// ---------------- User functions ----------------------------
// TODO: register state: written into db, mails sended, update state only if new state is higher as old state
// create User send e-mail activation link
bool createUser(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password);
//! \brief new register function, without showing user pubkeys, using controller/user
bool createUserDirect(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password);
// adminRegister without passwort
bool adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email);
// TODO: check if email exist and if not, fake waiting on password hashing with profiled times of real password hashing
UserStates loadUser(const std::string& email, const std::string& password);
bool ifUserExist(const std::string& email);
inline void setUser(Poco::AutoPtr<User> user) { mSessionUser = user; }
bool deleteUser();
Poco::AutoPtr<User> getUser() {
return mSessionUser;
}
// ------------------------- Email Verification Code functions -------------------------------
bool loadFromEmailVerificationCode(Poco::UInt64 emailVerificationCode);
//! \return 1 = konto already exist
//! -1 = invalid code
//! -2 = critical error
//! 0 = ok
int updateEmailVerification(Poco::UInt64 emailVerificationCode);
// called from page with same name
//! \return 1 = reset password email already send
//! \return 2 = reset password email already shortly before
//! \return 0 = ok
int sendResetPasswordEmail(Poco::AutoPtr<controller::User> user, bool passphraseMemorized);
//
//! \return 0 = not the same
//! \return 1 = same
//! \return -1 = error
//! \return -2 = critical error
int comparePassphraseWithSavedKeys(const std::string& inputPassphrase, Mnemonic* wordSource);
Poco::Net::HTTPCookie getLoginCookie();
inline int getHandle() { return mHandleId; }
// ------------------------ Passphrase functions ----------------------------
inline void setPassphrase(Poco::AutoPtr<Passphrase> passphrase) { mNewPassphrase = passphrase; }
inline Poco::AutoPtr<Passphrase> getPassphrase() { return mNewPassphrase; }
inline void setPassphrase(const std::string& passphrase) { mPassphrase = passphrase; }
inline const std::string& getOldPassphrase() { return mPassphrase; }
bool generatePassphrase();
bool generateKeys(bool savePrivkey, bool savePassphrase);
inline void setClientIp(Poco::Net::IPAddress ip) { mClientLoginIP = ip; }
inline Poco::Net::IPAddress getClientIp() { return mClientLoginIP; }
inline bool isIPValid(Poco::Net::IPAddress ip) { return mClientLoginIP == ip; }
bool isPwdValid(const std::string& pwd);
void reset();
void updateState(SessionStates newState);
const char* getSessionStateString();
inline SessionStates getSessionState() { SessionStates s; lock("Session::getSessionState"); s = mState; unlock(); return s; }
inline Poco::UInt64 getEmailVerificationCode() {
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
if (mEmailVerificationCodeObject.isNull()) return 0; return mEmailVerificationCodeObject->getModel()->getCode();
}
inline void setEmailVerificationCodeObject(Poco::AutoPtr<controller::EmailVerificationCode> emailVerficationObject) {
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
mEmailVerificationCodeObject = emailVerficationObject;
}
inline model::table::EmailOptInType getEmailVerificationType() {
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
if (mEmailVerificationCodeObject.isNull()) {
return model::table::EMAIL_OPT_IN_EMPTY;
}
return mEmailVerificationCodeObject->getModel()->getType();
}
//! \return -1 if session is locked
//! \return 1 if session is active
//! \return 0
int isActive();
//! \return false if session is locked
bool setActive(bool active);
bool isDeadLocked();
inline Poco::DateTime getLastActivity() { return mLastActivity; }
// ------------------------ transactions functions ----------------------------
//! \return true if succeed
bool startProcessingTransaction(const std::string& proto_message_base64, bool autoSign = false);
//! \param working if set will filled with transaction running
Poco::AutoPtr<ProcessingTransaction> getNextReadyTransaction(size_t* working = nullptr);
bool finalizeTransaction(bool sign, bool reject);
size_t getProcessingTransactionCount();
inline LanguageCatalog* getLanguageCatalog() { return mLanguageCatalog.isNull() ? nullptr : mLanguageCatalog; }
void setLanguage(Languages lang);
inline void setLanguageCatalog(Poco::AutoPtr<LanguageCatalog> languageCatalog) { mLanguageCatalog = languageCatalog; }
Languages getLanguage();
inline const char* gettext(const char* text) { if (mLanguageCatalog.isNull()) return text; return mLanguageCatalog->gettext(text); }
// last referer
inline void setLastReferer(const std::string& lastReferer) { mLastExternReferer = lastReferer; }
inline const std::string& getLastReferer() const { return mLastExternReferer; }
protected:
void updateTimeout();
inline void setHandle(int newHandle) { mHandleId = newHandle; }
void detectSessionState();
static const char* translateSessionStateToString(SessionStates state);
inline const std::string& getPassphrase() const { return mPassphrase; }
private:
int mHandleId;
Poco::AutoPtr<User> mSessionUser;
Poco::AutoPtr<controller::User> mNewUser;
std::string mPassphrase;
Poco::AutoPtr<Passphrase> mNewPassphrase;
Poco::DateTime mLastActivity;
Poco::Net::IPAddress mClientLoginIP;
std::string mLastExternReferer;
Poco::AutoPtr<controller::EmailVerificationCode> mEmailVerificationCodeObject;
std::shared_mutex mSharedMutex;
SessionStates mState;
bool mActive;
std::list<Poco::AutoPtr<ProcessingTransaction>> mProcessingTransactions;
Poco::AutoPtr<ProcessingTransaction> mCurrentActiveProcessingTransaction;
Poco::AutoPtr<LanguageCatalog> mLanguageCatalog;
};
class WriteEmailVerification : public UniLib::controller::CPUTask
{
public:
WriteEmailVerification(Poco::AutoPtr<User> user, Poco::AutoPtr<controller::EmailVerificationCode> emailVerificationCode, UniLib::controller::CPUSheduler* cpuScheduler, size_t taskDependenceCount = 0)
: UniLib::controller::CPUTask(cpuScheduler, taskDependenceCount), mUser(user), mEmailVerificationCode(emailVerificationCode) {
#ifdef _UNI_LIB_DEBUG
setName(user->getEmail());
#endif
}
virtual const char* getResourceType() const { return "WriteEmailVerification"; };
virtual int run();
private:
Poco::AutoPtr<User> mUser;
Poco::AutoPtr<controller::EmailVerificationCode> mEmailVerificationCode;
};
class WritePassphraseIntoDB : public UniLib::controller::CPUTask
{
public:
WritePassphraseIntoDB(int userId, const std::string& passphrase)
: mUserId(userId), mPassphrase(passphrase) {
#ifdef _UNI_LIB_DEBUG
setName(std::to_string(userId).data());
#endif
}
virtual int run();
virtual const char* getResourceType() const { return "WritePassphraseIntoDB"; };
protected:
int mUserId;
std::string mPassphrase;
};
class SessionStateUpdateCommand : public UniLib::controller::Command
{
public:
SessionStateUpdateCommand(SessionStates state, Session* session)
: mState(state), mSession(session) {}
virtual int taskFinished(UniLib::controller::Task* task) {
mSession->updateState(mState);
return 0;
}
protected:
SessionStates mState;
Session* mSession;
};
#endif // DR_LUA_WEB_MODULE_SESSION_SESSION_H
/*!
*
* \author: einhornimmond
*
* \date: 02.03.19
*
* \brief: store session data
*/
#ifndef DR_LUA_WEB_MODULE_SESSION_SESSION_H
#define DR_LUA_WEB_MODULE_SESSION_SESSION_H
#include "../lib/ErrorList.h"
#include "User.h"
#include "../controller/User.h"
#include "../lib/MultithreadContainer.h"
#include "../tasks/ProcessingTransaction.h"
#include "../SingletonManager/LanguageManager.h"
#include "../controller/EmailVerificationCode.h"
#include "Poco/Thread.h"
#include "Poco/Types.h"
#include "Poco/DateTime.h"
#include "Poco/Net/IPAddress.h"
#include "Poco/Net/HTTPCookie.h"
#include <mutex>
class WriteEmailVerification;
enum SessionStates {
SESSION_STATE_EMPTY,
SESSION_STATE_CRYPTO_KEY_GENERATED,
SESSION_STATE_USER_WRITTEN,
SESSION_STATE_EMAIL_VERIFICATION_WRITTEN,
SESSION_STATE_EMAIL_VERIFICATION_SEND,
SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED,
SESSION_STATE_PASSPHRASE_GENERATED,
SESSION_STATE_PASSPHRASE_SHOWN,
SESSION_STATE_PASSPHRASE_WRITTEN,
SESSION_STATE_KEY_PAIR_GENERATED,
SESSION_STATE_KEY_PAIR_WRITTEN,
SESSION_STATE_RESET_PASSWORD_REQUEST,
SESSION_STATE_RESET_PASSWORD_SUCCEED,
SESSION_STATE_COUNT
};
class SessionManager;
class UpdateUserPasswordPage;
class PassphrasePage;
class RepairDefectPassphrase;
class Session : public ErrorList, public UniLib::lib::MultithreadContainer
{
friend WriteEmailVerification;
friend SessionManager;
friend UpdateUserPasswordPage;
friend PassphrasePage;
friend RepairDefectPassphrase;
public:
Session(int handle);
~Session();
// get new model objects
Poco::AutoPtr<controller::EmailVerificationCode> getEmailVerificationCodeObject();
// set new model objects
inline void setUser(Poco::AutoPtr<controller::User> user) { mNewUser = user; }
inline Poco::AutoPtr<controller::User> getNewUser() { return mNewUser; }
// ---------------- User functions ----------------------------
// TODO: register state: written into db, mails sended, update state only if new state is higher as old state
// create User send e-mail activation link
bool createUser(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password);
//! \brief new register function, without showing user pubkeys, using controller/user
bool createUserDirect(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password);
// adminRegister without passwort
bool adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email);
// TODO: check if email exist and if not, fake waiting on password hashing with profiled times of real password hashing
UserStates loadUser(const std::string& email, const std::string& password);
bool ifUserExist(const std::string& email);
inline void setUser(Poco::AutoPtr<User> user) { mSessionUser = user; }
bool deleteUser();
Poco::AutoPtr<User> getUser() {
return mSessionUser;
}
// ------------------------- Email Verification Code functions -------------------------------
bool loadFromEmailVerificationCode(Poco::UInt64 emailVerificationCode);
//! \return 1 = konto already exist
//! -1 = invalid code
//! -2 = critical error
//! 0 = ok
int updateEmailVerification(Poco::UInt64 emailVerificationCode);
// called from page with same name
//! \return 1 = reset password email already send
//! \return 2 = reset password email already shortly before
//! \return 0 = ok
int sendResetPasswordEmail(Poco::AutoPtr<controller::User> user, bool passphraseMemorized);
//
//! \return 0 = not the same
//! \return 1 = same
//! \return -1 = error
//! \return -2 = critical error
int comparePassphraseWithSavedKeys(const std::string& inputPassphrase, Mnemonic* wordSource);
Poco::Net::HTTPCookie getLoginCookie();
inline int getHandle() { return mHandleId; }
// ------------------------ Passphrase functions ----------------------------
inline void setPassphrase(Poco::AutoPtr<Passphrase> passphrase) { mNewPassphrase = passphrase; }
inline Poco::AutoPtr<Passphrase> getPassphrase() { return mNewPassphrase; }
inline void setPassphrase(const std::string& passphrase) { mPassphrase = passphrase; }
inline const std::string& getOldPassphrase() { return mPassphrase; }
bool generatePassphrase();
bool generateKeys(bool savePrivkey, bool savePassphrase);
inline void setClientIp(Poco::Net::IPAddress ip) { mClientLoginIP = ip; }
inline Poco::Net::IPAddress getClientIp() { return mClientLoginIP; }
inline bool isIPValid(Poco::Net::IPAddress ip) { return mClientLoginIP == ip; }
bool isPwdValid(const std::string& pwd);
void reset();
void updateState(SessionStates newState);
const char* getSessionStateString();
inline SessionStates getSessionState() { SessionStates s; lock("Session::getSessionState"); s = mState; unlock(); return s; }
inline Poco::UInt64 getEmailVerificationCode() {
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
if (mEmailVerificationCodeObject.isNull()) return 0; return mEmailVerificationCodeObject->getModel()->getCode();
}
inline void setEmailVerificationCodeObject(Poco::AutoPtr<controller::EmailVerificationCode> emailVerficationObject) {
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
mEmailVerificationCodeObject = emailVerficationObject;
}
inline model::table::EmailOptInType getEmailVerificationType() {
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
if (mEmailVerificationCodeObject.isNull()) {
return model::table::EMAIL_OPT_IN_EMPTY;
}
return mEmailVerificationCodeObject->getModel()->getType();
}
//! \return -1 if session is locked
//! \return 1 if session is active
//! \return 0
int isActive();
//! \return false if session is locked
bool setActive(bool active);
bool isDeadLocked();
inline Poco::DateTime getLastActivity() { return mLastActivity; }
// ------------------------ transactions functions ----------------------------
//! \return true if succeed
bool startProcessingTransaction(const std::string& proto_message_base64, bool autoSign = false);
//! \param working if set will filled with transaction running
Poco::AutoPtr<ProcessingTransaction> getNextReadyTransaction(size_t* working = nullptr);
bool finalizeTransaction(bool sign, bool reject);
size_t getProcessingTransactionCount();
inline LanguageCatalog* getLanguageCatalog() { return mLanguageCatalog.isNull() ? nullptr : mLanguageCatalog; }
void setLanguage(Languages lang);
inline void setLanguageCatalog(Poco::AutoPtr<LanguageCatalog> languageCatalog) { mLanguageCatalog = languageCatalog; }
Languages getLanguage();
inline const char* gettext(const char* text) { if (mLanguageCatalog.isNull()) return text; return mLanguageCatalog->gettext(text); }
// last referer
inline void setLastReferer(const std::string& lastReferer) { mLastExternReferer = lastReferer; }
inline const std::string& getLastReferer() const { return mLastExternReferer; }
protected:
void updateTimeout();
inline void setHandle(int newHandle) { mHandleId = newHandle; }
void detectSessionState();
static const char* translateSessionStateToString(SessionStates state);
inline const std::string& getPassphrase() const { return mPassphrase; }
private:
int mHandleId;
Poco::AutoPtr<User> mSessionUser;
Poco::AutoPtr<controller::User> mNewUser;
std::string mPassphrase;
Poco::AutoPtr<Passphrase> mNewPassphrase;
Poco::DateTime mLastActivity;
Poco::Net::IPAddress mClientLoginIP;
std::string mLastExternReferer;
Poco::AutoPtr<controller::EmailVerificationCode> mEmailVerificationCodeObject;
std::shared_mutex mSharedMutex;
SessionStates mState;
bool mActive;
std::list<Poco::AutoPtr<ProcessingTransaction>> mProcessingTransactions;
Poco::AutoPtr<ProcessingTransaction> mCurrentActiveProcessingTransaction;
Poco::AutoPtr<LanguageCatalog> mLanguageCatalog;
};
class WriteEmailVerification : public UniLib::controller::CPUTask
{
public:
WriteEmailVerification(Poco::AutoPtr<User> user, Poco::AutoPtr<controller::EmailVerificationCode> emailVerificationCode, UniLib::controller::CPUSheduler* cpuScheduler, size_t taskDependenceCount = 0)
: UniLib::controller::CPUTask(cpuScheduler, taskDependenceCount), mUser(user), mEmailVerificationCode(emailVerificationCode) {
#ifdef _UNI_LIB_DEBUG
setName(user->getEmail());
#endif
}
virtual const char* getResourceType() const { return "WriteEmailVerification"; };
virtual int run();
private:
Poco::AutoPtr<User> mUser;
Poco::AutoPtr<controller::EmailVerificationCode> mEmailVerificationCode;
};
class WritePassphraseIntoDB : public UniLib::controller::CPUTask
{
public:
WritePassphraseIntoDB(int userId, const std::string& passphrase)
: mUserId(userId), mPassphrase(passphrase) {
#ifdef _UNI_LIB_DEBUG
setName(std::to_string(userId).data());
#endif
}
virtual int run();
virtual const char* getResourceType() const { return "WritePassphraseIntoDB"; };
protected:
int mUserId;
std::string mPassphrase;
};
class SessionStateUpdateCommand : public UniLib::controller::Command
{
public:
SessionStateUpdateCommand(SessionStates state, Session* session)
: mState(state), mSession(session) {}
virtual int taskFinished(UniLib::controller::Task* task) {
mSession->updateState(mState);
return 0;
}
protected:
SessionStates mState;
Session* mSession;
};
#endif // DR_LUA_WEB_MODULE_SESSION_SESSION_H

View File

@ -1,72 +1,72 @@
#include "TransactionCreation.h"
#include "Poco/DateTimeFormatter.h"
#include <sodium.h>
TransactionCreation::TransactionCreation(const std::string& memo, const model::messages::gradido::TransactionCreation& protoCreation)
: TransactionBase(memo), mProtoCreation(protoCreation), mReceiverUser(nullptr)
{
memset(mReceiverPublicHex, 0, 65);
}
TransactionCreation::~TransactionCreation()
{
if (mReceiverUser) {
delete mReceiverUser;
mReceiverUser = nullptr;
}
}
int TransactionCreation::prepare()
{
const static char functionName[] = { "TransactionCreation::prepare" };
if (!mProtoCreation.has_receiveramount()) {
addError(new Error(functionName, "hasn't receiver amount"));
return -1;
}
auto receiverAmount = mProtoCreation.receiveramount();
if (receiverAmount.amount() <= 0) {
addError(new Error(functionName, "amount must be > 0"));
return -4;
}
if (receiverAmount.amount() > 10000000) {
addError(new Error(functionName, "amount must be <= 1000 GDD"));
return -5;
}
auto receiverPublic = receiverAmount.ed25519_receiver_pubkey();
if (receiverPublic.size() != 32) {
addError(new Error(functionName, "receiver public invalid (size not 32)"));
return -2;
}
mReceiverUser = new User((const unsigned char*)receiverPublic.data());
getErrors(mReceiverUser);
if (mReceiverUser->getUserState() == USER_EMPTY) {
sodium_bin2hex(mReceiverPublicHex, 65, (const unsigned char*)receiverPublic.data(), receiverPublic.size());
delete mReceiverUser;
mReceiverUser = nullptr;
}
else {
memcpy(mReceiverPublicHex, mReceiverUser->getPublicKeyHex().data(), 64);
// uncomment because not correctly working
/*if (!mReceiverUser->validateIdentHash(mProtoCreation.ident_hash())) {
addError(new Error(functionName, "ident hash isn't the same"));
addError(new ParamError(functionName, "hash calculated from email: ", mReceiverUser->getEmail()));
addError(new ParamError(functionName, "hash: ", std::to_string(mProtoCreation.ident_hash())));
return -3;
}*/
}
//
return 0;
}
std::string TransactionCreation::getTargetDateString()
{
// proto format is seconds, poco timestamp format is microseconds
Poco::Timestamp pocoStamp(mProtoCreation.target_date().seconds() * 1000*1000);
//Poco::DateTime(pocoStamp);
return Poco::DateTimeFormatter::format(pocoStamp, "%d. %b %y");
}
#include "TransactionCreation.h"
#include "Poco/DateTimeFormatter.h"
#include <sodium.h>
TransactionCreation::TransactionCreation(const std::string& memo, const model::messages::gradido::TransactionCreation& protoCreation)
: TransactionBase(memo), mProtoCreation(protoCreation), mReceiverUser(nullptr)
{
memset(mReceiverPublicHex, 0, 65);
}
TransactionCreation::~TransactionCreation()
{
if (mReceiverUser) {
delete mReceiverUser;
mReceiverUser = nullptr;
}
}
int TransactionCreation::prepare()
{
const static char functionName[] = { "TransactionCreation::prepare" };
if (!mProtoCreation.has_receiveramount()) {
addError(new Error(functionName, "hasn't receiver amount"));
return -1;
}
auto receiverAmount = mProtoCreation.receiveramount();
if (receiverAmount.amount() <= 0) {
addError(new Error(functionName, "amount must be > 0"));
return -4;
}
if (receiverAmount.amount() > 10000000) {
addError(new Error(functionName, "amount must be <= 1000 GDD"));
return -5;
}
auto receiverPublic = receiverAmount.ed25519_receiver_pubkey();
if (receiverPublic.size() != 32) {
addError(new Error(functionName, "receiver public invalid (size not 32)"));
return -2;
}
mReceiverUser = new User((const unsigned char*)receiverPublic.data());
getErrors(mReceiverUser);
if (mReceiverUser->getUserState() == USER_EMPTY) {
sodium_bin2hex(mReceiverPublicHex, 65, (const unsigned char*)receiverPublic.data(), receiverPublic.size());
delete mReceiverUser;
mReceiverUser = nullptr;
}
else {
memcpy(mReceiverPublicHex, mReceiverUser->getPublicKeyHex().data(), 64);
// uncomment because not correctly working
/*if (!mReceiverUser->validateIdentHash(mProtoCreation.ident_hash())) {
addError(new Error(functionName, "ident hash isn't the same"));
addError(new ParamError(functionName, "hash calculated from email: ", mReceiverUser->getEmail()));
addError(new ParamError(functionName, "hash: ", std::to_string(mProtoCreation.ident_hash())));
return -3;
}*/
}
//
return 0;
}
std::string TransactionCreation::getTargetDateString()
{
// proto format is seconds, poco timestamp format is microseconds
Poco::Timestamp pocoStamp(mProtoCreation.target_date().seconds() * 1000*1000);
//Poco::DateTime(pocoStamp);
return Poco::DateTimeFormatter::format(pocoStamp, "%d. %b %y");
}

View File

@ -1,172 +1,172 @@
#include "TransactionTransfer.h"
const std::string TransactionTransfer::mInvalidIndexMessage("invalid index");
TransactionTransfer::KontoTableEntry::KontoTableEntry(model::table::User* user, google::protobuf::int64 amount, bool negativeAmount/* = false*/)
{
//<span class="content-cell">Normaler&nbsp;User&nbsp;&lt;info@software-labor.de&gt;</span>
if (!user) return;
composeAmountCellString(amount, negativeAmount);
/*kontoNameCell = "<td>";
kontoNameCell += user->getFirstName();
kontoNameCell += "&nbsp;";
kontoNameCell += user->getLastName();
kontoNameCell += "&nbsp;&lt;";
kontoNameCell += user->getEmail();
kontoNameCell += "&gt;</td>";*/
kontoNameCell = "<span class=\"content-cell\">";
kontoNameCell += user->getNameWithEmailHtml();
kontoNameCell += "</span>";
}
TransactionTransfer::KontoTableEntry::KontoTableEntry(const std::string& pubkeyHex, google::protobuf::int64 amount, bool negativeAmount/* = false*/)
{
composeAmountCellString(amount, negativeAmount);
//kontoNameCell = "<td class=\"small\">0x" + pubkeyHex + "</td>";
kontoNameCell = "<span class = \"content-cell\">" + pubkeyHex + "</span>";
}
void TransactionTransfer::KontoTableEntry::composeAmountCellString(google::protobuf::int64 amount, bool negativeAmount)
{
//<span class="content-cell alert-color">-10 GDD</span>
//<span class="content-cell success-color">10 GDD</span>
amountCell = "<span class=\"content-cell ";
if (negativeAmount) {
amountCell += "alert-color\">-";
}
else {
amountCell += "success-color\">";
}
amountCell += amountToString(amount);
//amountCell += " GDD</td>";
amountCell += " GDD</span>";
}
// ********************************************************************************************************************************
TransactionTransfer::TransactionTransfer(const std::string& memo, const model::messages::gradido::Transfer& protoTransfer)
: TransactionBase(memo), mProtoTransfer(protoTransfer)
{
}
TransactionTransfer::~TransactionTransfer()
{
mKontoTable.clear();
}
int TransactionTransfer::prepare()
{
lock();
const static char functionName[] = { "TransactionTransfer::prepare" };
if (mProtoTransfer.senderamounts_size() == 0) {
addError(new Error(functionName, "hasn't sender amount(s)"));
unlock();
return -1;
}
if (mProtoTransfer.receiveramounts_size() == 0) {
addError(new Error(functionName, "hasn't receiver amount(s)"));
unlock();
return -2;
}
mKontoTable.reserve(mProtoTransfer.senderamounts_size() + mProtoTransfer.receiveramounts_size());
//auto receiverAmount = mProtoTransfer.receiveramount();
//auto senderAmount
int senderSum = 0;
int receiverSum = 0;
char pubkeyHexTemp[65];
for (int i = 0; i < mProtoTransfer.senderamounts_size(); i++) {
auto senderAmount = mProtoTransfer.senderamounts(i);
auto pubkey = senderAmount.ed25519_sender_pubkey();
senderSum += senderAmount.amount();
if (pubkey.size() != 32) {
addError(new ParamError(functionName, "invalid public key for sender ", i));
unlock();
return -3;
}
//User user((const unsigned char*)pubkey.data());
auto user = controller::User::create();
if (!user->load((const unsigned char*)pubkey.data())) {
sodium_bin2hex(pubkeyHexTemp, 65, (const unsigned char*)pubkey.data(), pubkey.size());
mKontoTable.push_back(KontoTableEntry(pubkeyHexTemp, senderAmount.amount(), true));
}
else {
mKontoTable.push_back(KontoTableEntry(user->getModel(), senderAmount.amount(), true));
}
}
for (int i = 0; i < mProtoTransfer.receiveramounts_size(); i++) {
auto receiverAmount = mProtoTransfer.receiveramounts(i);
auto pubkey = receiverAmount.ed25519_receiver_pubkey();
receiverSum += receiverAmount.amount();
if (receiverAmount.ed25519_receiver_pubkey().size() != 32) {
addError(new ParamError(functionName, "invalid public key for receiver ", i));
unlock();
return -4;
}
auto user = controller::User::create();
if (!user->load((const unsigned char*)pubkey.data())) {
sodium_bin2hex(pubkeyHexTemp, 65, (const unsigned char*)pubkey.data(), pubkey.size());
mKontoTable.push_back(KontoTableEntry(pubkeyHexTemp, receiverAmount.amount(), false));
}
else {
mKontoTable.push_back(KontoTableEntry(user->getModel(), receiverAmount.amount(), false));
}
}
if (senderSum != receiverSum) {
addError(new Error(functionName, "sender amounts sum != receiver amounts sum"));
unlock();
return -5;
}
if (senderSum < 0) {
addError(new Error(functionName, "negative amount not supported"));
unlock();
return -6;
}
/*
mReceiverUser = new User(receiverPublic.data());
getErrors(mReceiverUser);
if (mReceiverUser->getUserState() == USER_EMPTY) {
sodium_bin2hex(mReceiverPublicHex, 65, (const unsigned char*)receiverPublic.data(), receiverPublic.size());
delete mReceiverUser;
mReceiverUser = nullptr;
}
else {
memcpy(mReceiverPublicHex, mReceiverUser->getPublicKeyHex().data(), 64);
}
//*/
unlock();
return 0;
}
const std::string& TransactionTransfer::getKontoNameCell(int index)
{
lock();
if (index >= mKontoTable.size()) {
unlock();
return mInvalidIndexMessage;
}
unlock();
return mKontoTable[index].kontoNameCell;
}
const std::string& TransactionTransfer::getAmountCell(int index)
{
lock();
if (index >= mKontoTable.size()) {
unlock();
return mInvalidIndexMessage;
}
unlock();
return mKontoTable[index].amountCell;
}
#include "TransactionTransfer.h"
const std::string TransactionTransfer::mInvalidIndexMessage("invalid index");
TransactionTransfer::KontoTableEntry::KontoTableEntry(model::table::User* user, google::protobuf::int64 amount, bool negativeAmount/* = false*/)
{
//<span class="content-cell">Normaler&nbsp;User&nbsp;&lt;info@software-labor.de&gt;</span>
if (!user) return;
composeAmountCellString(amount, negativeAmount);
/*kontoNameCell = "<td>";
kontoNameCell += user->getFirstName();
kontoNameCell += "&nbsp;";
kontoNameCell += user->getLastName();
kontoNameCell += "&nbsp;&lt;";
kontoNameCell += user->getEmail();
kontoNameCell += "&gt;</td>";*/
kontoNameCell = "<span class=\"content-cell\">";
kontoNameCell += user->getNameWithEmailHtml();
kontoNameCell += "</span>";
}
TransactionTransfer::KontoTableEntry::KontoTableEntry(const std::string& pubkeyHex, google::protobuf::int64 amount, bool negativeAmount/* = false*/)
{
composeAmountCellString(amount, negativeAmount);
//kontoNameCell = "<td class=\"small\">0x" + pubkeyHex + "</td>";
kontoNameCell = "<span class = \"content-cell\">" + pubkeyHex + "</span>";
}
void TransactionTransfer::KontoTableEntry::composeAmountCellString(google::protobuf::int64 amount, bool negativeAmount)
{
//<span class="content-cell alert-color">-10 GDD</span>
//<span class="content-cell success-color">10 GDD</span>
amountCell = "<span class=\"content-cell ";
if (negativeAmount) {
amountCell += "alert-color\">-";
}
else {
amountCell += "success-color\">";
}
amountCell += amountToString(amount);
//amountCell += " GDD</td>";
amountCell += " GDD</span>";
}
// ********************************************************************************************************************************
TransactionTransfer::TransactionTransfer(const std::string& memo, const model::messages::gradido::Transfer& protoTransfer)
: TransactionBase(memo), mProtoTransfer(protoTransfer)
{
}
TransactionTransfer::~TransactionTransfer()
{
mKontoTable.clear();
}
int TransactionTransfer::prepare()
{
lock();
const static char functionName[] = { "TransactionTransfer::prepare" };
if (mProtoTransfer.senderamounts_size() == 0) {
addError(new Error(functionName, "hasn't sender amount(s)"));
unlock();
return -1;
}
if (mProtoTransfer.receiveramounts_size() == 0) {
addError(new Error(functionName, "hasn't receiver amount(s)"));
unlock();
return -2;
}
mKontoTable.reserve(mProtoTransfer.senderamounts_size() + mProtoTransfer.receiveramounts_size());
//auto receiverAmount = mProtoTransfer.receiveramount();
//auto senderAmount
int senderSum = 0;
int receiverSum = 0;
char pubkeyHexTemp[65];
for (int i = 0; i < mProtoTransfer.senderamounts_size(); i++) {
auto senderAmount = mProtoTransfer.senderamounts(i);
auto pubkey = senderAmount.ed25519_sender_pubkey();
senderSum += senderAmount.amount();
if (pubkey.size() != 32) {
addError(new ParamError(functionName, "invalid public key for sender ", i));
unlock();
return -3;
}
//User user((const unsigned char*)pubkey.data());
auto user = controller::User::create();
if (!user->load((const unsigned char*)pubkey.data())) {
sodium_bin2hex(pubkeyHexTemp, 65, (const unsigned char*)pubkey.data(), pubkey.size());
mKontoTable.push_back(KontoTableEntry(pubkeyHexTemp, senderAmount.amount(), true));
}
else {
mKontoTable.push_back(KontoTableEntry(user->getModel(), senderAmount.amount(), true));
}
}
for (int i = 0; i < mProtoTransfer.receiveramounts_size(); i++) {
auto receiverAmount = mProtoTransfer.receiveramounts(i);
auto pubkey = receiverAmount.ed25519_receiver_pubkey();
receiverSum += receiverAmount.amount();
if (receiverAmount.ed25519_receiver_pubkey().size() != 32) {
addError(new ParamError(functionName, "invalid public key for receiver ", i));
unlock();
return -4;
}
auto user = controller::User::create();
if (!user->load((const unsigned char*)pubkey.data())) {
sodium_bin2hex(pubkeyHexTemp, 65, (const unsigned char*)pubkey.data(), pubkey.size());
mKontoTable.push_back(KontoTableEntry(pubkeyHexTemp, receiverAmount.amount(), false));
}
else {
mKontoTable.push_back(KontoTableEntry(user->getModel(), receiverAmount.amount(), false));
}
}
if (senderSum != receiverSum) {
addError(new Error(functionName, "sender amounts sum != receiver amounts sum"));
unlock();
return -5;
}
if (senderSum < 0) {
addError(new Error(functionName, "negative amount not supported"));
unlock();
return -6;
}
/*
mReceiverUser = new User(receiverPublic.data());
getErrors(mReceiverUser);
if (mReceiverUser->getUserState() == USER_EMPTY) {
sodium_bin2hex(mReceiverPublicHex, 65, (const unsigned char*)receiverPublic.data(), receiverPublic.size());
delete mReceiverUser;
mReceiverUser = nullptr;
}
else {
memcpy(mReceiverPublicHex, mReceiverUser->getPublicKeyHex().data(), 64);
}
//*/
unlock();
return 0;
}
const std::string& TransactionTransfer::getKontoNameCell(int index)
{
lock();
if (index >= mKontoTable.size()) {
unlock();
return mInvalidIndexMessage;
}
unlock();
return mKontoTable[index].kontoNameCell;
}
const std::string& TransactionTransfer::getAmountCell(int index)
{
lock();
if (index >= mKontoTable.size()) {
unlock();
return mInvalidIndexMessage;
}
unlock();
return mKontoTable[index].amountCell;
}

View File

@ -130,6 +130,16 @@ Gradido Login-Server\n\
: mUser(user), mType(type)
{
}
Email::Email(
AutoPtr<controller::EmailVerificationCode> emailVerification,
AutoPtr<controller::User> user,
const std::string& emailCustomText,
const std::string& customSubject
)
: mEmailVerificationCode(emailVerification), mUser(user), mType(EMAIL_CUSTOM_TEXT), mCustomText(emailCustomText), mCustomSubject(customSubject)
{
}
Email::~Email()
@ -177,6 +187,7 @@ Gradido Login-Server\n\
case EMAIL_USER_REGISTER_OLD_ELOPAGE:
case EMAIL_ADMIN_USER_VERIFICATION_CODE:
case EMAIL_ADMIN_USER_VERIFICATION_CODE_RESEND:
case EMAIL_CUSTOM_TEXT:
if (userTableModel.isNull() || mUser->getModel()->getEmail() == "") {
addError(new Error(functionName, "no receiver email set for user email verification email"));
return false;
@ -204,14 +215,19 @@ Gradido Login-Server\n\
else if (mType == EMAIL_USER_REGISTER_OLD_ELOPAGE) {
messageTemplate = EmailText_emailVerificationOldElopageTransaction;
}
else if (mType == EMAIL_CUSTOM_TEXT) {
messageTemplate = mCustomText.data();
mailMessage->setSubject(mCustomSubject);
}
content_string = replaceUserNamesAndLink(
langCatalog->gettext(messageTemplate),
userTableModel->getFirstName(),
userTableModel->getLastName(),
mEmailVerificationCode->getLink()
mEmailVerificationCode->getLink(),
mEmailVerificationCode->getModel()->getCode()
);
if (EMAIL_USER_VERIFICATION_CODE_RESEND_AFTER_LONG_TIME == mType) {
if (EMAIL_USER_VERIFICATION_CODE_RESEND_AFTER_LONG_TIME == mType || EMAIL_CUSTOM_TEXT == mType) {
content_string = replaceDuration(content_string, mEmailVerificationCode->getAge(), langCatalog);
}
mailMessage->addContent(new Poco::Net::StringPartSource(content_string, mt.toString()));
@ -234,7 +250,8 @@ Gradido Login-Server\n\
langCatalog->gettext(EmailText_emailResetPassword),
userTableModel->getFirstName(),
userTableModel->getLastName(),
mEmailVerificationCode->getLink()
mEmailVerificationCode->getLink(),
mEmailVerificationCode->getModel()->getCode()
), mt.toString())
);
break;
@ -264,8 +281,13 @@ Gradido Login-Server\n\
return true;
}
std::string Email::replaceUserNamesAndLink(const char* src, const std::string& first_name, const std::string& last_name, const std::string& link)
{
std::string Email::replaceUserNamesAndLink(
const char* src,
const std::string& first_name,
const std::string& last_name,
const std::string& link,
Poco::UInt64 code
) {
std::string result = src;
int findCursor = 0;
static const char* functionName = "Email::replaceUserNamesAndLink";
@ -296,6 +318,12 @@ Gradido Login-Server\n\
else {
//addError(new Error(functionName, "no email placeholder found"));
}
findPos = result.find("[code]", findCursor);
if (findPos != result.npos) {
auto code_string = std::to_string(code);
findCursor = findPos + code_string.size();
result.replace(findPos, 6, code_string);
}
return result;
}
@ -376,12 +404,38 @@ Gradido Login-Server\n\
case EMAIL_ADMIN_USER_VERIFICATION_CODE_RESEND: return "email admin user verification code resend";
case EMAIL_USER_RESET_PASSWORD: return "user reset Password";
case EMAIL_ADMIN_RESET_PASSWORD_REQUEST_WITHOUT_MEMORIZED_PASSPHRASE: return "user reset password without memorized passphrase";
case EMAIL_NOTIFICATION_TRANSACTION_CREATION: return "email notification transaction creation";
case EMAIL_NOTIFICATION_TRANSACTION_TRANSFER: return "email notification transaction transfer";
case EMAIL_USER_REGISTER_OLD_ELOPAGE: return "user register automatic throw elopage";
case EMAIL_CUSTOM_TEXT: return "email custom text";
case EMAIL_MAX: return "<last entry, invalid>";
}
return "<unknown>";
}
EmailType Email::emailType(const std::string& emailTypeString)
{
if ("email user verification code" == emailTypeString) {
return EMAIL_USER_VERIFICATION_CODE;
}
else if ("email user verification code resend" == emailTypeString) {
return EMAIL_USER_VERIFICATION_CODE_RESEND;
}
else if ("email user verification code resend after long time" == emailTypeString) {
return EMAIL_USER_VERIFICATION_CODE_RESEND_AFTER_LONG_TIME;
}
else if ("email admin user verification code") {
return EMAIL_ADMIN_USER_VERIFICATION_CODE;
}
else if ("email admin user verification code resend") {
return EMAIL_ADMIN_USER_VERIFICATION_CODE_RESEND;
}
else if ("user reset Password") {
return EMAIL_USER_RESET_PASSWORD;
}
else if ("email custom text") {
return EMAIL_CUSTOM_TEXT;
}
else {
return EMAIL_ERROR;
}
}
}

View File

@ -22,21 +22,20 @@
namespace model {
using namespace Poco;
enum EmailType
enum EmailType
{
EMAIL_DEFAULT,
EMAIL_ERROR,
EMAIL_USER_VERIFICATION_CODE,
EMAIL_USER_VERIFICATION_CODE_RESEND,
EMAIL_USER_VERIFICATION_CODE_RESEND_AFTER_LONG_TIME,
EMAIL_ADMIN_USER_VERIFICATION_CODE,
EMAIL_ADMIN_USER_VERIFICATION_CODE_RESEND,
EMAIL_USER_RESET_PASSWORD,
EMAIL_ADMIN_RESET_PASSWORD_REQUEST_WITHOUT_MEMORIZED_PASSPHRASE,
EMAIL_NOTIFICATION_TRANSACTION_CREATION,
EMAIL_NOTIFICATION_TRANSACTION_TRANSFER,
EMAIL_USER_REGISTER_OLD_ELOPAGE,
EMAIL_MAX
EMAIL_DEFAULT = 0,
EMAIL_ERROR = 1,
EMAIL_USER_VERIFICATION_CODE = 2,
EMAIL_USER_VERIFICATION_CODE_RESEND = 3,
EMAIL_USER_VERIFICATION_CODE_RESEND_AFTER_LONG_TIME = 4,
EMAIL_ADMIN_USER_VERIFICATION_CODE = 5,
EMAIL_ADMIN_USER_VERIFICATION_CODE_RESEND = 6,
EMAIL_USER_RESET_PASSWORD = 7,
EMAIL_CUSTOM_TEXT = 8,
EMAIL_ADMIN_RESET_PASSWORD_REQUEST_WITHOUT_MEMORIZED_PASSPHRASE = 9,
EMAIL_USER_REGISTER_OLD_ELOPAGE = 10,
EMAIL_MAX = 11
};
class Email: public ErrorList
@ -44,6 +43,7 @@ namespace model {
public:
Email(AutoPtr<controller::EmailVerificationCode> emailVerification, AutoPtr<controller::User> user, EmailType type);
Email(AutoPtr<controller::User> user, EmailType type);
Email(AutoPtr<controller::EmailVerificationCode> emailVerification, AutoPtr<controller::User> user, const std::string& emailCustomText, const std::string& customSubject);
//! \param errors copy errors into own memory
Email(const std::string& errorHtml, EmailType type);
~Email();
@ -51,6 +51,7 @@ namespace model {
static EmailType convertTypeFromInt(int type);
inline EmailType getType() { return mType; }
static const char* emailTypeString(EmailType type);
static EmailType emailType(const std::string& emailTypeString);
inline controller::User* getUser() { if (!mUser.isNull()) return mUser.get(); return nullptr; }
virtual bool draft(Net::MailMessage* mailMessage, LanguageCatalog* langCatalog);
@ -58,7 +59,7 @@ namespace model {
protected:
std::string replaceUserNamesAndLink(const char* src, const std::string& first_name, const std::string& last_name, const std::string& link);
std::string replaceUserNamesAndLink(const char* src, const std::string& first_name, const std::string& last_name, const std::string& link, Poco::UInt64 code);
std::string replaceEmail(const char* src, const std::string& email);
std::string replaceAmount(const char* src, Poco::Int64 gradido_cent);
std::string replaceDuration(std::string src, Poco::Timespan duration, LanguageCatalog* lang);
@ -69,7 +70,9 @@ namespace model {
EmailType mType;
std::queue<Poco::Net::StringPartSource*> mAdditionalStringPartSrcs;
std::string mCustomText;
std::string mCustomSubject;
};
}
#endif //GRADIDO_LOGIN_SERVER_MODEL_EMAIL_INCLUDE
#endif //GRADIDO_LOGIN_SERVER_MODEL_EMAIL_INCLUDE

View File

@ -172,6 +172,19 @@ namespace model {
default: return "<unknown>";
}
}
EmailOptInType EmailOptIn::stringToType(const std::string& typeString)
{
if (typeString == "register") {
return EMAIL_OPT_IN_REGISTER;
}
else if (typeString == "resetPassword") {
return EMAIL_OPT_IN_RESET_PASSWORD;
}
else if (typeString == "registerDirect") {
return EMAIL_OPT_IN_REGISTER_DIRECT;
}
return EMAIL_OPT_IN_EMPTY;
}
}
}

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