diff --git a/.gitmodules b/.gitmodules index 246626547..7ebe00a4d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,24 +2,30 @@ path = gn url = https://github.com/gradido/gn.git branch = master -#[submodule "mithril_client"] -# path = community_server/mithril_client -# url = https://github.com/gradido/gradido_mithrilJS_client.git -[submodule "src/protobuf"] - path = community_server/src/protobuf - url = https://github.com/gradido/gradido_protocol.git -[submodule "dependencies/tinf"] - path = login_server/dependencies/tinf - url = https://github.com/jibsen/tinf.git -[submodule "dependencies/mariadb-connector-c"] - path = login_server/dependencies/mariadb-connector-c - url = https://github.com/MariaDB/mariadb-connector-c.git -[submodule "src/proto"] - path = login_server/src/proto - url = https://github.com/gradido/gradido_protocol.git -[submodule "dependencies/iroha-ed25519"] - path = login_server/dependencies/iroha-ed25519 - url = https://github.com/gradido/iroha-ed25519.git -[submodule "dependencies/spirit-po"] - path = login_server/dependencies/spirit-po - url = https://github.com/cbeck88/spirit-po.git \ No newline at end of file + +[submodule "login_server/dependencies/tinf"] + path = login_server/dependencies/tinf + url = https://github.com/jibsen/tinf.git +[submodule "login_server/dependencies/mariadb-connector-c"] + path = login_server/dependencies/mariadb-connector-c + url = https://github.com/MariaDB/mariadb-connector-c.git +[submodule "login_server/src/proto"] + path = login_server/src/proto + url = https://github.com/gradido/gradido_protocol.git +[submodule "login_server/dependencies/spirit-po"] + path = login_server/dependencies/spirit-po + url = https://github.com/cbeck88/spirit-po.git +[submodule "login_server/dependencies/grpc"] + path = login_server/dependencies/grpc + url = https://github.com/grpc/grpc.git +[submodule "login_server/dependencies/poco"] + path = login_server/dependencies/poco + url = https://github.com/pocoproject/poco.git +[submodule "login_server/dependencies/cmake-modules"] + path = login_server/dependencies/cmake-modules + url = https://github.com/viaduck/cmake-modules.git + +[submodule "community_server/src/protobuf"] + path = community_server/src/protobuf + url = git@github.com:gradido/gradido_protocol.git + diff --git a/community_server/.gitignore b/community_server/.gitignore index 4a3ce5c25..633978598 100644 --- a/community_server/.gitignore +++ b/community_server/.gitignore @@ -3,7 +3,6 @@ logs/ src/GPBMetadata/ tmp/ vendor/ -composer.lock websrc/node_modules/ websrc/package-lock.json mithril_client/ diff --git a/community_server/.gitmodules b/community_server/.gitmodules index 9077bcecf..8499eaac6 100644 --- a/community_server/.gitmodules +++ b/community_server/.gitmodules @@ -1,6 +1,3 @@ -#[submodule "mithril_client"] -# path = mithril_client -# url = git@github.com:gradido/gradido_mithrilJS_client.git [submodule "src/protobuf"] path = src/protobuf url = git@github.com:gradido/gradido_protocol.git diff --git a/community_server/composer.json b/community_server/composer.json index 784c6d123..4f9203bd4 100644 --- a/community_server/composer.json +++ b/community_server/composer.json @@ -6,7 +6,7 @@ "license": "MIT", "require": { "php": ">=5.6", - "cakephp/cakephp": "3.8.*", + "cakephp/cakephp": "3.9.*", "cakephp/migrations": "^2.0.0", "cakephp/plugin-installer": "^1.0", "datto/json-rpc": "^6.0", @@ -30,9 +30,9 @@ "autoload": { "psr-4": { "App\\": "src/", - "" : "src/", - "GPBMetadata\\": "src/GPBMetadata", - "Model\\Messages\\Gradido\\" : "src/Model/Messages/Gradido" + "" : "src/", + "GPBMetadata\\Gradido\\": "src/Model/Messages/GPBMetadata/Gradido/", + "Proto\\Gradido\\" : "src/Model/Messages/Proto/Gradido/" } }, "autoload-dev": { diff --git a/community_server/composer.lock b/community_server/composer.lock new file mode 100644 index 000000000..41674bb88 --- /dev/null +++ b/community_server/composer.lock @@ -0,0 +1,5577 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "8a3d1923190a6c9d6066359057844457", + "packages": [ + { + "name": "aura/intl", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/auraphp/Aura.Intl.git", + "reference": "7fce228980b19bf4dee2d7bbd6202a69b0dde926" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/auraphp/Aura.Intl/zipball/7fce228980b19bf4dee2d7bbd6202a69b0dde926", + "reference": "7fce228980b19bf4dee2d7bbd6202a69b0dde926", + "shasum": "" + }, + "require": { + "php": "^5.6|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Aura\\Intl\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aura.Intl Contributors", + "homepage": "https://github.com/auraphp/Aura.Intl/contributors" + } + ], + "description": "The Aura Intl package provides internationalization tools, specifically message translation.", + "homepage": "https://github.com/auraphp/Aura.Intl", + "keywords": [ + "g11n", + "globalization", + "i18n", + "internationalization", + "intl", + "l10n", + "localization" + ], + "support": { + "issues": "https://github.com/auraphp/Aura.Intl/issues", + "source": "https://github.com/auraphp/Aura.Intl/tree/3.x" + }, + "time": "2017-01-20T05:00:11+00:00" + }, + { + "name": "cakephp/cakephp", + "version": "3.9.8", + "source": { + "type": "git", + "url": "https://github.com/cakephp/cakephp.git", + "reference": "b0e43e810132a8b1f66cf89b038b54c090811c32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/cakephp/zipball/b0e43e810132a8b1f66cf89b038b54c090811c32", + "reference": "b0e43e810132a8b1f66cf89b038b54c090811c32", + "shasum": "" + }, + "require": { + "aura/intl": "^3.0.0", + "cakephp/chronos": "^1.0.1", + "ext-intl": "*", + "ext-mbstring": "*", + "laminas/laminas-diactoros": "^1.4.0", + "paragonie/random_compat": "^1.4|^2.0|9.99.99", + "php": ">=5.6.0,<8.0.0", + "psr/log": "^1.0.0", + "psr/simple-cache": "^1.0.0" + }, + "conflict": { + "phpunit/phpunit": "<5.7" + }, + "replace": { + "cakephp/cache": "self.version", + "cakephp/collection": "self.version", + "cakephp/core": "self.version", + "cakephp/database": "self.version", + "cakephp/datasource": "self.version", + "cakephp/event": "self.version", + "cakephp/filesystem": "self.version", + "cakephp/form": "self.version", + "cakephp/i18n": "self.version", + "cakephp/log": "self.version", + "cakephp/orm": "self.version", + "cakephp/utility": "self.version", + "cakephp/validation": "self.version" + }, + "require-dev": { + "cakephp/cakephp-codesniffer": "^3.0", + "cakephp/chronos": "^1.2.1", + "paragonie/csp-builder": "^1.4|^2.3", + "phpunit/phpunit": "^5.7.14|^6.0" + }, + "suggest": { + "ext-curl": "To enable more efficient network calls in Http\\Client.", + "ext-openssl": "To use Security::encrypt() or have secure CSRF token generation.", + "lib-ICU": "The intl PHP library, to use Text::transliterate() or Text::slug()", + "paragonie/csp-builder": "CSP builder, to use the CSP Middleware" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cake\\": "src/" + }, + "files": [ + "src/Core/functions.php", + "src/Collection/functions.php", + "src/I18n/functions.php", + "src/Utility/bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/cakephp/graphs/contributors" + } + ], + "description": "The CakePHP framework", + "homepage": "https://cakephp.org", + "keywords": [ + "conventions over configuration", + "dry", + "form", + "framework", + "mvc", + "orm", + "psr-7", + "rapid-development", + "validation" + ], + "support": { + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/cakephp/issues", + "source": "https://github.com/cakephp/cakephp" + }, + "time": "2021-03-10T02:10:31+00:00" + }, + { + "name": "cakephp/chronos", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/cakephp/chronos.git", + "reference": "ba2bab98849e7bf29b02dd634ada49ab36472959" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/chronos/zipball/ba2bab98849e7bf29b02dd634ada49ab36472959", + "reference": "ba2bab98849e7bf29b02dd634ada49ab36472959", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "athletic/athletic": "~0.1", + "cakephp/cakephp-codesniffer": "^3.0", + "phpbench/phpbench": "@dev", + "phpunit/phpunit": "<6.0 || ^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cake\\Chronos\\": "src/" + }, + "files": [ + "src/carbon_compat.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + }, + { + "name": "The CakePHP Team", + "homepage": "http://cakephp.org" + } + ], + "description": "A simple API extension for DateTime.", + "homepage": "http://cakephp.org", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/chronos/issues", + "source": "https://github.com/cakephp/chronos" + }, + "time": "2019-11-30T02:33:19+00:00" + }, + { + "name": "cakephp/migrations", + "version": "2.4.2", + "source": { + "type": "git", + "url": "https://github.com/cakephp/migrations.git", + "reference": "7fa4f1f8a4cd90df59cd8e3a46958c822abe457e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/migrations/zipball/7fa4f1f8a4cd90df59cd8e3a46958c822abe457e", + "reference": "7fa4f1f8a4cd90df59cd8e3a46958c822abe457e", + "shasum": "" + }, + "require": { + "cakephp/cache": "^3.6.0", + "cakephp/orm": "^3.6.0", + "php": ">=5.6.0", + "robmorgan/phinx": "^0.10.3|^0.11.1" + }, + "require-dev": { + "cakephp/bake": "^1.7.0", + "cakephp/cakephp": "^3.6.0", + "cakephp/cakephp-codesniffer": "^3.0", + "phpunit/phpunit": "^5.7.14|^6.0" + }, + "suggest": { + "cakephp/bake": "If you want to generate migrations." + }, + "type": "cakephp-plugin", + "autoload": { + "psr-4": { + "Migrations\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/migrations/graphs/contributors" + } + ], + "description": "Database Migration plugin for CakePHP based on Phinx", + "homepage": "https://github.com/cakephp/migrations", + "keywords": [ + "cakephp", + "migrations" + ], + "support": { + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/migrations/issues", + "source": "https://github.com/cakephp/migrations" + }, + "time": "2020-02-05T15:00:43+00:00" + }, + { + "name": "cakephp/plugin-installer", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/cakephp/plugin-installer.git", + "reference": "e27027aa2d3d8ab64452c6817629558685a064cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/plugin-installer/zipball/e27027aa2d3d8ab64452c6817629558685a064cb", + "reference": "e27027aa2d3d8ab64452c6817629558685a064cb", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.6.0" + }, + "require-dev": { + "cakephp/cakephp-codesniffer": "^3.3", + "composer/composer": "^2.0", + "phpunit/phpunit": "^5.7 || ^6.5 || ^8.5 || ^9.3" + }, + "type": "composer-plugin", + "extra": { + "class": "Cake\\Composer\\Plugin" + }, + "autoload": { + "psr-4": { + "Cake\\Composer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://cakephp.org" + } + ], + "description": "A composer installer for CakePHP 3.0+ plugins.", + "support": { + "issues": "https://github.com/cakephp/plugin-installer/issues", + "source": "https://github.com/cakephp/plugin-installer/tree/1.3.1" + }, + "time": "2020-10-29T04:00:42+00:00" + }, + { + "name": "datto/json-rpc", + "version": "6.1.0", + "source": { + "type": "git", + "url": "https://github.com/datto/php-json-rpc.git", + "reference": "ad4d735f48d80c6b53f7405e5007d97c996533f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/datto/php-json-rpc/zipball/ad4d735f48d80c6b53f7405e5007d97c996533f6", + "reference": "ad4d735f48d80c6b53f7405e5007d97c996533f6", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Datto\\JsonRpc\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0+" + ], + "authors": [ + { + "name": "Spencer Mortensen", + "email": "smortensen@datto.com", + "homepage": "http://spencermortensen.com", + "role": "Developer" + } + ], + "description": "Fully unit-tested JSON-RPC 2.0 for PHP", + "homepage": "http://datto.com", + "keywords": [ + "json", + "json-rpc", + "jsonrpc", + "php", + "php-json-rpc", + "rpc" + ], + "support": { + "issues": "https://github.com/datto/php-json-rpc/issues", + "source": "https://github.com/datto/php-json-rpc/tree/6.1.0" + }, + "time": "2020-02-28T23:54:06+00:00" + }, + { + "name": "google/protobuf", + "version": "v3.10.0", + "source": { + "type": "git", + "url": "https://github.com/protocolbuffers/protobuf-php.git", + "reference": "5dffdd2c84112e6c91fd84f92e3df96649426881" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/5dffdd2c84112e6c91fd84f92e3df96649426881", + "reference": "5dffdd2c84112e6c91fd84f92e3df96649426881", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4.8.0" + }, + "suggest": { + "ext-bcmath": "Need to support JSON deserialization" + }, + "type": "library", + "autoload": { + "psr-4": { + "Google\\Protobuf\\": "src/Google/Protobuf", + "GPBMetadata\\Google\\Protobuf\\": "src/GPBMetadata/Google/Protobuf" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "proto library for PHP", + "homepage": "https://developers.google.com/protocol-buffers/", + "keywords": [ + "proto" + ], + "support": { + "issues": "https://github.com/protocolbuffers/protobuf-php/issues", + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v3.10.0" + }, + "time": "2019-10-03T20:08:37+00:00" + }, + { + "name": "laminas/laminas-diactoros", + "version": "1.8.7p2", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-diactoros.git", + "reference": "6991c1af7c8d2c8efee81b22ba97024781824aaa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/6991c1af7c8d2c8efee81b22ba97024781824aaa", + "reference": "6991c1af7c8d2c8efee81b22ba97024781824aaa", + "shasum": "" + }, + "require": { + "laminas/laminas-zendframework-bridge": "^1.0", + "php": "^5.6 || ^7.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "replace": { + "zendframework/zend-diactoros": "~1.8.7.0" + }, + "require-dev": { + "ext-dom": "*", + "ext-libxml": "*", + "laminas/laminas-coding-standard": "~1.0", + "php-http/psr7-integration-tests": "dev-master", + "phpunit/phpunit": "^5.7.16 || ^6.0.8 || ^7.2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-release-1.8": "1.8.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions/create_uploaded_file.php", + "src/functions/marshal_headers_from_sapi.php", + "src/functions/marshal_method_from_sapi.php", + "src/functions/marshal_protocol_version_from_sapi.php", + "src/functions/marshal_uri_from_sapi.php", + "src/functions/normalize_server.php", + "src/functions/normalize_uploaded_files.php", + "src/functions/parse_cookie_header.php", + "src/functions/create_uploaded_file.legacy.php", + "src/functions/marshal_headers_from_sapi.legacy.php", + "src/functions/marshal_method_from_sapi.legacy.php", + "src/functions/marshal_protocol_version_from_sapi.legacy.php", + "src/functions/marshal_uri_from_sapi.legacy.php", + "src/functions/normalize_server.legacy.php", + "src/functions/normalize_uploaded_files.legacy.php", + "src/functions/parse_cookie_header.legacy.php" + ], + "psr-4": { + "Laminas\\Diactoros\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR HTTP Message implementations", + "homepage": "https://laminas.dev", + "keywords": [ + "http", + "laminas", + "psr", + "psr-7" + ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-diactoros/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-diactoros/issues", + "rss": "https://github.com/laminas/laminas-diactoros/releases.atom", + "source": "https://github.com/laminas/laminas-diactoros" + }, + "time": "2020-03-23T15:28:28+00:00" + }, + { + "name": "laminas/laminas-zendframework-bridge", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-zendframework-bridge.git", + "reference": "6ede70583e101030bcace4dcddd648f760ddf642" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642", + "reference": "6ede70583e101030bcace4dcddd648f760ddf642", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "laminas": { + "module": "Laminas\\ZendFrameworkBridge" + } + }, + "autoload": { + "files": [ + "src/autoload.php" + ], + "psr-4": { + "Laminas\\ZendFrameworkBridge\\": "src//" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Alias legacy ZF class names to Laminas Project equivalents.", + "keywords": [ + "ZendFramework", + "autoloading", + "laminas", + "zf" + ], + "support": { + "forum": "https://discourse.laminas.dev/", + "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues", + "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom", + "source": "https://github.com/laminas/laminas-zendframework-bridge" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2020-09-14T14:23:00+00:00" + }, + { + "name": "mobiledetect/mobiledetectlib", + "version": "2.8.37", + "source": { + "type": "git", + "url": "https://github.com/serbanghita/Mobile-Detect.git", + "reference": "9841e3c46f5bd0739b53aed8ac677fa712943df7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/9841e3c46f5bd0739b53aed8ac677fa712943df7", + "reference": "9841e3c46f5bd0739b53aed8ac677fa712943df7", + "shasum": "" + }, + "require": { + "php": ">=5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.35||~5.7" + }, + "type": "library", + "autoload": { + "classmap": [ + "Mobile_Detect.php" + ], + "psr-0": { + "Detection": "namespaced/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Serban Ghita", + "email": "serbanghita@gmail.com", + "homepage": "http://mobiledetect.net", + "role": "Developer" + } + ], + "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.", + "homepage": "https://github.com/serbanghita/Mobile-Detect", + "keywords": [ + "detect mobile devices", + "mobile", + "mobile detect", + "mobile detector", + "php mobile detect" + ], + "support": { + "issues": "https://github.com/serbanghita/Mobile-Detect/issues", + "source": "https://github.com/serbanghita/Mobile-Detect/tree/2.8.37" + }, + "funding": [ + { + "url": "https://github.com/serbanghita", + "type": "github" + } + ], + "time": "2021-02-19T21:22:57+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.99", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2018-07-02T15:55:56+00:00" + }, + { + "name": "paragonie/sodium_compat", + "version": "v1.14.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/sodium_compat.git", + "reference": "a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3", + "reference": "a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3", + "shasum": "" + }, + "require": { + "paragonie/random_compat": ">=1", + "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9" + }, + "suggest": { + "ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.", + "ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security." + }, + "type": "library", + "autoload": { + "files": [ + "autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com" + }, + { + "name": "Frank Denis", + "email": "jedisct1@pureftpd.org" + } + ], + "description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists", + "keywords": [ + "Authentication", + "BLAKE2b", + "ChaCha20", + "ChaCha20-Poly1305", + "Chapoly", + "Curve25519", + "Ed25519", + "EdDSA", + "Edwards-curve Digital Signature Algorithm", + "Elliptic Curve Diffie-Hellman", + "Poly1305", + "Pure-PHP cryptography", + "RFC 7748", + "RFC 8032", + "Salpoly", + "Salsa20", + "X25519", + "XChaCha20-Poly1305", + "XSalsa20-Poly1305", + "Xchacha20", + "Xsalsa20", + "aead", + "cryptography", + "ecdh", + "elliptic curve", + "elliptic curve cryptography", + "encryption", + "libsodium", + "php", + "public-key cryptography", + "secret-key cryptography", + "side-channel resistant" + ], + "support": { + "issues": "https://github.com/paragonie/sodium_compat/issues", + "source": "https://github.com/paragonie/sodium_compat/tree/v1.14.0" + }, + "time": "2020-12-03T16:26:19+00:00" + }, + { + "name": "psr/container", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, + "time": "2021-03-05T17:36:06+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.3" + }, + "time": "2020-03-23T09:12:05+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/master" + }, + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "robmorgan/phinx", + "version": "0.11.7", + "source": { + "type": "git", + "url": "https://github.com/cakephp/phinx.git", + "reference": "3cdde73e0c33c410e076108b3e1603fabb5b330d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/phinx/zipball/3cdde73e0c33c410e076108b3e1603fabb5b330d", + "reference": "3cdde73e0c33c410e076108b3e1603fabb5b330d", + "shasum": "" + }, + "require": { + "cakephp/collection": "^3.7", + "cakephp/database": "^3.7", + "php": ">=5.6", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/console": "^3.4|^4.0|^5.0", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "require-dev": { + "cakephp/cakephp-codesniffer": "^3.0", + "ext-json": "*", + "phpunit/phpunit": ">=5.7,<8.0", + "sebastian/comparator": ">=1.2.3" + }, + "suggest": { + "ext-json": "Install if using JSON configuration format", + "symfony/yaml": "Install if using YAML configuration format" + }, + "bin": [ + "bin/phinx" + ], + "type": "library", + "autoload": { + "psr-4": { + "Phinx\\": "src/Phinx/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Morgan", + "email": "robbym@gmail.com", + "homepage": "https://robmorgan.id.au", + "role": "Lead Developer" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com", + "homepage": "https://shadowhand.me", + "role": "Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Developer" + }, + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/phinx/graphs/contributors", + "role": "Developer" + } + ], + "description": "Phinx makes it ridiculously easy to manage the database migrations for your PHP app.", + "homepage": "https://phinx.org", + "keywords": [ + "database", + "database migrations", + "db", + "migrations", + "phinx" + ], + "support": { + "issues": "https://github.com/cakephp/phinx/issues", + "source": "https://github.com/cakephp/phinx/tree/0.11.7" + }, + "time": "2020-05-09T13:59:05+00:00" + }, + { + "name": "symfony/config", + "version": "v5.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "212d54675bf203ff8aef7d8cee8eecfb72f4a263" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/212d54675bf203ff8aef7d8cee8eecfb72f4a263", + "reference": "212d54675bf203ff8aef7d8cee8eecfb72f4a263", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/filesystem": "^4.4|^5.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/config/tree/v5.2.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-23T23:58:19+00:00" + }, + { + "name": "symfony/console", + "version": "v5.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/35f039df40a3b335ebf310f244cb242b3a83ac8d", + "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.1|^2", + "symfony/string": "^5.1" + }, + "conflict": { + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.2.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-28T09:42:18+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/master" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-09-07T11:33:47+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "8c86a82f51658188119e62cff0a050a12d09836f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/8c86a82f51658188119e62cff0a050a12d09836f", + "reference": "8c86a82f51658188119e62cff0a050a12d09836f", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.2.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-28T14:30:26+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5601e09b69f26c1828b13b6bb87cb07cddba3170", + "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-22T09:19:47+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/43a0283138253ed1d48d352ab6d0bdb3f809f248", + "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-22T09:19:47+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1", + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-22T09:19:47+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1", + "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/master" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-09-07T11:33:47+00:00" + }, + { + "name": "symfony/string", + "version": "v5.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", + "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "files": [ + "Resources/functions.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.2.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-17T17:12:15+00:00" + }, + { + "name": "symfony/yaml", + "version": "v5.2.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "298a08ddda623485208506fcee08817807a251dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/298a08ddda623485208506fcee08817807a251dd", + "reference": "298a08ddda623485208506fcee08817807a251dd", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<4.4" + }, + "require-dev": { + "symfony/console": "^4.4|^5.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v5.2.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-06T07:59:01+00:00" + }, + { + "name": "tuupola/base58", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/tuupola/base58.git", + "reference": "4cd1a3972679946e87c0746f59ff8f0760240b4c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tuupola/base58/zipball/4cd1a3972679946e87c0746f59ff8f0760240b4c", + "reference": "4cd1a3972679946e87c0746f59ff8f0760240b4c", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "require-dev": { + "overtrue/phplint": "^1.0.0", + "phpbench/phpbench": "^0.13.0", + "phpstan/phpstan": "^0.12.37", + "phpunit/phpunit": "^7.0|^8.0|^9.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "suggest": { + "ext-gmp": "GMP extension provides the fastest encoding and decoding." + }, + "type": "library", + "autoload": { + "psr-4": { + "Tuupola\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mika Tuupola", + "email": "tuupola@appelsiini.net", + "homepage": "https://appelsiini.net/", + "role": "Developer" + } + ], + "description": "Base58 encoder and decoder for arbitrary data", + "homepage": "https://github.com/tuupola/base58", + "keywords": [ + "base58" + ], + "support": { + "issues": "https://github.com/tuupola/base58/issues", + "source": "https://github.com/tuupola/base58/tree/2.1.0" + }, + "funding": [ + { + "url": "https://github.com/tuupola", + "type": "github" + } + ], + "time": "2020-09-09T11:38:20+00:00" + } + ], + "packages-dev": [ + { + "name": "ajgl/breakpoint-twig-extension", + "version": "0.3.5", + "source": { + "type": "git", + "url": "https://github.com/ajgarlag/AjglBreakpointTwigExtension.git", + "reference": "9875feea0ac4bc3c9f308c62bae4727669d6052a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ajgarlag/AjglBreakpointTwigExtension/zipball/9875feea0ac4bc3c9f308c62bae4727669d6052a", + "reference": "9875feea0ac4bc3c9f308c62bae4727669d6052a", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "twig/twig": "^1.34|^2.0|^3.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.18", + "symfony/framework-bundle": "^2.7|^3.4|^4.4|^5.2", + "symfony/phpunit-bridge": "^4.4|^5.2", + "symfony/twig-bundle": "^2.7|^3.4|^4.4|^5.2" + }, + "suggest": { + "ext-xdebug": "The Xdebug extension is required for the breakpoint to work", + "symfony/framework-bundle": "The framework bundle to integrate the extension into Symfony", + "symfony/twig-bundle": "The twig bundle to integrate the extension into Symfony" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Ajgl\\Twig\\Extension\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Antonio J. García Lagar", + "email": "aj@garcialagar.es", + "homepage": "http://aj.garcialagar.es", + "role": "developer" + } + ], + "description": "Twig extension to set breakpoints", + "homepage": "https://github.com/ajgarlag/AjglBreakpointTwigExtension", + "keywords": [ + "Xdebug", + "breakpoint", + "twig" + ], + "support": { + "issues": "https://github.com/ajgarlag/AjglBreakpointTwigExtension/issues", + "source": "https://github.com/ajgarlag/AjglBreakpointTwigExtension/tree/0.3.5" + }, + "time": "2021-02-08T10:48:05+00:00" + }, + { + "name": "aptoma/twig-markdown", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/aptoma/twig-markdown.git", + "reference": "64a9c5c7418c08faf91c4410b34bdb65fb25c23d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aptoma/twig-markdown/zipball/64a9c5c7418c08faf91c4410b34bdb65fb25c23d", + "reference": "64a9c5c7418c08faf91c4410b34bdb65fb25c23d", + "shasum": "" + }, + "require": { + "twig/twig": "~1.12" + }, + "require-dev": { + "codeclimate/php-test-reporter": "dev-master", + "erusev/parsedown": "^1.6", + "knplabs/github-api": "~1.2", + "league/commonmark": "~0.5", + "michelf/php-markdown": "~1", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "~0.6" + }, + "suggest": { + "knplabs/github-api": "Needed for using GitHub's Markdown engine provided through their API.", + "michelf/php-markdown": "Original Markdown engine with MarkdownExtra." + }, + "type": "library", + "autoload": { + "psr-0": { + "Aptoma": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joris Berthelot", + "email": "joris@berthelot.tel" + }, + { + "name": "Gunnar Lium", + "email": "gunnar@aptoma.com" + } + ], + "description": "Twig extension to work with Markdown content", + "keywords": [ + "markdown", + "twig" + ], + "support": { + "issues": "https://github.com/aptoma/twig-markdown/issues", + "source": "https://github.com/aptoma/twig-markdown/tree/master" + }, + "time": "2015-10-23T20:27:08+00:00" + }, + { + "name": "asm89/twig-cache-extension", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/asm89/twig-cache-extension.git", + "reference": "13787226956ec766f4770722082288097aebaaf3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/asm89/twig-cache-extension/zipball/13787226956ec766f4770722082288097aebaaf3", + "reference": "13787226956ec766f4770722082288097aebaaf3", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "twig/twig": "^1.0|^2.0" + }, + "require-dev": { + "doctrine/cache": "~1.0", + "phpunit/phpunit": "^5.0 || ^4.8.10" + }, + "suggest": { + "psr/cache-implementation": "To make use of PSR-6 cache implementation via PsrCacheAdapter." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alexander", + "email": "iam.asm89@gmail.com" + } + ], + "description": "Cache fragments of templates directly within Twig.", + "homepage": "https://github.com/asm89/twig-cache-extension", + "keywords": [ + "cache", + "extension", + "twig" + ], + "support": { + "issues": "https://github.com/asm89/twig-cache-extension/issues", + "source": "https://github.com/asm89/twig-cache-extension/tree/1.4.0" + }, + "abandoned": "twig/cache-extension", + "time": "2020-01-01T20:47:37+00:00" + }, + { + "name": "cakephp/bake", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/cakephp/bake.git", + "reference": "33e8ee8419ba36c13fa4074c208c93352b5530cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/bake/zipball/33e8ee8419ba36c13fa4074c208c93352b5530cf", + "reference": "33e8ee8419ba36c13fa4074c208c93352b5530cf", + "shasum": "" + }, + "require": { + "cakephp/cakephp": "^3.8.0", + "cakephp/plugin-installer": "^1.0", + "php": ">=5.6.0", + "wyrihaximus/twig-view": "^4.3.7" + }, + "require-dev": { + "cakephp/cakephp-codesniffer": "^3.0", + "phpunit/phpunit": "^5.7.14|^6.0" + }, + "type": "cakephp-plugin", + "autoload": { + "psr-4": { + "Bake\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/bake/graphs/contributors" + } + ], + "description": "Bake plugin for CakePHP 3", + "homepage": "https://github.com/cakephp/bake", + "keywords": [ + "bake", + "cakephp" + ], + "support": { + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/bake/issues", + "source": "https://github.com/cakephp/bake" + }, + "time": "2019-12-07T20:34:43+00:00" + }, + { + "name": "cakephp/cakephp-codesniffer", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/cakephp/cakephp-codesniffer.git", + "reference": "7998a191e787fd5b68cb635d7050cb0d7b55e1a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/cakephp-codesniffer/zipball/7998a191e787fd5b68cb635d7050cb0d7b55e1a1", + "reference": "7998a191e787fd5b68cb635d7050cb0d7b55e1a1", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "squizlabs/php_codesniffer": "^3.0.0" + }, + "require-dev": { + "phpunit/phpunit": "<6.0" + }, + "type": "phpcodesniffer-standard", + "autoload": { + "psr-4": { + "CakePHP\\": "CakePHP/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/cakephp-codesniffer/graphs/contributors" + } + ], + "description": "CakePHP CodeSniffer Standards", + "homepage": "https://cakephp.org", + "keywords": [ + "codesniffer", + "framework" + ], + "support": { + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/cakephp-codesniffer/issues", + "source": "https://github.com/cakephp/cakephp-codesniffer" + }, + "time": "2019-12-07T03:02:34+00:00" + }, + { + "name": "cakephp/debug_kit", + "version": "3.22.4", + "source": { + "type": "git", + "url": "https://github.com/cakephp/debug_kit.git", + "reference": "5bec3c49a2b8d9bd12655f2ec35e52ec90befe17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/debug_kit/zipball/5bec3c49a2b8d9bd12655f2ec35e52ec90befe17", + "reference": "5bec3c49a2b8d9bd12655f2ec35e52ec90befe17", + "shasum": "" + }, + "require": { + "cakephp/cakephp": "^3.7.0", + "cakephp/chronos": "^1.0.0", + "cakephp/plugin-installer": "^1.0.0", + "composer/composer": "^1.3.0", + "jdorn/sql-formatter": "^1.2.0", + "php": ">=5.6.0" + }, + "require-dev": { + "cakephp/authorization": "^1.3.2", + "cakephp/cakephp-codesniffer": "^3.0", + "phpunit/phpunit": "^5.7.14|^6.0" + }, + "suggest": { + "ext-pdo_sqlite": "DebugKit needs to store panel data in a database. SQLite is simple and easy to use." + }, + "type": "cakephp-plugin", + "autoload": { + "psr-4": { + "DebugKit\\": "src/", + "DebugKit\\Test\\Fixture\\": "tests/Fixture/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Story", + "homepage": "https://mark-story.com", + "role": "Author" + }, + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/debug_kit/graphs/contributors" + } + ], + "description": "CakePHP Debug Kit", + "homepage": "https://github.com/cakephp/debug_kit", + "keywords": [ + "cakephp", + "debug", + "kit" + ], + "support": { + "forum": "http://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/debug_kit/issues", + "source": "https://github.com/cakephp/debug_kit" + }, + "time": "2020-04-22T17:27:39+00:00" + }, + { + "name": "composer/ca-bundle", + "version": "1.2.9", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/78a0e288fdcebf92aa2318a8d3656168da6ac1a5", + "reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "psr/log": "^1.0", + "symfony/phpunit-bridge": "^4.2 || ^5", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/ca-bundle/issues", + "source": "https://github.com/composer/ca-bundle/tree/1.2.9" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-01-12T12:10:35+00:00" + }, + { + "name": "composer/composer", + "version": "1.10.21", + "source": { + "type": "git", + "url": "https://github.com/composer/composer.git", + "reference": "04021432f4a9cbd9351dd166b8c193f42c36a39c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/composer/zipball/04021432f4a9cbd9351dd166b8c193f42c36a39c", + "reference": "04021432f4a9cbd9351dd166b8c193f42c36a39c", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "composer/semver": "^1.0", + "composer/spdx-licenses": "^1.2", + "composer/xdebug-handler": "^1.1", + "justinrainbow/json-schema": "^5.2.10", + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1.0", + "seld/jsonlint": "^1.4", + "seld/phar-utils": "^1.0", + "symfony/console": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0" + }, + "conflict": { + "symfony/console": "2.8.38" + }, + "require-dev": { + "phpspec/prophecy": "^1.10", + "symfony/phpunit-bridge": "^4.2" + }, + "suggest": { + "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", + "ext-zip": "Enabling the zip extension allows you to unzip archives", + "ext-zlib": "Allow gzip compression of HTTP requests" + }, + "bin": [ + "bin/composer" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\": "src/Composer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.", + "homepage": "https://getcomposer.org/", + "keywords": [ + "autoload", + "dependency", + "package" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/composer/issues", + "source": "https://github.com/composer/composer/tree/1.10.21" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-04-01T07:16:35+00:00" + }, + { + "name": "composer/semver", + "version": "1.7.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "647490bbcaf7fc4891c58f47b825eb99d19c377a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/647490bbcaf7fc4891c58f47b825eb99d19c377a", + "reference": "647490bbcaf7fc4891c58f47b825eb99d19c377a", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5 || ^5.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/1.7.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2020-12-03T15:47:16+00:00" + }, + { + "name": "composer/spdx-licenses", + "version": "1.5.5", + "source": { + "type": "git", + "url": "https://github.com/composer/spdx-licenses.git", + "reference": "de30328a7af8680efdc03e396aad24befd513200" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/de30328a7af8680efdc03e396aad24befd513200", + "reference": "de30328a7af8680efdc03e396aad24befd513200", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Spdx\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "SPDX licenses list and validation library.", + "keywords": [ + "license", + "spdx", + "validator" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/spdx-licenses/issues", + "source": "https://github.com/composer/spdx-licenses/tree/1.5.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2020-12-03T16:04:16+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "1.4.6", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "f27e06cd9675801df441b3656569b328e04aa37c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f27e06cd9675801df441b3656569b328e04aa37c", + "reference": "f27e06cd9675801df441b3656569b328e04aa37c", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/1.4.6" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-03-25T17:01:18+00:00" + }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^8.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-11-10T18:47:58+00:00" + }, + { + "name": "jasny/twig-extensions", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/jasny/twig-extensions.git", + "reference": "30bdf3a3903c021544f36332c9d5d4d563527da4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jasny/twig-extensions/zipball/30bdf3a3903c021544f36332c9d5d4d563527da4", + "reference": "30bdf3a3903c021544f36332c9d5d4d563527da4", + "shasum": "" + }, + "require": { + "php": ">=7.0.0 | >=5.6.0", + "twig/twig": "^2.0 | ^1.12" + }, + "require-dev": { + "ext-intl": "*", + "ext-pcre": "*", + "jasny/php-code-quality": "^2.1", + "phpunit/phpunit": "^5.0" + }, + "suggest": { + "ext-intl": "Required for the use of the LocalDate Twig extension", + "ext-pcre": "Required for the use of the PCRE Twig extension" + }, + "type": "library", + "autoload": { + "psr-4": { + "Jasny\\Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Arnold Daniels", + "email": "arnold@jasny.net", + "homepage": "http://www.jasny.net" + } + ], + "description": "A set of useful Twig filters", + "homepage": "http://github.com/jasny/twig-extensions#README", + "keywords": [ + "PCRE", + "array", + "date", + "datetime", + "preg", + "regex", + "templating", + "text", + "time" + ], + "support": { + "issues": "https://github.com/jasny/twig-extensions/issues", + "source": "https://github.com/jasny/twig-extensions" + }, + "time": "2017-09-13T07:38:01+00:00" + }, + { + "name": "jdorn/sql-formatter", + "version": "v1.2.17", + "source": { + "type": "git", + "url": "https://github.com/jdorn/sql-formatter.git", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jdorn/sql-formatter/zipball/64990d96e0959dff8e059dfcdc1af130728d92bc", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "lib" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "http://jeremydorn.com/" + } + ], + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/jdorn/sql-formatter/", + "keywords": [ + "highlight", + "sql" + ], + "support": { + "issues": "https://github.com/jdorn/sql-formatter/issues", + "source": "https://github.com/jdorn/sql-formatter/tree/master" + }, + "time": "2014-01-12T16:20:24+00:00" + }, + { + "name": "josegonzalez/dotenv", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/josegonzalez/php-dotenv.git", + "reference": "f19174d9d7213a6c20e8e5e268aa7dd042d821ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/josegonzalez/php-dotenv/zipball/f19174d9d7213a6c20e8e5e268aa7dd042d821ca", + "reference": "f19174d9d7213a6c20e8e5e268aa7dd042d821ca", + "shasum": "" + }, + "require": { + "m1/env": "2.*", + "php": ">=5.5.0" + }, + "require-dev": { + "php-mock/php-mock-phpunit": "^1.1", + "satooshi/php-coveralls": "1.*", + "squizlabs/php_codesniffer": "2.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "josegonzalez\\Dotenv": [ + "src", + "tests" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jose Diaz-Gonzalez", + "email": "dotenv@josegonzalez.com", + "homepage": "http://josediazgonzalez.com", + "role": "Maintainer" + } + ], + "description": "dotenv file parsing for PHP", + "homepage": "https://github.com/josegonzalez/php-dotenv", + "keywords": [ + "configuration", + "dotenv", + "php" + ], + "support": { + "issues": "https://github.com/josegonzalez/php-dotenv/issues", + "source": "https://github.com/josegonzalez/php-dotenv/tree/master" + }, + "time": "2017-09-19T15:49:58+00:00" + }, + { + "name": "justinrainbow/json-schema", + "version": "5.2.10", + "source": { + "type": "git", + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "2ba9c8c862ecd5510ed16c6340aa9f6eadb4f31b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ba9c8c862ecd5510ed16c6340aa9f6eadb4f31b", + "reference": "2ba9c8c862ecd5510ed16c6340aa9f6eadb4f31b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", + "json-schema/json-schema-test-suite": "1.2.0", + "phpunit/phpunit": "^4.8.35" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "support": { + "issues": "https://github.com/justinrainbow/json-schema/issues", + "source": "https://github.com/justinrainbow/json-schema/tree/5.2.10" + }, + "time": "2020-05-27T16:41:55+00:00" + }, + { + "name": "m1/env", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/m1/Env.git", + "reference": "5c296e3e13450a207e12b343f3af1d7ab569f6f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/m1/Env/zipball/5c296e3e13450a207e12b343f3af1d7ab569f6f3", + "reference": "5c296e3e13450a207e12b343f3af1d7ab569f6f3", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "scrutinizer/ocular": "~1.1", + "squizlabs/php_codesniffer": "^2.3" + }, + "suggest": { + "josegonzalez/dotenv": "For loading of .env", + "m1/vars": "For loading of configs" + }, + "type": "library", + "autoload": { + "psr-4": { + "M1\\Env\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Miles Croxford", + "email": "hello@milescroxford.com", + "homepage": "http://milescroxford.com", + "role": "Developer" + } + ], + "description": "Env is a lightweight library bringing .env file parser compatibility to PHP. In short - it enables you to read .env files with PHP.", + "homepage": "https://github.com/m1/Env", + "keywords": [ + ".env", + "config", + "dotenv", + "env", + "loader", + "m1", + "parser", + "support" + ], + "support": { + "issues": "https://github.com/m1/Env/issues", + "source": "https://github.com/m1/Env/tree/2.2.0" + }, + "time": "2020-02-19T09:02:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.10.2", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2020-11-13T09:40:50+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.10.4", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4" + }, + "time": "2020-12-20T10:01:03+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^1.0.1", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/master" + }, + "time": "2017-03-05T18:14:27+00:00" + }, + { + "name": "phar-io/version", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/master" + }, + "time": "2017-03-05T17:38:23+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.2.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + }, + "time": "2020-09-03T19:13:55+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" + }, + "time": "2020-09-17T18:55:26+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "v1.10.3", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "451c3cd1418cf640de218914901e51b064abb093" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" + }, + "time": "2020-03-05T15:02:03+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "5.3.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "c89677919c5dd6d3b3852f230a663118762218ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", + "reference": "c89677919c5dd6d3b3852f230a663118762218ac", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.0", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^2.0.1", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-xdebug": "^2.5.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/5.3" + }, + "time": "2018-04-06T15:36:58+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" + }, + "time": "2017-11-27T13:52:08+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + }, + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/master" + }, + "time": "2017-02-26T11:10:40+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "791198a2c6254db10131eecfe8c06670700904db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master" + }, + "abandoned": true, + "time": "2017-11-27T05:48:46+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "6.5.14", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bac23fe7ff13dbdb461481f706f0e9fe746334b7", + "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.6.1", + "phar-io/manifest": "^1.0.1", + "phar-io/version": "^1.0", + "php": "^7.0", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^1.0.9", + "phpunit/phpunit-mock-objects": "^5.0.9", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^2.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2", + "phpunit/dbunit": "<3.0" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "^1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.5.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/6.5.14" + }, + "time": "2019-02-01T05:22:47+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "5.0.10", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/cd1cf05c553ecfec36b170070573e540b67d3f1f", + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.5", + "php": "^7.0", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.1" + }, + "conflict": { + "phpunit/phpunit": "<6.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5.11" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", + "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/5.0.10" + }, + "abandoned": true, + "time": "2018-08-09T05:50:03+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.10.7", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "a395af46999a12006213c0c8346c9445eb31640c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/a395af46999a12006213c0c8346c9445eb31640c", + "reference": "a395af46999a12006213c0c8346c9445eb31640c", + "shasum": "" + }, + "require": { + "dnoegel/php-xdg-base-dir": "0.1.*", + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "~4.0|~3.0|~2.0|~1.3", + "php": "^8.0 || ^7.0 || ^5.5.9", + "symfony/console": "~5.0|~4.0|~3.0|^2.4.2|~2.3.10", + "symfony/var-dumper": "~5.0|~4.0|~3.0|~2.7" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "hoa/console": "3.17.*" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.", + "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.10.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.10.7" + }, + "time": "2021-03-14T02:14:56+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:15:22+00:00" + }, + { + "name": "sebastian/comparator", + "version": "2.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/diff": "^2.0 || ^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/master" + }, + "time": "2018-02-01T13:46:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/master" + }, + "time": "2017-08-03T08:09:46+00:00" + }, + { + "name": "sebastian/environment", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/master" + }, + "time": "2017-07-01T08:51:00+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/6b853149eab67d4da22291d36f5b0631c0fd856e", + "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:47:53+00:00" + }, + { + "name": "sebastian/global-state", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/2.0.0" + }, + "time": "2017-04-27T15:39:26+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:40:27+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:37:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:34:24+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/master" + }, + "time": "2015-07-28T20:34:47+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/master" + }, + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "seld/jsonlint", + "version": "1.8.3", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9ad6ce79c342fbd44df10ea95511a1b24dee5b57", + "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "support": { + "issues": "https://github.com/Seldaek/jsonlint/issues", + "source": "https://github.com/Seldaek/jsonlint/tree/1.8.3" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", + "type": "tidelift" + } + ], + "time": "2020-11-11T09:19:24+00:00" + }, + { + "name": "seld/phar-utils", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/phar-utils.git", + "reference": "8674b1d84ffb47cc59a101f5d5a3b61e87d23796" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/8674b1d84ffb47cc59a101f5d5a3b61e87d23796", + "reference": "8674b1d84ffb47cc59a101f5d5a3b61e87d23796", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Seld\\PharUtils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "PHAR file format utilities, for when PHP phars you up", + "keywords": [ + "phar" + ], + "support": { + "issues": "https://github.com/Seldaek/phar-utils/issues", + "source": "https://github.com/Seldaek/phar-utils/tree/master" + }, + "time": "2020-07-07T18:42:57+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.6.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2021-04-09T00:54:41+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "0d639a0943822626290d169965804f79400e6a04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/0d639a0943822626290d169965804f79400e6a04", + "reference": "0d639a0943822626290d169965804f79400e6a04", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.2.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-15T18:55:04+00:00" + }, + { + "name": "symfony/process", + "version": "v5.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/313a38f09c77fbcdc1d223e57d368cea76a2fd2f", + "reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.15" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v5.2.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-27T10:15:41+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v5.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "89412a68ea2e675b4e44f260a5666729f77f668e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/89412a68ea2e675b4e44f260a5666729f77f668e", + "reference": "89412a68ea2e675b4e44f260a5666729f77f668e", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v5.2.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-28T09:42:18+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "75a63c33a8577608444246075ea0af0d052e452a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", + "reference": "75a63c33a8577608444246075ea0af0d052e452a", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/master" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2020-07-12T23:59:07+00:00" + }, + { + "name": "twig/twig", + "version": "v1.44.2", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "138c493c5b8ee7cff3821f80b8896d371366b5fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/138c493c5b8ee7cff3821f80b8896d371366b5fe", + "reference": "138c493c5b8ee7cff3821f80b8896d371366b5fe", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "^1.8" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.44-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v1.44.2" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2021-01-05T10:10:05+00:00" + }, + { + "name": "umpirsky/twig-php-function", + "version": "v0.1", + "source": { + "type": "git", + "url": "https://github.com/umpirsky/twig-php-function.git", + "reference": "53b4b1eb0c5eacbd7d66c504b7d809c79b4bedbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/umpirsky/twig-php-function/zipball/53b4b1eb0c5eacbd7d66c504b7d809c79b4bedbc", + "reference": "53b4b1eb0c5eacbd7d66c504b7d809c79b4bedbc", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "twig/twig": "~1.12" + }, + "require-dev": { + "phpspec/phpspec": "~2.0", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "autoload": { + "psr-0": { + "Umpirsky\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Saša Stamenković", + "email": "umpirsky@gmail.com" + } + ], + "description": "Call (almost) any PHP function from your Twig templates.", + "support": { + "issues": "https://github.com/umpirsky/twig-php-function/issues", + "source": "https://github.com/umpirsky/twig-php-function/tree/master" + }, + "time": "2016-03-12T16:36:32+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.10.0" + }, + "time": "2021-03-09T10:59:23+00:00" + }, + { + "name": "wyrihaximus/twig-view", + "version": "4.4.0", + "source": { + "type": "git", + "url": "https://github.com/cakephp/legacy-twig-view.git", + "reference": "463e1a6ed493d4fe99eaeaaf39d80172b51fc0fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/legacy-twig-view/zipball/463e1a6ed493d4fe99eaeaaf39d80172b51fc0fb", + "reference": "463e1a6ed493d4fe99eaeaaf39d80172b51fc0fb", + "shasum": "" + }, + "require": { + "ajgl/breakpoint-twig-extension": "^0.3.0", + "aptoma/twig-markdown": "^2.0", + "asm89/twig-cache-extension": "^1.0", + "cakephp/cakephp": "^3.7", + "jasny/twig-extensions": "^1.0", + "php": "^5.6 || ^7.0", + "twig/twig": "^1.27", + "umpirsky/twig-php-function": "0.1" + }, + "require-dev": { + "cakephp/bake": "^1.5", + "cakephp/debug_kit": "^3.0", + "phake/phake": "^2.3.2", + "phpunit/phpunit": "^5.7.14", + "squizlabs/php_codesniffer": "^3.4.0", + "wyrihaximus/phpunit-class-reflection-helpers": "dev-master" + }, + "type": "cakephp-plugin", + "autoload": { + "psr-4": { + "WyriHaximus\\TwigView\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com", + "homepage": "http://wyrihaximus.net/" + } + ], + "description": "Twig powered View for CakePHP3", + "keywords": [ + "cakephp", + "cakephp3", + "twig", + "view" + ], + "support": { + "issues": "https://github.com/cakephp/legacy-twig-view/issues", + "source": "https://github.com/cakephp/legacy-twig-view/tree/4.4.0" + }, + "time": "2021-04-06T15:42:50+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "psy/psysh": 0 + }, + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": ">=5.6" + }, + "platform-dev": [], + "plugin-api-version": "2.0.0" +} diff --git a/community_server/config/routes.php b/community_server/config/routes.php index ec3b5fd27..5a537b9c2 100644 --- a/community_server/config/routes.php +++ b/community_server/config/routes.php @@ -57,12 +57,12 @@ Router::scope('/', function (RouteBuilder $routes) { $csrf->whitelistCallback(function ($request) { // Skip token check for API URLs. //die($request->getParam('controller')); - $whitelist = ['JsonRequestHandler', 'ElopageWebhook']; + $whitelist = ['JsonRequestHandler', 'ElopageWebhook', 'AppRequests']; $ajaxWhitelist = ['TransactionSendCoins', 'TransactionCreations']; - + foreach($whitelist as $entry) { if($request->getParam('controller') === $entry) { - if($entry == 'ElopageWebhook') { + if($entry == 'ElopageWebhook' || $entry == 'AppRequests') { return true; } if($request->clientIp() == '127.0.0.1' || $request->clientIp() == 'localhost') { @@ -110,7 +110,11 @@ Router::scope('/', function (RouteBuilder $routes) { */ //$routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']); $routes->connect('/', ['controller' => 'Dashboard', 'action' => 'index']); + $routes->connect('/api/:action/*', ['controller' => 'AppRequests'], ['routeClass' => 'DashedRoute']); + //$routes->connect('/client', ['controller' => 'Pages', 'action' => 'display', 'js']); $routes->connect('/server', ['controller' => 'Dashboard', 'action' => 'serverIndex']); + $routes->connect('/client', ['controller' => 'Pages', 'action' => 'display', 'vue']); + $routes->connect('/vue-dev', ['controller' => 'Pages', 'action' => 'display', 'vue-dev']); //$routes->connect('/', 'https://gradido2.dario-rekowski.de/account', array('status' => 303)); /** diff --git a/community_server/docu/community-server.api.md b/community_server/docu/community-server.api.md new file mode 100644 index 000000000..6032ce0a2 --- /dev/null +++ b/community_server/docu/community-server.api.md @@ -0,0 +1,132 @@ + +# community server api + +In this examples I assume that you use gradido with docker-compose build on your local maschine + +## Konto Overview +return current account balance + +GET http://localhost/state-balances/ajaxGetBalance/-127182 + +If session is valid, return: +```json +{"state":"success","balance":174500} +``` +- balance: Gradido Cent, 4 Nachkommastellen (2 Reserve), 174500 = 17,45 GDD + +## List Transactions +List all transactions from logged in user, currently without paging +Ajax: +GET http://localhost/state-balances/ajaxListTransactions/-127182/ +or +GET http://localhost/state-balances/ajaxListTransactions/-127182/DESC +to get transaction in descending order + +Antwort: +Wenn alles okay: +```json +{"state":"success", "transactions": + [ + { + "name": "Max Mustermann", + "email": "Maxim Mustermann", + "type": "send", + "transaction_id": 2, + "date": "2021-02-19T13:25:36+00:00", + "balance": 1920000, + "memo": "a piece of cake :)", + "pubkey": "038a6f93270dc57b91d76bf110ad3863fcb7d1b08e7692e793fcdb4467e5b6a7" + } + ], + "transactionExecutingCount": 0, + "count": 1, + "gdtSum": 0, + "timeUsed": 0.04562687873840332 +} +``` + +- name: name of other involved party or empty if unknown (if other party don't belong to group) + - if type is send, name is name of receiver + - if type is receive, name is name of sender + - if type is creation currently I use a static string ("Gradido Akademie) +- email: optional, only if type is send or receive and other user is known +- pubkey: optional, only if type is send or receive and other user isn't known +- type: type of transaction + - creation: user has get gradidos created + - send: user has send another user gradidos + - receiver: user has received gradidos from another user +- transaction_id: id of transaction in db, in stage2 also the hedera sequence number of transaction +- date: date of ordering transaction (booking date) +- balance: Gradido Cent, 4 Nachkommastellen (2 Reserve), 1920000 = 192,00 GDD +- memo: Details about transaction +- pubkey: optional, if other party isn't known, hexadecimal representation of 32 Byte public key of user [0-9a-f] + +- transactionExecutingCount: how many transaction for this user currently pending and waiting for signing +- count: sum of finished transactions user is involved +- gdtSum: sum of gdt of user in cent with 2 places (Nachkommastellen) +- timeUsed: time used for getting data from db in seconds, only for analyse backend performance + +## Creation Transaction +Make a creation transaction +With new Option set in Login-Server: +```ini +unsecure.allow_auto_sign_transactions = 1 +``` +transactions can be auto-signed directly with handing in transaction. +Normally a forwarding to login-server check transactions side is neccessary to minimize security risks. + +POST http://localhost/transaction-creations/ajaxCreate +```json +{ + "session_id" : -127182, + "email": "max.musterman@gmail.de", + "amount": 10000000, + "target_date":"2021-02-19T13:25:36+00:00", + "memo":"AGE", + "auto_sign": true +} +``` +return if everything is ok: +```json +{"state":"success", "timeUsed": 0.0122} +``` +- timeUsed: time used for getting data from db in seconds, only for analyse backend performance + +## Send Coins Transaction +Make a simple GDD Transaction, send Coins from one user to other. +With new Option set in Login-Server: +```ini +unsecure.allow_auto_sign_transactions = 1 +``` +transactions can be auto-signed directly with handing in transaction. +Normally a forwarding to login-server check transactions side is neccessary to minimize security risks. + +POST http://localhost/transaction-send-coins/ajaxCreate +```json +{ + "session_id" : -127182, + "amount": 2000000, + "email": "max.musterman@gmail.de", + "memo":"Thank you :)", + "auto_sign": true +} +``` +- amout: amount to transfer, 2000000 = 200,00 GDD +- email: receiver email address, must be differ from user email +- memo: Details about transaction +- auto_sign: set to true to directly sign transaction if unsecure.allow_auto_sign_transactions = 1 is set + +return if everything is ok: +```json +{"state":"success", "timeUsed": 0.0122} +``` +- timeUsed: time used for getting data from db in seconds, only for analyse backend performance + +Than the transaction was created on community server, send to login-server, signed (if unsecure.allow_auto_sign_transactions = 1 and auto_sign = true) +and send back to community server and put into db. +After you get this answear you see the new transaction if you list transactions or call for the balance. + +Without auto-sign the transaction is pending on login-server and waits for the user to review it at +http://localhost/account/checkTransactions + + diff --git a/community_server/parse_proto.sh b/community_server/parse_proto.sh index 576b99691..e6ccb451f 100755 --- a/community_server/parse_proto.sh +++ b/community_server/parse_proto.sh @@ -16,5 +16,5 @@ #PHP_PLUGIN="$(which grpc_php_plugin)" #protoc --proto_path=./src/protobuf/gradido --php_out=./src/ --grpc_out=./src/ --plugin=protoc-gen-grpc=$PHP_PLUGIN ./src/protobuf/gradido/*.proto -protoc --proto_path=./src/protobuf/gradido --php_out=./src/ ./src/protobuf/gradido/*.proto +protoc --proto_path=./src/protobuf --php_out=./src/Model/Messages ./src/protobuf/gradido/*.proto diff --git a/community_server/skeema/gradido_community/address_types.sql b/community_server/skeema/gradido_community/address_types.sql new file mode 100644 index 000000000..cb5b1b943 --- /dev/null +++ b/community_server/skeema/gradido_community/address_types.sql @@ -0,0 +1,7 @@ +CREATE TABLE `address_types` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL, + `text` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + diff --git a/community_server/skeema/gradido_community/blockchain_types.sql b/community_server/skeema/gradido_community/blockchain_types.sql new file mode 100644 index 000000000..bd6a12604 --- /dev/null +++ b/community_server/skeema/gradido_community/blockchain_types.sql @@ -0,0 +1,17 @@ +/* + * 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. + */ +/** + * Author: einhornimmond + * Created: 06.04.2021 + */ + +CREATE TABLE `blockchain_types` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(45) NOT NULL, + `text` varchar(255) NULL, + `symbol` varchar(10) NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/community_server/skeema/gradido_community/insert/address_types.sql b/community_server/skeema/gradido_community/insert/address_types.sql new file mode 100644 index 000000000..2a6dc00a5 --- /dev/null +++ b/community_server/skeema/gradido_community/insert/address_types.sql @@ -0,0 +1,2 @@ +INSERT INTO `address_types` (`id`, `name`, `text`) VALUES +(1, 'user main', 'user main address'); diff --git a/community_server/skeema/gradido_community/insert/insert_blockchain_types.sql b/community_server/skeema/gradido_community/insert/insert_blockchain_types.sql new file mode 100644 index 000000000..0a58e4392 --- /dev/null +++ b/community_server/skeema/gradido_community/insert/insert_blockchain_types.sql @@ -0,0 +1,5 @@ +INSERT INTO `blockchain_types` (`id`, `name`, `text`, `symbol`) VALUES +(1, 'mysql', 'use mysql db as blockchain, work only with single community-server', NULL), +(2, 'hedera', 'use hedera for transactions', 'HBAR'); + + diff --git a/community_server/skeema/gradido_community/insert/insert_transaction_types.sql b/community_server/skeema/gradido_community/insert/insert_transaction_types.sql index 9dbf5b93f..02ef8374a 100644 --- a/community_server/skeema/gradido_community/insert/insert_transaction_types.sql +++ b/community_server/skeema/gradido_community/insert/insert_transaction_types.sql @@ -1,5 +1,10 @@ - INSERT INTO `transaction_types` (`id`, `name`, `text`) VALUES -(1, 'creation', 'Aktives oder Bedingungsloses Grundeinkommen.'), -(2, 'transfer', 'Einfache Überweisung'); +(1, 'creation', 'create new gradidos for member and also for group (in development)'), +(2, 'transfer', 'send gradidos from one member to another, also cross group transfer'), +(3, 'group create', 'create a new group, trigger creation of new hedera topic and new blockchain on node server'), +(4, 'group add member', 'add user to a group or move if he was already in a group'), +(5, 'group remove member', 'remove user from group, maybe he was moved elsewhere'), +(6, 'hedera topic create', 'create new topic on hedera'), +(7, 'hedera topic send message', 'send consensus message over hedera topic'), +(8, 'hedera account create', 'create new account on hedera for holding some founds with unencrypted keys'); diff --git a/community_server/skeema/gradido_community/state_group_addresses.sql b/community_server/skeema/gradido_community/state_group_addresses.sql index 1d256f3e0..698a79b98 100644 --- a/community_server/skeema/gradido_community/state_group_addresses.sql +++ b/community_server/skeema/gradido_community/state_group_addresses.sql @@ -3,5 +3,6 @@ CREATE TABLE `state_group_addresses` ( `group_id` int(10) unsigned NOT NULL, `public_key` binary(32) NOT NULL, `address_type_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + UNIQUE(`public_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/community_server/skeema/gradido_community/state_user_transactions.sql b/community_server/skeema/gradido_community/state_user_transactions.sql index 272552845..5e01cac4a 100644 --- a/community_server/skeema/gradido_community/state_user_transactions.sql +++ b/community_server/skeema/gradido_community/state_user_transactions.sql @@ -4,6 +4,6 @@ CREATE TABLE `state_user_transactions` ( `transaction_id` int UNSIGNED NOT NULL, `transaction_type_id` int UNSIGNED NOT NULL, `balance` bigint(20) DEFAULT 0, - `balance_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `balance_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/community_server/skeema/gradido_community/transaction_group_addaddress.sql b/community_server/skeema/gradido_community/transaction_group_addaddress.sql index dceac273c..cb21ed99f 100644 --- a/community_server/skeema/gradido_community/transaction_group_addaddress.sql +++ b/community_server/skeema/gradido_community/transaction_group_addaddress.sql @@ -1,7 +1,9 @@ CREATE TABLE `transaction_group_addaddress` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `transaction_id` int(10) unsigned NOT NULL, - `address_type_id` int(10) unsigned NOT NULL, + `id` int unsigned NOT NULL AUTO_INCREMENT, + `transaction_id` int unsigned NOT NULL, + `address_type_id` int unsigned NOT NULL, + `remove_from_group` BOOLEAN DEFAULT FALSE, `public_key` binary(32) NOT NULL, + `state_user_id` int unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/community_server/skeema/gradido_community/transaction_send_coins.sql b/community_server/skeema/gradido_community/transaction_send_coins.sql index f57a2175e..49423fdbc 100644 --- a/community_server/skeema/gradido_community/transaction_send_coins.sql +++ b/community_server/skeema/gradido_community/transaction_send_coins.sql @@ -1,9 +1,10 @@ CREATE TABLE `transaction_send_coins` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `transaction_id` int(10) unsigned NOT NULL, - `state_user_id` int(10) unsigned NOT NULL, + `sender_public_key` binary(32) NOT NULL, + `state_user_id` int(10) unsigned DEFAULT 0, `receiver_public_key` binary(32) NOT NULL, - `receiver_user_id` int(10) unsigned NOT NULL, + `receiver_user_id` int(10) unsigned DEFAULT 0, `amount` bigint(20) NOT NULL, `sender_final_balance` bigint(20) NOT NULL, PRIMARY KEY (`id`) diff --git a/community_server/skeema/gradido_community/transaction_types.sql b/community_server/skeema/gradido_community/transaction_types.sql index 87492e1fe..a3e6779d9 100644 --- a/community_server/skeema/gradido_community/transaction_types.sql +++ b/community_server/skeema/gradido_community/transaction_types.sql @@ -1,6 +1,6 @@ CREATE TABLE `transaction_types` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(24) COLLATE utf8mb4_unicode_ci NOT NULL, + `name` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL, `text` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/community_server/skeema/gradido_community/transactions.sql b/community_server/skeema/gradido_community/transactions.sql index 0e8c00ce6..8641f0057 100644 --- a/community_server/skeema/gradido_community/transactions.sql +++ b/community_server/skeema/gradido_community/transactions.sql @@ -2,8 +2,9 @@ CREATE TABLE `transactions` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `state_group_id` int(10) unsigned DEFAULT NULL, `transaction_type_id` int(10) unsigned NOT NULL, - `tx_hash` binary(32) DEFAULT NULL, + `tx_hash` binary(48) DEFAULT NULL, `memo` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `received` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `blockchain_type_id` bigint(20) unsigned NOT NULL DEFAULT 1, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/community_server/src/Controller/AddressTypesController.php b/community_server/src/Controller/AddressTypesController.php index 348a8e9e6..9b13a7720 100644 --- a/community_server/src/Controller/AddressTypesController.php +++ b/community_server/src/Controller/AddressTypesController.php @@ -2,7 +2,6 @@ namespace App\Controller; use App\Controller\AppController; -use Cake\I18n\Number; /** * AddressTypes Controller @@ -35,7 +34,7 @@ class AddressTypesController extends AppController public function view($id = null) { $addressType = $this->AddressTypes->get($id, [ - 'contain' => ['StateGroupAddresses', 'TransactionGroupAddaddress'] + 'contain' => ['StateGroupAddresses', 'TransactionGroupAddaddress'], ]); $this->set('addressType', $addressType); @@ -71,7 +70,7 @@ class AddressTypesController extends AppController public function edit($id = null) { $addressType = $this->AddressTypes->get($id, [ - 'contain' => [] + 'contain' => [], ]); if ($this->request->is(['patch', 'post', 'put'])) { $addressType = $this->AddressTypes->patchEntity($addressType, $this->request->getData()); diff --git a/community_server/src/Controller/AppController.php b/community_server/src/Controller/AppController.php index 83ec01572..98a690bd1 100644 --- a/community_server/src/Controller/AppController.php +++ b/community_server/src/Controller/AppController.php @@ -35,6 +35,7 @@ class AppController extends Controller { var $loginServerUrl = ''; + var $blockchainType = 'mysql'; /** * Initialization hook method. * @@ -91,12 +92,11 @@ class AppController extends Controller $stateBalancesTable = TableRegistry::getTableLocator()->get('stateBalances'); $stateBalanceQuery = $stateBalancesTable ->find('all') - ->select('amount') ->contain(false) ->where(['state_user_id' => $state_user_id]); if ($stateBalanceQuery->count() == 1) { //var_dump($stateBalanceEntry->first()); - $session->write('StateUser.balance', $stateBalanceQuery->first()->amount); + $session->write('StateUser.balance', $stateBalanceQuery->first()->decay); //echo "stateUser.balance: " . $session->read('StateUser.balance'); } } @@ -137,16 +137,42 @@ class AppController extends Controller } else { $this->loginServerUrl = Router::url('/', true); } + /* + * + * 'GradidoBlockchain' => [ + * // type: + * // - mysql: centralized blockchain in mysql db, no cross group transactions + * // - hedera: send transaction over hedera + * 'type' => 'hedera', + * // gradido nodes with blockchain (if type != mysql) + * 'nodes' => [ + * ['host' => 'http://192.168.178.225', 'port' => 13702] + * ] + * ], + */ + $blockchain = Configure::read('GradidoBlockchain'); + if($blockchain && isset($blockchain['type'])) { + $this->blockchainType = $blockchain['type']; + } } - protected function requestLogin($session_id = 0, $redirect = true) + protected function requestLogin($sessionId = 0, $redirect = true) { $session = $this->getRequest()->getSession(); // check login // disable encryption for cookies - //$this->Cookie->configKey('User', 'encryption', false); - if(!$session_id) { - $session_id = intval($this->request->getCookie('GRADIDO_LOGIN', '')); + $session_id = 0; + $php_session_id = 0; + if($session->check('session_id')) { + $php_session_id = intval($session->read('session_id')); + } + $cookie_session_id = intval($this->request->getCookie('GRADIDO_LOGIN', '')); + if($php_session_id != 0) { + $session_id = $php_session_id; + } else if($cookie_session_id != 0) { + $session_id = $cookie_session_id; + } else { + $session_id = $sessionId; } $ip = $this->request->clientIp(); if (!$session->check('client_ip')) { @@ -158,14 +184,16 @@ class AppController extends Controller if ($session_id != 0) { $userStored = $session->read('StateUser'); - + $transactionPendings = $session->read('Transactions.pending'); - $transactionExecutings = $session->read('Transactions.executing'); - + $transactionExecutings = $session->read('Transactions.executing'); + $transaction_can_signed = $session->read('Transactions.can_signed'); + if ($session->read('session_id') != $session_id || ( $userStored && (!isset($userStored['id']) || !$userStored['email_checked'])) || intval($transactionPendings) > 0 || - intval($transactionExecutings) > 0) { + intval($transactionExecutings) > 0 || + intval($transaction_can_signed > 0)) { $http = new Client(); try { @@ -189,9 +217,11 @@ class AppController extends Controller //var_dump($json); $transactionPendings = $json['Transactions.pending']; $transactionExecuting = $json['Transactions.executing']; + $transaction_can_signed = $json['Transactions.can_signed']; //echo "read transaction pending: $transactionPendings
"; $session->write('Transactions.pending', $transactionPendings); $session->write('Transactions.executing', $transactionExecuting); + $session->write('Transactions.can_signed', $transaction_can_signed); $session->write('session_id', $session_id); $stateUserTable = TableRegistry::getTableLocator()->get('StateUsers'); @@ -200,12 +230,15 @@ class AppController extends Controller $stateUserQuery = $stateUserTable ->find('all') ->where(['public_key' => $public_key_bin]) - ->contain(['StateBalances']); + ->contain('StateBalances', function ($q) { + return $q->order(['record_date' => 'DESC']) + ->limit(1); + }); if ($stateUserQuery->count() == 1) { $stateUser = $stateUserQuery->first(); if ($stateUser->first_name != $json['user']['first_name'] || $stateUser->last_name != $json['user']['last_name'] || - $stateUser->disabled != intval($json['user']['disabled']) || + $stateUser->disabled != $json['user']['disabled'] || //$stateUser->username != $json['user']['username'] || // -> throws error $stateUser->email != $json['user']['email'] @@ -221,7 +254,8 @@ class AppController extends Controller } //var_dump($stateUser); if (count($stateUser->state_balances) > 0) { - $session->write('StateUser.balance', $stateUser->state_balances[0]->amount); + + $session->write('StateUser.balance', $stateUser->state_balances[0]->decay); } $session->write('StateUser.id', $stateUser->id); //echo $stateUser['id']; @@ -258,6 +292,9 @@ class AppController extends Controller $this->Flash->error(__('Konto ist nicht aktiviert!')); } //die(json_encode($json)); + if(preg_match('/client ip/', $json['msg'])) { + return $this->redirect($this->loginServerUrl . 'account/error500/ipError', 303); + } return $this->redirect($this->loginServerUrl . 'account/', 303); } } diff --git a/community_server/src/Controller/AppRequestsController.php b/community_server/src/Controller/AppRequestsController.php new file mode 100644 index 000000000..c7ac060e9 --- /dev/null +++ b/community_server/src/Controller/AppRequestsController.php @@ -0,0 +1,274 @@ +loadComponent('JsonRequestClient'); + //$this->loadComponent('JsonRpcRequestClient'); + //$this->Auth->allow(['add', 'edit']); + $this->Auth->allow(['index', 'sendCoins', 'createCoins']); + } + + + public function index() + { + if($this->request->is('get')) { + $method = $this->request->getQuery('method'); + switch($method) { + + } + return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for get', 'details' => $method]); + } + else if($this->request->is('post')) { + $jsonData = $this->request->input('json_decode'); + //var_dump($jsonData); + if($jsonData == NULL || !isset($jsonData->method)) { + return $this->returnJson(['state' => 'error', 'msg' => 'parameter error']); + } + $method = $jsonData->method; + + switch($method) { + + } + return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); + } + return $this->returnJson(['state' => 'error', 'msg' => 'no post or get']); + } + + private function checkAndCopyRequiredFields($fields, &$param, $data = null) { + if($data == null) { + $data = $this->request->input('json_decode'); + } + foreach($fields as $field) { + if(is_array($field)) { + $one_exist = false; + foreach($field as $oneField) { + if(isset($data[$oneField])) { + $param[$oneField] = $data[$oneField]; + $one_exist = true; + break; + } + } + if(!$one_exist) { + return ['state' => 'error', 'msg' => 'missing field of set', 'details' => $field]; + } + } else { + if(!isset($data[$field])) { + return ['state' => 'error', 'msg' => 'missing field', 'details' => $field . ' not found']; + } else { + $param[$field] = $data[$field]; + } + } + } + return true; + } + + private function rewriteKeys(&$data, $replaceKeys) + { + foreach(array_keys($replaceKeys) as $key) { + $newKey = $replaceKeys[$key]; + if(isset($data[$key])) { + $data[$newKey] = $data[$key]; + unset($data[$key]); + } + } + } + + private function parseParameterForCreateTransaction(&$param, $data = null) + { + if($data == null) { + $data = $this->request->input('json_decode'); + } + $session_id = 0; + if(isset($data['session_id'])) { + $session_id = $data['session_id']; + } + $login_request_result = $this->requestLogin($session_id, false); + if($login_request_result !== true) { + return $login_request_result; + } + $session = $this->getRequest()->getSession(); + $param['session_id'] = $session->read('session_id'); + $param['blockchain_type'] = $this->blockchainType; + + $this->rewriteKeys($data, ['email' => 'target_email', 'username' => 'target_username', 'pubkey' => 'target_pubkey']); + $required_fields = $this->checkAndCopyRequiredFields(['amount', ['target_email', 'target_username', 'target_pubkey']], $param, $data); + if($required_fields !== true) { + return $required_fields; + } + + if(intval($param['amount']) <= 0) { + return ['state' => 'error', 'msg' => 'amount is invalid', 'details' => $param['amount']]; + } + + if(isset($data['memo'])) { + $param['memo'] = $data['memo']; + } + + if(isset($data['auto_sign'])) { + $param['auto_sign'] = boolval($data['auto_sign']); + } + + return true; + } + + public function sendCoins() + { + /* + * { + "session_id" : -127182, + "amount": 2000000, + "email": "max.musterman@gmail.de", + "memo":"Thank you :)", + "group": "gdd1", + "auto_sign": true + */ + if(!$this->request->is('post')) { + return $this->returnJson(['state' => 'error', 'msg' => 'no post']); + } + $data = $this->request->input('json_decode'); + $params = []; + $result = $this->parseParameterForCreateTransaction($params, $data); + if($result !== true) { + return $this->returnJson($result); + } + $required_fields = $this->checkAndCopyRequiredFields(['target_date'], $params, $data); + if($required_fields !== true) { + return $this->returnJson($required_fields); + } + $params['transaction_type'] = 'transfer'; + + $requestAnswear = $this->JsonRequestClient->sendRequest(json_encode($params), '/createTransaction'); + + + if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) { + $session = $this->getRequest()->getSession(); + $pendingTransactionCount = $session->read('Transactions.pending'); + if($pendingTransactionCount == null) { + $pendingTransactionCount = 1; + } else { + $pendingTransactionCount++; + } + $session->write('Transactions.pending', $pendingTransactionCount); + //echo "pending: " . $pendingTransactionCount; + return $this->returnJson(['state' => 'success']); + } else { + + /* + * if request contain unknown parameter format, shouldn't happen't at all + * {"state": "error", "msg": "parameter format unknown"} + * if json parsing failed + * {"state": "error", "msg": "json exception", "details":"exception text"} + * if session_id is zero or not set + * {"state": "error", "msg": "session_id invalid"} + * if session id wasn't found on login server, if server was restartet or user logged out (also per timeout, default: 15 minutes) + * {"state": "error", "msg": "session not found"} + * if session hasn't active user, shouldn't happen't at all, login-server should be checked if happen + * {"state": "code error", "msg":"user is zero"} + * if transaction type not known + * {"state": "error", "msg":"transaction_type unknown"} + * if receiver wasn't known to Login-Server + * {"state": "not found", "msg":"receiver not found"} + * if receiver account disabled, and therefor cannto receive any coins + * {"state": "disabled", "msg":"receiver is disabled"} + * if transaction was okay and will be further proccessed + * {"state":"success"} + */ + $answear_data = $requestAnswear['data']; + return $this->returnJson($answear_data); + + } + + } + + public function createCoins() + { + /* + * "session_id" : -127182, + * "email": "max.musterman@gmail.de", + * "amount": 10000000, + * "target_date":"2021-02-19T13:25:36+00:00", + * "memo":"AGE", + * "auto_sign": true + */ + if(!$this->request->is('post')) { + return $this->returnJson(['state' => 'error', 'msg' => 'no post']); + } + $data = $this->request->input('json_decode'); + $params = []; + $result = $this->parseParameterForCreateTransaction($params, $data); + if($result !== true) { + return $this->returnJson($result); + } + $required_fields = $this->checkAndCopyRequiredFields(['target_date'], $params, $data); + if($required_fields !== true) { + return $this->returnJson($required_fields); + } + $params['transaction_type'] = 'creation'; + + $requestAnswear = $this->JsonRequestClient->sendRequest(json_encode($params), '/createTransaction'); + + if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) { + $session = $this->getRequest()->getSession(); + $pendingTransactionCount = $session->read('Transactions.pending'); + if($pendingTransactionCount == null) { + $pendingTransactionCount = 1; + } else { + $pendingTransactionCount++; + } + $session->write('Transactions.pending', $pendingTransactionCount); + //echo "pending: " . $pendingTransactionCount; + return $this->returnJson(['state' => 'success']); + } else { + + /* + * if request contain unknown parameter format, shouldn't happen't at all + * {"state": "error", "msg": "parameter format unknown"} + * if json parsing failed + * {"state": "error", "msg": "json exception", "details":"exception text"} + * if session_id is zero or not set + * {"state": "error", "msg": "session_id invalid"} + * if session id wasn't found on login server, if server was restartet or user logged out (also per timeout, default: 15 minutes) + * {"state": "error", "msg": "session not found"} + * if session hasn't active user, shouldn't happen't at all, login-server should be checked if happen + * {"state": "code error", "msg":"user is zero"} + * if transaction type not known + * {"state": "error", "msg":"transaction_type unknown"} + * if receiver wasn't known to Login-Server + * {"state": "not found", "msg":"receiver not found"} + * if receiver account disabled, and therefor cannto receive any coins + * {"state": "disabled", "msg":"receiver is disabled"} + * if transaction was okay and will be further proccessed + * {"state":"success"} + */ + $answear_data = $requestAnswear['data']; + return $this->returnJson($answear_data); + + } + + } + + private function acquireAccessToken($session_id) + { + + } + +} + \ No newline at end of file diff --git a/community_server/src/Controller/BlockchainTypesController.php b/community_server/src/Controller/BlockchainTypesController.php new file mode 100644 index 000000000..2a94037df --- /dev/null +++ b/community_server/src/Controller/BlockchainTypesController.php @@ -0,0 +1,106 @@ +paginate($this->BlockchainTypes); + + $this->set(compact('blockchainTypes')); + } + + /** + * View method + * + * @param string|null $id Blockchain Type id. + * @return \Cake\Http\Response|null + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function view($id = null) + { + $blockchainType = $this->BlockchainTypes->get($id, [ + 'contain' => [], + ]); + + $this->set('blockchainType', $blockchainType); + } + + /** + * Add method + * + * @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise. + */ + public function add() + { + $blockchainType = $this->BlockchainTypes->newEntity(); + if ($this->request->is('post')) { + $blockchainType = $this->BlockchainTypes->patchEntity($blockchainType, $this->request->getData()); + if ($this->BlockchainTypes->save($blockchainType)) { + $this->Flash->success(__('The blockchain type has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The blockchain type could not be saved. Please, try again.')); + } + $this->set(compact('blockchainType')); + } + + /** + * Edit method + * + * @param string|null $id Blockchain Type id. + * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function edit($id = null) + { + $blockchainType = $this->BlockchainTypes->get($id, [ + 'contain' => [], + ]); + if ($this->request->is(['patch', 'post', 'put'])) { + $blockchainType = $this->BlockchainTypes->patchEntity($blockchainType, $this->request->getData()); + if ($this->BlockchainTypes->save($blockchainType)) { + $this->Flash->success(__('The blockchain type has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The blockchain type could not be saved. Please, try again.')); + } + $this->set(compact('blockchainType')); + } + + /** + * Delete method + * + * @param string|null $id Blockchain Type id. + * @return \Cake\Http\Response|null Redirects to index. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function delete($id = null) + { + $this->request->allowMethod(['post', 'delete']); + $blockchainType = $this->BlockchainTypes->get($id); + if ($this->BlockchainTypes->delete($blockchainType)) { + $this->Flash->success(__('The blockchain type has been deleted.')); + } else { + $this->Flash->error(__('The blockchain type could not be deleted. Please, try again.')); + } + + return $this->redirect(['action' => 'index']); + } +} diff --git a/community_server/src/Controller/Component/JsonRequestClientComponent.php b/community_server/src/Controller/Component/JsonRequestClientComponent.php index 66e65e3bb..09856d7e2 100644 --- a/community_server/src/Controller/Component/JsonRequestClientComponent.php +++ b/community_server/src/Controller/Component/JsonRequestClientComponent.php @@ -15,7 +15,7 @@ use Cake\Core\Configure; class JsonRequestClientComponent extends Component { - public function sendTransaction($session_id, $base64Message, $user_balance = 0, $auto_sign = false) { + public function sendTransaction($session_id, $base64Message, $user_balance = 0, $auto_sign = false, $blockchain_type = 'mysql') { if(!is_numeric($session_id)) { return ['state' => 'error', 'type' => 'parameter error', 'msg' => 'session_id isn\'t numeric']; } @@ -36,11 +36,17 @@ class JsonRequestClientComponent extends Component 'session_id' => $session_id, 'transaction_base64' => $base64Message, 'balance' => $user_balance, - 'auto_sign' => $auto_sign + 'auto_sign' => $auto_sign, + 'blockchain_type' => $this->blockchainType ]), '/checkTransaction'); } + public function findePublicKeyForEmailHash($emailHash) { + //'ask' = ['account_publickey' => ''] + $results = $this->sendRequestLoginServerNeighbors(json_encode(['ask' => ['account_publickey' => $emailHash]]), 'search'); + } + public function getRunningUserTasks($email) { if($email == "") { @@ -122,6 +128,39 @@ class JsonRequestClientComponent extends Component return ['state' => 'success', 'data' => $json]; } + public function sendRequestLoginServerNeighbors($transactionBody, $url) { + + $http = new Client(); + if(!Configure::check('NeighborLoginServers')) { + return ['state' => 'warning', 'msg' => 'no neighbor server configured']; + } + $nServers = Configure::read('NeighborLoginServers'); + $results = ['errors' => [], 'data' => []]; + foreach($nServers as $nServer) { + $full_url = $nServer['host'] . ':' . $nServer['port'] . '/' . $url; + $response = $http->post($full_url, $transactionBody, ['type' => 'json']); + $responseStatus = $response->getStatusCode(); + if($responseStatus != 200) { + $results['errors'][] = [ + 'state' => 'error', + 'type' => 'request error', + 'msg' => 'server response status code isn\'t 200', + 'details' => $responseStatus, + 'fullUrl' => $full_url + ]; + continue; + } + $json = $response->getJson(); + if($json == null) { + //$responseType = $response->getType(); + $results['errors'][] = ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t valid json']; + continue; + } + $results['data'][] = $json; + } + return $results; + } + static public function getLoginServerUrl() { $loginServer = Configure::read('LoginServer'); diff --git a/community_server/src/Controller/Component/JsonRpcRequestClientComponent.php b/community_server/src/Controller/Component/JsonRpcRequestClientComponent.php index 5ccf6d898..504fc8fdd 100644 --- a/community_server/src/Controller/Component/JsonRpcRequestClientComponent.php +++ b/community_server/src/Controller/Component/JsonRpcRequestClientComponent.php @@ -41,7 +41,15 @@ class JsonRpcRequestClientComponent extends Component public function sendRequest($message) { $http = new Client(); - $response = $http->post($this->getGradidoNodeUrl(), $message, ['type' => 'json']); + try { + $url = $this->pickGradidoNodeUrl(); + if(is_array($url)) { + return $url; + } + $response = $http->post($url, $message, ['type' => 'json']); + } catch(Exception $e) { + return ['state' => 'error', 'type' => 'http exception', 'details' => $e->getMessage()]; + } $responseStatus = $response->getStatusCode(); if($responseStatus != 200) { return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response status code isn\'t 200', 'details' => $responseStatus]; @@ -55,14 +63,18 @@ class JsonRpcRequestClientComponent extends Component //$responseType = $response->getType(); return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t valid json']; } - return $json; + return $json['result']; //return ['state' => 'success', 'data' => $json]; } - static public function getGradidoNodeUrl() + static public function pickGradidoNodeUrl() { - $gradidoNode = Configure::read('GradidoNode'); - return $gradidoNode['host'] . ':' . $gradidoNode['port']; + $gradidoNodes = Configure::read('GradidoBlockchain.nodes'); + if(count($gradidoNodes) == 0) { + return ['state' => 'error', 'msg' => 'no gradido nodes in config']; + } + $i = rand(0, count($gradidoNodes)-1); + return $gradidoNodes[$i]['host'] . ':' . $gradidoNodes[$i]['port']; } diff --git a/community_server/src/Controller/ErrorController.php b/community_server/src/Controller/ErrorController.php index 43bd2fb52..c5421a24d 100644 --- a/community_server/src/Controller/ErrorController.php +++ b/community_server/src/Controller/ErrorController.php @@ -54,7 +54,7 @@ class ErrorController extends AppController public function beforeRender(Event $event) { parent::beforeRender($event); - + $this->RequestHandler->renderAs($this, 'json'); $this->viewBuilder()->setTemplatePath('Error'); } diff --git a/community_server/src/Controller/JsonRequestHandlerController.php b/community_server/src/Controller/JsonRequestHandlerController.php index e5823397e..ba68f2b5a 100644 --- a/community_server/src/Controller/JsonRequestHandlerController.php +++ b/community_server/src/Controller/JsonRequestHandlerController.php @@ -10,6 +10,7 @@ use Cake\Core\Configure; use Model\Transactions\TransactionTransfer; use Model\Transactions\Transaction; +use Model\Transactions\Record; /*! * @author: Dario Rekowski# * @@ -24,6 +25,7 @@ class JsonRequestHandlerController extends AppController { { parent::initialize(); $this->loadComponent('JsonRequestClient'); + $this->loadComponent('JsonRpcRequestClient'); //$this->Auth->allow(['add', 'edit']); $this->Auth->allow('index'); } @@ -58,28 +60,277 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); - case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionGenericHash, $jsonData->error, $jsonData->errorMessage); + case 'errorInTransaction': return $this->errorInTransaction($jsonData); + case 'updateReadNode': return $this->updateReadNode(); + case 'addUser' : return $this->addUser($jsonData->user); } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } return $this->returnJson(['state' => 'error', 'msg' => 'no post or get']); } - + + private function addUser($newUser) + { + $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); + $entity = $stateUsersTable->newEntity(); + $required_fields = ['first_name', 'last_name', 'email', 'public_key', 'disabled']; + foreach($required_fields as $required_field) { + if(!isset($newUser->$required_field)) { + return $this->returnJson(['state' => 'error', 'msg' => 'missing required field in addUser', 'details' => $required_field]); + } + if('public_key' == $required_field) { + $entity->$required_field = hex2bin($newUser->public_hex); + } else { + $entity->$required_field = $newUser->$required_field; + } + } + if($stateUsersTable->save($entity)) { + return $this->returnJson(['state' => 'success']); + } else { + return $this->returnJson(['state' => 'error', 'msg' => 'error saving state_user', 'details' => $entity->getErrors()]); + } + } + + // Called from login server like a cron job every 10 minutes or after sending transaction to hedera + private function updateReadNode() + { + $this->autoRender = false; + $response = $this->response->withType('application/json'); + + $transactionsTable = TableRegistry::getTableLocator()->get('Transactions'); + $last_transaction_query = $transactionsTable->find('all')->order(['id' => 'DESC']); + $last_transaction_id = 0; + if(!$last_transaction_query->isEmpty()) { + $last_transaction_id = $last_transaction_query->first()->id; + } + $last_known_sequence_number = $last_transaction_id; + + if($last_transaction_query->count() < $last_transaction_id) { + $last_transaction_id = $last_transaction_query->count(); + } + //$last_transaction_id = 0; + + + $group_alias = Configure::read('GroupAlias'); + $result = (array)$this->JsonRpcRequestClient->request('getTransactions', ['groupAlias' => $group_alias, 'lastKnownSequenceNumber' => $last_transaction_id]); + if(isset($result['state']) && $result['state'] == 'error') { + return $this->returnJson(['state' => 'error', 'msg' => 'jsonrpc error', 'details' => ['return' => $result, 'groupAlias' => $group_alias]]); + } + /* example + $result = json_decode("[ + { + \"record_type\":\"GRADIDO_TRANSACTION\", + \"transaction\":{ + \"version_number\":1, + \"signature\":{ + \"pubkey\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\", + \"signature\":\"aed6725baacabf903e51f92503d49fa7e6b93c6402d56d9e3784be9a3366a77459213d858af46b579287aba8b1b63d206febce18bc80cec6fa63da6289e56403\" + }, + \"signature_count\":1, + \"hedera_transaction\":{ + \"consensusTimestamp\":{ + \"seconds\":1604392811, + \"nanos\":172812 + }, + \"runningHash\":\"f9ccf04137be418c3117a28bb5add6dced9745bcab74b7a2f46c182c8c98eeabf0127c131d15ebea7d0ac376f5d2de45\", + \"sequenceNumber\":94, + \"runningHashVersion\":3 + }, + \"transaction_type\":\"ADD_USER\", + \"add_user\":{ + \"user\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\" + }, + \"result\":\"result\", + \"parts\":1, + \"memo\":\"\" + } + }, + { + \"record_type\":\"GRADIDO_TRANSACTION\", + \"transaction\":{ + \"version_number\":1, + \"signature\":{ + \"pubkey\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\", + \"signature\":\"3134adcd6cbccee17c2db398f91b6b6bdd098b6306fb2fa213eb9eb5a322af9078acca4d8b0383d4e906f3139eb3369e7c1ef0f3ac5fec724be0d085ba44af0b\" + }, + \"signature_count\":2, + \"hedera_transaction\":{ + \"consensusTimestamp\":{ + \"seconds\":1604392886, + \"nanos\":1528 + }, + \"runningHash\":\"e1df5526331e3def11d6b652b8f248d20c250739b6eb98f1fe7b338901753d9d573a14601ba84f61318a48940b3c237a\", + \"sequenceNumber\":95, + \"runningHashVersion\":3 + }, + \"transaction_type\":\"ADD_USER\", + \"add_user\":{ + \"user\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\" + }, + \"result\":\"result\", + \"parts\":2, + \"memo\":\"\" + } + }, + { + \"record_type\":\"SIGNATURES\", + \"signature\":[ + { + \"pubkey\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\", + \"signature\":\"401717e768617c0f3311931c34a61e66ab362599a0e2a48ae7c4955645aec6573773985dafb84a11bfaf2bc12140c30b2f8c8ee094bc35d609bc56d15b4e9f04\" + } + ] + }, + { + \"record_type\": \"GRADIDO_TRANSACTION\", + \"transaction\":{ + \"version_number\":1, + \"signature\":{ + \"pubkey\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\", + \"signature\":\"99665dee9f2b475e426a2f449d0dae61924f6cf025903666ff72f2c7ef1af27523ebcd5fb684d17813fe7906b2f8cfe5ef4bdbb264ebf3ef80363491d9b86807\" + }, + \"signature_count\":1, + \"hedera_transaction\":{ + \"consensusTimestamp\":{ + \"seconds\":1604392904, + \"nanos\":798541 + }, + \"runningHash\":\"f1fd03610a9788e9bac01e1efb8b99bafae450f9088cb940db954842e0799235c57d842be83d998e6c21786f77f967a7\", + \"sequenceNumber\":96, + \"runningHashVersion\":3 + }, + \"transaction_type\":\"GRADIDO_CREATION\", + \"gradido_creation\":{ + \"user\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\", + \"new_balance\":10000000, + \"prev_transfer_rec_num\":0, + \"amount\":10000000 + }, + \"result\":\"result\", + \"parts\":1, + \"memo\":\"\" + } + }, + { + \"record_type\": \"GRADIDO_TRANSACTION\", + \"transaction\":{ + \"version_number\":1, + \"signature\":{ + \"pubkey\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\", + \"signature\":\"90125e0cfce61397d50ed9ba6c5df4cd4e0cf6fee8b10c70fee2898765982570d9a1208c222981429ae3c229e3fd36c2bf2333518cd0a4f0515937822e499d0b\" + }, + \"signature_count\":1, + \"hedera_transaction\":{ + \"consensusTimestamp\":{ + \"seconds\":1604392929, + \"nanos\":52539 + }, + \"runningHash\":\"a4be8f54be4f806b61d31f6bd770d7742822f14f03ffe09c07f08bac3031a06d12de5e38fec5c307149c7faf6e9879b8\", + \"sequenceNumber\":97, + \"runningHashVersion\":3 + }, + \"transaction_type\":\"LOCAL_TRANSFER\", + \"local_transfer\":{ + \"sender\":{ + \"user\":\"8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d\", + \"new_balance\":9825500, + \"prev_transfer_rec_num\":0 + }, + \"receiver\":{ + \"user\":\"2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b\", + \"new_balance\":174500, + \"prev_transfer_rec_num\":0 + }, + \"amount\":174500 + }, + \"result\":\"result\", + \"parts\":1, + \"memo\":\"\" + } + } +]", true);*/ + $part_count = -1; + $temp_record = new Record; + $errors = []; + foreach($result['blocks'] as $_record) { + if(is_string($_record)) continue; + $parse_result = $temp_record->parseRecord($_record); + + if($parse_result == true) { + $sequenceNumber = $temp_record->getSequenceNumber(); + if($part_count == -1) { + $part_count = $temp_record->getPartCount(); + } + $part_count--; + + if($part_count == 0) { + if($sequenceNumber > $last_known_sequence_number) { + $finalize_result = $temp_record->finalize(); + if($finalize_result !== true) { + $errors[] = ['msg' => 'error in finalize', 'record' => $_record, 'details' => $finalize_result, 'sequenceNumber' => $sequenceNumber]; + } + } + + $temp_record = new Record; + $part_count = -1; + } + } else { + $temp_record = new Record; + $part_count = -1; + $errors[] = ['msg' => 'error in parse record', 'record' => $_record, 'details' => $parse_result]; + } + } + if(count($errors)) { + return $this->returnJson(['state' => 'error', 'msg' => 'error in parsing records', 'details' => $errors]); + } + return $this->returnJson(['state' => 'success']); + } + + /* + * payload.set("created", created); + * payload.set("id", task_model->getID()); + * payload.set("type", task_model->getTaskTypeString()); + * payload.set("public_key", user_model->getPublicKeyHex()); + * payload.set("error", error); + * payload.set("errorMessage", errorDetails); + */ //! \param $transactionCreated creation of transaction in timestamp in seconds //! -1 if transaction couldn't decode //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 //! using sodium_crypto_generichash to calculate // hash also in base64 format //! \param $error short error name in user language - //! \param $errorDetails more detailed error message in user language - private function errorInTransaction($transactionCreated, $transactionBodyBase64GenericHash, $error, $errorDetails) { - /* - * payload.set("created", created); - * payload.set("id", task_model->getID()); - * payload.set("public_key", user_model->getPublicKeyHex()); - * payload.set("error", error); - * payload.set("errorMessage", errorDetails); - */ + //! \param $errorDetails more detailed error message in user language + private function errorInTransaction($jsonData) { + $stateErrorTable = TableRegistry::getTableLocator()->get('StateErrors'); + $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); + $transactionTypesTable = TableRegistry::getTableLocator()->get('TransactionTypes'); + $stateError = $stateErrorTable->newEntity(); + // + $pubkey = hex2bin($jsonData->public_key); + $user_query = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $pubkey]); + if($user_query->count() != 1) { + return $this->returnJson(['state' => 'error', 'msg' => 'user not found', 'details' => 'user pubkey hex:' . $jsonData->public_key]); + } + $stateError->state_user_id = $user_query->first()->id; + //$stateError->transaction_type_id + // TODO: + // - show state errors in navi_notify.ctp + $transaction_type_query = $transactionTypesTable->find('all')->select(['id'])->where(['name' => $jsonData->type]); + if($transaction_type_query->count() != 1) { + return $this->returnJson(['state' => 'error', 'msg' => 'transaction type not found', 'details' => 'transaction type name: ' . $jsonData->type]); + } + $stateError->transaction_type_id = $transaction_type_query->first()->id; + $stateError->created = $jsonData->created; + $stateError->message_json = json_encode(['task_id' => $jsonData->id, 'error' => $jsonData->error, 'errorMessage' => $jsonData->errorMessage]); + if(!$stateErrorTable->save($stateError)) { + $this->returnJsonSaveError($stateError, [ + 'state' => 'error', + 'msg' => 'error saving state_error in db', + 'details' => json_encode($stateError->getErrors()) + ]); + } + return $this->returnJson(['state' => 'success']); } private function putTransaction($transactionBase64) { diff --git a/community_server/src/Controller/PagesController.php b/community_server/src/Controller/PagesController.php index 94508ad8b..69f57356b 100644 --- a/community_server/src/Controller/PagesController.php +++ b/community_server/src/Controller/PagesController.php @@ -46,6 +46,7 @@ class PagesController extends AppController */ public function display(...$path) { + $count = count($path); if (!$count) { return $this->redirect('/'); @@ -61,6 +62,16 @@ class PagesController extends AppController if (!empty($path[1])) { $subpage = $path[1]; } + /*$session = $this->getRequest()->getSession(); + $result = $this->requestLogin(); + if($result !== true) { + return $result; + } + $user = $session->read('StateUser'); + $login_server_session = $this->request->getCookie('GRADIDO_LOGIN', '');*/ + if($page == "vue" || $page == "vue-dev") { + $this->viewBuilder()->setLayout(false); + } $this->set(compact('page', 'subpage')); try { diff --git a/community_server/src/Controller/RolesController.php b/community_server/src/Controller/RolesController.php new file mode 100644 index 000000000..80aa493d3 --- /dev/null +++ b/community_server/src/Controller/RolesController.php @@ -0,0 +1,108 @@ +paginate($this->Roles); + + $this->set(compact('roles')); + } + + /** + * View method + * + * @param string|null $id Role id. + * @return \Cake\Http\Response|null + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function view($id = null) + { + $role = $this->Roles->get($id, [ + 'contain' => [], + ]); + + $this->set('role', $role); + } + + /** + * Add method + * + * @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise. + */ + public function add() + { + $role = $this->Roles->newEntity(); + if ($this->request->is('post')) { + $role = $this->Roles->patchEntity($role, $this->request->getData()); + if ($this->Roles->save($role)) { + $this->Flash->success(__('The role has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The role could not be saved. Please, try again.')); + } + $this->set(compact('role')); + } + + /** + * Edit method + * + * @param string|null $id Role id. + * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function edit($id = null) + { + $role = $this->Roles->get($id, [ + 'contain' => [], + ]); + if ($this->request->is(['patch', 'post', 'put'])) { + $role = $this->Roles->patchEntity($role, $this->request->getData()); + if ($this->Roles->save($role)) { + $this->Flash->success(__('The role has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The role could not be saved. Please, try again.')); + } + $this->set(compact('role')); + } + + /** + * Delete method + * + * @param string|null $id Role id. + * @return \Cake\Http\Response|null Redirects to index. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function delete($id = null) + { + $this->request->allowMethod(['post', 'delete']); + $role = $this->Roles->get($id); + if ($this->Roles->delete($role)) { + $this->Flash->success(__('The role has been deleted.')); + } else { + $this->Flash->error(__('The role could not be deleted. Please, try again.')); + } + + return $this->redirect(['action' => 'index']); + } +} diff --git a/community_server/src/Controller/StateBalancesController.php b/community_server/src/Controller/StateBalancesController.php index ce5b2cac8..c89dce8db 100644 --- a/community_server/src/Controller/StateBalancesController.php +++ b/community_server/src/Controller/StateBalancesController.php @@ -2,11 +2,14 @@ namespace App\Controller; use Cake\ORM\TableRegistry; -use App\Controller\AppController; +use Cake\I18n\Time; use Model\Navigation\NaviHierarchy; use Model\Navigation\NaviHierarchyEntry; +use App\Controller\AppController; + + /** * StateBalances Controller * @@ -21,7 +24,7 @@ class StateBalancesController extends AppController { parent::initialize(); //$this->Auth->allow(['add', 'edit']); - $this->Auth->allow(['overview', 'overviewGdt', 'ajaxGetBalance', 'ajaxListTransactions']); + $this->Auth->allow(['overview', 'overviewGdt', 'ajaxListTransactions', 'ajaxGdtOverview', 'ajaxGetBalance', 'ajaxGdtTransactions']); $this->loadComponent('JsonRequestClient'); } /** @@ -38,8 +41,8 @@ class StateBalancesController extends AppController $this->set(compact('stateBalances')); } - - private function updateBalances($stateUserId) + + private function updateBalance($stateUserId) { $stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions'); $transactionsTable = TableRegistry::getTableLocator()->get('Transactions'); @@ -51,7 +54,7 @@ class StateBalancesController extends AppController ->order(['transaction_id ASC']) ->contain(false); - if(!$state_user_transactions) { + if(!$state_user_transactions || !$state_user_transactions->count()) { //debug($state_user_transactions); return true; } @@ -91,6 +94,28 @@ class StateBalancesController extends AppController if(!$create_state_balance) { $update_state_balance = true; } + } else if(!$last_state_user_transaction) { + + $creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations'); + $creationTransactions = $creationsTable + ->find('all') + ->where(['state_user_id' => $stateUserId]) + ->contain(false); + + $transferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins'); + $transferTransactions = $transferTable + ->find('all') + ->where(['OR' => ['state_user_id' => $stateUserId, 'receiver_user_id' => $stateUserId]]) + ->contain(false); + if($creationTransactions->count() > 0 || $transferTransactions->count() > 0) { + $this->addAdminError( + 'StateBalances', + 'updateBalance', [ + 'state' => 'error', + 'msg' => 'state_user_transactions is empty but it exist transactions for user' + ], + $stateUserId); + } } } // second: do what is needed @@ -176,6 +201,7 @@ class StateBalancesController extends AppController } } return true; + } public function overview() @@ -195,7 +221,10 @@ class StateBalancesController extends AppController } $user = $session->read('StateUser'); - $this->updateBalances($user['id']); + $update_balance_result = $this->updateBalance($user['id']); + if($update_balance_result !== true) { + $this->addAdminError('StateBalances', 'overview', $update_balance_result, $user['id']); + } // sendRequestGDT // listPerEmailApi @@ -215,6 +244,7 @@ class StateBalancesController extends AppController //} // // + $stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions'); $creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations'); $creationTransactions = $creationsTable @@ -283,17 +313,22 @@ class StateBalancesController extends AppController foreach ($transferTransactions as $sendCoins) { $type = ''; $otherUser = null; + $other_user_public = ''; if ($sendCoins->state_user_id == $user['id']) { $type = 'send'; if(isset($involvedUserIndices[$sendCoins->receiver_user_id])) { $otherUser = $involvedUserIndices[$sendCoins->receiver_user_id]; } + $other_user_public = bin2hex(stream_get_contents($sendCoins->receiver_public_key)); } else if ($sendCoins->receiver_user_id == $user['id']) { $type = 'receive'; if(isset($involvedUserIndices[$sendCoins->state_user_id])) { $otherUser = $involvedUserIndices[$sendCoins->state_user_id]; } + if($sendCoins->sender_public_key) { + $other_user_public = bin2hex(stream_get_contents($sendCoins->sender_public_key)); + } } if(null == $otherUser) { $otherUser = $this->StateBalances->StateUsers->newEntity(); @@ -305,17 +340,101 @@ class StateBalancesController extends AppController 'transaction_id' => $sendCoins->transaction_id, 'date' => $sendCoins->transaction->received, 'balance' => $sendCoins->amount, - 'memo' => $sendCoins->transaction->memo + 'memo' => $sendCoins->transaction->memo, + 'pubkey' => $other_user_public ]); } uasort($transactions, array($this, 'sortTransactions')); - $this->set('transactions', $transactions); + + // add decay transactions + $month_start_state_balance = null; + $current_state_balance = null; + $cursor = 0; + $transactions_reversed = array_reverse($transactions); + $maxI = count($transactions_reversed); + foreach($transactions_reversed as $i => $transaction) { + if(!isset($transaction['transaction_id'])) { + continue; + } + $transaction_id = $transaction['transaction_id']; + $decay_transaction = NULL; + $state_balance = $this->StateBalances->newEntity(); + + if($i > 0 && isset($transactions_reversed[$i-1]['transaction_id'])) { + $prev_transaction = $transactions_reversed[$i-1]; + $stateUserTransactions = $stateUserTransactionsTable + ->find() + ->where([ + 'transaction_id IN' => [$transaction_id, $prev_transaction['transaction_id']], + 'state_user_id' => $user['id'] + ]) + ->order(['transaction_id ASC']) + ->toArray(); + + $prev = $stateUserTransactions[0]; + if($prev->balance > 0) { + // var_dump($stateUserTransactions); + $current = $stateUserTransactions[1]; + $interval = $current->balance_date->diff($prev->balance_date); + $state_balance->amount = $prev->balance; + $state_balance->record_date = $prev->balance_date; + $diff_amount = $state_balance->partDecay($current->balance_date); + /* echo "prev date: $prev->balance_date, current date: $current->balance_date, interval: "; + var_dump($interval); + echo "
"; + echo "prev balance: $prev->balance
diff: $diff_amount
"; + echo "current balance: $current->balance
"; + * + */ + //echo $interval->format('%R%a days'); + $decay_transaction = [ + 'type' => 'decay', + 'balance' => -($prev->balance - $diff_amount), + 'decay_duration' => $interval->format('%a days, %H hours, %I minutes, %S seconds'), + 'memo' => '' + ]; + } + } + + if($decay_transaction) { + array_splice($transactions_reversed, $i + $cursor, 0, [$decay_transaction]); + $cursor++; + } + if($i == $maxI-1) { + $stateUserTransaction = $stateUserTransactionsTable + ->find() + ->where(['transaction_id' => $transaction_id, 'state_user_id' => $user['id']]) + ->order(['transaction_id ASC'])->first(); + //var_dump($stateUserTransaction); + $state_balance->amount = $stateUserTransaction->balance; + $state_balance->record_date = $stateUserTransaction->balance_date; + $transactions_reversed[] = [ + 'type' => 'decay', + 'balance' => -($stateUserTransaction->balance - $state_balance->decay), + 'decay_duration' => $stateUserTransaction->balance_date->timeAgoInWords(), + 'memo' => '' + ]; + + } + } + // for debugging + $calculated_balance = 0; + foreach($transactions_reversed as $tr) { + if($tr['type'] == 'send') { + $calculated_balance -= intval($tr['balance']); + } else { + $calculated_balance += intval($tr['balance']); + } + } + $this->set('calculated_balance', $calculated_balance); + + $this->set('transactions', array_reverse($transactions_reversed)); $this->set('transactionExecutingCount', $session->read('Transactions.executing')); $this->set('balance', $session->read('StateUser.balance')); $this->set('timeUsed', microtime(true) - $startTime); $this->set('gdtSum', $gdtSum); } - + public function ajaxGetBalance($session_id = 0) { if(!$session_id) { @@ -357,8 +476,9 @@ class StateBalancesController extends AppController return $this->returnJson(['state' => 'success', 'balance' => $state_balances[0]->amount]); } - - public function ajaxListTransactions($session_id = 0, $sort = 'ASC') + + + public function ajaxListTransactions($session_id, $page, $count) { if(!$session_id) { return $this->returnJson(['state' => 'error', 'msg' => 'invalid session id']); @@ -491,6 +611,42 @@ class StateBalancesController extends AppController ]); } + + + public function ajaxGdtOverview() + { + $gdtSum = 0; + $gdtCount = -1; + $session = $this->getRequest()->getSession(); + $user = $session->read('StateUser'); + + if(!$user) { + return $this->returnJson(['state' => 'error', 'msg' => 'user not found', 'details' => 'exist a valid session cookie?']); + } + $gdtEntries = $this->JsonRequestClient->sendRequestGDT(['email' => $user['email']], 'GdtEntries' . DS . 'sumPerEmailApi'); + + if('success' == $gdtEntries['state'] && 'success' == $gdtEntries['data']['state']) { + $gdtSum = intval($gdtEntries['data']['sum']); + if(isset($gdtEntries['data']['count'])) { + $gdtCount = intval($gdtEntries['data']['count']); + } + } else { + if($user) { + $this->addAdminError('StateBalancesController', 'ajaxGdtOverview', $gdtEntries, $user['id']); + } else { + $this->addAdminError('StateBalancesController', 'ajaxGdtOverview', $gdtEntries, 0); + } + } + + return $this->returnJson([ + 'state' => 'success', + 'transactions' => $transactions, + 'transactionExecutingCount' => $session->read('Transaction.executing'), + 'count' => $all_user_transactions_count + ]); + } + + public function overviewGdt() { $this->set( @@ -536,9 +692,9 @@ class StateBalancesController extends AppController //echo "gdtSum: $gdtSum
"; $this->set('gdtSum', $gdtSum); $this->set('ownEntries', $ownEntries); - $this->set('gdtSumPerEmail', $requestResult['data']['gdtSumPerEmail']); - $this->set('moreEntrysAsShown', $requestResult['data']['moreEntrysAsShown']); - $this->set('user', $user); + $this->set('gdtSumPerEmail', $requestResult['data']['gdtSumPerEmail']); + $this->set('moreEntrysAsShown', $requestResult['data']['moreEntrysAsShown']); + $this->set('user', $user); if (isset($requestResult['data']['publishers'])) { $publishers = $requestResult['data']['publishers']; @@ -549,6 +705,66 @@ class StateBalancesController extends AppController $this->Flash->error(__('Fehler beim GDT Server, bitte abwarten oder den Admin benachrichtigen!')); } } + + public function ajaxGdtTransactions() + { + $startTime = microtime(true); + $session = $this->getRequest()->getSession(); + $user = $session->read('StateUser'); + if(!$user) { + return $this->returnJson(['state' => 'error', 'msg' => 'user not found', 'details' => 'exist a valid session cookie?']); + } + + $requestResult = $this->JsonRequestClient->sendRequestGDT(['email' => $user['email']], 'GdtEntries' . DS . 'listPerEmailApi'); + $connectEntries = []; + $publishers = []; + + //var_dump($requestResult); + if('success' === $requestResult['state'] && 'success' === $requestResult['data']['state']) { + + //var_dump(array_keys($requestResult['data'])); + $ownEntries = $requestResult['data']['ownEntries']; + //$gdtEntries = $requestResult['data']['entries']; + + $gdtSum = 0; + foreach ($ownEntries as $i => $gdtEntry) { + $gdtSum += $gdtEntry['gdt']; + //echo "index: $i
"; + //var_dump($gdtEntry); + } + if (isset($requestResult['data']['connectEntrys'])) { + $connectEntries = $requestResult['data']['connectEntrys']; + + foreach ($connectEntries as $entry) { + //if(!$count) var_dump($entry); + //$count++; + $gdtSum += $entry['connect']['gdt_entry']['gdt']; + } + } + + //echo "gdtSum: $gdtSum
"; + + if (isset($requestResult['data']['publishers'])) { + $publishers = $requestResult['data']['publishers']; + } + } else { + $this->addAdminError('StateBalancesController', 'ajaxGdtTransactions', $requestResult, $user['id']); + //$this->Flash->error(__('Fehler beim GDT Server, bitte abwarten oder den Admin benachrichtigen!')); + return $this->returnJson(['state' => 'error', 'msg' => 'error from gdt server', 'details' => $requestResult]); + } + + + return $this->returnJson([ + 'state' => 'success', + 'gdtSum' => $gdtSum, + 'ownEntries' => $ownEntries, + 'connectEntries' => $connectEntries, + 'publishers' => $publishers, + 'gdtSumPerEmail' => $requestResult['data']['gdtSumPerEmail'], + 'moreEntrysAsShown' => $requestResult['data']['moreEntrysAsShown'], + 'timeUsed' => microtime(true) - $startTime + ]); + } public function sortTransactions($a, $b) { diff --git a/community_server/src/Controller/StateGroupAddressesController.php b/community_server/src/Controller/StateGroupAddressesController.php index 13f2b1f78..25afc82c7 100644 --- a/community_server/src/Controller/StateGroupAddressesController.php +++ b/community_server/src/Controller/StateGroupAddressesController.php @@ -20,7 +20,7 @@ class StateGroupAddressesController extends AppController public function index() { $this->paginate = [ - 'contain' => ['StateGroups', 'AddressTypes'] + 'contain' => ['AddressTypes'], ]; $stateGroupAddresses = $this->paginate($this->StateGroupAddresses); @@ -37,7 +37,7 @@ class StateGroupAddressesController extends AppController public function view($id = null) { $stateGroupAddress = $this->StateGroupAddresses->get($id, [ - 'contain' => ['StateGroups', 'AddressTypes'] + 'contain' => ['StateGroups', 'AddressTypes'], ]); $this->set('stateGroupAddress', $stateGroupAddress); @@ -75,7 +75,7 @@ class StateGroupAddressesController extends AppController public function edit($id = null) { $stateGroupAddress = $this->StateGroupAddresses->get($id, [ - 'contain' => [] + 'contain' => [], ]); if ($this->request->is(['patch', 'post', 'put'])) { $stateGroupAddress = $this->StateGroupAddresses->patchEntity($stateGroupAddress, $this->request->getData()); diff --git a/community_server/src/Controller/StateUserRolesController.php b/community_server/src/Controller/StateUserRolesController.php new file mode 100644 index 000000000..9238c7ad6 --- /dev/null +++ b/community_server/src/Controller/StateUserRolesController.php @@ -0,0 +1,185 @@ +loadComponent('JsonRequestClient'); + $this->Auth->allow([ +// 'search' + ]); + $this->set( + 'naviHierarchy', + (new NaviHierarchy())-> + add(new NaviHierarchyEntry(__('Startseite'), 'Dashboard', 'index', false))->add(new NaviHierarchyEntry(__('Benutzer suchen'), 'StateUsers', 'search', true)) + ); + } + + public function search() + { + $this->loadModel('StateUsers'); + $startTime = microtime(true); + I18n::setLocale('de_DE'); + $this->viewBuilder()->setLayout('frontend'); + + $searchForm = new UserSearchForm(); + + $timeUsed = microtime(true) - $startTime; + //$this->set('timeUsed', $timeUsed); + $this->set(compact('timeUsed', 'searchForm')); + + if ($this->request->is('post')) { + $requestData = $this->request->getData(); + + if ($searchForm->validate($requestData)) { + //var_dump($requestData); + $searchString = $requestData['search']; + + // find user on community server db + $globalSearch = '%' . $searchString . '%'; + $communityUsers = $this->StateUsers + ->find('all') + ->contain([]); + + $communityUsers->where(['OR' => [ + 'first_name LIKE' => $globalSearch, + 'last_name LIKE' => $globalSearch, + //'username LIKE' => $globalSearch, + 'email LIKE' => $globalSearch + ]]); + + //var_dump($communityUsers->toArray()); + $finalUserEntrys = []; + // detect states + $this->loadModel('Roles'); +// foreach ($pubkeySorted as $pubhex => $user) { + foreach($communityUsers as $communityUser) { + $finalUser = $communityUser; + $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); + + $state_user_id = $communityUser->id; + $stateUserRole = $this->StateUserRoles->find('all')->where(['state_user_id' => $state_user_id])->all(); + + $role_ids = ""; + foreach ($stateUserRole as $userRole) { + if($role_ids != "") + $role_ids .= ",".$userRole->role_id; + else + $role_ids = $userRole->role_id; + } + + $roles = $this->Roles->find('all')->where(['id IN' => explode(",",$role_ids)])->all(); + + $role_names = ""; + foreach($roles as $role) + { + if($role_names != "") + $role_names .= "
".$role->title; + else + $role_names = $role->title; + } + + $finalUser['role_name'] = $role_names; + + array_push($finalUserEntrys, $finalUser); + } + + //var_dump($pubkeySorted); + } else { + $this->Flash->error(__('Something was invalid, please try again!')); + } + $this->set('finalUserEntrys', $finalUserEntrys); + } + $timeUsed = microtime(true) - $startTime; + $this->set('timeUsed', $timeUsed); + } + + public function assignRole() + { + $this->loadModel('Roles'); + $this->loadModel('StateUsers'); + + if ($this->request->is('post')) { + $requestData = $this->request->getData(); + + $public_hex = hex2bin($requestData['public_hex']); + + $stateUser = $this->StateUsers->find('all')->where(['public_key' => $public_hex])->first(); + + foreach($requestData['role_id'] as $role_id) + { + $newStateUserRole = $this->StateUserRoles->newEntity(); + + $post_data = []; + $post_data['state_user_id'] = $stateUser->id; + $post_data['role_id'] = $role_id; + $this->StateUserRoles->patchEntity($newStateUserRole, $post_data); + $this->StateUserRoles->save($newStateUserRole); + + } + + $this->Flash->success(__('Role has been assigned to User.')); + + return $this->redirect(['controller' => 'state-user-roles', 'action' => 'search']); + + } + + $assignRoleForm = new AssignRoleForm(); + + $public_hex = $this->request->getParam('pass')[0]; + + $publichex = hex2bin($public_hex); + + $stateUser = $this->StateUsers->find('all')->where(['public_key' => $publichex])->first(); + + $stateUserRoles = $this->StateUserRoles->find('all')->where(['state_user_id' => $stateUser->id])->all(); + + $role_ids = ""; + foreach ($stateUserRoles as $userRole) { + if($role_ids != "") + $role_ids .= ",".$userRole->role_id; + else + $role_ids = $userRole->role_id; + } + + $role_ids = explode(",", $role_ids); + + $roles = $this->Roles->find('list', array('fields' => array('id', 'title'))); + + + $this->set('roles', $roles); + $this->set('stateUser', $stateUser); + $this->set('role_ids', $role_ids); + $this->set('assignRoleForm', $assignRoleForm); + $this->set('public_hex', $public_hex); + } + +} diff --git a/community_server/src/Controller/StateUserTransactionsController.php b/community_server/src/Controller/StateUserTransactionsController.php index b51dd350f..f816192f3 100644 --- a/community_server/src/Controller/StateUserTransactionsController.php +++ b/community_server/src/Controller/StateUserTransactionsController.php @@ -20,6 +20,7 @@ class StateUserTransactionsController extends AppController $this->Auth->allow(['ajaxListTransactions']); //$this->loadComponent('JsonRequestClient'); } + /** * Index method * diff --git a/community_server/src/Controller/StateUsersController.php b/community_server/src/Controller/StateUsersController.php index 43c6664c0..fc6ec8614 100644 --- a/community_server/src/Controller/StateUsersController.php +++ b/community_server/src/Controller/StateUsersController.php @@ -5,8 +5,8 @@ use Cake\Routing\Router; use Cake\I18n\I18n; use Cake\I18n\FrozenTime; use Cake\ORM\TableRegistry; -use Cake\Http\Client; use Cake\Core\Configure; +use Cake\Http\Client; use App\Controller\AppController; use App\Form\UserSearchForm; @@ -42,10 +42,11 @@ class StateUsersController extends AppController parent::initialize(); $this->loadComponent('GradidoNumber'); $this->loadComponent('JsonRequestClient'); + $this->loadComponent('Cookie'); $this->Auth->allow([ 'search', 'ajaxCopyLoginToCommunity', 'ajaxCopyCommunityToLogin', 'ajaxDelete', 'ajaxCountTransactions', 'ajaxVerificationEmailResend', - 'ajaxGetUserEmailVerificationCode', 'ajaxGetCSFRToken' + 'ajaxGetUserEmailVerificationCode', 'ajaxGetCSFRToken', 'login' ]); $this->set( 'naviHierarchy', @@ -72,11 +73,39 @@ class StateUsersController extends AppController /*public function listIdentHashes() { $stateUsers = $this->StateUsers->find('all')->toArray(); - foreach ($stateUsers as $i => $user) { - $stateUsers[$i]->identHash = TransactionCreation::DRMakeStringHash($user->email); + foreach($stateUsers as $i => $user) { + $stateUsers[$i]->identHash = TransactionCreation::DRMakeStringHash($user->email); } $this->set('stateUsers', $stateUsers); }*/ + + public function login($session_id) + { + if(isset($session_id) && intval($session_id) !== 0) { + $loginServer = Configure::read('LoginServer'); + $http = new Client(); + + try { + $url = $loginServer['host'] . ':' . $loginServer['port']; + + $response = $http->get($url . '/login', ['session_id' => $session_id]); + $json = $response->getJson(); + + if (isset($json) && count($json) > 0) { + if ($json['state'] === 'success') { + $this->Cookie->configKey('GRADIDO_LOGIN', 'encryption', false); + $this->Cookie->write('GRADIDO_LOGIN', $session_id); + return $this->redirect(['controller' => 'Dashboard', 'action' => 'index']); + } + } + } catch (\Exception $e) { + $msg = $e->getMessage(); + $this->Flash->error(__('error http request: ') . $msg); + return $this->redirect(['controller' => 'Dashboard', 'action' => 'errorHttpRequest']); + } + } + throw new NotFoundException(); + } public function search() { @@ -85,12 +114,12 @@ class StateUsersController extends AppController $this->viewBuilder()->setLayout('frontend'); $session = $this->getRequest()->getSession(); $result = $this->requestLogin(); - if ($result !== true) { - return $result; + if($result !== true) { + return $result; } $user = $session->read('StateUser'); - if ($user['role'] != 'admin') { - return $this->redirect(['controller' => 'dashboard', 'action' => 'index']); + if($user['role'] != 'admin') { + return $this->redirect(['controller' => 'dashboard', 'action' => 'index']); } $searchForm = new UserSearchForm(); @@ -102,55 +131,55 @@ class StateUsersController extends AppController $empty_string = '... empty ...'; if ($this->request->is('post')) { $finalUserEntrys = []; - $requestData = $this->request->getData(); + $requestData = $this->request->getData(); $account_state = $requestData['account_state']; if($requestData['search'] == '' && $account_state != 'all') { $requestData['search'] = $empty_string; } - if ($searchForm->validate($requestData)) { - //var_dump($requestData); - $searchString = $requestData['search']; - $searchType = 'unknown'; - if (GenericValidation::email($searchString, [])) { - $searchType = 'email'; - } - // find users on login server + if($searchForm->validate($requestData)) { + //var_dump($requestData); + $searchString = $requestData['search']; + $searchType = 'unknown'; + if(GenericValidation::email($searchString, [])) { + $searchType = 'email'; + } + // find users on login server $resultJson = $this->JsonRequestClient->getUsers($session->read('session_id'), $searchString, $account_state); - $loginServerUser = []; - if ($resultJson['state'] == 'success') { - $dataJson = $resultJson['data']; - if ($dataJson['state'] != 'success') { - if ($dataJson['msg'] == 'session not found') { - $session->destroy(); - return $this->redirect(Router::url('/', true) . 'account', 303); - } - } - //var_dump($dataJson); - if (isset($dataJson['users'])) { - $loginServerUser = $dataJson['users']; - } + $loginServerUser = []; + if($resultJson['state'] == 'success') { + $dataJson = $resultJson['data']; + if($dataJson['state'] != 'success') { + if($dataJson['msg'] == 'session not found') { + $session->destroy(); + return $this->redirect(Router::url('/', true) . 'account', 303); + } + } + //var_dump($dataJson); + if(isset($dataJson['users'])) { + $loginServerUser = $dataJson['users']; + } + } + $pubkeySorted = []; + $emptyPubkeys = []; + foreach($loginServerUser as $u) { + if(!isset($u['public_hex']) || $u['public_hex'] == '') { + array_push($emptyPubkeys, $u); + } else { + if(!isset($pubkeySorted[$u['public_hex']])) { + $pubkeySorted[$u['public_hex']] = ['login' => [], 'community' => []]; } - $pubkeySorted = []; - $emptyPubkeys = []; - foreach ($loginServerUser as $u) { - if (!isset($u['public_hex']) || $u['public_hex'] == '') { - array_push($emptyPubkeys, $u); - } else { - if (!isset($pubkeySorted[$u['public_hex']])) { - $pubkeySorted[$u['public_hex']] = ['login' => [], 'community' => []]; - } - array_push($pubkeySorted[$u['public_hex']]['login'], $u); - } - } - // find user on community server db + array_push($pubkeySorted[$u['public_hex']]['login'], $u); + } + } + // find user on community server db - $communityUsers = $this->StateUsers + $communityUsers = $this->StateUsers ->find('all') ->contain(['StateBalances' => ['fields' => ['amount', 'state_user_id']]]); - + if($account_state == 'email not activated') { if(count($pubkeySorted) > 0) { $communityUsers->where(['hex(public_key) IN' => array_keys($pubkeySorted)]); @@ -159,112 +188,110 @@ class StateUsersController extends AppController } } else { $globalSearch = '%' . $searchString . '%'; - $communityUsers->where(['OR' => [ - 'first_name LIKE' => $globalSearch, - 'last_name LIKE' => $globalSearch, - //'username LIKE' => $globalSearch, - 'email LIKE' => $globalSearch - ]]); + $communityUsers->where(['OR' => [ + 'first_name LIKE' => $globalSearch, + 'last_name LIKE' => $globalSearch, + 'email LIKE' => $globalSearch + ]]); } - //var_dump($communityUsers->toArray()); + //var_dump($communityUsers->toArray()); if($communityUsers) { - foreach ($communityUsers as $u) { - $pubkey_hex = bin2hex(stream_get_contents($u->public_key)); - $u->public_hex = $pubkey_hex; - if (!isset($pubkeySorted[$pubkey_hex])) { - $pubkeySorted[$pubkey_hex] = ['login' => [], 'community' => []]; - } - array_push($pubkeySorted[$pubkey_hex]['community'], $u); - } + foreach($communityUsers as $u) { + $pubkey_hex = bin2hex(stream_get_contents($u->public_key)); + $u->public_hex = $pubkey_hex; + if(!isset($pubkeySorted[$pubkey_hex])) { + $pubkeySorted[$pubkey_hex] = ['login' => [], 'community' => []]; + } + array_push($pubkeySorted[$pubkey_hex]['community'], $u); + } } - // detect states - foreach ($pubkeySorted as $pubhex => $user) { - $finalUser = []; - $state = 'account created'; - $color = 'secondary'; - $finalUser['balance'] = 0; - $finalUser['pubkeyhex'] = $pubhex; - $finalUser['created'] = null; + // detect states + foreach($pubkeySorted as $pubhex => $user) { + $finalUser = []; + $state = 'account created'; + $color = 'secondary'; + $finalUser['balance'] = 0; + $finalUser['pubkeyhex'] = $pubhex; + $finalUser['created'] = null; - if (count($user['community']) == 1) { - if (isset($user['community'][0]->state_balances) && - isset($user['community'][0]->state_balances[0]['amount'])) { - $finalUser['balance'] = $user['community'][0]->state_balances[0]->amount; - } - } - - if (count($user['login']) == 0) { - $state = 'account not on login-server'; - $color = 'danger'; - if (count($user['community']) == 1) { - $c_user = $user['community'][0]; - $finalUser['name'] = $c_user->first_name . ' ' . $c_user->last_name; - $finalUser['first_name'] = $c_user->first_name; - $finalUser['last_name'] = $c_user->last_name; - //$finalUser['username'] = $c_user->username; - $finalUser['email'] = $c_user->email; - } - } elseif (count($user['login']) == 1) { - if ($user['login'][0]['email_checked'] == true) { - $state = 'email activated'; - $color = 'primary'; - - if (count($user['community']) == 1) { - $state = 'account copied to community'; - $color = 'success'; - //var_dump($user['community'][0]->state_balances[0]['amount']); - } - } else { - $state = 'email not activated'; - $color = 'warning'; - } - - $l_user = $user['login'][0]; - $finalUser['name'] = $l_user['first_name'] . ' ' . $l_user['last_name']; - $finalUser['first_name'] = $l_user['first_name']; - $finalUser['last_name'] = $l_user['last_name']; - //$finalUser['username'] = $l_user['username']; - $finalUser['email'] = $l_user['email']; - $finalUser['created'] = new FrozenTime($l_user['created']); - } else { - $state = 'account multiple times on login-server'; - $color = 'danger'; - } - $finalUser['indicator'] = ['name' => $state, 'color' => $color]; - array_push($finalUserEntrys, $finalUser); + if(count($user['community']) == 1) { + if(isset($user['community'][0]->state_balances) && + isset($user['community'][0]->state_balances[0]['amount'])) { + $finalUser['balance'] = $user['community'][0]->state_balances[0]->amount; } + } - foreach ($emptyPubkeys as $user) { - $finalUser = []; - $state = 'account not on community server'; - $color = 'secondary'; - if ($user['email_checked'] == false) { - $state = 'email not activated'; - $color = 'warning'; - } else { - $state = 'no keys'; - $color = 'warning'; - } - $finalUser['balance'] = 0; - $finalUser['pubkeyhex'] = ''; - $finalUser['name'] = $user['first_name'] . ' ' . $user['last_name']; - $finalUser['first_name'] = $user['first_name']; - $finalUser['last_name'] = $user['last_name']; - //$finalUser['username'] = $user['username']; - $finalUser['email'] = $user['email']; - $finalUser['created'] = new FrozenTime($user['created']); - $finalUser['indicator'] = ['name' => $state, 'color' => $color]; - array_push($finalUserEntrys, $finalUser); + if(count($user['login']) == 0) { + $state = 'account not on login-server'; + $color = 'danger'; + if(count($user['community']) == 1) { + $c_user = $user['community'][0]; + $finalUser['name'] = $c_user->first_name . ' ' . $c_user->last_name; + $finalUser['first_name'] = $c_user->first_name; + $finalUser['last_name'] = $c_user->last_name; + $finalUser['email'] = $c_user->email; } - //var_dump($pubkeySorted); - } else { - $this->Flash->error(__('Something was invalid, please try again!')); + } else if(count($user['login']) == 1) { + if($user['login'][0]['email_checked'] == true) { + $state = 'email activated'; + $color = 'primary'; + + if(count($user['community']) == 1) { + $state = 'account copied to community'; + $color = 'success'; + //var_dump($user['community'][0]->state_balances[0]['amount']); + } + + } else { + $state = 'email not activated'; + $color = 'warning'; + } + + $l_user = $user['login'][0]; + $finalUser['name'] = $l_user['first_name'] . ' ' . $l_user['last_name']; + $finalUser['first_name'] = $l_user['first_name']; + $finalUser['last_name'] = $l_user['last_name']; + $finalUser['email'] = $l_user['email']; + $finalUser['created'] = new FrozenTime($l_user['created']); + + } else { + $state = 'account multiple times on login-server'; + $color = 'danger'; + } + $finalUser['indicator'] = ['name' => $state, 'color' => $color]; + array_push($finalUserEntrys, $finalUser); } - $this->set('finalUserEntrys', $finalUserEntrys); + foreach($emptyPubkeys as $user) { + $finalUser = []; + $state = 'account not on community server'; + $color = 'secondary'; + if($user['email_checked'] == false) { + $state = 'email not activated'; + $color = 'warning'; + } else { + $state = 'no keys'; + $color = 'warning'; + } + $finalUser['balance'] = 0; + $finalUser['pubkeyhex'] = ''; + $finalUser['name'] = $user['first_name'] . ' ' . $user['last_name']; + $finalUser['first_name'] = $user['first_name']; + $finalUser['last_name'] = $user['last_name']; + $finalUser['email'] = $user['email']; + $finalUser['created'] = new FrozenTime($user['created']); + $finalUser['indicator'] = ['name' => $state, 'color' => $color]; + array_push($finalUserEntrys, $finalUser); + } + //var_dump($pubkeySorted); + } else { + $this->Flash->error(__('Something was invalid, please try again!')); + } + + $this->set('finalUserEntrys', $finalUserEntrys); } $timeUsed = microtime(true) - $startTime; $this->set('timeUsed', $timeUsed); @@ -272,187 +299,189 @@ class StateUsersController extends AppController public function ajaxCopyCommunityToLogin() { - $session = $this->getRequest()->getSession(); - $result = $this->requestLogin(); - if ($result !== true) { - return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); - } - $user = $session->read('StateUser'); - if ($user['role'] != 'admin') { - return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); - } - if ($this->request->is('post')) { - $jsonData = $this->request->input('json_decode', true); - } - return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); + $session = $this->getRequest()->getSession(); + $result = $this->requestLogin(); + if($result !== true) { + return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); + } + $user = $session->read('StateUser'); + if($user['role'] != 'admin') { + return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); + } + if($this->request->is('post')) { + $jsonData = $this->request->input('json_decode', true); + } + return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); } public function ajaxCopyLoginToCommunity() { - $session = $this->getRequest()->getSession(); - $result = $this->requestLogin(); - if ($result !== true) { - return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); - } - $user = $session->read('StateUser'); - if ($user['role'] != 'admin') { - return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); - } + $session = $this->getRequest()->getSession(); + $result = $this->requestLogin(); + if($result !== true) { + return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); + } + $user = $session->read('StateUser'); + if($user['role'] != 'admin') { + return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); + } - if ($this->request->is('post')) { - $jsonData = $this->request->input('json_decode', true); - //$user = $jsonData['user']; - //var_dump($jsonData); + if($this->request->is('post')) { + $jsonData = $this->request->input('json_decode', true); + //$user = $jsonData['user']; + //var_dump($jsonData); - $newStateUser = $this->StateUsers->newEntity(); - $this->StateUsers->patchEntity($newStateUser, $jsonData); - $newStateUser->public_key = hex2bin($jsonData['pubkeyhex']); + $newStateUser = $this->StateUsers->newEntity(); + $this->StateUsers->patchEntity($newStateUser, $jsonData); + $newStateUser->public_key = hex2bin($jsonData['pubkeyhex']); - if (!$this->StateUsers->save($newStateUser)) { - return $this->returnJson(['state' => 'error', 'msg' => 'error by saving', 'details' => json_encode($newStateUser->errors())]); - } + if(!$this->StateUsers->save($newStateUser)) { + return $this->returnJson(['state' => 'error', 'msg' => 'error by saving', 'details' => json_encode($newStateUser->errors())]); + } - return $this->returnJson(['state' => 'success']); - } - return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); + return $this->returnJson(['state' => 'success']); + } + return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); } public function ajaxVerificationEmailResend() { - $session = $this->getRequest()->getSession(); - $result = $this->requestLogin(); - if ($result !== true) { - return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); - } - $user = $session->read('StateUser'); - if ($user['role'] != 'admin') { - return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); - } - if ($this->request->is('post')) { - $jsonData = $this->request->input('json_decode', true); - $email = $jsonData['email']; - $session_id = $session->read('session_id'); + $session = $this->getRequest()->getSession(); + $result = $this->requestLogin(); + if($result !== true) { + return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); + } + $user = $session->read('StateUser'); + if($user['role'] != 'admin') { + return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); + } + if($this->request->is('post')) { + $jsonData = $this->request->input('json_decode', true); + $email = $jsonData['email']; + $session_id = $session->read('session_id'); - return $this->returnJson($this->JsonRequestClient->sendRequest(json_encode([ + return $this->returnJson($this->JsonRequestClient->sendRequest(json_encode([ 'session_id' => $session_id, 'email' => $email - ]), '/adminEmailVerificationResend')); - /*return $this->sendRequest(json_encode([ + ]), '/adminEmailVerificationResend')); + /*return $this->sendRequest(json_encode([ 'session_id' => $session_id, 'search' => $searchString - ]), '/getUsers');*/ - } - return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); + ]), '/getUsers');*/ + } + return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); } public function ajaxGetUserEmailVerificationCode() { - $session = $this->getRequest()->getSession(); - $result = $this->requestLogin(); - if ($result !== true) { - return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); - } - $user = $session->read('StateUser'); - if ($user['role'] != 'admin') { - return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); - } - if ($this->request->is('post')) { - $jsonData = $this->request->input('json_decode', true); - $email = $jsonData['email']; - $session_id = $session->read('session_id'); + $session = $this->getRequest()->getSession(); + $result = $this->requestLogin(); + if($result !== true) { + return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); + } + $user = $session->read('StateUser'); + if($user['role'] != 'admin') { + return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); + } + if($this->request->is('post')) { + $jsonData = $this->request->input('json_decode', true); + $email = $jsonData['email']; + $session_id = $session->read('session_id'); - return $this->returnJson($this->JsonRequestClient->sendRequest(json_encode([ + return $this->returnJson($this->JsonRequestClient->sendRequest(json_encode([ 'session_id' => $session_id, 'email' => $email, 'ask' => ['EmailVerificationCode.Register', 'loginServer.path'] - ]), '/getUserInfos')); - } - return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); + ]), '/getUserInfos')); + } + return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); } public function ajaxDelete() { - $session = $this->getRequest()->getSession(); - $result = $this->requestLogin(); - if ($result !== true) { - return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); - } - $user = $session->read('StateUser'); - if ($user['role'] != 'admin') { - return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); - } + $session = $this->getRequest()->getSession(); + $result = $this->requestLogin(); + if($result !== true) { + return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); + } + $user = $session->read('StateUser'); + if($user['role'] != 'admin') { + return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); + } - if ($this->request->is('post')) { - $jsonData = $this->request->input('json_decode', true); - //$user = $jsonData['user']; - //var_dump($jsonData); - $pubkey = hex2bin($jsonData['pubkeyhex']); - $stateUsers = $this->StateUsers->find('all')->where(['public_key' => $pubkey]); - if ($stateUsers->count() != 1) { - return $this->returnJson(['state' => 'error', 'msg' => 'invalid result count']); - } + if($this->request->is('post')) { + $jsonData = $this->request->input('json_decode', true); + //$user = $jsonData['user']; + //var_dump($jsonData); + $pubkey = hex2bin($jsonData['pubkeyhex']); + $stateUsers = $this->StateUsers->find('all')->where(['public_key' => $pubkey]); + if($stateUsers->count() != 1) { + return $this->returnJson(['state' => 'error', 'msg' => 'invalid result count']); + } - if ($this->StateUsers->delete($stateUsers->first())) { - return $this->returnJson(['state' => 'success']); - } else { - return $this->returnJson(['state' => 'error', 'msg' => 'error by deleting', 'details' => json_encode($stateUser->errors())]); - } - } - return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); + if ($this->StateUsers->delete($stateUsers->first())) { + return $this->returnJson(['state' => 'success']); + } else { + return $this->returnJson(['state' => 'error', 'msg' => 'error by deleting', 'details' => json_encode($stateUser->errors())]); + } + } + return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); } public function ajaxCountTransactions() { - $session = $this->getRequest()->getSession(); - $result = $this->requestLogin(); - if ($result !== true) { - return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); - } - $user = $session->read('StateUser'); - if ($user['role'] != 'admin') { - return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); - } + $session = $this->getRequest()->getSession(); + $result = $this->requestLogin(); + if($result !== true) { + return $this->returnJson(['state' => 'error', 'msg' => 'invalid session']); + } + $user = $session->read('StateUser'); + if($user['role'] != 'admin') { + return $this->returnJson(['state' => 'error', 'msg' => 'not an admin']); + } - if ($this->request->is('post')) { - $jsonData = $this->request->input('json_decode', true); - //$user = $jsonData['user']; - //var_dump($jsonData); - $pubkey = hex2bin($jsonData['pubkeyhex']); - $stateUsers = $this->StateUsers + if($this->request->is('post')) { + $jsonData = $this->request->input('json_decode', true); + //$user = $jsonData['user']; + //var_dump($jsonData); + $pubkey = hex2bin($jsonData['pubkeyhex']); + $stateUsers = $this->StateUsers ->find('all') ->where(['public_key' => $pubkey]) ->select(['id']); - if ($stateUsers->count() != 1) { - return $this->returnJson(['state' => 'error', 'msg' => 'invalid result count']); - } - $stateUser = $stateUsers->first(); - //var_dump($stateUser); - //var_dump($stateUser->toArray()); - $creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations'); - $creationTransactions = $creationsTable + if($stateUsers->count() != 1) { + return $this->returnJson(['state' => 'error', 'msg' => 'invalid result count']); + } + $stateUser = $stateUsers->first(); + //var_dump($stateUser); + //var_dump($stateUser->toArray()); + $creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations'); + $creationTransactions = $creationsTable ->find('all') ->select(['id']) ->where(['state_user_id' => $stateUser->id]); - $transferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins'); - $transferTransactions = $transferTable + $transferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins'); + $transferTransactions = $transferTable ->find('all') ->where(['OR' => ['state_user_id' => $stateUser->id, 'receiver_user_id' => $stateUser->id]]) ->select(['state_user_id', 'receiver_user_id']); - $counts = ['creation' => $creationTransactions->count(), 'receive' => 0, 'sended' => 0]; - foreach ($transferTransactions as $transfer) { - //var_dump($transfer); - if ($transfer->state_user_id == $stateUser->id) { - $counts['sended']++; - } - if ($transfer->receiver_user_id == $stateUser->id) { - $counts['receive']++; - } + $counts = ['creation' => $creationTransactions->count(), 'receive' => 0, 'sended' => 0]; + foreach($transferTransactions as $transfer) { + //var_dump($transfer); + if($transfer->state_user_id == $stateUser->id) { + $counts['sended']++; } - return $this->returnJson(['state' => 'success', 'counts' => $counts]); - } - return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); + if($transfer->receiver_user_id == $stateUser->id) { + $counts['receive']++; + } + } + return $this->returnJson(['state' => 'success', 'counts' => $counts]); + + } + return $this->returnJson(['state' => 'error', 'msg' => 'no post request']); + } public function ajaxGetCSFRToken($session_id) @@ -560,9 +589,9 @@ class StateUsersController extends AppController } $this->Flash->error(__('The state user could not be saved. Please, try again.')); } - + $indices = $this->StateUsers->Indices->find('list', ['limit' => 200]); $stateGroups = $this->StateUsers->StateGroups->find('list', ['limit' => 200]); - $this->set(compact('stateUser', 'stateGroups')); + $this->set(compact('stateUser', 'indices', 'stateGroups')); } /** diff --git a/community_server/src/Controller/TransactionCreationsController.php b/community_server/src/Controller/TransactionCreationsController.php index 46a7a37f4..d02320d25 100644 --- a/community_server/src/Controller/TransactionCreationsController.php +++ b/community_server/src/Controller/TransactionCreationsController.php @@ -130,8 +130,7 @@ class TransactionCreationsController extends AppController $builderResult = TransactionCreation::build( $amountCent, $requestData['memo'], - $pubKeyHex, - $identHash + $pubKeyHex ); if ($builderResult['state'] == 'success') { $user_balance = 0; @@ -335,6 +334,7 @@ class TransactionCreationsController extends AppController if (isset($requestData['add'])) { $mode = 'add'; } + //echo "mode: $mode
"; $memo = $requestData['memo']; $amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']); //$targetDate = $requestData['target_date']; @@ -342,17 +342,20 @@ class TransactionCreationsController extends AppController $this->Flash->error(__('No user selected')); } else { $users = $requestData['user']; + $pendingTransactionCount = $session->read('Transactions.pending'); + if ($pendingTransactionCount == null) { + $pendingTransactionCount = 0; + } if (isset($requestData['user_pending'])) { $pendings = $requestData['user_pending']; } else { $pendings = []; } - $receiverUsers = $stateUserTable - ->find('all') - ->where(['id IN' => array_keys($users)]) - ->select(['public_key', 'email', 'id']) - ->contain(false); - $transactions = []; + $receiverUsers = $stateUserTable->find('all') + ->where(['id IN' => array_keys($users)]) + ->select(['public_key', 'email', 'id']) + ->contain(false); + foreach ($receiverUsers as $receiverUser) { $localAmountCent = $amountCent; //$localTargetDate = $targetDate; @@ -385,22 +388,85 @@ class TransactionCreationsController extends AppController //$identHash = TransactionCreation::DRMakeStringHash($receiverUser->email); $localTargetDateFrozen = FrozenDate::now(); $localTargetDateFrozen = $localTargetDateFrozen - ->year($localTargetDate['year']) - ->month($localTargetDate['month']) - ->day($localTargetDate['day']); - //echo "input: "; var_dump($localTargetDate);echo "
"; - //echo "output: "; var_dump($localTargetDateFrozen); - //die('a'); - $builderResult = TransactionCreation::build( - $localAmountCent, - $memo, - $pubKeyHex, - $identHash, - $localTargetDateFrozen - ); - if ($builderResult['state'] == 'success') { - array_push($transactions, base64_encode($builderResult['transactionBody']->serializeToString())); + ->year($localTargetDate['year']) + ->month($localTargetDate['month']) + ->day($localTargetDate['day']); + + $requestAnswear = $this->JsonRequestClient->sendRequest(json_encode([ + 'session_id' => $session->read('session_id'), + 'transaction_type' => 'creation', + 'memo' => $memo, + 'amount' => $localAmountCent, + 'target_pubkey' => $pubKeyHex, + 'target_date' => $localTargetDateFrozen, + 'blockchain_type' => $this->blockchainType + ]), '/createTransaction'); + + if('success' != $requestAnswear['state']) { + $this->addAdminError('TransactionCreations', 'createMulti', $requestAnswear, $user['id']); + if ($requestResult['type'] == 'request error') { + $this->Flash->error(__('Error by requesting LoginServer, please try again')); + } else { + $this->Flash->error(__('Error, please wait for the admin to fix it')); + } } + if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) { + $pendingTransactionCount++; + //echo "pending transaction count: $pendingTransactionCount
"; + } else { + /* + * if request contain unknown parameter format, shouldn't happen't at all + * {"state": "error", "msg": "parameter format unknown"} + * if json parsing failed + * {"state": "error", "msg": "json exception", "details":"exception text"} + * if session_id is zero or not set + * {"state": "error", "msg": "session_id invalid"} + * if session id wasn't found on login server, if server was restartet or user logged out (also per timeout, default: 15 minutes) + * {"state": "error", "msg": "session not found"} + * if session hasn't active user, shouldn't happen't at all, login-server should be checked if happen + * {"state": "code error", "msg":"user is zero"} + * if transaction type not known + * {"state": "error", "msg":"transaction_type unknown"} + * if receiver wasn't known to Login-Server + * {"state": "not found", "msg":"receiver not found"} + * if receiver account disabled, and therefor cannto receive any coins + * {"state": "disabled", "msg":"receiver is disabled"} + * if amount is invalid in creation + * {"state": "invalid parameter", "msg":"invalid amount", "details":"GDD amount in GDD cent ]0,10000000]"} + * if transaction was okay and will be further proccessed + * {"state":"success"} + */ + $answear_data = $requestAnswear['data']; + if($answear_data['state'] === 'error') { + if($answear_data['msg'] === 'session_id invalid' || $answear_data['msg'] === 'session not found') { + $this->Flash->error(__('Fehler mit der Session, bitte logge dich erneut ein!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + if($answear_data['msg'] === 'user not in group') { + $this->Flash->error(__('Fehler, Benutzer gehört zu einer anderen Gruppe!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + } else if($answear_data['state'] === 'not found' && $answear_data['msg'] === 'receiver not found') { + $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else if($answear_data['state'] === 'disabled') { + $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else if($answear_data['msg'] === 'invalid amount') { + $this->Flash->error(__('Der Betrag ist ungültig, er muss größer als 0 und <= 1000 sein.')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else { + $this->Flash->error(__('Unbehandelter Fehler: ') . json_encode($answear_data)); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + } + } /*echo "pendings: "; var_dump($pendings); @@ -412,49 +478,17 @@ class TransactionCreationsController extends AppController } } $this->set('possibleReceivers', $possibleReceivers); - $creationTransactionCount = count($transactions); - if ($creationTransactionCount > 0) { + if ($pendingTransactionCount > 0) { $user_balance = 0; if (isset($user['balance'])) { $user_balance = $user['balance']; } - // $session_id, $base64Message, $user_balance = 0 - $requestResult = $this->JsonRequestClient->sendTransaction( - $session->read('session_id'), - $transactions, - $user_balance - ); - if ($requestResult['state'] != 'success') { - $this->addAdminError('TransactionCreations', 'createMulti', $requestResult, $user['id']); - if ($requestResult['type'] == 'request error') { - $this->Flash->error(__('Error by requesting LoginServer, please try again')); - } else { - $this->Flash->error(__('Error, please wait for the admin to fix it')); - } + $session->write('Transactions.pending', $pendingTransactionCount); + + if ($mode === 'next') { + return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); } else { - $json = $requestResult['data']; - if ($json['state'] != 'success') { - if ($json['msg'] == 'session not found') { - $session->destroy(); - return $this->redirect($this->loginServerUrl . 'account', 303); - } else { - $this->addAdminError('TransactionCreations', 'createMulti', $json, $user['id']); - $this->Flash->error(__('Login Server Error, please wait for the admin to fix it')); - } - } else { - $pendingTransactionCount = $session->read('Transactions.pending'); - if ($pendingTransactionCount == null) { - $pendingTransactionCount = $creationTransactionCount; - } else { - $pendingTransactionCount += $creationTransactionCount; - } - $session->write('Transactions.pending', $pendingTransactionCount); - if ($mode === 'next') { - return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); - } else { - $this->Flash->success(__('Transaction submitted for review.')); - } - } + $this->Flash->success(__('Transaction submitted for review.')); } } } @@ -533,7 +567,6 @@ class TransactionCreationsController extends AppController $amount, $memo, $receiverPubKeyHex, - $requestAnswear['data']['userData']['identHash'], new FrozenDate($jsonData['target_date']) ); $transaction_base64 = ''; @@ -546,7 +579,8 @@ class TransactionCreationsController extends AppController $session_id, $transaction_base64, $user['balance'], - $auto_sign + $auto_sign, + $this->blockchainType ); if ($requestResult['state'] != 'success') { $msg = 'error returned from login server'; diff --git a/community_server/src/Controller/TransactionSendCoinsController.php b/community_server/src/Controller/TransactionSendCoinsController.php index 2f48de063..033e2343f 100644 --- a/community_server/src/Controller/TransactionSendCoinsController.php +++ b/community_server/src/Controller/TransactionSendCoinsController.php @@ -57,8 +57,9 @@ class TransactionSendCoinsController extends AppController 'contain' => ['Transactions', 'StateUsers', 'ReceiverUsers'] ]; $transactionSendCoins = $this->paginate($this->TransactionSendCoins); + $simple = $this->TransactionSendCoins->find('all'); - $this->set(compact('transactionSendCoins')); + $this->set(compact('transactionSendCoins', 'simple')); } /** @@ -146,10 +147,17 @@ class TransactionSendCoinsController extends AppController } $user = $session->read('StateUser'); } + + $known_groups = $this->JsonRequestClient->sendRequest(json_encode([ + 'ask' => ['groups'] + ]), '/networkInfos'); + $transferForm = new TransferForm(); $this->set('transferForm', $transferForm); $this->set('timeUsed', microtime(true) - $startTime); + $this->set('groups', $known_groups['data']['data']['groups']); + $this->set('user', $user); if ($this->request->is('post')) { //$this->Flash->error(__('Wird zurzeit noch entwickelt!')); @@ -159,134 +167,94 @@ class TransactionSendCoinsController extends AppController if(isset($requestData['add'])) {$mode = 'add'; } if($transferForm->validate($requestData)) { - $receiverPubKeyHex = ''; - $senderPubKeyHex = $user['public_hex']; $amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']); if(!isset($user['balance']) || $amountCent > $user['balance']) { $this->Flash->error(__('Du hast nicht genug Geld!')); return; } - + $receiverEmail = $requestData['email']; if($receiverEmail === $user['email']) { $this->Flash->error(__('Du kannst dir leider nicht selbst Geld schicken!')); return; } - $receiverPubkeyHex =''; $requestAnswear = $this->JsonRequestClient->sendRequest(json_encode([ 'session_id' => $session->read('session_id'), - 'email' => $receiverEmail, - 'ask' => ['user.pubkeyhex', 'user.disabled'] - ]), '/getUserInfos'); + 'transaction_type' => 'transfer', + 'memo' => $requestData['memo'], + 'amount' => $amountCent, + 'target_group' => $known_groups['data']['data']['groups'][$requestData['group']], + 'target_email' => $receiverEmail, + 'blockchain_type' => $this->blockchainType + ]), '/createTransaction'); + if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) { - // will be allways 64 byte long, even if it is empty - $receiverPubKeyHex = $requestAnswear['data']['userData']['pubkeyhex']; - } else { - $this->addAdminError('TransactionSendCoins', 'create', $requestAnswear, $user['id']); - $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); - $this->set('timeUsed', microtime(true) - $startTime); - return; - } - if($requestAnswear['data']['userData']['disabled']) { - $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); - $this->set('timeUsed', microtime(true) - $startTime); - return; - } - - - if(0 == ord($receiverPubKeyHex)) { - $stateUserTable = TableRegistry::getTableLocator()->get('StateUsers'); - $receiverUser = $stateUserTable - ->find('all') - ->select(['public_key']) - ->contain(false) - ->where(['email' => $receiverEmail]); - - - if(!$receiverUser) { - $this->Flash->error(__('Diese E-Mail ist mir nicht bekannt, hat dein Empfänger denn schon ein Gradido-Konto?')); - $this->set('timeUsed', microtime(true) - $startTime); - return; - } - - if(isset($receiverUser->public_key)) { - $receiverPubKeyHex = bin2hex(stream_get_contents($receiverUser->public_key)); + $pendingTransactionCount = $session->read('Transactions.pending'); + if($pendingTransactionCount == null) { + $pendingTransactionCount = 1; } else { - $this->Flash->error(__('Das Konto mit der E-Mail: ' . $receiverEmail . ' wurde noch nicht aktiviert und kann noch keine GDD empfangen!')); + $pendingTransactionCount++; + } + $session->write('Transactions.pending', $pendingTransactionCount); + //echo "pending: " . $pendingTransactionCount; + if($mode === 'next') { + return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); + } else { + $this->Flash->success(__('Transaction submitted for review.')); + } + } else { + + /* + * if request contain unknown parameter format, shouldn't happen't at all + * {"state": "error", "msg": "parameter format unknown"} + * if json parsing failed + * {"state": "error", "msg": "json exception", "details":"exception text"} + * if session_id is zero or not set + * {"state": "error", "msg": "session_id invalid"} + * if session id wasn't found on login server, if server was restartet or user logged out (also per timeout, default: 15 minutes) + * {"state": "error", "msg": "session not found"} + * if session hasn't active user, shouldn't happen't at all, login-server should be checked if happen + * {"state": "code error", "msg":"user is zero"} + * if transaction type not known + * {"state": "error", "msg":"transaction_type unknown"} + * if receiver wasn't known to Login-Server + * {"state": "not found", "msg":"receiver not found"} + * if receiver account disabled, and therefor cannto receive any coins + * {"state": "disabled", "msg":"receiver is disabled"} + * if transaction was okay and will be further proccessed + * {"state":"success"} + */ + $answear_data = $requestAnswear['data']; + if($answear_data['state'] === 'error') { + if($answear_data['msg'] === 'session_id invalid' || $answear_data['msg'] === 'session not found') { + $this->Flash->error(__('Fehler mit der Session, bitte logge dich erneut ein!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + if($answear_data['msg'] === 'user not in group') { + $this->Flash->error(__('Empfänger befindet sich nicht in Zielgruppe!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + } else if($answear_data['state'] === 'not found' && $answear_data['msg'] === 'receiver not found') { + $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); $this->set('timeUsed', microtime(true) - $startTime); return; - } + } else if($answear_data['state'] === 'disabled') { + $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else { + $this->Flash->error(__('Unbehandelter Fehler: ') . json_encode($answear_data)); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } } - //var_dump($sessionStateUser); - - $builderResult = TransactionTransfer::build( - $amountCent, - $requestData['memo'], - $receiverPubKeyHex, - $senderPubKeyHex - ); - if($builderResult['state'] === 'success') { - - $http = new Client(); - try { - $loginServer = Configure::read('LoginServer'); - $url = $loginServer['host'] . ':' . $loginServer['port']; - $session_id = $session->read('session_id'); - /* - * - * $response = $http->post( - * 'http://example.com/tasks', - * json_encode($data), - * ['type' => 'json'] - * ); - */ - $response = $http->post($url . '/checkTransaction', json_encode([ - 'session_id' => $session_id, - 'transaction_base64' => base64_encode($builderResult['transactionBody']->serializeToString()), - 'balance' => $user['balance'] - ]), ['type' => 'json']); - $json = $response->getJson(); - if($json['state'] != 'success') { - if($json['msg'] == 'session not found') { - $session->destroy(); - return $this->redirect($this->loginServerUrl . 'account', 303); - //$this->Flash->error(__('session not found, please login again')); - } else { - $this->Flash->error(__('login server return error: ' . json_encode($json))); - } - } else { - $pendingTransactionCount = $session->read('Transactions.pending'); - if($pendingTransactionCount == null) { - $pendingTransactionCount = 1; - } else { - $pendingTransactionCount++; - } - $session->write('Transactions.pending', $pendingTransactionCount); - //echo "pending: " . $pendingTransactionCount; - if($mode === 'next') { - return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); - } else { - $this->Flash->success(__('Transaction submitted for review.')); - } - } - - } catch(\Exception $e) { - $msg = $e->getMessage(); - $this->Flash->error(__('error http request: ') . $msg); - } - - } else { - $this->Flash->error(__('No Valid Receiver Public given: ' . $receiverPubKeyHex)); - } - -// */ - } else { - $this->Flash->error(__('Something was invalid, please try again!')); } } - + $this->set('timeUsed', microtime(true) - $startTime); } diff --git a/community_server/src/Form/AssignRoleForm.php b/community_server/src/Form/AssignRoleForm.php new file mode 100644 index 000000000..158fa2296 --- /dev/null +++ b/community_server/src/Form/AssignRoleForm.php @@ -0,0 +1,30 @@ +addField('role_id', ['type' => 'string']); + } + + function validationDefault(Validator $validator) + { + $validator->setProvider('custom', 'App\Model\Validation\GenericValidation'); + + return $validator; + } + + + protected function _execute(array $data) + { + // Send an email. + return true; + } +} \ No newline at end of file diff --git a/community_server/src/Form/TransferForm.php b/community_server/src/Form/TransferForm.php index 5572ddaf9..cb135ab9e 100644 --- a/community_server/src/Form/TransferForm.php +++ b/community_server/src/Form/TransferForm.php @@ -1,5 +1,5 @@ -addField('email', ['type' => 'string']) + ->addField('group', ['type' => 'string']) ->addField('amount', ['type' => 'decimal', 'precision' => 2]) ->addField('memo', ['type' =>'text', 'default' => '', 'rows' => 3, 'maxlength' => 150]); } function validationDefault(Validator $validator) { - $validator->setProvider('custom', 'App\Model\Validation\TransactionValidation'); + $validator->setProvider('custom', 'App\Model\Validation\TransactionValidation'); /* $validator->add('receiver_pubkey_hex', 'length', [ 'rule' => ['length', 64], @@ -34,6 +35,12 @@ class TransferForm extends Form 'rule' => 'email', 'message' => __('A valid email address is required') ]) + ->add('group', 'custom', [ + 'rule' => 'alphaNumeric', + 'provider' => 'custom', + //'message' => __('Only Alpha Numeric Character allowed') + 'message' => __('No HTML Tags like > or < please.') + ]) ->add('memo', 'length', [ 'rule' => ['maxLength', 150], 'message' => __('The memo should contain max 150 character') @@ -54,7 +61,7 @@ class TransferForm extends Form ->allowEmptyString('receiver_pubkey_hex', null, 'create')*/ ->add('amount', 'custom', [ 'rule' => 'amount', - 'provider' => 'custom', + 'provider' => 'custom', 'message' => __('Please give a valid positive number with maximal 2 decimal places') ]); return $validator; @@ -72,4 +79,4 @@ class TransferForm extends Form // Send an email. return true; } -} +} \ No newline at end of file diff --git a/community_server/src/GPBMetadata/BasicTypes.php b/community_server/src/GPBMetadata/BasicTypes.php deleted file mode 100644 index f74eb472b..000000000 --- a/community_server/src/GPBMetadata/BasicTypes.php +++ /dev/null @@ -1,41 +0,0 @@ -internalAddGeneratedFile(hex2bin( - "0afe030a10426173696354797065732e70726f746f12166d6f64656c2e6d" . - "657373616765732e6772616469646f22380a034b657912110a0765643235" . - "35313918022001280c480012170a0d656432353531395f72656631301803" . - "2001280c480042050a036b657922580a0d5369676e617475726550616972" . - "120e0a067075624b657918012001280c12110a0765643235353139180220" . - "01280c480012170a0d656432353531395f726566313018032001280c4800" . - "420b0a097369676e617475726522460a0c5369676e61747572654d617012" . - "360a077369675061697218012003280b32252e6d6f64656c2e6d65737361" . - "6765732e6772616469646f2e5369676e617475726550616972222b0a0954" . - "696d657374616d70120f0a077365636f6e6473180120012803120d0a056e" . - "616e6f7318022001280522230a1054696d657374616d705365636f6e6473" . - "120f0a077365636f6e647318012001280322590a0c53656e646572416d6f" . - "756e74121d0a15656432353531395f73656e6465725f7075626b65791801" . - "2001280c120e0a06616d6f756e74180220012812121a0a1273656e646572" . - "46696e616c42616c616e636518032001281222410a0e5265636569766572" . - "416d6f756e74121f0a17656432353531395f72656365697665725f707562" . - "6b657918012001280c120e0a06616d6f756e74180220012812620670726f" . - "746f33" - ), true); - - static::$is_initialized = true; - } -} - diff --git a/community_server/src/GPBMetadata/StateCreateGroup.php b/community_server/src/GPBMetadata/StateCreateGroup.php deleted file mode 100644 index 7098eb808..000000000 --- a/community_server/src/GPBMetadata/StateCreateGroup.php +++ /dev/null @@ -1,32 +0,0 @@ -internalAddGeneratedFile(hex2bin( - "0ae4010a16537461746543726561746547726f75702e70726f746f12166d" . - "6f64656c2e6d657373616765732e6772616469646f22a9010a1053746174" . - "6543726561746547726f7570120c0a046e616d6518012001280912330a0e" . - "67726f75705075626c69634b657918022001280b321b2e6d6f64656c2e6d" . - "657373616765732e6772616469646f2e4b657912390a14706172656e7447" . - "726f75705075626c69634b657918032001280b321b2e6d6f64656c2e6d65" . - "7373616765732e6772616469646f2e4b65794a0408041005521168656465" . - "7261436f6e73656e7375734964620670726f746f33" - ), true); - - static::$is_initialized = true; - } -} - diff --git a/community_server/src/GPBMetadata/StateGroupChangeParent.php b/community_server/src/GPBMetadata/StateGroupChangeParent.php deleted file mode 100644 index c87782041..000000000 --- a/community_server/src/GPBMetadata/StateGroupChangeParent.php +++ /dev/null @@ -1,33 +0,0 @@ -internalAddGeneratedFile(hex2bin( - "0a8a020a1c537461746547726f75704368616e6765506172656e742e7072" . - "6f746f12166d6f64656c2e6d657373616765732e6772616469646f22c901" . - "0a16537461746547726f75704368616e6765506172656e7412330a0e6772" . - "6f75705075626c69634b657918012001280b321b2e6d6f64656c2e6d6573" . - "73616765732e6772616469646f2e4b6579123c0a176e6577506172656e74" . - "47726f75705075626c69634b657918022001280b321b2e6d6f64656c2e6d" . - "657373616765732e6772616469646f2e4b6579123c0a176f6c6450617265" . - "6e7447726f75705075626c69634b657918032001280b321b2e6d6f64656c" . - "2e6d657373616765732e6772616469646f2e4b6579620670726f746f33" - ), true); - - static::$is_initialized = true; - } -} - diff --git a/community_server/src/GPBMetadata/Transaction.php b/community_server/src/GPBMetadata/Transaction.php deleted file mode 100644 index d86999450..000000000 --- a/community_server/src/GPBMetadata/Transaction.php +++ /dev/null @@ -1,32 +0,0 @@ -internalAddGeneratedFile(hex2bin( - "0ae4010a115472616e73616374696f6e2e70726f746f12166d6f64656c2e" . - "6d657373616765732e6772616469646f22ae010a0b5472616e7361637469" . - "6f6e120a0a026964180120012804123a0a08726563656976656418022001" . - "280b32282e6d6f64656c2e6d657373616765732e6772616469646f2e5469" . - "6d657374616d705365636f6e647312340a067369674d617018032001280b" . - "32242e6d6f64656c2e6d657373616765732e6772616469646f2e5369676e" . - "61747572654d6170120e0a0674784861736818042001280c12110a09626f" . - "6479427974657318052001280c620670726f746f33" - ), true); - - static::$is_initialized = true; - } -} - diff --git a/community_server/src/GPBMetadata/TransactionBody.php b/community_server/src/GPBMetadata/TransactionBody.php deleted file mode 100644 index 61d99eb96..000000000 --- a/community_server/src/GPBMetadata/TransactionBody.php +++ /dev/null @@ -1,46 +0,0 @@ -internalAddGeneratedFile(hex2bin( - "0a84040a155472616e73616374696f6e426f64792e70726f746f12166d6f" . - "64656c2e6d657373616765732e6772616469646f1a165374617465437265" . - "61746547726f75702e70726f746f1a1c537461746547726f75704368616e" . - "6765506172656e742e70726f746f1a195472616e73616374696f6e437265" . - "6174696f6e2e70726f746f1a10426173696354797065732e70726f746f22" . - "e7020a0f5472616e73616374696f6e426f6479120c0a046d656d6f180120" . - "01280912390a076372656174656418022001280b32282e6d6f64656c2e6d" . - "657373616765732e6772616469646f2e54696d657374616d705365636f6e" . - "6473123f0a0b63726561746547726f757018062001280b32282e6d6f6465" . - "6c2e6d657373616765732e6772616469646f2e5374617465437265617465" . - "47726f75704800124b0a1167726f75704368616e6765506172656e741807" . - "2001280b322e2e6d6f64656c2e6d657373616765732e6772616469646f2e" . - "537461746547726f75704368616e6765506172656e74480012340a087472" . - "616e7366657218082001280b32202e6d6f64656c2e6d657373616765732e" . - "6772616469646f2e5472616e736665724800123f0a086372656174696f6e" . - "18092001280b322b2e6d6f64656c2e6d657373616765732e677261646964" . - "6f2e5472616e73616374696f6e4372656174696f6e480042060a04646174" . - "61620670726f746f33" - ), true); - - static::$is_initialized = true; - } -} - diff --git a/community_server/src/GPBMetadata/TransactionCreation.php b/community_server/src/GPBMetadata/TransactionCreation.php deleted file mode 100644 index f1ce2cf1a..000000000 --- a/community_server/src/GPBMetadata/TransactionCreation.php +++ /dev/null @@ -1,32 +0,0 @@ -internalAddGeneratedFile(hex2bin( - "0ae6010a195472616e73616374696f6e4372656174696f6e2e70726f746f" . - "12166d6f64656c2e6d657373616765732e6772616469646f22a8010a1354" . - "72616e73616374696f6e4372656174696f6e123e0a0e7265636569766572" . - "416d6f756e7418012001280b32262e6d6f64656c2e6d657373616765732e" . - "6772616469646f2e5265636569766572416d6f756e7412120a0a6964656e" . - "745f68617368180220012811123d0a0b7461726765745f64617465180320" . - "01280b32282e6d6f64656c2e6d657373616765732e6772616469646f2e54" . - "696d657374616d705365636f6e6473620670726f746f33" - ), true); - - static::$is_initialized = true; - } -} - diff --git a/community_server/src/GPBMetadata/Transfer.php b/community_server/src/GPBMetadata/Transfer.php deleted file mode 100644 index b0b2c3a2d..000000000 --- a/community_server/src/GPBMetadata/Transfer.php +++ /dev/null @@ -1,31 +0,0 @@ -internalAddGeneratedFile(hex2bin( - "0abb010a0e5472616e736665722e70726f746f12166d6f64656c2e6d6573" . - "73616765732e6772616469646f2288010a085472616e73666572123b0a0d" . - "73656e646572416d6f756e747318012003280b32242e6d6f64656c2e6d65" . - "7373616765732e6772616469646f2e53656e646572416d6f756e74123f0a" . - "0f7265636569766572416d6f756e747318022003280b32262e6d6f64656c" . - "2e6d657373616765732e6772616469646f2e5265636569766572416d6f75" . - "6e74620670726f746f33" - ), true); - - static::$is_initialized = true; - } -} - diff --git a/community_server/src/Model/Entity/AddressType.php b/community_server/src/Model/Entity/AddressType.php index 08dbba281..87d64d61a 100644 --- a/community_server/src/Model/Entity/AddressType.php +++ b/community_server/src/Model/Entity/AddressType.php @@ -8,7 +8,7 @@ use Cake\ORM\Entity; * * @property int $id * @property string $name - * @property string|null $text + * @property string $text * * @property \App\Model\Entity\StateGroupAddress[] $state_group_addresses * @property \App\Model\Entity\TransactionGroupAddaddres[] $transaction_group_addaddress @@ -28,6 +28,6 @@ class AddressType extends Entity 'name' => true, 'text' => true, 'state_group_addresses' => true, - 'transaction_group_addaddress' => true + 'transaction_group_addaddress' => true, ]; } diff --git a/community_server/src/Model/Entity/BlockchainType.php b/community_server/src/Model/Entity/BlockchainType.php new file mode 100644 index 000000000..c2e21402c --- /dev/null +++ b/community_server/src/Model/Entity/BlockchainType.php @@ -0,0 +1,30 @@ + true, + 'text' => true, + 'symbol' => true, + ]; +} diff --git a/community_server/src/Model/Entity/Role.php b/community_server/src/Model/Entity/Role.php new file mode 100644 index 000000000..ae0ddd0ba --- /dev/null +++ b/community_server/src/Model/Entity/Role.php @@ -0,0 +1,26 @@ + true, + ]; +} diff --git a/community_server/src/Model/Entity/StateBalance.php b/community_server/src/Model/Entity/StateBalance.php index c5fcf5976..a93a0a4b1 100644 --- a/community_server/src/Model/Entity/StateBalance.php +++ b/community_server/src/Model/Entity/StateBalance.php @@ -28,6 +28,7 @@ class StateBalance extends Entity protected $_accessible = [ 'state_user_id' => true, 'modified' => true, + 'record_date' => true, 'amount' => true, 'record_date' => true, 'state_user' => true @@ -39,8 +40,12 @@ class StateBalance extends Entity { if(method_exists($dateOrTime, 'getTimestamp')) { return $dateOrTime->getTimestamp(); - } else { + } else if(method_exists($dateOrTime, 'i18nFormat')) { return $dateOrTime->i18nFormat(Time::UNIX_TIMESTAMP_FORMAT); + } else { + var_dump($dateOrTime); + debug_print_backtrace(0, 4); + die("date or time unexpected object"); } } @@ -53,28 +58,28 @@ class StateBalance extends Entity // SELECT TIMESTAMPDIFF(SECOND, modified, CURDATE()) AS age_in_seconds from state_balances // decay_for_duration = decay_factor^seconds // decay = gradido_cent * decay_for_duration - $decay_duration = $this->decayDuration(Time::now()); + + $decay_duration = intval(Time::now()->getTimestamp() - $this->convertToTimestamp($this->record_date)); if($decay_duration === 0) { return $this->amount; } - return $this->amount; - //return $this->amount * pow(0.99999997802044727, $decay_duration); + //return $this->amount; + return $this->amount * pow(0.99999997802044727, $decay_duration); } public function partDecay($target_date) { - if($target_date == null) return 0; - $decay_duration = $this->decayDuration($target_date); + $decay_duration = intval($this->convertToTimestamp($target_date) - $this->convertToTimestamp($this->record_date)); if($decay_duration <= 0) { return $this->amount; } - return 0; - //return $this->amount * pow(0.99999997802044727, $decay_duration); + //return 0; + return $this->amount * pow(0.99999997802044727, $decay_duration); } public function decayDuration($target_date) - { - if($this->record_date == null) return 0; - return intval($this->convertToTimestamp($target_date) - $this->record_date->getTimestamp()); + { + return intval($this->convertToTimestamp($target_date) - $this->convertToTimestamp($this->record_date)); } } + diff --git a/community_server/src/Model/Entity/StateGroupAddress.php b/community_server/src/Model/Entity/StateGroupAddress.php index e5ce71681..e2d669d09 100644 --- a/community_server/src/Model/Entity/StateGroupAddress.php +++ b/community_server/src/Model/Entity/StateGroupAddress.php @@ -7,7 +7,7 @@ use Cake\ORM\Entity; * StateGroupAddress Entity * * @property int $id - * @property int $state_group_id + * @property int $group_id * @property string|resource $public_key * @property int $address_type_id * @@ -26,10 +26,10 @@ class StateGroupAddress extends Entity * @var array */ protected $_accessible = [ - 'state_group_id' => true, + 'group_id' => true, 'public_key' => true, 'address_type_id' => true, 'state_group' => true, - 'address_type' => true + 'address_type' => true, ]; } diff --git a/community_server/src/Model/Entity/StateUserRole.php b/community_server/src/Model/Entity/StateUserRole.php new file mode 100644 index 000000000..d510bb025 --- /dev/null +++ b/community_server/src/Model/Entity/StateUserRole.php @@ -0,0 +1,30 @@ + true, + 'role_id' => true + ]; +} diff --git a/community_server/src/Model/Entity/Transaction.php b/community_server/src/Model/Entity/Transaction.php index d4ebf68c4..209b8997e 100644 --- a/community_server/src/Model/Entity/Transaction.php +++ b/community_server/src/Model/Entity/Transaction.php @@ -39,6 +39,7 @@ class Transaction extends Entity 'tx_hash' => true, 'memo' => true, 'received' => true, + 'blockchain_type_id' => true, 'state_group' => true, 'transaction_type' => true, 'state_created' => true, diff --git a/community_server/src/Model/Entity/TransactionGroupAddaddres.php b/community_server/src/Model/Entity/TransactionGroupAddaddres.php index 3cb73b9ee..30819209f 100644 --- a/community_server/src/Model/Entity/TransactionGroupAddaddres.php +++ b/community_server/src/Model/Entity/TransactionGroupAddaddres.php @@ -28,8 +28,10 @@ class TransactionGroupAddaddres extends Entity protected $_accessible = [ 'transaction_id' => true, 'address_type_id' => true, + 'remove_from_group' => true, 'public_key' => true, 'transaction' => true, - 'address_type' => true + 'address_type' => true, + 'state_user_id' => true ]; } diff --git a/community_server/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php b/community_server/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php new file mode 100644 index 000000000..781ac8f25 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php @@ -0,0 +1,146 @@ +proto.gradido.CrossGroupTransfer + */ +class CrossGroupTransfer extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + */ + private $sender = null; + /** + * Generated from protobuf field bytes receiver = 2; + */ + private $receiver = ''; + /** + * Generated from protobuf field string other_group = 3; + */ + private $other_group = ''; + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + */ + private $paired_transaction_id = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $sender + * @type string $receiver + * @type string $other_group + * @type \Proto\Gradido\Timestamp $paired_transaction_id + * this matches related OutboundTransfer.paired_transaction_id + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getSender() + { + return $this->sender; + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setSender($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->sender = $var; + + return $this; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @return string + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @param string $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkString($var, False); + $this->receiver = $var; + + return $this; + } + + /** + * Generated from protobuf field string other_group = 3; + * @return string + */ + public function getOtherGroup() + { + return $this->other_group; + } + + /** + * Generated from protobuf field string other_group = 3; + * @param string $var + * @return $this + */ + public function setOtherGroup($var) + { + GPBUtil::checkString($var, True); + $this->other_group = $var; + + return $this; + } + + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + * @return \Proto\Gradido\Timestamp + */ + public function getPairedTransactionId() + { + return $this->paired_transaction_id; + } + + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + * @param \Proto\Gradido\Timestamp $var + * @return $this + */ + public function setPairedTransactionId($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\Timestamp::class); + $this->paired_transaction_id = $var; + + return $this; + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/GradidoCreation.php b/community_server/src/Model/Messages/Proto/Gradido/GradidoCreation.php new file mode 100644 index 000000000..9b4c3208d --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/GradidoCreation.php @@ -0,0 +1,102 @@ +proto.gradido.GradidoCreation + */ +class GradidoCreation extends \Google\Protobuf\Internal\Message +{ + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + */ + private $receiver = null; + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + */ + private $target_date = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $receiver + * 40 Byte + * @type \Proto\Gradido\TimestampSeconds $target_date + * 8 Byte + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoCreation::initOnce(); + parent::__construct($data); + } + + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->receiver = $var; + + return $this; + } + + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + * @return \Proto\Gradido\TimestampSeconds + */ + public function getTargetDate() + { + return $this->target_date; + } + + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + * @param \Proto\Gradido\TimestampSeconds $var + * @return $this + */ + public function setTargetDate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TimestampSeconds::class); + $this->target_date = $var; + + return $this; + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/GradidoTransaction.php b/community_server/src/Model/Messages/Proto/Gradido/GradidoTransaction.php new file mode 100644 index 000000000..b4b34c77e --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/GradidoTransaction.php @@ -0,0 +1,116 @@ +proto.gradido.GradidoTransaction + */ +class GradidoTransaction extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + */ + private $sig_map = null; + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + */ + private $body_bytes = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\SignatureMap $sig_map + * @type string $body_bytes + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransaction::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + * @return \Proto\Gradido\SignatureMap + */ + public function getSigMap() + { + return $this->sig_map; + } + + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + * @param \Proto\Gradido\SignatureMap $var + * @return $this + */ + public function setSigMap($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\SignatureMap::class); + $this->sig_map = $var; + + return $this; + } + + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + * @return string + */ + public function getBodyBytes() + { + return $this->body_bytes; + } + + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + * @param string $var + * @return $this + */ + public function setBodyBytes($var) + { + GPBUtil::checkString($var, False); + $this->body_bytes = $var; + + return $this; + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/GradidoTransfer.php b/community_server/src/Model/Messages/Proto/Gradido/GradidoTransfer.php new file mode 100644 index 000000000..a76954c2e --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/GradidoTransfer.php @@ -0,0 +1,109 @@ +proto.gradido.GradidoTransfer + */ +class GradidoTransfer extends \Google\Protobuf\Internal\Message +{ + protected $data; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\LocalTransfer $local + * @type \Proto\Gradido\CrossGroupTransfer $inbound + * @type \Proto\Gradido\CrossGroupTransfer $outbound + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.LocalTransfer local = 1; + * @return \Proto\Gradido\LocalTransfer + */ + public function getLocal() + { + return $this->readOneof(1); + } + + /** + * Generated from protobuf field .proto.gradido.LocalTransfer local = 1; + * @param \Proto\Gradido\LocalTransfer $var + * @return $this + */ + public function setLocal($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\LocalTransfer::class); + $this->writeOneof(1, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer inbound = 2; + * @return \Proto\Gradido\CrossGroupTransfer + */ + public function getInbound() + { + return $this->readOneof(2); + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer inbound = 2; + * @param \Proto\Gradido\CrossGroupTransfer $var + * @return $this + */ + public function setInbound($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\CrossGroupTransfer::class); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer outbound = 3; + * @return \Proto\Gradido\CrossGroupTransfer + */ + public function getOutbound() + { + return $this->readOneof(3); + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer outbound = 3; + * @param \Proto\Gradido\CrossGroupTransfer $var + * @return $this + */ + public function setOutbound($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\CrossGroupTransfer::class); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getData() + { + return $this->whichOneof("data"); + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php new file mode 100644 index 000000000..22e86d3e1 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php @@ -0,0 +1,92 @@ +proto.gradido.GroupFriendsUpdate + */ +class GroupFriendsUpdate extends \Google\Protobuf\Internal\Message +{ + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + */ + private $group = ''; + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + */ + private $action = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $group + * char[16], alias + * @type int $action + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GroupFriendsUpdate::initOnce(); + parent::__construct($data); + } + + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + * @return string + */ + public function getGroup() + { + return $this->group; + } + + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + * @param string $var + * @return $this + */ + public function setGroup($var) + { + GPBUtil::checkString($var, True); + $this->group = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + * @return int + */ + public function getAction() + { + return $this->action; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + * @param int $var + * @return $this + */ + public function setAction($var) + { + GPBUtil::checkEnum($var, \Proto\Gradido\GroupFriendsUpdate_Action::class); + $this->action = $var; + + return $this; + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php new file mode 100644 index 000000000..2a3396c55 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php @@ -0,0 +1,51 @@ +proto.gradido.GroupFriendsUpdate.Action + */ +class Action +{ + /** + * Generated from protobuf enum ADD_FRIEND = 0; + */ + const ADD_FRIEND = 0; + /** + * Generated from protobuf enum REMOVE_FRIEND = 1; + */ + const REMOVE_FRIEND = 1; + + private static $valueToName = [ + self::ADD_FRIEND => 'ADD_FRIEND', + self::REMOVE_FRIEND => 'REMOVE_FRIEND', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Action::class, \Proto\Gradido\GroupFriendsUpdate_Action::class); + diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php new file mode 100644 index 000000000..24f8cef70 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php @@ -0,0 +1,16 @@ +proto.gradido.GroupMemberUpdate + */ +class GroupMemberUpdate extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes user_pubkey = 1; + */ + private $user_pubkey = ''; + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + */ + private $member_update_type = 0; + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + */ + private $paired_transaction_id = null; + /** + * Generated from protobuf field string target_group = 4; + */ + private $target_group = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $user_pubkey + * @type int $member_update_type + * @type \Proto\Gradido\Timestamp $paired_transaction_id + * this only makes sense for user move, TODO: probably restructure + * @type string $target_group + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GroupMemberUpdate::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes user_pubkey = 1; + * @return string + */ + public function getUserPubkey() + { + return $this->user_pubkey; + } + + /** + * Generated from protobuf field bytes user_pubkey = 1; + * @param string $var + * @return $this + */ + public function setUserPubkey($var) + { + GPBUtil::checkString($var, False); + $this->user_pubkey = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + * @return int + */ + public function getMemberUpdateType() + { + return $this->member_update_type; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + * @param int $var + * @return $this + */ + public function setMemberUpdateType($var) + { + GPBUtil::checkEnum($var, \Proto\Gradido\GroupMemberUpdate_MemberUpdateType::class); + $this->member_update_type = $var; + + return $this; + } + + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + * @return \Proto\Gradido\Timestamp + */ + public function getPairedTransactionId() + { + return $this->paired_transaction_id; + } + + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + * @param \Proto\Gradido\Timestamp $var + * @return $this + */ + public function setPairedTransactionId($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\Timestamp::class); + $this->paired_transaction_id = $var; + + return $this; + } + + /** + * Generated from protobuf field string target_group = 4; + * @return string + */ + public function getTargetGroup() + { + return $this->target_group; + } + + /** + * Generated from protobuf field string target_group = 4; + * @param string $var + * @return $this + */ + public function setTargetGroup($var) + { + GPBUtil::checkString($var, True); + $this->target_group = $var; + + return $this; + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php b/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php new file mode 100644 index 000000000..57580cd75 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php @@ -0,0 +1,56 @@ +proto.gradido.GroupMemberUpdate.MemberUpdateType + */ +class MemberUpdateType +{ + /** + * Generated from protobuf enum ADD_USER = 0; + */ + const ADD_USER = 0; + /** + * Generated from protobuf enum MOVE_USER_INBOUND = 1; + */ + const MOVE_USER_INBOUND = 1; + /** + * Generated from protobuf enum MOVE_USER_OUTBOUND = 2; + */ + const MOVE_USER_OUTBOUND = 2; + + private static $valueToName = [ + self::ADD_USER => 'ADD_USER', + self::MOVE_USER_INBOUND => 'MOVE_USER_INBOUND', + self::MOVE_USER_OUTBOUND => 'MOVE_USER_OUTBOUND', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(MemberUpdateType::class, \Proto\Gradido\GroupMemberUpdate_MemberUpdateType::class); + diff --git a/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php b/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php new file mode 100644 index 000000000..b7080cf75 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php @@ -0,0 +1,16 @@ +proto.gradido.Key + */ +class Key extends \Google\Protobuf\Internal\Message +{ + protected $key; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $ed25519 + * ed25519 signature (libsodium default) + * @type string $ed25519_ref10 + * ed25519 ref10 signature + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @return string + */ + public function getEd25519() + { + return $this->readOneof(2); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @param string $var + * @return $this + */ + public function setEd25519($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @return string + */ + public function getEd25519Ref10() + { + return $this->readOneof(3); + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @param string $var + * @return $this + */ + public function setEd25519Ref10($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getKey() + { + return $this->whichOneof("key"); + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/LocalTransfer.php b/community_server/src/Model/Messages/Proto/Gradido/LocalTransfer.php new file mode 100644 index 000000000..58f5e23ae --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/LocalTransfer.php @@ -0,0 +1,85 @@ +proto.gradido.LocalTransfer + */ +class LocalTransfer extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + */ + private $sender = null; + /** + * Generated from protobuf field bytes receiver = 2; + */ + private $receiver = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $sender + * @type string $receiver + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getSender() + { + return $this->sender; + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setSender($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->sender = $var; + + return $this; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @return string + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @param string $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkString($var, False); + $this->receiver = $var; + + return $this; + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/SignatureMap.php b/community_server/src/Model/Messages/Proto/Gradido/SignatureMap.php new file mode 100644 index 000000000..0977169d7 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/SignatureMap.php @@ -0,0 +1,65 @@ +proto.gradido.SignatureMap + */ +class SignatureMap extends \Google\Protobuf\Internal\Message +{ + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + */ + private $sigPair; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $sigPair + * Each signature pair corresponds to a unique Key required to sign the transaction. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getSigPair() + { + return $this->sigPair; + } + + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + * @param \Proto\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setSigPair($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Proto\Gradido\SignaturePair::class); + $this->sigPair = $arr; + + return $this; + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/SignaturePair.php b/community_server/src/Model/Messages/Proto/Gradido/SignaturePair.php new file mode 100644 index 000000000..2ef0e81c5 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/SignaturePair.php @@ -0,0 +1,123 @@ +proto.gradido.SignaturePair + */ +class SignaturePair extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes pubKey = 1; + */ + private $pubKey = ''; + protected $signature; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $pubKey + * @type string $ed25519 + * ed25519 signature (libsodium default) + * @type string $ed25519_ref10 + * ed25519 ref10 signature + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes pubKey = 1; + * @return string + */ + public function getPubKey() + { + return $this->pubKey; + } + + /** + * Generated from protobuf field bytes pubKey = 1; + * @param string $var + * @return $this + */ + public function setPubKey($var) + { + GPBUtil::checkString($var, False); + $this->pubKey = $var; + + return $this; + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @return string + */ + public function getEd25519() + { + return $this->readOneof(2); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @param string $var + * @return $this + */ + public function setEd25519($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @return string + */ + public function getEd25519Ref10() + { + return $this->readOneof(3); + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @param string $var + * @return $this + */ + public function setEd25519Ref10($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getSignature() + { + return $this->whichOneof("signature"); + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/Timestamp.php b/community_server/src/Model/Messages/Proto/Gradido/Timestamp.php new file mode 100644 index 000000000..ae3ecea0e --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/Timestamp.php @@ -0,0 +1,101 @@ +proto.gradido.Timestamp + */ +class Timestamp extends \Google\Protobuf\Internal\Message +{ + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + */ + private $seconds = 0; + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + */ + private $nanos = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Number of complete seconds since the start of the epoch + * @type int $nanos + * Number of nanoseconds since the start of the last second + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + * @return int + */ + public function getNanos() + { + return $this->nanos; + } + + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + * @param int $var + * @return $this + */ + public function setNanos($var) + { + GPBUtil::checkInt32($var); + $this->nanos = $var; + + return $this; + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/TimestampSeconds.php b/community_server/src/Model/Messages/Proto/Gradido/TimestampSeconds.php new file mode 100644 index 000000000..d31aa40d2 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/TimestampSeconds.php @@ -0,0 +1,67 @@ +proto.gradido.TimestampSeconds + */ +class TimestampSeconds extends \Google\Protobuf\Internal\Message +{ + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + */ + private $seconds = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Number of complete seconds since the start of the epoch + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/TransactionBody.php b/community_server/src/Model/Messages/Proto/Gradido/TransactionBody.php new file mode 100644 index 000000000..b1ad01ea4 --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/TransactionBody.php @@ -0,0 +1,220 @@ +proto.gradido.TransactionBody + */ +class TransactionBody extends \Google\Protobuf\Internal\Message +{ + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + */ + private $memo = ''; + /** + * Generated from protobuf field .proto.gradido.TimestampSeconds created = 2; + */ + private $created = null; + /** + * Generated from protobuf field uint64 version_number = 3; + */ + private $version_number = 0; + protected $data; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $memo + * max 150 chars + * @type \Proto\Gradido\TimestampSeconds $created + * @type int|string $version_number + * @type \Proto\Gradido\GradidoTransfer $transfer + * @type \Proto\Gradido\GradidoCreation $creation + * @type \Proto\Gradido\GroupFriendsUpdate $group_friends_update + * @type \Proto\Gradido\GroupMemberUpdate $group_member_update + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\TransactionBody::initOnce(); + parent::__construct($data); + } + + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + * @return string + */ + public function getMemo() + { + return $this->memo; + } + + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + * @param string $var + * @return $this + */ + public function setMemo($var) + { + GPBUtil::checkString($var, True); + $this->memo = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.TimestampSeconds created = 2; + * @return \Proto\Gradido\TimestampSeconds + */ + public function getCreated() + { + return $this->created; + } + + /** + * Generated from protobuf field .proto.gradido.TimestampSeconds created = 2; + * @param \Proto\Gradido\TimestampSeconds $var + * @return $this + */ + public function setCreated($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TimestampSeconds::class); + $this->created = $var; + + return $this; + } + + /** + * Generated from protobuf field uint64 version_number = 3; + * @return int|string + */ + public function getVersionNumber() + { + return $this->version_number; + } + + /** + * Generated from protobuf field uint64 version_number = 3; + * @param int|string $var + * @return $this + */ + public function setVersionNumber($var) + { + GPBUtil::checkUint64($var); + $this->version_number = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 6; + * @return \Proto\Gradido\GradidoTransfer + */ + public function getTransfer() + { + return $this->readOneof(6); + } + + /** + * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 6; + * @param \Proto\Gradido\GradidoTransfer $var + * @return $this + */ + public function setTransfer($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GradidoTransfer::class); + $this->writeOneof(6, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GradidoCreation creation = 7; + * @return \Proto\Gradido\GradidoCreation + */ + public function getCreation() + { + return $this->readOneof(7); + } + + /** + * Generated from protobuf field .proto.gradido.GradidoCreation creation = 7; + * @param \Proto\Gradido\GradidoCreation $var + * @return $this + */ + public function setCreation($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GradidoCreation::class); + $this->writeOneof(7, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 8; + * @return \Proto\Gradido\GroupFriendsUpdate + */ + public function getGroupFriendsUpdate() + { + return $this->readOneof(8); + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 8; + * @param \Proto\Gradido\GroupFriendsUpdate $var + * @return $this + */ + public function setGroupFriendsUpdate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GroupFriendsUpdate::class); + $this->writeOneof(8, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 9; + * @return \Proto\Gradido\GroupMemberUpdate + */ + public function getGroupMemberUpdate() + { + return $this->readOneof(9); + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 9; + * @param \Proto\Gradido\GroupMemberUpdate $var + * @return $this + */ + public function setGroupMemberUpdate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GroupMemberUpdate::class); + $this->writeOneof(9, $var); + + return $this; + } + + /** + * @return string + */ + public function getData() + { + return $this->whichOneof("data"); + } + +} + diff --git a/community_server/src/Model/Messages/Proto/Gradido/TransferAmount.php b/community_server/src/Model/Messages/Proto/Gradido/TransferAmount.php new file mode 100644 index 000000000..7673582fa --- /dev/null +++ b/community_server/src/Model/Messages/Proto/Gradido/TransferAmount.php @@ -0,0 +1,85 @@ +proto.gradido.TransferAmount + */ +class TransferAmount extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes pubkey = 1; + */ + private $pubkey = ''; + /** + * Generated from protobuf field sint64 amount = 2; + */ + private $amount = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $pubkey + * @type int|string $amount + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes pubkey = 1; + * @return string + */ + public function getPubkey() + { + return $this->pubkey; + } + + /** + * Generated from protobuf field bytes pubkey = 1; + * @param string $var + * @return $this + */ + public function setPubkey($var) + { + GPBUtil::checkString($var, False); + $this->pubkey = $var; + + return $this; + } + + /** + * Generated from protobuf field sint64 amount = 2; + * @return int|string + */ + public function getAmount() + { + return $this->amount; + } + + /** + * Generated from protobuf field sint64 amount = 2; + * @param int|string $var + * @return $this + */ + public function setAmount($var) + { + GPBUtil::checkInt64($var); + $this->amount = $var; + + return $this; + } + +} + diff --git a/community_server/src/Model/Table/AddressTypesTable.php b/community_server/src/Model/Table/AddressTypesTable.php index ea0c86d6e..ba94c99c7 100644 --- a/community_server/src/Model/Table/AddressTypesTable.php +++ b/community_server/src/Model/Table/AddressTypesTable.php @@ -38,10 +38,10 @@ class AddressTypesTable extends Table $this->setPrimaryKey('id'); $this->hasMany('StateGroupAddresses', [ - 'foreignKey' => 'address_type_id' + 'foreignKey' => 'address_type_id', ]); $this->hasMany('TransactionGroupAddaddress', [ - 'foreignKey' => 'address_type_id' + 'foreignKey' => 'address_type_id', ]); } @@ -54,19 +54,20 @@ class AddressTypesTable extends Table public function validationDefault(Validator $validator) { $validator - ->integer('id') + ->nonNegativeInteger('id') ->allowEmptyString('id', null, 'create'); $validator ->scalar('name') - ->maxLength('name', 25) + ->maxLength('name', 45) ->requirePresence('name', 'create') ->notEmptyString('name'); $validator ->scalar('text') ->maxLength('text', 255) - ->allowEmptyString('text'); + ->requirePresence('text', 'create') + ->notEmptyString('text'); return $validator; } diff --git a/community_server/src/Model/Table/BlockchainTypesTable.php b/community_server/src/Model/Table/BlockchainTypesTable.php new file mode 100644 index 000000000..90213ac9f --- /dev/null +++ b/community_server/src/Model/Table/BlockchainTypesTable.php @@ -0,0 +1,68 @@ +setTable('blockchain_types'); + $this->setDisplayField('name'); + $this->setPrimaryKey('id'); + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->nonNegativeInteger('id') + ->allowEmptyString('id', null, 'create'); + + $validator + ->scalar('name') + ->maxLength('name', 45) + ->requirePresence('name', 'create') + ->notEmptyString('name'); + + $validator + ->scalar('text') + ->maxLength('text', 255) + ->allowEmptyString('text'); + + $validator + ->scalar('symbol') + ->maxLength('symbol', 10) + ->allowEmptyString('symbol'); + + return $validator; + } +} diff --git a/community_server/src/Model/Table/RolesTable.php b/community_server/src/Model/Table/RolesTable.php new file mode 100644 index 000000000..940b7f246 --- /dev/null +++ b/community_server/src/Model/Table/RolesTable.php @@ -0,0 +1,72 @@ +setTable('roles'); + $this->setDisplayField('title'); + $this->setPrimaryKey('id'); + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->integer('id') + ->allowEmptyString('id', null, 'create') + ->add('id', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']); + + $validator + ->scalar('title') + ->maxLength('title', 255) + ->allowEmptyString('title'); + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. + * @return \Cake\ORM\RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + $rules->add($rules->isUnique(['id'])); + + return $rules; + } +} diff --git a/community_server/src/Model/Table/StateBalancesTable.php b/community_server/src/Model/Table/StateBalancesTable.php index 85b2f7837..cae6e0fe8 100644 --- a/community_server/src/Model/Table/StateBalancesTable.php +++ b/community_server/src/Model/Table/StateBalancesTable.php @@ -6,6 +6,10 @@ use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; +use Cake\ORM\TableRegistry; +use Cake\I18n\Date; +use Cake\I18n\Time; + /** * StateBalances Model * @@ -78,4 +82,271 @@ class StateBalancesTable extends Table return $rules; } + /* + * create new state balance at beginning of next month from $previousStateBalance + * calculate decay for the time diff + */ + private function calculateStateBalance($previousStateBalance) + { + $entity = $this->newEntity(); + $entity->state_user_id = $previousStateBalance->state_user_id; + $newDate = $previousStateBalance->record_date; + $newDate->day(1); + if($newDate->month <= 12) { + $newDate->month($newDate->month + 1); + } else { + $newDate->month(1); + $newDate->year($newDate->year + 1); + } + $entity->record_date = $newDate; + $entity->amount = $previousStateBalance->partDecay($newDate); + if($this->save($entity)) { + return $entity; + } + return ['state' => 'error', 'msg' => 'couldn\'t save', 'details' => $entity->getErrors()]; + } + + public function sortTransactions($a, $b) + { + if ($a['date'] == $b['date']) { + return 0; + } + return ($a['date'] > $b['date']) ? -1 : 1; + } + /* + * calculate balance at end of month + * work only if state balance at begin of month exist + * use transaction_send_coins and transaction_creations + */ + public function updateLastStateBalanceOfMonth($month, $year, $state_user_id) + { + $first_of_month = new Time("$year-$month-01 00:00"); + $last_of_month = new Time($first_of_month); + $last_of_month->addMonth(1); + $last_of_month->subSecond(1); + $query = $this->find('all') + ->where(['AND' => [ + 'state_user_id' => $state_user_id, + 'record_date >=' => $first_of_month, + 'record_date <=' => $last_of_month + ]]) + ->order(['record_date' => 'ASC']); + if($query->isEmpty()) { + return [ + 'state' => 'error', + 'msg' => 'no state balance in this month found', + 'details' => [ + 'month' => $month, + 'year' => $year, + 'state_user_id' => $state_user_id + ] + ]; + } + // get transactions from this month + $balance_changes = []; + $transactionCreationsTable = TableRegistry::getTableLocator()->get('TransactionCreations'); + $transactionTransfersTable = TableRegistry::getTableLocator()->get('TransactionSendCoins'); + $relevant_creations = $transactionCreationsTable + ->find('all') + ->where(['AND' => [ + 'state_user_id' => $state_user_id, + 'target_date >=' => $first_of_month, + 'target_date <=' => $last_of_month + ]])->contain(false); + foreach($relevant_creations as $creation) { + $balance_changes[] = ['amount' => $creation->amount, 'date' => $creation->target_date]; + } + $relevant_transfers = $transactionTransfersTable + ->find('all') + ->where(['AND' => [ + 'OR' => [ + 'state_user_id' => $state_user_id, + 'receiver_user_id' => $state_user_id + ], + 'transaction.received >= ' => $first_of_month, + 'transaction.received <=' => $last_of_month + ]])->contain(['Transactions']); + debug($relevant_transfers); + foreach($relevant_transfers as $transfer) { + $amount = $transfer->amount; + // if it is a send transaction, negate the value + if($transfer->state_user_id == $state_user_id) { + $amount *= -1.0; + } + $balance_changes[] = ['amount' => $amount, 'date' => $transfer->transaction->received]; + } + uasort($balance_changes, array($this, 'sortTransactions')); + $current_state_balance = null; + if($query->count() == 1) { + $current_state_balance = $this->newEntity(); + $current_state_balance->amount = $query->first()->amount; + $current_state_balance->state_user_id = $state_user_id; + $current_state_balance->record_date = $query->first()->record_date; + } else if($query->count() == 2) { + $array = $query->toArray(); + $current_state_balance = $array[1]; + } else { + throw new Exception('Should\'n occure, never'); + } + + foreach($balance_changes as $change) { + $current_state_balance->amount = $current_state_balance->getDecay($change['date']); + $current_state_balance->amount += $change['amount']; + $current_state_balance->record_date = $change['date']; + } + if(!$this->save($current_state_balance)) { + return ['state' => 'error', 'msg' => 'couldn\'t save', 'details' => $current_state_balance->getErrors()]; + } + return $current_state_balance; + } + + /* + * getting start balance for month + * create and create all missing state_balances before if not exist + * in while loop + */ + + public function chooseForMonthAndUser($month, $year, $state_user_id) + { + $first_of_month = new Time("$year-$month-01 00:00"); + $last_of_month = new Time($first_of_month); + $last_of_month->addMonth(1); + $last_of_month->subSecond(1); + //echo "first of month: " . $first_of_month->i18nFormat() . ", last of month: " . $last_of_month->i18nFormat() . "
"; + $query = $this->find('all'); + + $query->select([ + 'month' => $query->func()->month(['record_date' => 'identifier']), + 'year' => $query->func()->year(['record_date' => 'identifier']) + ])->select($this) + //->where(['month' => $month, 'year' => $year, 'state_user_id' => $state_user_id]) + ->where(['AND' => [ + 'state_user_id' => $state_user_id, + 'record_date >=' => $first_of_month, + 'record_date <=' => $last_of_month + ] + ]) + ->order(['record_date' => 'ASC']) + ->limit(1) + ->contain([]); + if($query->count() == 0) + { + // if any state balance for user exist, pick last one + $state_balances = $this->find('all') + ->where(['state_user_id' => $state_user_id]) + ->limit(1) + ->order(['record_date' => 'DESC']) + ; + // create one for first user transaction + if($state_balances->isEmpty()) + { + $state_user_transactions_table = TableRegistry::getTableLocator()->get('StateUserTransactions'); + $state_user_transaction = $state_user_transactions_table->find('all') + ->where(['state_user_id' => $state_user_id, 'StateUserTransactions.transaction_type_id <' => 3]) + ->contain(['Transactions' => ['TransactionCreations', 'TransactionSendCoins']]) + ->limit(1) + ->order(['transaction_id' => 'ASC']) + ->first() + ; + if(!$state_user_transaction) { + return null; + } + $entity = $this->newEntity(); + $entity->state_user_id = $state_user_id; + if($state_user_transaction->transaction_type_id == 1) { + $creation = $state_user_transaction->transaction->transaction_creations[0]; + $entity->amount = $creation->amount; + $entity->record_date = $creation->target_date; + } else if($state_user_transaction->transaction_type_id == 2) { + $transfer = $state_user_transaction->transaction->transaction_send_coins[0]; + $entity->amount = $transfer->amount; + $entity->record_date = $state_user_transaction->transaction->received; + } + if(!$this->save($entity)) { + return ['state' => 'error', 'msg' => 'error by saving state balance', 'details' => $entity->getErrors()]; + } + } + $state_balances = $this->find('all') + ->where(['state_user_id' => $state_user_id]) + ->limit(1) + ->order(['record_date' => 'DESC']) + ; + if($state_balances->count() == 1) + { + $current_state_balance = $state_balances->first(); + while(true) + { + $new_state_balance_begin = $this->calculateStateBalance($current_state_balance); + if(is_array($new_state_balance_begin)) { + return ['state' => 'error', 'msg' => 'error calculate state balance', 'details' => $new_state_balance_begin]; + } + $record_date = $new_state_balance_begin->record_date; + if($record_date->month === $month && $record_date->year === $year) { + return $new_state_balance_begin; + } + $current_state_balance = $this->updateLastStateBalanceOfMonth($month, $year, $state_user_id); + } + } + else + { + return ['state' => 'error', 'msg' => 'creation of first state_balance failes']; + } + } + return $query->first(); + } + + public function updateBalanceWithTransaction($newBalance, $recordDate, $userId) + { + // max 2 StateBalance Entrys per month: + // 1. first of month or first transaction of user + // 2. last of month or last transaction of user + $first_state_balance_of_month = $this->chooseForMonthAndUser($recordDate->month, $recordDate->year, $userId); + $updated_state_balance = null; + + if($first_state_balance_of_month == null || is_array($first_state_balance_of_month)) { + return $first_state_balance_of_month; + } + + if($first_state_balance_of_month->record_date->day == $recordDate->day && + $recordDate > $first_state_balance_of_month->record_date) { + if($first_state_balance_of_month->amount == $newBalance) { + // nothing to do here + return true; + } + $updated_state_balance = $first_state_balance_of_month; + $updated_state_balance->amount = $newBalance; + // copy complete record date, inclusive time + $first_state_balance_of_month->record_date = $recordDate; + } else { + $query = $this->find('all') + ->where(['AND' => [ + 'record_date >' => $first_state_balance_of_month->record_date, + 'record_date <=' => $recordDate, + 'state_user_id' => $userId + ]]); + if(!$query->isEmpty()) { + $updated_state_balance = $query->first(); + if($updated_state_balance->record_date == $recordDate) { + return true; + } + } else { + $updated_state_balance = $this->newEntity(); + $updated_state_balance->state_user_id = $userId; + } + $updated_state_balance->record_date = $recordDate; + $updated_state_balance->amount = $newBalance; + } + + if($updated_state_balance) { + if(!$this->save($updated_state_balance)) { + return ['state' => 'error', 'msg' => 'error by saving state balance', 'details' => $entity->getErrors()]; + } + + // delete all state_balances which came after + // they will be automaticlly recovered by next call of chooseForMonthAndUser + $this->deleteAll(['state_user_id' => $userId, 'record_date >' => $recordDate]); + } + + return true; + } } diff --git a/community_server/src/Model/Table/StateGroupAddressesTable.php b/community_server/src/Model/Table/StateGroupAddressesTable.php index 62fcf9470..a63e2ae1c 100644 --- a/community_server/src/Model/Table/StateGroupAddressesTable.php +++ b/community_server/src/Model/Table/StateGroupAddressesTable.php @@ -9,7 +9,7 @@ use Cake\Validation\Validator; /** * StateGroupAddresses Model * - * @property \App\Model\Table\StateGroupsTable&\Cake\ORM\Association\BelongsTo $StateGroups + * @property &\Cake\ORM\Association\BelongsTo $Groups * @property \App\Model\Table\AddressTypesTable&\Cake\ORM\Association\BelongsTo $AddressTypes * * @method \App\Model\Entity\StateGroupAddress get($primaryKey, $options = []) @@ -37,13 +37,13 @@ class StateGroupAddressesTable extends Table $this->setDisplayField('id'); $this->setPrimaryKey('id'); - $this->belongsTo('StateGroups', [ - 'foreignKey' => 'state_group_id', - 'joinType' => 'INNER' - ]); + /*$this->belongsTo('Groups', [ + 'foreignKey' => 'group_id', + 'joinType' => 'INNER', + ]);*/ $this->belongsTo('AddressTypes', [ 'foreignKey' => 'address_type_id', - 'joinType' => 'INNER' + 'joinType' => 'INNER', ]); } @@ -56,12 +56,13 @@ class StateGroupAddressesTable extends Table public function validationDefault(Validator $validator) { $validator - ->integer('id') + ->nonNegativeInteger('id') ->allowEmptyString('id', null, 'create'); $validator ->requirePresence('public_key', 'create') - ->notEmptyString('public_key'); + ->notEmptyString('public_key') + ->add('public_key', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']); return $validator; } @@ -75,7 +76,8 @@ class StateGroupAddressesTable extends Table */ public function buildRules(RulesChecker $rules) { - $rules->add($rules->existsIn(['state_group_id'], 'StateGroups')); + $rules->add($rules->isUnique(['public_key'])); + //$rules->add($rules->existsIn(['group_id'], 'Groups')); $rules->add($rules->existsIn(['address_type_id'], 'AddressTypes')); return $rules; diff --git a/community_server/src/Model/Table/StateUserRolesTable.php b/community_server/src/Model/Table/StateUserRolesTable.php new file mode 100644 index 000000000..895e788b2 --- /dev/null +++ b/community_server/src/Model/Table/StateUserRolesTable.php @@ -0,0 +1,86 @@ +setTable('state_user_roles'); + $this->setPrimaryKey('id'); + + + $this->belongsTo('StateUser', [ + 'foreignKey' => 'state_user_id', + 'joinType' => 'INNER' + ]); + + $this->belongsTo('Role', [ + 'foreignKey' => 'role_id', + 'joinType' => 'INNER' + ]); + + + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->integer('id') + ->allowEmptyString('id', null, 'create'); + + + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. + * @return \Cake\ORM\RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + // $rules->add($rules->existsIn(['index_id'], 'Indices')); + //$rules->add($rules->existsIn(['state_group_id'], 'StateGroups')); + + return $rules; + } + + +} diff --git a/community_server/src/Model/Table/TransactionGroupAddaddressTable.php b/community_server/src/Model/Table/TransactionGroupAddaddressTable.php index 3fd03f32a..cb9912083 100644 --- a/community_server/src/Model/Table/TransactionGroupAddaddressTable.php +++ b/community_server/src/Model/Table/TransactionGroupAddaddressTable.php @@ -45,6 +45,10 @@ class TransactionGroupAddaddressTable extends Table 'foreignKey' => 'address_type_id', 'joinType' => 'INNER' ]); + $this->belongsTo('StateUsers', [ + 'foreignKey' => 'state_user_id', + 'joinType' => 'INNER' + ]); } /** @@ -77,6 +81,7 @@ class TransactionGroupAddaddressTable extends Table { $rules->add($rules->existsIn(['transaction_id'], 'Transactions')); $rules->add($rules->existsIn(['address_type_id'], 'AddressTypes')); + $rules->add($rules->existsIn(['state_user_id'], 'StateUsers')); return $rules; } diff --git a/community_server/src/Model/Table/TransactionsTable.php b/community_server/src/Model/Table/TransactionsTable.php index 6777070fe..198feda73 100644 --- a/community_server/src/Model/Table/TransactionsTable.php +++ b/community_server/src/Model/Table/TransactionsTable.php @@ -52,6 +52,10 @@ class TransactionsTable extends Table 'foreignKey' => 'transaction_type_id', 'joinType' => 'INNER' ]); + $this->belongsTo('BlockchainTypes', [ + 'foreignKey' => 'blockchain_type_id', + 'joinType' => 'INNER' + ]); $this->hasMany('StateCreated', [ 'foreignKey' => 'transaction_id' ]); @@ -114,6 +118,7 @@ class TransactionsTable extends Table { $rules->add($rules->existsIn(['state_group_id'], 'StateGroups')); $rules->add($rules->existsIn(['transaction_type_id'], 'TransactionTypes')); + $rules->add($rules->existsIn(['blockchain_type_id'], 'BlockchainTypes')); return $rules; } diff --git a/community_server/src/Model/Transactions/Record.php b/community_server/src/Model/Transactions/Record.php new file mode 100644 index 000000000..5572730ef --- /dev/null +++ b/community_server/src/Model/Transactions/Record.php @@ -0,0 +1,575 @@ +signature = $signature; + $this->publicKey = $pubkey; + } + + public function finalize($transactionId) + { + $signaturesTable = TableRegistry::getTableLocator()->get('TransactionSignatures'); + $entity = $signaturesTable->newEntity(); + $entity->transaction_id = $transactionId; + if(strlen($this->signature) != 128) { + return ['state' => 'error', 'msg' => 'invalid signature size', 'details' => strlen($this->signature)]; + } + if(strlen($this->publicKey) != 64) { + return ['state' => 'error', 'msg' => 'invalid pubkey size', 'details' => strlen($this->publicKey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->signature)) { + return ['state' => 'error', 'msg' => 'signature isn\'t in hex format']; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->publicKey)) { + return ['state' => 'error', 'msg' => 'publicKey isn\'t in hex format']; + } + $entity->signature = hex2bin($this->signature); + $entity->pubkey = hex2bin($this->publicKey); + + if(!$signaturesTable->save($entity)) { + return ['state' => 'error', 'msg' => 'error saving signature', 'details' => $entity->getErrors()]; + } + return true; + } +} + + + +class GradidoModifieUserBalance +{ + private $state_users = []; + private $user_balances = []; + + public function getUserId($userPublicKey) + { + $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); + + $stateUser = $stateUsersTable->find('all')->where(['public_key' => hex2bin($userPublicKey)]); + if($stateUser->isEmpty()) { + return ['state' => 'error', 'msg' => '[GradidoModifieUserBalance::getUserId] couldn\'t find user via public key']; + } + $id = $stateUser->first()->id; + if($id && is_int($id) && (int)$id > 0 && !in_array((int)$id, $this->state_users)) { + array_push($this->state_users, (int)$id); + } + return $id; + } + + public function updateBalance($newBalance, $recordDate, $userId) + { + $stateBalancesTable = TableRegistry::getTableLocator()->get('StateBalances'); + $state_balance_query = $stateBalancesTable->find()->where(['state_user_id' => $userId])->order(['record_date ASC']); + $state_balance = null; + if($state_balance_query->count() > 0) { + $state_balance = $state_balance_query->last(); + } else { + $state_balance = $stateBalancesTable->newEntity(); + $state_balance->state_user_id = $userId; + } + $state_balance->amount = $newBalance; + $state_balance->record_date = $recordDate; + $this->user_balances[$userId] = $state_balance; + $stateBalancesTable->save($state_balance); + return true; + //$this->user_balances[$userId] = ['balance' => $newBalance, ''] + // + //return $stateBalancesTable->updateBalanceWithTransaction($newBalance, $recordDate, $userId); + + /*$first_of_month = new Time("$year-$month-01 00:00"); + $stateBalanceQuery = $stateBalancesTable + ->find('all') + ->where(['state_user_id' => $userId]) + ->order(['record_date' => 'DESC']) + ->limit(1); + $entity = null; + + if(!$stateBalanceQuery->isEmpty()) { + $entity = $stateBalanceQuery->first(); + if($entity->record_date != NULL && + ($entity->record_date > $recordDate || $entity->record_date->day == 1)) { + return false; + } + } else { + $entity = $stateBalancesTable->newEntity(); + $entity->state_user_id = $userId; + } + $entity->record_date = $recordDate; + $entity->amount = $newBalance; + /*if(!$stateBalancesTable->save($entity)) { + return ['state' => 'error', 'msg' => 'error saving state balance', 'details' => $entity->getErrors()]; + }*/ + //return true; + } + + public function getAllStateUsers() + { + return $this->state_users; + } + public function getAllStateUserBalances() + { + return $this->user_balances; + } +} + +class ManageNodeGroupAdd extends GradidoModifieUserBalance +{ + /* + "add_user": { + "user\": " << user << ", + }, + OR + + "move_user_inbound|move_user_outbound": { + "user": " << user << ", + "other_group": " << other_group << ", + "paired_transaction_id": { + "seconds": << ts.seconds <<, + "nanos": << ts.nanos + } + }, + + */ + + private $user_pubkey; + private $other_group = ''; + private $remove_from_group = false; + + public function __construct($data) + { + $this->user_pubkey = $data['user']; + if(isset($data['other_group'])) { + $this->other_group = $data['other_group']; + } + } + + public function finalize($transactionId, $received) + { + $transactionGroupAddadressTable = TableRegistry::getTableLocator()->get('TransactionGroupAddaddress'); + $stateGroupAddresses = TableRegistry::getTableLocator()->get('StateGroupAddresses'); + $transactionGroupEntity = $transactionGroupAddadressTable->newEntity(); + if(!is_int($transactionId)) { + return ['state' => 'error', 'msg' => '[ManageNodeGroupAdd::finalize] transaction id is not int', 'details' => $transactionId]; + } + $transactionGroupEntity->transaction_id = $transactionId; + $transactionGroupEntity->address_type_id = 1; + if(strlen($this->user_pubkey) != 64) { + return ['state' => 'error', 'msg' => 'invalid size user pubkey', 'details' => strlen($this->user_pubkey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->user_pubkey)) { + return ['state' => 'error', 'msg' => 'user_pubkey isn\'t in hex format']; + } + + $userPubkeyBin = hex2bin($this->user_pubkey); + + $transactionGroupEntity->public_key = $userPubkeyBin; + $user_id = $this->getUserId($this->user_pubkey); + if(!is_int($user_id)) { + return ['state' => 'error', 'msg' => '[ManageNodeGroupAdd::finalize] user id is not int', 'details' => $user_id]; + } + $transactionGroupEntity->state_user_id = $user_id; + $transactionGroupEntity->remove_from_group = $this->remove_from_group; + if(!$transactionGroupAddadressTable->save($transactionGroupEntity)) { + return ['state' => 'error', 'msg' => 'error saving TransactionGroupAddaddress Entity', 'details' => $transactionGroupEntity->getErrors()]; + } + + + if($this->remove_from_group) { + $stateGroup_query = $stateGroupAddresses->find('all')->where(['public_key' => hex2bin($this->user_pubkey)]); + if(!$stateGroup_query->isEmpty()) { + $stateGroupAddresses->delete($stateGroup_query->first()); + } + } else { + $stateGroupAddressesEntity = $stateGroupAddresses->newEntity(); + $stateGroupAddressesEntity->group_id = 1; + $stateGroupAddressesEntity->public_key = $userPubkeyBin; + $stateGroupAddressesEntity->address_type_id = 1; + if(!$stateGroupAddresses->save($stateGroupAddressesEntity)) { + return ['state' => 'error', 'msg' => 'error saving state group addresses entity', 'details' => $stateGroupAddressesEntity->getErrors()]; + } + } + + return true; + } + + public function setRemoveFromGroup($removeFromGroup) { + $this->remove_from_group = $removeFromGroup; + } +} + + +class GradidoCreation extends GradidoModifieUserBalance +{ + /* + * "gradido_creation": { + "user": " << user << ", + "new_balance": << v.new_balance << , + "prev_transfer_rec_num": << v.prev_transfer_rec_num <<, + "amount": << v.amount << + } + */ + private $userPubkey; + private $amount; + private $targetDate; // seems currently not in node server implementet, use hedera date until it is implemented + private $new_balance; + + + public function __construct($data) + { + $this->userPubkey = $data['user']; + $this->amount = $data['amount']['amount']; + $this->new_balance = $data['new_balance']['amount']; + //$this->targetDate = $received; + } + + public function finalize($transactionId, $received) + { + // TODO: don't use, after node server transmit correct date + $this->targetDate = $received; + + $transactionCreationTable = TableRegistry::getTableLocator()->get('TransactionCreations'); + + + $state_user_id = $this->getUserId($this->userPubkey); + if(!is_int($state_user_id)) { + return $state_user_id; + } + + $entity = $transactionCreationTable->newEntity(); + $entity->transaction_id = $transactionId; + $entity->amount = $this->amount; + $entity->target_date = $this->targetDate; + $entity->state_user_id = $state_user_id; + + if(!$transactionCreationTable->save($entity)) { + return ['state' => 'error', 'msg' => 'error saving create transaction', 'details' => $entity->getErrors()]; + } + + $balance_result = $this->updateBalance($this->new_balance, $received, $state_user_id); + if(is_array($balance_result)) { + return $balance_result; + } + + return true; + } + + + +} + +class GradidoTransfer extends GradidoModifieUserBalance +{ + /* + "local_transfer|inbound_transfer|outbound_transfer": { + "sender": { + "user": " << sender << ", + "new_balance": << tt.sender.new_balance << , + "prev_transfer_rec_num": << tt.sender.prev_transfer_rec_num << + }, + "receiver": { + "user": " << receiver << ", + "new_balance": << tt.receiver.new_balance << , + "prev_transfer_rec_num": << tt.receiver.prev_transfer_rec_num << + }, + "amount": << tt.amount << + }, + * */ + private $amount; + private $sender_new_balance = null; + private $sender_pubkey; + + private $receiver_pubkey; + private $receiver_new_balance = null; + + + public function __construct($data) + { + $this->amount = $data['amount']['amount']; + + $sender = $data['sender']; + $this->sender_pubkey = $sender['user']; + if(isset($sender['new_balance'])) { + $this->sender_new_balance = $sender['new_balance']['amount']; + } + + $receiver = $data['receiver']; + $this->receiver_pubkey = $receiver['user']; + if(isset($receiver['new_balance'])) { + $this->receiver_new_balance = $receiver['new_balance']['amount']; + } + + } + + public function finalize($transactionId, $received) + { + $transactionTransferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins'); + if(strlen($this->sender_pubkey) != 64) { + return ['state' => 'error', 'msg' => 'invalid size sender pubkey', 'details' => strlen($this->user_pubkey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->sender_pubkey)) { + return ['state' => 'error', 'msg' => 'sender_pubkey isn\'t in hex format']; + } + if(strlen($this->receiver_pubkey) != 64) { + return ['state' => 'error', 'msg' => 'invalid size receiver pubkey', 'details' => strlen($this->user_pubkey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->receiver_pubkey)) { + return ['state' => 'error', 'msg' => 'receiver_pubkey isn\'t in hex format']; + } + + $sender_id = $this->getUserId($this->sender_pubkey); + $receiver_id = $this->getUserId($this->receiver_pubkey); + if(is_array($sender_id) && is_array($receiver_id)) { + return ['state' => 'error', 'msg' => 'neither sender or receiver known']; + } + $transferEntity = $transactionTransferTable->newEntity(); + $transferEntity->transaction_id = $transactionId; + $transferEntity->sender_public_key = hex2bin($this->sender_pubkey); + $transferEntity->receiver_public_key = hex2bin($this->receiver_pubkey); + $transferEntity->amount = $this->amount; + if($this->sender_new_balance != null) { + $transferEntity->sender_final_balance = $this->sender_new_balance; + + if(is_int($sender_id) && $sender_id > 0) { + $transferEntity->state_user_id = $sender_id; + $balance_result = $this->updateBalance($this->sender_new_balance, $received, $sender_id); + if(is_array($balance_result)) { + return $balance_result; + } + } + } + if($this->receiver_new_balance != null && is_int($receiver_id) && $receiver_id > 0) { + $transferEntity->receiver_user_id = $receiver_id; + $balance_result = $this->updateBalance($this->receiver_new_balance, $received, $receiver_id); + if(is_array($balance_result)) { + return $balance_result; + } + } + + if(!$transactionTransferTable->save($transferEntity)) { + return ['state' => 'error', 'msg' => 'error saving transaction send coins entity', 'details' => $transferEntity->getErrors()]; + } + + return true; + } + +} + + + + +class Record +{ + private $sequenceNumber = 0; + private $runningHash = null; + private $transactionType = ''; + private $memo = ''; + private $signatures = []; + private $received; + private $transactionObj = null; + private $result; + private $partCount = 0; + + public function __construct() + { + + } + + + public function parseRecord($json) { + if(!isset($json['record_type'])) { + return false; + } + //var_dump($json); + switch($json['record_type']) { + case 'GRADIDO_TRANSACTION': + return $this->parseTransaction($json['transaction']); + case 'MEMO': + $this->memo .= $json['memo']; + return true; + case 'SIGNATURES': + return $this->parseSignatures($json['signature']); + case 'STRUCTURALLY_BAD_MESSAGE': + case 'RAW_MESSAGE': + case 'BLANK': + return false; + } + } + + /*! + * \brief save data parts in db + */ + public function finalize() + { + $transactionTypesTable = TableRegistry::getTableLocator()->get('TransactionTypes'); + $transactionsTable = TableRegistry::getTableLocator()->get('Transactions'); + $stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions'); + + $transactionTypeName = $this->nodeTransactionTypeToDBTransactionType($this->transactionType); + $transactionTypeResults = $transactionTypesTable->find('all')->where(['name' => $transactionTypeName]); + if($transactionTypeResults->isEmpty()) { + return [ + 'state' => 'error', 'msg' => 'transaction type not found', + 'details' => ['nodeType' => $this->transactionType, 'dbType' => $transactionTypeName] + ]; + } + if(!$this->transactionObj) { + return ['state' => 'error', 'msg' => 'transaction obj is null']; + } + if($this->sequenceNumber <= 0) { + return ['state' => 'error', 'msg' => 'sequence number invalid', 'details' => $this->sequenceNumber]; + } + $transactionExistResult = $transactionsTable->find('all')->where(['id' => intval($this->sequenceNumber)]); + if(!$transactionExistResult->isEmpty()) { + return ['state' => 'warning', 'msg' => 'transaction already exist in db', 'details' => $this->sequenceNumber]; + } + $newTransaction = $transactionsTable->newEntity(); + $newTransaction->id = $this->sequenceNumber; + $newTransaction->transaction_type_id = $transactionTypeResults->first()->id; + $newTransaction->memo = $this->memo; + if($this->runningHash != '' && strlen($this->runningHash) % 2 == 0) { + $newTransaction->tx_hash = hex2bin($this->runningHash); + } + $newTransaction->received = $this->received; + + //! TODO change into transaction, if at least one fail, rollback + /* + // In a controller. + $articles->getConnection()->transactional(function () use ($articles, $entities) { + foreach ($entities as $entity) { + $articles->save($entity, ['atomic' => false]); + } + }); + */ + if(!$transactionsTable->save($newTransaction)) { + return ['state' => 'error', 'msg' => 'error saving transaction', 'details' => $newTransaction->getErrors()]; + } + + foreach($this->signatures as $sign) { + $sign_result = $sign->finalize($this->sequenceNumber); + if($sign_result !== true) { + return ['state' => 'error', 'msg', 'error finalizing signature', 'details' => $sign_result]; + } + } + $transaction_obj_result = $this->transactionObj->finalize($newTransaction->id, $this->received); + if($transaction_obj_result !== true) { + return ['state' => 'error', 'msg' => 'error finalizing transaction object', 'details' => $transaction_obj_result]; + } + $state_users = $this->transactionObj->getAllStateUsers(); + $sut_entities = []; + $state_user_balances = $this->transactionObj->getAllStateUserBalances(); + foreach($state_users as $state_user_id) { + $entity = $stateUserTransactionsTable->newEntity(); + $entity->state_user_id = $state_user_id; + $entity->transaction_id = $newTransaction->id; + $entity->transaction_type_id = $newTransaction->transaction_type_id; + $entity->balance = $state_user_balances[$state_user_id]->amount; + $entity->balance_date = $state_user_balances[$state_user_id]->record_date; + $sut_entities[] = $entity; + } + $sut_results = $stateUserTransactionsTable->saveMany($sut_entities); + foreach($sut_results as $i => $result) { + if(false == $result) { + return ['state' => 'error', 'msg' => 'error saving state_user_transaction', 'details' => $sut_entities[$i]->getErrors()]; + } + } + + return true; + + } + + private function nodeTransactionTypeToDBTransactionType($nodeTransactionType) + { + switch($nodeTransactionType) { + case 'GRADIDO_CREATION': + return 'creation'; + + case 'MOVE_USER_INBOUND': + case 'ADD_USER': + return 'group add member'; + + case 'MOVE_USER_OUTBOUND': + return 'group remove member'; + + case 'LOCAL_TRANSFER': + case 'INBOUND_TRANSFER': + case 'OUTBOUND_TRANSFER': + return 'transfer'; + } + return 'unknown'; + } + + private function parseSignatures($signaturesArray) + { + foreach($signaturesArray as $sign) { + $this->signatures[] = new Signature($sign['signature'], $sign['pubkey']); + } + return true; + } + + private function parseTransaction($data) + { + $this->transactionType = $data['transaction_type']; + $sign = $data['signature']; + $this->signatures[] = new Signature($sign['signature'], $sign['pubkey']); + + $hedera = $data['hedera_transaction']; + $this->sequenceNumber = $hedera['sequenceNumber']; + $this->runningHash = $hedera['runningHash']; + $this->received = Time::createFromTimestamp($hedera['consensusTimestamp']['seconds']); + + $field_index = ''; + $class_name = ''; + + $removeFromGroup = false; + switch($this->transactionType) + { + case 'GRADIDO_CREATION': $field_index = 'gradido_creation'; $class_name = 'GradidoCreation'; break; + case 'ADD_USER': $field_index = 'add_user'; $class_name = 'ManageNodeGroupAdd'; break; + case 'MOVE_USER_INBOUND': $field_index = 'move_user_inbound'; $class_name = 'ManageNodeGroupAdd'; break; + case 'MOVE_USER_OUTBOUND': $field_index = 'move_user_outbound'; $class_name = 'ManageNodeGroupAdd'; $removeFromGroup = true; break; + case 'LOCAL_TRANSFER': $field_index = 'local_transfer'; $class_name = 'GradidoTransfer'; break; + case 'INBOUND_TRANSFER': $field_index = 'inbound_transfer'; $class_name = 'GradidoTransfer'; break; + case 'OUTBOUND_TRANSFER': $field_index = 'outbound_transfer'; $class_name = 'GradidoTransfer'; break; + } + if($class_name == '' || $field_index == '') { + return ['state' => 'error', 'msg' => 'node transaction type unknown', 'details' => $this->transactionType]; + } + $class_name = 'Model\\Transactions\\' . $class_name; + $this->transactionObj = new $class_name($data[$field_index]); + if($class_name == 'ManageNodeGroupAdd') { + $this->transactionObj->setRemoveFromGroup($removeFromGroup); + } + + $this->result = $data['result']; + $this->partCount = intval($data['parts']); + $this->memo = $data['memo']; + return true; + } + + public function getSequenceNumber() { + return $this->sequenceNumber; + } + public function getPartCount() { + return $this->partCount; + } + +} \ No newline at end of file diff --git a/community_server/src/Model/Transactions/SignatureMap.php b/community_server/src/Model/Transactions/SignatureMap.php index d8cf35929..cbe48e636 100644 --- a/community_server/src/Model/Transactions/SignatureMap.php +++ b/community_server/src/Model/Transactions/SignatureMap.php @@ -29,12 +29,12 @@ class SignatureMap { static public function fromEntity($transactionSignatures) { - $protoSigMap = new \Model\Messages\Gradido\SignatureMap(); + $protoSigMap = new \Proto\Gradido\SignatureMap(); $sigPairs = $protoSigMap->getSigPair(); //echo "sigPairs: "; var_dump($sigPairs); echo "
"; //return null; foreach($transactionSignatures as $signature) { - $sigPair = new \Model\Messages\Gradido\SignaturePair(); + $sigPair = new \Proto\Gradido\SignaturePair(); $sigPair->setPubKey(stream_get_contents($signature->pubkey)); $sigPair->setEd25519(stream_get_contents($signature->signature)); @@ -46,14 +46,14 @@ class SignatureMap { static public function build($bodyBytes, array $keys) { - $protoSigMap = new \Model\Messages\Gradido\SignatureMap(); + $protoSigMap = new \Proto\Gradido\SignatureMap(); $sigPairs = $protoSigMap->getSigPair(); //echo "sigPairs: "; var_dump($sigPairs); echo "
"; //return null; // sign with keys foreach($keys as $key) { - $sigPair = new \Model\Messages\Gradido\SignaturePair(); + $sigPair = new \Proto\Gradido\SignaturePair(); $sigPair->setPubKey(hex2bin($key['pub'])); $sigPair->setEd25519(sodium_crypto_sign_detached($bodyBytes, hex2bin($key['priv']))); diff --git a/community_server/src/Model/Transactions/Transaction.php b/community_server/src/Model/Transactions/Transaction.php index 99bd5fae7..da21495b9 100644 --- a/community_server/src/Model/Transactions/Transaction.php +++ b/community_server/src/Model/Transactions/Transaction.php @@ -25,7 +25,7 @@ class Transaction extends TransactionBase { //$transactionBin = base64_decode($base64Data, true); //if($transactionBin == false) { //sodium_base64_VARIANT_URLSAFE_NO_PADDING - if(is_a($base64Data, '\Model\Messages\Gradido\Transaction')) { + if(is_a($base64Data, '\Proto\Gradido\Transaction')) { $this->mProtoTransaction = $base64Data; $this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes()); return; @@ -39,6 +39,7 @@ class Transaction extends TransactionBase { $transactionBin = base64_decode($base64Data, true); if($transactionBin == false) { $this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data); + $this->addError('base64', $base64Data); return; } } @@ -49,7 +50,7 @@ class Transaction extends TransactionBase { $this->addError('Transaction', 'base64 decode error: ' . $base64Data); } else { //var_dump($transactionBin); - $this->mProtoTransaction = new \Model\Messages\Gradido\Transaction(); + $this->mProtoTransaction = new \Proto\Gradido\GradidoTransaction(); try { $this->mProtoTransaction->mergeFromString($transactionBin); //var_dump($this->mProtoTransaction); @@ -69,11 +70,11 @@ class Transaction extends TransactionBase { } } - static public function build(\Model\Messages\Gradido\TransactionBody $transactionBody, $senderKeyPair) + static public function build(\Proto\Gradido\TransactionBody $transactionBody, $senderKeyPair) { - $protoTransaction = new \Model\Messages\Gradido\Transaction(); + $protoTransaction = new \Proto\Gradido\GradidoTransaction(); - $recevied = new \Model\Messages\Gradido\TimestampSeconds(); + $recevied = new \Proto\Gradido\TimestampSeconds(); $recevied->setSeconds(time()); $protoTransaction->setReceived($recevied); @@ -197,14 +198,14 @@ class Transaction extends TransactionBase { 'TransactionSignatures']) ->first(); //var_dump($transactionEntry->toArray()); - $protoTransaction = new \Model\Messages\Gradido\Transaction(); + $protoTransaction = new \Proto\Gradido\Transaction(); $protoTransaction->setId($transactionEntry->id); - $recevied = new \Model\Messages\Gradido\TimestampSeconds(); + $recevied = new \Proto\Gradido\TimestampSeconds(); $recevied->setSeconds($transactionEntry->received->getTimestamp()); $protoTransaction->setReceived($recevied); @@ -228,7 +229,7 @@ class Transaction extends TransactionBase { } //echo "verify bodybytes:
" . bin2hex($bodyBytes) . '
'; - $created = new \Model\Messages\Gradido\TimestampSeconds(); + $created = new \Proto\Gradido\TimestampSeconds(); $created->setSeconds($recevied->getSeconds()); $body->setCreated($created); $bodyBytes = $body->serializeToString(); diff --git a/community_server/src/Model/Transactions/TransactionBase.php b/community_server/src/Model/Transactions/TransactionBase.php index 31a26f2ee..3102d2341 100644 --- a/community_server/src/Model/Transactions/TransactionBase.php +++ b/community_server/src/Model/Transactions/TransactionBase.php @@ -67,7 +67,7 @@ class TransactionBase { $stateBalancesTable = self::getTable('stateBalances'); $stateBalanceQuery = $stateBalancesTable ->find('all') - ->select(['amount', 'id']) + ->select(['amount', 'id', 'record_date']) ->contain(false) ->where(['state_user_id' => $stateUserId]);//->first(); //debug($stateBalanceQuery); @@ -101,9 +101,14 @@ class TransactionBase { if($stateUserTransactions->count() > 0) { $stateBalanceTable = self::getTable('state_balances'); + $state_user_transaction = $stateUserTransactions->first(); + if(!$state_user_transaction) { + $this->addError('TransactionBase::addStateUserTransaction', 'state_user_transaction is zero, no first entry exist?'); + return false; + } $balance_entity = $stateBalanceTable->newEntity(); - $balance_entity->amount = $stateUserTransactions->first()->balance; - $balance_entity->record_date = $stateUserTransactions->first()->balance_date; + $balance_entity->amount = $state_user_transaction->balance; + $balance_entity->record_date = $state_user_transaction->balance_date; $balance = $balance_entity->decay + $balance; } $entity = $stateUserTransactionTable->newEntity(); diff --git a/community_server/src/Model/Transactions/TransactionBody.php b/community_server/src/Model/Transactions/TransactionBody.php index ef785705c..e0d688dbb 100644 --- a/community_server/src/Model/Transactions/TransactionBody.php +++ b/community_server/src/Model/Transactions/TransactionBody.php @@ -12,7 +12,7 @@ class TransactionBody extends TransactionBase { private $transactionTypeId = 0; public function __construct($bodyBytes) { - $this->mProtoTransactionBody = new \Model\Messages\Gradido\TransactionBody(); + $this->mProtoTransactionBody = new \Proto\Gradido\TransactionBody(); try { $this->mProtoTransactionBody->mergeFromString($bodyBytes); // cannot catch Exception with cakePHP, I don't know why @@ -155,7 +155,7 @@ class TransactionBody extends TransactionBase { static public function fromEntity($memo, $transaction) { - $protoBody = new \Model\Messages\Gradido\TransactionBody(); + $protoBody = new \Proto\Gradido\TransactionBody(); $protoBody->setMemo($memo); //$created->setSeconds($var); @@ -176,7 +176,7 @@ class TransactionBody extends TransactionBase { static public function build($memo, $specificTransaction) { - $protoBody = new \Model\Messages\Gradido\TransactionBody(); + $protoBody = new \Proto\Gradido\TransactionBody(); $protoBody->setMemo($memo); if(is_a($specificTransaction, 'TransactionCreation')) { diff --git a/community_server/src/Model/Transactions/TransactionCreation.php b/community_server/src/Model/Transactions/TransactionCreation.php index aeac73ce8..54a87e1cb 100644 --- a/community_server/src/Model/Transactions/TransactionCreation.php +++ b/community_server/src/Model/Transactions/TransactionCreation.php @@ -26,34 +26,33 @@ class TransactionCreation extends TransactionBase { return $this->protoTransactionCreation; } - static public function build($amount, $memo, $receiver_public_hex, $ident_hash, $targetDate = null) + static public function build($amount, $memo, $receiver_public_hex, $targetDate = null) { - $receiver = new \Model\Messages\Gradido\ReceiverAmount(); + $receiver = new \Proto\Gradido\TransferAmount(); $receiver->setAmount($amount); //$this->receiver_pubkey_hex = $receiver_public_hex; if(strlen($receiver_public_hex) != 64) { return ['state' => 'error', 'msg' => 'invalid pubkey']; } $pubKeyBin = hex2bin($receiver_public_hex); - $receiver->setEd25519ReceiverPubkey($pubKeyBin); + $receiver->setPubkey($pubKeyBin); //var_dump($requestData); - $creationDate = new \Model\Messages\Gradido\TimestampSeconds(); + $creationDate = new \Proto\Gradido\TimestampSeconds(); $creationDate->setSeconds(time()); - $transactionBody = new \Model\Messages\Gradido\TransactionBody(); + $transactionBody = new \Proto\Gradido\TransactionBody(); $transactionBody->setMemo($memo); $transactionBody->setCreated($creationDate); - $transaction = new \Model\Messages\Gradido\TransactionCreation(); - $transaction->setReceiverAmount($receiver); - $transaction->setIdentHash($ident_hash); + $transaction = new \Proto\Gradido\GradidoTransaction(); + $transaction->setReceiver($receiver); //echo "target date: "; //var_dump($targetDate); //die('die'); if($targetDate) { - $targetDateTimestamp = new \Model\Messages\Gradido\TimestampSeconds(); + $targetDateTimestamp = new \Proto\Gradido\TimestampSeconds(); $targetDateTimestamp->setSeconds($targetDate->getTimestamp()); //var_dump($targetDateTimestamp); die('target'); $transaction->setTargetDate($targetDateTimestamp); @@ -65,16 +64,13 @@ class TransactionCreation extends TransactionBase { public function getAmount() { - return $this->protoTransactionCreation->getReceiverAmount()->getAmount(); + return $this->protoTransactionCreation->getReceiver()->getAmount(); } public function getReceiverPublic() { - return $this->protoTransactionCreation->getReceiverAmount()->getEd25519ReceiverPubkey(); + return $this->protoTransactionCreation->getReceiver()->getPubkey(); } - public function getIdentHash() { - return $this->protoTransactionCreation->getIdentHash(); - } public function validate($sigPairs) { @@ -88,54 +84,6 @@ class TransactionCreation extends TransactionBase { } } - // check if creation threshold for this month isn't reached - - //$identHashBin = sprintf("%0d", $this->getIdentHash()); - // padding with zero in case hash is smaller than 32 bytes, static length binary field in db - // ident hash isn't collision ressistent, it is for speed up search - $identHashBin = pack('a32', $this->getIdentHash()); - - ////////// old validation not more than 3k GDD for 3 Month /////////////// - /*$existingCreations = $this->transactionCreationsTable - ->find('all') - ->select(['amount', 'state_user_id', 'target_date']) - ->contain(['StateUsers' => ['fields' => ['StateUsers.public_key']]]) - ->where(['target_date' => NULL]); - //$targetDate = $this->protoTransactionCreation->getTargetDate(); - //echo "choose existing transactions
"; - //$existingCreations->where([$q->func()->extract('YEAR_MONTH', 'target_date') . ' LIKE ' . $q->func()->extract('YEAR_MONTH', $targetDate)]); - // ->where(['EXTRACT(YEAR_MONTH FROM target_date) LIKE EXTRACT(YEAR_MONTH FROM']); - // uncomment because ident hash didn't work at the moment - //->where(['ident_hash' => $identHashBin]); - //$existingCreations->select(['amount_sum' => $existingCreations->func()->sum('amount')]); - - $existingCreations->matching('Transactions', function ($q) { - - return $q->where( - ['OR' => - ['EXTRACT(YEAR_MONTH FROM Transactions.received) LIKE EXTRACT(YEAR_MONTH FROM NOW())', - 'EXTRACT(YEAR_MONTH FROM DATE_ADD(Transactions.received, INTERVAL 2 MONTH)) LIKE EXTRACT(YEAR_MONTH FROM NOW())'] - ])->select('received'); - - - }); - //debug($existingCreations); - //echo "after choose existing transactions
"; - $newSum = $this->getAmount(); - //var_dump($existingCreations->toArray()); - foreach($existingCreations as $creation) { - $keyHex = bin2hex(stream_get_contents($creation->state_user->public_key)); - //echo "\ncompare \n$keyHex\nwith: \n". $this->receiver_pubkey_hex."\n"; - if($keyHex == $this->receiver_pubkey_hex) { - $newSum += $creation->amount; - } - } - - - if($newSum > 30000000) { - $this->addError('TransactionCreation::validate', 'Creation more than 1.000 GDD per Month (3 Month) not allowed'); - return false; - }//*/ /////////////// new validation, not more than 1K GDD per month via target_date /////////////////////////// $existingCreations2 = $this->transactionCreationsTable @@ -204,7 +152,6 @@ class TransactionCreation extends TransactionBase { } $transactionCreationEntity->state_user_id = $receiverUserId; $transactionCreationEntity->amount = $this->getAmount(); - $transactionCreationEntity->ident_hash = $this->getIdentHash(); $transactionCreationEntity->target_date = $this->protoTransactionCreation->getTargetDate()->getSeconds(); if(!$this->transactionCreationsTable->save($transactionCreationEntity)) { @@ -262,7 +209,7 @@ class TransactionCreation extends TransactionBase { static public function fromEntity($transactionCreationEntity) { - $protoCreation = new \Model\Messages\Gradido\TransactionCreation(); + $protoCreation = new \Proto\Gradido\GradidoCreation(); //var_dump($transactionCreationEntity); $stateUsersTable = TableRegistry::getTableLocator()->get('state_users'); @@ -273,12 +220,14 @@ class TransactionCreation extends TransactionBase { $stateUser = $stateUsersTable->get($userId); - $receiverAmount = new \Model\Messages\Gradido\ReceiverAmount(); - $receiverAmount->setEd25519ReceiverPubkey(stream_get_contents($stateUser->public_key)); - + $receiverAmount = new \Proto\Gradido\TransferAmount(); + $receiverAmount->setPubkey(stream_get_contents($stateUser->public_key)); $receiverAmount->setAmount($transactionCreationEntity->amount); - $protoCreation->setReceiverAmount($receiverAmount); + $protoCreation->setReceiver($receiverAmount); + + // TODO: add target_date + // function currently not used, maybe can even be deleted //echo "receiver amount: check
"; //$identHashBytes = stream_get_contents($transactionCreationEntity->ident_hash); diff --git a/community_server/src/Model/Transactions/TransactionTransfer.php b/community_server/src/Model/Transactions/TransactionTransfer.php index b9182c3ba..c8e9e7973 100644 --- a/community_server/src/Model/Transactions/TransactionTransfer.php +++ b/community_server/src/Model/Transactions/TransactionTransfer.php @@ -22,9 +22,8 @@ class TransactionTransfer extends TransactionBase { { // repeated SenderAmount senderAmounts = 1; // repeated ReceiverAmount receiverAmounts = 2; - $receiver = new \Model\Messages\Gradido\ReceiverAmount(); - $sender = new \Model\Messages\Gradido\SenderAmount(); - $receiver->setAmount($amount); + + $sender = new \Proto\Gradido\TransferAmount(); $sender->setAmount($amount); if(strlen($receiver_public_hex) != 64) { @@ -34,71 +33,56 @@ class TransactionTransfer extends TransactionBase { return ['state' => 'error', 'msg' => 'invalid sender pubkey']; } $receiverPubKeyBin = hex2bin($receiver_public_hex); - $receiver->setEd25519ReceiverPubkey($receiverPubKeyBin); $senderPubKeyBin = hex2bin($sender_public_hex); - $sender->setEd25519SenderPubkey($senderPubKeyBin); + $sender->setPubkey($senderPubKeyBin); //var_dump($requestData); - $creationDate = new \Model\Messages\Gradido\TimestampSeconds(); + $creationDate = new \Proto\Gradido\TimestampSeconds(); $creationDate->setSeconds(time()); - $transactionBody = new \Model\Messages\Gradido\TransactionBody(); + $transactionBody = new \Proto\Gradido\TransactionBody(); $transactionBody->setMemo($memo); $transactionBody->setCreated($creationDate); - $transaction = new \Model\Messages\Gradido\Transfer(); - $transaction->setReceiverAmounts([$receiver]); - $transaction->setSenderAmounts([$sender]); - $transactionBody->setTransfer($transaction); + $transfer = new \Proto\Gradido\GradidoTransfer(); + $local_transfer = new \Proto\Gradido\LocalTransfer(); + $local_transfer->setReceiver($receiverPubKeyBin); + $local_transfer->setSender($sender); + $transfer->setLocal($local_transfer); + $transactionBody->setTransfer($transfer); return ['state' => 'success', 'transactionBody' => $transactionBody]; } public function validate($sigPairs) { - //$this->addError('TransactionTransfer::validate', 'not implemented yet'); - //return false; - //$time = microtime(true); - static $functionName = 'TransactionCreation::validate'; - /* - * // check signature(s) - foreach($sigPairs as $sigPair) { - //echo 'sig Pair: '; var_dump($sigPair); echo "
"; - $pubkey = $sigPair->getPubKey(); - $signature = $sigPair->getEd25519(); - if (!\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) { - $this->addError('Transaction::validate', 'signature for key ' . bin2hex($pubkey) . ' isn\'t valid ' ); - return false; - } - } - */ - $sigPubHexs = []; - foreach($sigPairs as $sigPair) { - //echo 'sig Pair: '; var_dump($sigPair); echo "
"; - $pubkey = bin2hex($sigPair->getPubKey()); - //$hash = TransactionCreation::DRMakeStringHash($pubkey); - $hash = $pubkey; - if(!isset($sigPubHexs[$hash])) { - $sigPubHexs[$hash] = [$pubkey]; - } else { - array_push($sigPubHexs[$hash], $pubkey); - } - //array_push($sigPubHexs, $pubkey); - } - - $stateUsersTable = TableRegistry::getTableLocator()->get('state_users'); - $senderAmounts = $this->protoTransactionTransfer->getSenderAmounts(); - $senderSum = 0; - $receiverSum = 0; - - $senderPublics = []; - foreach($senderAmounts as $i => $senderAmount) { - $senderPublic = $senderAmount->getEd25519SenderPubkey(); - $senderPublicHex = bin2hex($senderPublic); - array_push($senderPublics, $senderPublic); + //$this->addError('TransactionTransfer::validate', 'not implemented yet'); + //return false; + //$time = microtime(true); + static $functionName = 'TransactionCreation::validate'; + $sigPubHexs = []; + foreach($sigPairs as $sigPair) + { + $pubkey = $sigPair->getPubKey(); + $pubkey_hex = bin2hex($pubkey); + //$hash = TransactionCreation::DRMakeStringHash($pubkey); + $hash = $pubkey_hex; + if(!isset($sigPubHexs[$hash])) { + $sigPubHexs[$hash] = [$pubkey_hex]; + } else { + array_push($sigPubHexs[$hash], $pubkey_hex); + } + //array_push($sigPubHexs, $pubkey); + } + + $stateUsersTable = TableRegistry::getTableLocator()->get('state_users'); + $local_transfer = $this->protoTransactionTransfer->getLocal(); + $sender = $local_transfer->getSender(); + $senderPublic = $sender->getPubkey(); + $senderPublicHex = bin2hex($senderPublic); if(strlen($senderPublicHex) != 64) { - $this->addError($functionName, 'invalid sender public key'); - return false; + $this->addError($functionName, 'invalid sender public key'); + return false; } // check if signature exist for sender //$hash = TransactionCreation::DRMakeStringHash($senderPublicHex); @@ -108,7 +92,7 @@ class TransactionTransfer extends TransactionBase { return false; } // check if sender has enough Gradido - $amount = $senderAmount->getAmount(); + $amount = $sender->getAmount(); $user = $stateUsersTable ->find('all') ->select(['id']) @@ -123,66 +107,37 @@ class TransactionTransfer extends TransactionBase { $this->addError($functionName, 'sender ' . $i . ' hasn\t enough GDD'); return false; } - $senderSum += $amount; - } - $uniqueSenderPublics = array_unique($senderPublics); - if(count($senderPublics) !== count($uniqueSenderPublics)) { - $this->addError($functionName, 'duplicate sender public key'); - return false; - } - $receiverAmounts = $this->protoTransactionTransfer->getReceiverAmounts(); - $receiverPublics = []; - foreach($receiverAmounts as $reveiverAmount) { - if(strlen($reveiverAmount->getEd25519ReceiverPubkey()) != 32) { + $receiver_public_key = $local_transfer->getReceiver(); + if(strlen($receiver_public_key) != 32) { $this->addError($functionName, 'invalid receiver public key'); return false; } - array_push($receiverPublics, $reveiverAmount->getEd25519ReceiverPubkey()); - $receiverSum += $reveiverAmount->getAmount(); - } - $uniqueReceiverPublic = array_unique($receiverPublics); - if(count($uniqueReceiverPublic) !== count($receiverPublics)) { - $this->addError($functionName, 'duplicate receiver public key'); - return false; - } - $uniquePublics = array_unique(array_merge($receiverPublics, $senderPublics)); - if(count($uniquePublics) !== count($senderPublics) + count($receiverPublics)) { - // means at least one sender is the same as one receiver - $this->addError($functionName, 'duplicate public in sender and receiver'); - return false; - } - if($senderSum !== $receiverSum) { - $this->addError($functionName, 'sender amount doesn\'t match receiver amount'); - return false; - } - if($senderSum < 0) { - $this->addError($functionName, 'negative amount not supported'); - return false; - } - //die("\n"); - return true; + // check if receiver exist + $receiver_user = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $receiver_public_key])->first(); + if(!$receiver_user) { + $this->addError($functionName, 'couldn\'t find receiver ' . $i .' in db' ); + return false; + } + if($amount < 0) { + $this->addError($functionName, 'negative amount not supported'); + return false; + } + return true; } public function save($transaction_id, $firstPublic, $received) { static $functionName = 'TransactionCreation::save'; + $local_transfer = $this->protoTransactionTransfer->getLocal(); - if(count($this->protoTransactionTransfer->getSenderAmounts()) !== 1) { - $this->addError($functionName, 'not more than one sender currently supported'); - return false; - } - $senderAmount = $this->protoTransactionTransfer->getSenderAmounts()[0]; + $senderAmount = $local_transfer->getSender(); + $receiver = $local_transfer->getReceiver(); - if(count($this->protoTransactionTransfer->getReceiverAmounts()) !== 1) { - $this->addError($functionName, 'not more than one receiver currently supported'); - return false; - } - $receiverAmount = $this->protoTransactionTransfer->getReceiverAmounts()[0]; $transactionTransferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins'); - $senderUserId = $this->getStateUserId($senderAmount->getEd25519SenderPubkey()); - $receiverUserId = $this->getStateUserId($receiverAmount->getEd25519ReceiverPubkey()); + $senderUserId = $this->getStateUserId($senderAmount->getPubkey()); + $receiverUserId = $this->getStateUserId($receiver); if($senderUserId === NULL || $receiverUserId === NULL) { return false; @@ -192,14 +147,14 @@ class TransactionTransfer extends TransactionBase { if(false === $finalSenderBalance) { return false; } - if(false === $this->updateStateBalance($receiverUserId, $receiverAmount->getAmount(), $received)) { + if(false === $this->updateStateBalance($receiverUserId, $senderAmount->getAmount(), $received)) { return false; } $transactionTransferEntity = $transactionTransferTable->newEntity(); $transactionTransferEntity->transaction_id = $transaction_id; $transactionTransferEntity->state_user_id = $senderUserId; - $transactionTransferEntity->receiver_public_key = $receiverAmount->getEd25519ReceiverPubkey(); + $transactionTransferEntity->receiver_public_key = $receiver; $transactionTransferEntity->receiver_user_id = $receiverUserId; $transactionTransferEntity->amount = $senderAmount->getAmount(); $transactionTransferEntity->sender_final_balance = $finalSenderBalance; @@ -227,10 +182,11 @@ class TransactionTransfer extends TransactionBase { $disable_email = Configure::read('disableEmail', false); if($disable_email) return true; - $senderAmount = $this->protoTransactionTransfer->getSenderAmounts()[0]; - $receiverAmount = $this->protoTransactionTransfer->getReceiverAmounts()[0]; - $senderUserId = $this->getStateUserId($senderAmount->getEd25519SenderPubkey()); - $receiverUserId = $this->getStateUserId($receiverAmount->getEd25519ReceiverPubkey()); + $local_transfer = $this->protoTransactionTransfer->getLocal(); + $sender = $local_transfer->getSender(); + $senderAmount = $sender->getAmount(); + $senderUserId = $this->getStateUserId($sender->getPubkey()); + $receiverUserId = $this->getStateUserId($local_transfer->getReceiver()); $receiverUser = $this->getStateUser($receiverUserId); $senderUser = $this->getStateUser($senderUserId); @@ -242,7 +198,7 @@ class TransactionTransfer extends TransactionBase { $emailViewBuilder->setTemplate('notificationTransfer') ->setVars(['receiverUser' => $receiverUser, 'senderUser' => $senderUser, - 'gdd_cent' => $receiverAmount->getAmount(), + 'gdd_cent' => $senderAmount, 'memo' => $memo]); $receiverNames = $receiverUser->getNames(); if($receiverNames == '' || $receiverUser->email == '') { @@ -263,7 +219,7 @@ class TransactionTransfer extends TransactionBase { static public function fromEntity($transactionTransferEntity) { - $protoTransfer = new \Model\Messages\Gradido\Transfer(); + $protoTransfer = new \Proto\Gradido\GradidoTransfer(); $stateUsersTable = TableRegistry::getTableLocator()->get('state_users'); diff --git a/community_server/src/Template/AddressTypes/add.ctp b/community_server/src/Template/AddressTypes/add.ctp index 7422b666a..f62c5115e 100644 --- a/community_server/src/Template/AddressTypes/add.ctp +++ b/community_server/src/Template/AddressTypes/add.ctp @@ -4,8 +4,8 @@ * @var \App\Model\Entity\AddressType $addressType */ ?> -