Merge branch 'master' into label_generator

This commit is contained in:
Jan Böhmer 2020-04-10 13:06:14 +02:00
commit b23dec0262
68 changed files with 1583 additions and 9521 deletions

View file

@ -51,7 +51,7 @@ Part-DB is also used by small companies and universities for managing their inve
## Requirements
* A **web server** (like Apache2 or nginx) that is capable of running [Symfony 4](https://symfony.com/doc/current/reference/requirements.html),
this includes a minimum PHP version of **PHP 7.2.5**
* A **MySQL**/**MariaDB** database server
* A **MySQL** (at least 5.6.5) /**MariaDB** (at least 10.0.1) database server
* Shell access to your server is highly suggested!
* For building the client side assets **yarn** and **nodejs** is needed.

8
codecov.yml Normal file
View file

@ -0,0 +1,8 @@
comment:
require_changes: true # Only post a comment if coverage changes.
coverage:
status:
project:
default:
threshold: 5%

View file

@ -22,7 +22,7 @@
"ocramius/proxy-manager": "2.2.*",
"omines/datatables-bundle": "^0.4.0",
"php-translation/symfony-bundle": "^0.12.0",
"r/u2f-two-factor-bundle": "dev-u2f-api",
"r/u2f-two-factor-bundle": "^0.7.0",
"s9e/text-formatter": "^2.1",
"scheb/two-factor-bundle": "^4.11",
"sensio/framework-extra-bundle": "^5.1",
@ -60,6 +60,7 @@
"require-dev": {
"dama/doctrine-test-bundle": "^6.0",
"doctrine/doctrine-fixtures-bundle": "^3.2",
"ekino/phpstan-banned-code": "^0.3.1",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.8",
"phpstan/phpstan-doctrine": "^0.12.9",
@ -70,7 +71,7 @@
"symfony/maker-bundle": "^1.13",
"symfony/profiler-pack": "*",
"symfony/test-pack": "^1.0",
"symplify/easy-coding-standard": "7.2.3",
"symplify/easy-coding-standard": "^7.2.3",
"vimeo/psalm": "^3.5"
},
"config": {
@ -115,11 +116,5 @@
"allow-contrib": false,
"require": "4.4.*"
}
},
"repositories": [
{
"type": "vcs",
"url": "git@github.com:stephanvierkant/u2f-two-factor-bundle.git"
}
]
}
}

273
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "482b6aa7bcf3371c734025dc6f151ac1",
"content-hash": "aef1b0fadcee2305438721839abb1400",
"packages": [
{
"name": "beberlei/assert",
@ -2426,16 +2426,16 @@
},
{
"name": "omines/datatables-bundle",
"version": "0.4.1",
"version": "0.4.2",
"source": {
"type": "git",
"url": "https://github.com/omines/datatables-bundle.git",
"reference": "4a1cd573551606b856b1158185fa87aa5a4a25f9"
"reference": "351227d3b3346727b020e44cc30ae880821cfeee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/omines/datatables-bundle/zipball/4a1cd573551606b856b1158185fa87aa5a4a25f9",
"reference": "4a1cd573551606b856b1158185fa87aa5a4a25f9",
"url": "https://api.github.com/repos/omines/datatables-bundle/zipball/351227d3b3346727b020e44cc30ae880821cfeee",
"reference": "351227d3b3346727b020e44cc30ae880821cfeee",
"shasum": ""
},
"require": {
@ -2448,18 +2448,22 @@
"require-dev": {
"doctrine/common": "^2.6",
"doctrine/doctrine-bundle": "^2.0",
"doctrine/orm": "^2.5",
"doctrine/persistence": "^1.3",
"doctrine/orm": "^2.6.3",
"doctrine/persistence": "^1.3.4",
"ext-curl": "*",
"ext-json": "*",
"ext-pdo_sqlite": "*",
"ext-zip": "*",
"friendsofphp/php-cs-fixer": "^2.7",
"mongodb/mongodb": "^1.2",
"phpunit/phpunit": "^7.5",
"ocramius/package-versions": "1.4.*",
"phpunit/phpunit": "^8.5|^9.0",
"ruflin/elastica": "^6.0|^7.0",
"symfony/browser-kit": "^4.1|^5.0",
"symfony/css-selector": "^4.1|^5.0",
"symfony/dom-crawler": "^4.1|^5.0",
"symfony/intl": "^4.1|^5.0",
"symfony/phpunit-bridge": "^4.1|^5.0",
"symfony/templating": "^4.1|^5.0",
"symfony/twig-bundle": "^4.1|^5.0",
"symfony/var-dumper": "^4.1|^5.0",
"symfony/yaml": "^4.1|^5.0"
@ -2510,7 +2514,7 @@
"orm",
"symfony"
],
"time": "2020-02-21T10:12:22+00:00"
"time": "2020-04-02T09:08:23+00:00"
},
{
"name": "paragonie/constant_time_encoding",
@ -3601,16 +3605,16 @@
},
{
"name": "r/u2f-two-factor-bundle",
"version": "dev-u2f-api",
"version": "0.7.0",
"source": {
"type": "git",
"url": "https://github.com/stephanvierkant/u2f-two-factor-bundle.git",
"reference": "81212afd7897911eb6bbf3f8b315ae336cb3e45b"
"url": "https://github.com/darookee/u2f-two-factor-bundle.git",
"reference": "dcf391e694a8f237883b4c39cfe7367c344c1556"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/stephanvierkant/u2f-two-factor-bundle/zipball/81212afd7897911eb6bbf3f8b315ae336cb3e45b",
"reference": "81212afd7897911eb6bbf3f8b315ae336cb3e45b",
"url": "https://api.github.com/repos/darookee/u2f-two-factor-bundle/zipball/dcf391e694a8f237883b4c39cfe7367c344c1556",
"reference": "dcf391e694a8f237883b4c39cfe7367c344c1556",
"shasum": ""
},
"require": {
@ -3636,6 +3640,7 @@
"R\\U2FTwoFactorBundle\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -3652,17 +3657,14 @@
"description": "Use U2F-Keys as 2FA for Symfony2, using scheb/two-factor-bundle",
"homepage": "https://github.com/darookee/u2f-two-factor-bundle",
"keywords": [
"authentication",
"Authentication",
"Symfony2",
"fido",
"symfony2",
"two-factor",
"two-step",
"yubikey"
],
"support": {
"source": "https://github.com/stephanvierkant/u2f-two-factor-bundle/tree/u2f-api"
},
"time": "2019-07-17T10:00:04+00:00"
"time": "2019-06-05T14:42:26+00:00"
},
{
"name": "s9e/regexp-builder",
@ -3841,25 +3843,25 @@
},
{
"name": "sensio/framework-extra-bundle",
"version": "v5.5.3",
"version": "v5.5.4",
"source": {
"type": "git",
"url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git",
"reference": "98f0807137b13d0acfdf3c255a731516e97015de"
"reference": "d0585d4825a87a5030ca8cd34adb4a17e1066c17"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/98f0807137b13d0acfdf3c255a731516e97015de",
"reference": "98f0807137b13d0acfdf3c255a731516e97015de",
"url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/d0585d4825a87a5030ca8cd34adb4a17e1066c17",
"reference": "d0585d4825a87a5030ca8cd34adb4a17e1066c17",
"shasum": ""
},
"require": {
"doctrine/annotations": "^1.0",
"php": ">=7.1.3",
"symfony/config": "^4.3|^5.0",
"symfony/dependency-injection": "^4.3|^5.0",
"symfony/framework-bundle": "^4.3|^5.0",
"symfony/http-kernel": "^4.3|^5.0"
"symfony/config": "^4.4|^5.0",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/framework-bundle": "^4.4|^5.0",
"symfony/http-kernel": "^4.4|^5.0"
},
"conflict": {
"doctrine/doctrine-cache-bundle": "<1.3.1"
@ -3868,24 +3870,19 @@
"doctrine/doctrine-bundle": "^1.11|^2.0",
"doctrine/orm": "^2.5",
"nyholm/psr7": "^1.1",
"symfony/browser-kit": "^4.3|^5.0",
"symfony/dom-crawler": "^4.3|^5.0",
"symfony/expression-language": "^4.3|^5.0",
"symfony/finder": "^4.3|^5.0",
"symfony/browser-kit": "^4.4|^5.0",
"symfony/dom-crawler": "^4.4|^5.0",
"symfony/expression-language": "^4.4|^5.0",
"symfony/finder": "^4.4|^5.0",
"symfony/monolog-bridge": "^4.0|^5.0",
"symfony/monolog-bundle": "^3.2",
"symfony/phpunit-bridge": "^4.3.5|^5.0",
"symfony/psr-http-message-bridge": "^1.1",
"symfony/security-bundle": "^4.3|^5.0",
"symfony/twig-bundle": "^4.3|^5.0",
"symfony/yaml": "^4.3|^5.0",
"symfony/security-bundle": "^4.4|^5.0",
"symfony/twig-bundle": "^4.4|^5.0",
"symfony/yaml": "^4.4|^5.0",
"twig/twig": "^1.34|^2.4|^3.0"
},
"suggest": {
"symfony/expression-language": "",
"symfony/psr-http-message-bridge": "To use the PSR-7 converters",
"symfony/security-bundle": ""
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
@ -3915,7 +3912,7 @@
"annotations",
"controllers"
],
"time": "2019-12-27T08:57:19+00:00"
"time": "2020-04-06T12:20:39+00:00"
},
{
"name": "sensiolabs/security-checker",
@ -9305,28 +9302,46 @@
"time": "2019-11-13T15:46:58+00:00"
},
{
"name": "easycorp/easy-log-handler",
"version": "v1.0.9",
"name": "ekino/phpstan-banned-code",
"version": "v0.3.1",
"source": {
"type": "git",
"url": "https://github.com/EasyCorp/easy-log-handler.git",
"reference": "224e1dfcf9455aceee89cd0af306ac097167fac1"
"url": "https://github.com/ekino/phpstan-banned-code.git",
"reference": "a266c3d28f355643067fe0da07097b17621fc558"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/EasyCorp/easy-log-handler/zipball/224e1dfcf9455aceee89cd0af306ac097167fac1",
"reference": "224e1dfcf9455aceee89cd0af306ac097167fac1",
"url": "https://api.github.com/repos/ekino/phpstan-banned-code/zipball/a266c3d28f355643067fe0da07097b17621fc558",
"reference": "a266c3d28f355643067fe0da07097b17621fc558",
"shasum": ""
},
"require": {
"monolog/monolog": "~1.6|~2.0",
"php": ">=7.1",
"symfony/yaml": "^3.4|^4.0|^5.0"
"php": "^7.1",
"phpstan/phpstan": "^0.12"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.12",
"localheinz/composer-normalize": "^1.3",
"nikic/php-parser": "^4.3",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^7.2",
"sensiolabs/security-checker": "^5.0",
"symfony/var-dumper": "^4.3"
},
"type": "phpstan-extension",
"extra": {
"branch-alias": {
"dev-master": "0.10-dev"
},
"phpstan": {
"includes": [
"extension.neon"
]
}
},
"type": "library",
"autoload": {
"psr-4": {
"EasyCorp\\EasyLog\\": "src"
"Ekino\\PHPStanBannedCode\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@ -9335,24 +9350,18 @@
],
"authors": [
{
"name": "Javier Eguiluz",
"email": "javiereguiluz@gmail.com"
},
{
"name": "Project Contributors",
"homepage": "https://github.com/EasyCorp/easy-log-handler"
"name": "Rémi Marseille",
"email": "remi.marseille@ekino.com",
"homepage": "https://www.ekino.com"
}
],
"description": "A handler for Monolog that optimizes log messages to be processed by humans instead of software. Improve your productivity with logs that are easy to understand.",
"homepage": "https://github.com/EasyCorp/easy-log-handler",
"description": "Detected banned code using PHPStan",
"homepage": "https://github.com/ekino/phpstan-banned-code",
"keywords": [
"easy",
"log",
"logging",
"monolog",
"productivity"
"PHPStan",
"code quality"
],
"time": "2019-10-24T07:13:31+00:00"
"time": "2020-01-17T13:08:23+00:00"
},
{
"name": "felixfbecker/advanced-json-rpc",
@ -10408,16 +10417,16 @@
},
{
"name": "phpstan/phpstan-symfony",
"version": "0.12.4",
"version": "0.12.5",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-symfony.git",
"reference": "5e4b7ba02f2235271a069deeb88340a210d6c87c"
"reference": "063c8289357d42cceba956589bfb8b57b5ac4d40"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/5e4b7ba02f2235271a069deeb88340a210d6c87c",
"reference": "5e4b7ba02f2235271a069deeb88340a210d6c87c",
"url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/063c8289357d42cceba956589bfb8b57b5ac4d40",
"reference": "063c8289357d42cceba956589bfb8b57b5ac4d40",
"shasum": ""
},
"require": {
@ -10474,7 +10483,7 @@
}
],
"description": "Symfony Framework extensions and rules for PHPStan",
"time": "2020-01-22T10:19:41+00:00"
"time": "2020-04-09T07:41:44+00:00"
},
{
"name": "psalm/plugin-symfony",
@ -11069,20 +11078,19 @@
},
{
"name": "symfony/debug-pack",
"version": "v1.0.7",
"version": "v1.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug-pack.git",
"reference": "09a4a1e9bf2465987d4f79db0ad6c11cc632bc79"
"reference": "7310a66f9f81c9f292ff9089f0b0062386cb83fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug-pack/zipball/09a4a1e9bf2465987d4f79db0ad6c11cc632bc79",
"reference": "09a4a1e9bf2465987d4f79db0ad6c11cc632bc79",
"url": "https://api.github.com/repos/symfony/debug-pack/zipball/7310a66f9f81c9f292ff9089f0b0062386cb83fb",
"reference": "7310a66f9f81c9f292ff9089f0b0062386cb83fb",
"shasum": ""
},
"require": {
"easycorp/easy-log-handler": "^1.0.7",
"php": "^7.0",
"symfony/debug-bundle": "*",
"symfony/monolog-bundle": "^3.0",
@ -11095,7 +11103,7 @@
"MIT"
],
"description": "A debug pack for Symfony projects",
"time": "2018-12-10T12:11:11+00:00"
"time": "2020-04-07T10:08:51+00:00"
},
{
"name": "symfony/dom-crawler",
@ -11160,16 +11168,16 @@
},
{
"name": "symfony/maker-bundle",
"version": "v1.14.6",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/maker-bundle.git",
"reference": "bc4df88792fbaaeb275167101dc714218475db5f"
"reference": "31396f2e61803f0e2debbb43ba5aa21acbc6e15a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/maker-bundle/zipball/bc4df88792fbaaeb275167101dc714218475db5f",
"reference": "bc4df88792fbaaeb275167101dc714218475db5f",
"url": "https://api.github.com/repos/symfony/maker-bundle/zipball/31396f2e61803f0e2debbb43ba5aa21acbc6e15a",
"reference": "31396f2e61803f0e2debbb43ba5aa21acbc6e15a",
"shasum": ""
},
"require": {
@ -11224,7 +11232,7 @@
"scaffold",
"scaffolding"
],
"time": "2020-03-04T13:57:29+00:00"
"time": "2020-04-05T10:50:59+00:00"
},
{
"name": "symfony/phpunit-bridge",
@ -11415,16 +11423,16 @@
},
{
"name": "symplify/auto-bind-parameter",
"version": "v7.2.8",
"version": "v7.2.12",
"source": {
"type": "git",
"url": "https://github.com/symplify/auto-bind-parameter.git",
"reference": "76a02d2ec1252ea58b3ef1d8d974b61529313096"
"reference": "e07e2d6228b8211321098647166c6c48fcd58498"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symplify/auto-bind-parameter/zipball/76a02d2ec1252ea58b3ef1d8d974b61529313096",
"reference": "76a02d2ec1252ea58b3ef1d8d974b61529313096",
"url": "https://api.github.com/repos/symplify/auto-bind-parameter/zipball/e07e2d6228b8211321098647166c6c48fcd58498",
"reference": "e07e2d6228b8211321098647166c6c48fcd58498",
"shasum": ""
},
"require": {
@ -11432,7 +11440,7 @@
"php": "^7.2",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/http-kernel": "^4.4|^5.0",
"symplify/package-builder": "^7.2.8"
"symplify/package-builder": "^7.2.12"
},
"require-dev": {
"phpunit/phpunit": "^8.5|^9.0"
@ -11453,20 +11461,20 @@
"MIT"
],
"description": "Auto bind parameters for your Symfony applications",
"time": "2020-03-18T23:25:54+00:00"
"time": "2020-04-09T23:55:34+00:00"
},
{
"name": "symplify/autowire-array-parameter",
"version": "v7.2.8",
"version": "v7.2.12",
"source": {
"type": "git",
"url": "https://github.com/symplify/autowire-array-parameter.git",
"reference": "6d4fba4b5c9290077891b4c6d21c14657bf829af"
"reference": "8a0b518432dfa8d9d5a6b3848683609683f0696b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symplify/autowire-array-parameter/zipball/6d4fba4b5c9290077891b4c6d21c14657bf829af",
"reference": "6d4fba4b5c9290077891b4c6d21c14657bf829af",
"url": "https://api.github.com/repos/symplify/autowire-array-parameter/zipball/8a0b518432dfa8d9d5a6b3848683609683f0696b",
"reference": "8a0b518432dfa8d9d5a6b3848683609683f0696b",
"shasum": ""
},
"require": {
@ -11474,7 +11482,7 @@
"nette/utils": "^3.0",
"php": "^7.2",
"symfony/dependency-injection": "^4.4|^5.0",
"symplify/package-builder": "^7.2.8"
"symplify/package-builder": "^7.2.12"
},
"require-dev": {
"phpunit/phpunit": "^8.5|^9.0"
@ -11495,20 +11503,20 @@
"MIT"
],
"description": "Autowire array parameters for your Symfony applications",
"time": "2020-03-18T23:25:54+00:00"
"time": "2020-04-09T23:55:34+00:00"
},
{
"name": "symplify/coding-standard",
"version": "v7.2.8",
"version": "v7.2.12",
"source": {
"type": "git",
"url": "https://github.com/symplify/coding-standard.git",
"reference": "b1ddc8c909b3f1199c6e6c0c48b66d219fbc3364"
"reference": "900e96cf4dc7315c038f6f8d565c9bc83d9fd649"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symplify/coding-standard/zipball/b1ddc8c909b3f1199c6e6c0c48b66d219fbc3364",
"reference": "b1ddc8c909b3f1199c6e6c0c48b66d219fbc3364",
"url": "https://api.github.com/repos/symplify/coding-standard/zipball/900e96cf4dc7315c038f6f8d565c9bc83d9fd649",
"reference": "900e96cf4dc7315c038f6f8d565c9bc83d9fd649",
"shasum": ""
},
"require": {
@ -11518,15 +11526,15 @@
"php": "^7.2",
"phpstan/phpdoc-parser": "^0.4",
"squizlabs/php_codesniffer": "^3.5",
"symplify/autowire-array-parameter": "^7.2.8",
"symplify/package-builder": "^7.2.8",
"symplify/smart-file-system": "^7.2.8"
"symplify/autowire-array-parameter": "^7.2.12",
"symplify/package-builder": "^7.2.12",
"symplify/smart-file-system": "^7.2.12"
},
"require-dev": {
"nette/application": "^3.0",
"phpunit/phpunit": "^8.5|^9.0",
"symplify/easy-coding-standard-tester": "^7.2.8",
"symplify/package-builder": "^7.2.8"
"symplify/easy-coding-standard-tester": "^7.2.12",
"symplify/package-builder": "^7.2.12"
},
"type": "library",
"extra": {
@ -11545,20 +11553,20 @@
"MIT"
],
"description": "Set of Symplify rules for PHP_CodeSniffer and PHP CS Fixer.",
"time": "2020-03-18T23:25:54+00:00"
"time": "2020-04-09T23:55:34+00:00"
},
{
"name": "symplify/easy-coding-standard",
"version": "v7.2.3",
"version": "v7.2.12",
"source": {
"type": "git",
"url": "https://github.com/symplify/easy-coding-standard.git",
"reference": "9dfbfc09994310ca43cec24ca86044aae7a5fe47"
"reference": "8b62588f3f7c6c2605d3d7693297ebed9b4956e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/9dfbfc09994310ca43cec24ca86044aae7a5fe47",
"reference": "9dfbfc09994310ca43cec24ca86044aae7a5fe47",
"url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/8b62588f3f7c6c2605d3d7693297ebed9b4956e5",
"reference": "8b62588f3f7c6c2605d3d7693297ebed9b4956e5",
"shasum": ""
},
"require": {
@ -11579,19 +11587,19 @@
"symfony/finder": "^4.4|^5.0",
"symfony/http-kernel": "^4.4|^5.0",
"symfony/yaml": "^4.4|^5.0",
"symplify/auto-bind-parameter": "^7.2.3",
"symplify/autowire-array-parameter": "^7.2.3",
"symplify/coding-standard": "^7.2.3",
"symplify/package-builder": "^7.2.3",
"symplify/set-config-resolver": "^7.2.3",
"symplify/smart-file-system": "^7.2.3"
"symplify/auto-bind-parameter": "^7.2.12",
"symplify/autowire-array-parameter": "^7.2.12",
"symplify/coding-standard": "^7.2.12",
"symplify/package-builder": "^7.2.12",
"symplify/set-config-resolver": "^7.2.12",
"symplify/smart-file-system": "^7.2.12"
},
"replace": {
"symfony/polyfill-php70": "*"
},
"require-dev": {
"phpunit/phpunit": "^8.5|^9.0",
"symplify/easy-coding-standard-tester": "^7.2.3"
"symplify/easy-coding-standard-tester": "^7.2.12"
},
"bin": [
"bin/ecs"
@ -11616,20 +11624,20 @@
"MIT"
],
"description": "Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer.",
"time": "2020-02-27T16:45:59+00:00"
"time": "2020-04-09T23:55:34+00:00"
},
{
"name": "symplify/package-builder",
"version": "v7.2.8",
"version": "v7.2.12",
"source": {
"type": "git",
"url": "https://github.com/symplify/package-builder.git",
"reference": "91e019cad6441b8a5e7b300e153cb1c3d3ec7e29"
"reference": "95f3ac3cccc6e247d71c5830879c25c8207b0297"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symplify/package-builder/zipball/91e019cad6441b8a5e7b300e153cb1c3d3ec7e29",
"reference": "91e019cad6441b8a5e7b300e153cb1c3d3ec7e29",
"url": "https://api.github.com/repos/symplify/package-builder/zipball/95f3ac3cccc6e247d71c5830879c25c8207b0297",
"reference": "95f3ac3cccc6e247d71c5830879c25c8207b0297",
"shasum": ""
},
"require": {
@ -11662,20 +11670,20 @@
"MIT"
],
"description": "Dependency Injection, Console and Kernel toolkit for Symplify packages.",
"time": "2020-03-18T23:14:48+00:00"
"time": "2020-04-07T13:55:45+00:00"
},
{
"name": "symplify/set-config-resolver",
"version": "v7.2.8",
"version": "v7.2.12",
"source": {
"type": "git",
"url": "https://github.com/symplify/set-config-resolver.git",
"reference": "992f7b2f11107835e122a5fa460716803a84cbb1"
"reference": "275e882c5cb175bbb9520c652b9d25a23a678d30"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symplify/set-config-resolver/zipball/992f7b2f11107835e122a5fa460716803a84cbb1",
"reference": "992f7b2f11107835e122a5fa460716803a84cbb1",
"url": "https://api.github.com/repos/symplify/set-config-resolver/zipball/275e882c5cb175bbb9520c652b9d25a23a678d30",
"reference": "275e882c5cb175bbb9520c652b9d25a23a678d30",
"shasum": ""
},
"require": {
@ -11684,7 +11692,7 @@
"symfony/console": "^4.4|^5.0",
"symfony/filesystem": "^4.4|^5.0",
"symfony/finder": "^4.4|^5.0",
"symplify/smart-file-system": "^7.2.8"
"symplify/smart-file-system": "^7.2.12"
},
"require-dev": {
"phpunit/phpunit": "^8.5|^9.0"
@ -11705,20 +11713,20 @@
"MIT"
],
"description": "Resolve config and sets from configs and cli opptions for CLI applications",
"time": "2020-03-18T23:25:54+00:00"
"time": "2020-04-09T23:55:34+00:00"
},
{
"name": "symplify/smart-file-system",
"version": "v7.2.8",
"version": "v7.2.12",
"source": {
"type": "git",
"url": "https://github.com/symplify/smart-file-system.git",
"reference": "0ece1df8c6904124750eae94c7b33c781ed3d72d"
"reference": "c7496682de3aeb006ef360431ba5d04ed262f802"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symplify/smart-file-system/zipball/0ece1df8c6904124750eae94c7b33c781ed3d72d",
"reference": "0ece1df8c6904124750eae94c7b33c781ed3d72d",
"url": "https://api.github.com/repos/symplify/smart-file-system/zipball/c7496682de3aeb006ef360431ba5d04ed262f802",
"reference": "c7496682de3aeb006ef360431ba5d04ed262f802",
"shasum": ""
},
"require": {
@ -11943,7 +11951,6 @@
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"r/u2f-two-factor-bundle": 20,
"roave/security-advisories": 20
},
"prefer-stable": false,

View file

@ -40,7 +40,7 @@ security:
logout:
path: logout
target: homepage
handlers: [App\EventSubscriber\LogoutListener]
handlers: [App\EventSubscriber\LogSystem\LogoutLoggerHandler]
remember_me:
secret: '%kernel.secret%'

View file

@ -48,7 +48,7 @@ services:
resource: '../src/Controller'
tags: ['controller.service_arguments']
App\EventSubscriber\MailFromListener:
App\EventSubscriber\SetMailFromSubscriber:
tags: ['kernel.event_subscriber']
arguments:
$email: '%sender_email%'
@ -75,7 +75,7 @@ services:
tags:
- { name: "doctrine.orm.entity_listener" }
App\EventSubscriber\EventLoggerSubscriber:
App\EventSubscriber\LogSystem\EventLoggerSubscriber:
arguments:
$save_changed_fields: '%env(bool:HISTORY_SAVE_CHANGED_FIELDS)%'
$save_changed_data: '%env(bool:HISTORY_SAVE_CHANGED_DATA)%'
@ -83,7 +83,7 @@ services:
tags:
- { name: 'doctrine.event_subscriber' }
App\EventSubscriber\MigrationListener:
App\EventSubscriber\LogSystem\LogDBMigrationSubscriber:
tags:
- { name: 'doctrine.event_subscriber' }
@ -138,7 +138,7 @@ services:
arguments:
$demo_mode: '%demo_mode%'
App\EventSubscriber\TimezoneListener:
App\EventSubscriber\UserSystem\SetUserTimezoneSubscriber:
arguments:
$timezone: '%timezone%'

View file

@ -51,7 +51,6 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

View file

@ -222,7 +222,7 @@ abstract class BaseAdminController extends AbstractController
protected function _new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?AbstractNamedDBElement $entity = null)
{
$master_picture_backup = null;
if ($entity === null) {
if (null === $entity) {
/** @var AbstractStructuralDBElement|User $new_entity */
$new_entity = new $this->entity_class();
} else {
@ -269,7 +269,6 @@ abstract class BaseAdminController extends AbstractController
$this->commentHelper->setMessage($form['log_comment']->getData());
dump($new_entity);
$em->persist($new_entity);
$em->flush();
$this->addFlash('success', 'entity.created_flash');

View file

@ -45,6 +45,7 @@ namespace App\Controller;
use App\DataTables\LogDataTable;
use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint;
use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartLot;
use App\Entity\Parts\Storelocation;
@ -52,7 +53,6 @@ use App\Entity\Parts\Supplier;
use App\Entity\PriceInformations\Orderdetail;
use App\Exceptions\AttachmentDownloadException;
use App\Form\Part\PartBaseType;
use App\Services\Attachments\AttachmentManager;
use App\Services\Attachments\AttachmentSubmitHandler;
use App\Services\Attachments\PartPreviewGenerator;
use App\Services\LogSystem\EventCommentHelper;
@ -62,7 +62,6 @@ use App\Services\Parameters\ParameterExtractor;
use App\Services\PricedetailHelper;
use Doctrine\ORM\EntityManagerInterface;
use Omines\DataTablesBundle\DataTableFactory;
use App\Entity\Parts\Manufacturer;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
@ -244,7 +243,7 @@ class PartController extends AbstractController
}
$fid = $request->get('footprint', null);
$footprint = $fid ? $em->find(Footprint::class, $cid) : null;
$footprint = $fid ? $em->find(Footprint::class, $fid) : null;
if (null !== $footprint && null === $new_part->getFootprint()) {
$new_part->setFootprint($footprint);
}
@ -256,7 +255,7 @@ class PartController extends AbstractController
}
$store_id = $request->get('storelocation', null);
$storelocation = $store_id ? $em->find(Storelocation::class, $store_id): null;
$storelocation = $store_id ? $em->find(Storelocation::class, $store_id) : null;
if (null !== $storelocation && $new_part->getPartLots()->isEmpty()) {
$partLot = new PartLot();
$partLot->setStorageLocation($storelocation);
@ -265,14 +264,13 @@ class PartController extends AbstractController
}
$supplier_id = $request->get('supplier', null);
$supplier = $supplier_id ? $em->find(Supplier::class, $supplier_id): null;
$supplier = $supplier_id ? $em->find(Supplier::class, $supplier_id) : null;
if (null !== $supplier && $new_part->getOrderdetails()->isEmpty()) {
$orderdetail = new Orderdetail();
$orderdetail->setSupplier($supplier);
$new_part->addOrderdetail($orderdetail);
}
$form = $this->createForm(PartBaseType::class, $new_part);
$form->handleRequest($request);

View file

@ -46,7 +46,6 @@ use App\Services\Attachments\BuiltinAttachmentsFinder;
use App\Services\TagFinder;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
@ -62,8 +61,6 @@ class TypeaheadController extends AbstractController
/**
* @Route("/builtInResources/search/{query}", name="typeahead_builtInRessources", requirements={"query"= ".+"})
*
* @param string $query
* @param BuiltinAttachmentsFinder $finder
* @return JsonResponse
*/
public function builtInResources(string $query, BuiltinAttachmentsFinder $finder)

View file

@ -56,7 +56,6 @@ use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Omines\DataTablesBundle\DataTableFactory;
use Symfony\Component\Asset\Packages;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
@ -194,7 +193,6 @@ class UserController extends AdminPages\BaseAdminController
return $table->getResponse();
}
if ($this->getParameter('use_gravatar')) {
$avatar = $this->getGravatar($user->getEmail(), 200, 'identicon');
} else {

View file

@ -52,8 +52,8 @@ use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\Storelocation;
use App\Entity\Parts\Supplier;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;
use InvalidArgumentException;
class DataStructureFixtures extends Fixture

View file

@ -73,7 +73,7 @@ class PartFixtures extends Fixture
/** Part with orderdetails, storelocations and Attachments */
$part = new Part();
$part->setFavorite(true);
$part->setName('Part 2');
$part->setName('Part 3');
$part->setCategory($manager->find(Category::class, 1));
$partLot1 = new PartLot();
$partLot1->setAmount(1.0);

View file

@ -44,8 +44,8 @@ namespace App\DataFixtures;
use App\Entity\UserSystem\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserFixtures extends Fixture

View file

@ -46,6 +46,7 @@ use App\Entity\Attachments\Attachment;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Contracts\NamedElementInterface;
use App\Entity\LogSystem\AbstractLogEntry;
use App\Entity\LogSystem\UserNotAllowedLogEntry;
use App\Entity\Parameters\AbstractParameter;
use App\Entity\Parts\PartLot;
use App\Entity\PriceInformations\Orderdetail;
@ -86,12 +87,17 @@ class LogEntryTargetColumn extends AbstractColumn
{
parent::configureOptions($resolver);
$resolver->setDefault('show_associated', true);
$resolver->setDefault('showAccessDeniedPath', true);
return $this;
}
public function render($value, $context)
{
if ($context instanceof UserNotAllowedLogEntry && $this->options['showAccessDeniedPath']) {
return htmlspecialchars($context->getPath());
}
/** @var AbstractLogEntry $context */
$target = $this->entryRepository->getTargetElement($context);

View file

@ -103,9 +103,10 @@ class LogDataTable implements DataTableTypeInterface
$optionsResolver->setAllowedTypes('mode', 'string');
$optionsResolver->setNormalizer('filter_elements', function (Options $options, $value) {
if (!is_array($value)) {
if (! is_array($value)) {
return [$value];
}
return $value;
});

View file

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
@ -20,7 +23,6 @@
namespace App\Entity\LogSystem;
use App\Entity\Base\AbstractDBElement;
use App\Entity\UserSystem\User;
use App\Events\SecurityEvents;
@ -57,24 +59,26 @@ class SecurityEventLogEntry extends AbstractLogEntry
public function setTargetElement(?AbstractDBElement $element): AbstractLogEntry
{
if (!$element instanceof User) {
if (! $element instanceof User) {
throw new \InvalidArgumentException('Target element must be a User object!');
}
return parent::setTargetElement($element);
}
/**
* Sets the type of this log entry.
* @param string $type
*
* @return $this
*/
public function setEventType(string $type): self
{
$key = array_search($type, static::SECURITY_TYPE_MAPPING);
if ($key === false) {
$key = array_search($type, static::SECURITY_TYPE_MAPPING, true);
if (false === $key) {
throw new \InvalidArgumentException('Given event type is not existing!');
}
$this->extra['e'] = $key;
return $this;
}
@ -84,7 +88,8 @@ class SecurityEventLogEntry extends AbstractLogEntry
}
/**
* Return what event this log entry represents (e.g. password_reset)
* Return what event this log entry represents (e.g. password_reset).
*
* @return string
*/
public function getEventType(): string
@ -121,6 +126,7 @@ class SecurityEventLogEntry extends AbstractLogEntry
$ip = IpUtils::anonymize($ip);
}
$this->extra['i'] = $ip;
return $this;
}
}
}

View file

@ -42,7 +42,6 @@ declare(strict_types=1);
namespace App\Entity\LogSystem;
use App\Exceptions\LogEntryObsoleteException;
use Doctrine\ORM\Mapping as ORM;
/**
@ -52,11 +51,22 @@ class UserNotAllowedLogEntry extends AbstractLogEntry
{
protected $typeString = 'user_not_allowed';
public function __construct()
public function __construct(string $path)
{
parent::__construct();
//Obsolete, use server log now.
throw new LogEntryObsoleteException();
$this->level = static::LEVEL_WARNING;
$this->extra['a'] = $path;
}
/**
* Returns the path the user tried to accessed and what was denied.
*
* @return string
*/
public function getPath(): string
{
return $this->extra['a'] ?? 'legacy';
}
public function getMessage(): string

View file

@ -306,13 +306,13 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
/**
* Sets the amount of parts in the part lot.
* If null is passed, amount will be set to unknown.
* @param float|null $new_amount
*
* @return $this
*/
public function setAmount(?float $new_amount): self
{
//Treat null like unknown amount
if ($new_amount === null) {
if (null === $new_amount) {
$this->instock_unknown = true;
$new_amount = 0.0;
}

View file

@ -44,9 +44,9 @@ namespace App\Entity\Parts\PartTraits;
use App\Entity\PriceInformations\Orderdetail;
use App\Security\Annotations\ColumnSecurity;
use Doctrine\ORM\Mapping as ORM;
use function count;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* This trait collects all aspects of a part related to orders and priceinformations.

View file

@ -164,11 +164,10 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
*
* You will get the price for $multiplier parts. If you want the price which is stored
* in the database, you have to pass the "price_related_quantity" count as $multiplier.
*
* @param float|string $multiplier The returned price (float or string) will be multiplied
* with this multiplier.
*
* @return null|string the price as a bcmath string
* @return string|null the price as a bcmath string
*/
public function getPricePerUnit($multiplier = 1.0): ?string
{

View file

@ -59,7 +59,10 @@ class U2FKey implements TwoFactorKeyInterface
use TimestampTrait;
/**
* @ORM\Column(type="string", length=64)
* We have to restrict the length here, as InnoDB only supports key index with max. 767 Bytes.
* Max length of keyhandles should be 128. (According to U2F_MAX_KH_SIZE in FIDO example C code).
*
* @ORM\Column(type="string", length=128)
*
* @var string
**/

View file

@ -506,11 +506,18 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
*/
public function getFullName(bool $including_username = false): string
{
$tmp = $this->getFirstName();
//Dont add a space, if the name has only one part (it would look strange)
if (! empty($this->getFirstName()) && ! empty($this->getLastName())) {
$tmp .= ' ';
}
$tmp .= $this->getLastName();
if ($including_username) {
return sprintf('%s %s (@%s)', $this->getFirstName(), $this->getLastName(), $this->getName());
$tmp .= sprintf(' (@%s)', $this->getName());
}
return sprintf('%s %s', $this->getFirstName(), $this->getLastName());
return $tmp;
}
/**

View file

@ -87,7 +87,7 @@ class AttachmentDeleteListener
$real_path = $this->pathResolver->placeholderToRealPath($old_path);
//If the attachment does not point to a valid file, ignore it!
if ($real_path === null) {
if (null === $real_path) {
return;
}

View file

@ -1,4 +1,22 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2020 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
@ -21,7 +39,7 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\EventSubscriber;
namespace App\EventSubscriber\LogSystem;
use App\Entity\Attachments\Attachment;
use App\Entity\Base\AbstractDBElement;
@ -47,6 +65,9 @@ use Doctrine\Persistence\Event\LifecycleEventArgs;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
* This event subscriber write to event log when entities are changed, removed, created.
*/
class EventLoggerSubscriber implements EventSubscriber
{
/** @var array The given fields will not be saved, because they contain sensitive informations */

View file

@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2020 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\EventSubscriber\LogSystem;
use App\Entity\LogSystem\UserNotAllowedLogEntry;
use App\Services\LogSystem\EventLogger;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
/**
* Write to event log when a user tries to access an forbidden page and recevies an 403 Access Denied message.
*/
class LogAccessDeniedSubscriber implements EventSubscriberInterface
{
private $logger;
public function __construct(EventLogger $logger)
{
$this->logger = $logger;
}
public function onKernelException(ExceptionEvent $event): void
{
$throwable = $event->getThrowable();
if ($throwable instanceof AccessDeniedHttpException) {
$throwable = $throwable->getPrevious();
}
//Ignore everything except AccessDeniedExceptions
if (! $throwable instanceof AccessDeniedException) {
return;
}
$path = $event->getRequest()->getPathInfo();
$log_entry = new UserNotAllowedLogEntry($path);
$this->logger->logAndFlush($log_entry);
}
public static function getSubscribedEvents()
{
return ['kernel.exception' => 'onKernelException'];
}
}

View file

@ -40,7 +40,7 @@ declare(strict_types=1);
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\EventSubscriber;
namespace App\EventSubscriber\LogSystem;
use App\Entity\LogSystem\DatabaseUpdatedLogEntry;
use App\Services\LogSystem\EventLogger;
@ -48,7 +48,10 @@ use Doctrine\Common\EventSubscriber;
use Doctrine\Migrations\Event\MigrationsEventArgs;
use Doctrine\Migrations\Events;
class MigrationListener implements EventSubscriber
/**
* This subscriber logs databaseMigrations to Event log.
*/
class LogDBMigrationSubscriber implements EventSubscriber
{
protected $old_version = null;
protected $new_version = null;

View file

@ -40,7 +40,7 @@ declare(strict_types=1);
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\EventSubscriber;
namespace App\EventSubscriber\LogSystem;
use App\Entity\LogSystem\UserLogoutLogEntry;
use App\Entity\UserSystem\User;
@ -50,7 +50,10 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
class LogoutListener implements LogoutHandlerInterface
/**
* This handler logs to event log, if a user logs out.
*/
class LogoutLoggerHandler implements LogoutHandlerInterface
{
protected $logger;
protected $gpdr_compliance;

View file

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
@ -18,20 +21,20 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\EventSubscriber;
namespace App\EventSubscriber\LogSystem;
use App\Entity\LogSystem\SecurityEventLogEntry;
use App\Events\SecurityEvent;
use App\Events\SecurityEvents;
use App\Services\LogSystem\EventLogger;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* This subscriber writes entries to log if an security related event happens (e.g. the user changes its password).
*/
final class SecurityEventLoggerSubscriber implements EventSubscriberInterface
{
private $requestStack;
private $gpdr_compliant;
private $eventLogger;
@ -43,27 +46,6 @@ final class SecurityEventLoggerSubscriber implements EventSubscriberInterface
$this->eventLogger = $eventLogger;
}
protected function addLog(string $type, SecurityEvent $event): void
{
$anonymize = $this->gpdr_compliant;
$request = $this->requestStack->getCurrentRequest();
if ($request !== null) {
$ip = $request->getClientIp() ?? 'unknown';
} else {
$ip = "Console";
//Dont try to apply IP filter rules to non numeric string
$anonymize = false;
}
$log = new SecurityEventLogEntry($type, $ip, $anonymize);
$log->setTargetElement($event->getTargetUser());
$this->eventLogger->logAndFlush($log);
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
{
return [
@ -123,4 +105,22 @@ final class SecurityEventLoggerSubscriber implements EventSubscriberInterface
{
$this->addLog(SecurityEvents::TRUSTED_DEVICE_RESET, $event);
}
}
private function addLog(string $type, SecurityEvent $event): void
{
$anonymize = $this->gpdr_compliant;
$request = $this->requestStack->getCurrentRequest();
if (null !== $request) {
$ip = $request->getClientIp() ?? 'unknown';
} else {
$ip = 'Console';
//Dont try to apply IP filter rules to non numeric string
$anonymize = false;
}
$log = new SecurityEventLogEntry($type, $ip, $anonymize);
$log->setTargetElement($event->getTargetUser());
$this->eventLogger->logAndFlush($log);
}
}

View file

@ -47,7 +47,10 @@ use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
final class MailFromListener implements EventSubscriberInterface
/**
* This subscriber set the "From" field for all sent email, based on the global configured sender name and email.
*/
final class SetMailFromSubscriber implements EventSubscriberInterface
{
private $email;
private $name;

View file

@ -42,11 +42,12 @@ declare(strict_types=1);
namespace App\EventSubscriber;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
/**
* This subscriber sets an Header in Debug mode that signals the Symfony Profiler to also update on Ajax requests.
*/
final class SymfonyDebugToolbarSubscriber implements EventSubscriberInterface
{
private $kernel_debug;

View file

@ -40,7 +40,7 @@ declare(strict_types=1);
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\EventSubscriber;
namespace App\EventSubscriber\UserSystem;
use App\Entity\LogSystem\UserLoginLogEntry;
use App\Entity\UserSystem\User;
@ -52,9 +52,9 @@ use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* This event listener shows an login successful flash to the user after login.
* This event listener shows an login successful flash to the user after login and write the login to event log.
*/
final class LoginSuccessListener implements EventSubscriberInterface
final class LoginSuccessSubscriber implements EventSubscriberInterface
{
private $translator;
private $flashBag;

View file

@ -40,7 +40,7 @@ declare(strict_types=1);
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\EventSubscriber;
namespace App\EventSubscriber\UserSystem;
use App\Entity\UserSystem\User;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@ -50,7 +50,11 @@ use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;
final class LogoutOnDisabledUserListener implements EventSubscriberInterface
/**
* This subscriber is used to log out a disabled user, as soon as he to do an request.
* It is not possible for him to login again, afterwards.
*/
final class LogoutDisabledUserSubscriber implements EventSubscriberInterface
{
private $security;
private $urlGenerator;

View file

@ -40,7 +40,7 @@ declare(strict_types=1);
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\EventSubscriber;
namespace App\EventSubscriber\UserSystem;
use App\Entity\UserSystem\User;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

View file

@ -40,7 +40,7 @@ declare(strict_types=1);
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\EventSubscriber;
namespace App\EventSubscriber\UserSystem;
use App\Entity\UserSystem\U2FKey;
use App\Entity\UserSystem\User;
@ -55,7 +55,10 @@ use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
final class U2FRegistrationSubscriber implements EventSubscriberInterface
/**
* This subscriber is used to write U2F keys to DB, after user added them via GUI.
*/
final class RegisterU2FSubscriber implements EventSubscriberInterface
{
private $em;

View file

@ -40,7 +40,7 @@ declare(strict_types=1);
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\EventSubscriber;
namespace App\EventSubscriber\UserSystem;
use App\Entity\UserSystem\User;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@ -51,7 +51,7 @@ use Symfony\Component\Security\Core\Security;
/**
* The purpose of this event listener is to set the timezone to the one preferred by the user.
*/
final class TimezoneListener implements EventSubscriberInterface
final class SetUserTimezoneSubscriber implements EventSubscriberInterface
{
private $default_timezone;
private $security;

View file

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
@ -20,14 +23,12 @@
namespace App\Events;
use App\Entity\UserSystem\User;
use Symfony\Contracts\EventDispatcher\Event;
/**
* This event is triggered when something security related to a user happens.
* For example when the password is reset or the an two factor authentication method was disabled.
* @package App\Events
*/
class SecurityEvent extends Event
{
@ -41,10 +42,11 @@ class SecurityEvent extends Event
/**
* Returns the affected user.
*
* @return User
*/
public function getTargetUser()
{
return $this->targetUser;
}
}
}

View file

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
@ -20,7 +23,6 @@
namespace App\Events;
class SecurityEvents
{
public const PASSWORD_CHANGED = 'security.password_changed';
@ -32,4 +34,4 @@ class SecurityEvents
public const GOOGLE_DISABLED = 'security.google_disabled';
public const TRUSTED_DEVICE_RESET = 'security.trusted_device_reset';
public const TFA_ADMIN_RESET = 'security.2fa_admin_reset';
}
}

View file

@ -106,7 +106,7 @@ class AttachmentFormType extends AbstractType
'required' => false,
'label' => 'attachment.edit.secure_file',
'mapped' => false,
'disabled' => !$this->security->isGranted('@parts_attachments.show_private'),
'disabled' => ! $this->security->isGranted('@parts_attachments.show_private'),
'attr' => [
'class' => 'form-control-sm',
],

View file

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
@ -20,7 +23,6 @@
namespace App\Form;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Form\AbstractTypeExtension;
@ -39,7 +41,6 @@ use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
* This prevents issues when the collection that is edited uses a OrderBy annotation and therefore the direction of the
* elements can change during requests.
* Must me enabled by setting reindex_enable to true in Type options.
* @package App\Form
*/
class CollectionTypeExtension extends AbstractTypeExtension
{
@ -55,26 +56,26 @@ class CollectionTypeExtension extends AbstractTypeExtension
return [CollectionType::class];
}
public function configureOptions(OptionsResolver $resolver)
public function configureOptions(OptionsResolver $resolver): void
{
/*$resolver->setDefault('error_mapping', function (Options $options) {
$options->
});*/
$resolver->setDefaults([
'reindex_enable' => false,
'reindex_prefix' => 'db_',
'reindex_path' => 'id',
]);
'reindex_enable' => false,
'reindex_prefix' => 'db_',
'reindex_path' => 'id',
]);
$resolver->setAllowedTypes('reindex_enable', 'bool');
$resolver->setAllowedTypes('reindex_prefix', 'string');
$resolver->setAllowedTypes('reindex_path', 'string');
}
public function buildForm(FormBuilderInterface $builder, array $options)
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options) {
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options): void {
$data = $event->getData();
$config = $event->getForm()->getConfig();
//If enabled do a reindexing of the collection
@ -86,8 +87,8 @@ class CollectionTypeExtension extends AbstractTypeExtension
foreach ($data->toArray() as $key => $item) {
$id = $this->propertyAccess->getValue($item, $options['reindex_path']);
//If element has an ID then use it. otherwise use default key
$index = $id === null ? $key : $options['reindex_prefix'] . $id;
$error_mapping['[' . $key . ']'] = $index;
$index = null === $id ? $key : $options['reindex_prefix'].$id;
$error_mapping['['.$key.']'] = $index;
$reindexed_data->set($index, $item);
}
$event->setData($reindexed_data);
@ -103,9 +104,7 @@ class CollectionTypeExtension extends AbstractTypeExtension
/**
* Set the option of the form.
* This a bit hacky cause we access private properties....
* @param FormBuilder $builder
* @param string $option
* @param mixed $value
*
* @throws \ReflectionException
*/
public function setOption(FormBuilder $builder, string $option, $value): void
@ -119,4 +118,4 @@ class CollectionTypeExtension extends AbstractTypeExtension
$property->setValue($builder, $tmp);
$property->setAccessible(false);
}
}
}

View file

@ -84,7 +84,7 @@ class CurrencyEntityType extends StructuralEntityType
});
}
public function generateChoiceLabels(AbstractStructuralDBElement $choice, $key, $value): string
public function generateChoiceLabels(AbstractStructuralDBElement $choice, $key, $value, $options): string
{
//Similar to StructuralEntityType, but we use the currency symbol instead if available
@ -93,12 +93,12 @@ class CurrencyEntityType extends StructuralEntityType
}
/** @var AbstractStructuralDBElement|null $parent */
$parent = $this->options['subentities_of'];
$parent = $options['subentities_of'];
/*** @var Currency $choice */
$level = $choice->getLevel();
//If our base entity is not the root level, we need to change the level, to get zero position
if (null !== $this->options['subentities_of']) {
if (null !== $options['subentities_of']) {
$level -= $parent->getLevel() - 1;
}
@ -112,7 +112,7 @@ class CurrencyEntityType extends StructuralEntityType
return $tmp;
}
protected function generateChoiceAttr(AbstractStructuralDBElement $choice, $key, $value): array
protected function generateChoiceAttr(AbstractStructuralDBElement $choice, $key, $value, $options): array
{
/** @var Currency $choice */
$tmp = [];
@ -123,7 +123,7 @@ class CurrencyEntityType extends StructuralEntityType
}
//Disable attribute if the choice is marked as not selectable
if ($this->options['disable_not_selectable'] && $choice->isNotSelectable()) {
if ($options['disable_not_selectable'] && $choice->isNotSelectable()) {
$tmp += ['disabled' => 'disabled'];
}

View file

@ -45,9 +45,6 @@ namespace App\Form\Type;
use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Entity\Contracts\HasMasterAttachmentInterface;
use Doctrine\ORM\EntityRepository;
use ReflectionClass;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
@ -62,36 +59,37 @@ class MasterPictureAttachmentType extends AbstractType
$resolver->setAllowedTypes('entity', HasMasterAttachmentInterface::class);
$resolver->setDefaults([
'filter' => 'picture',
'choice_translation_domain' => false,
'attr' => [
'class' => 'selectpicker',
],
'choice_attr' => function (Options $options) {
return function ($choice, $key, $value) use ($options) {
/** @var Attachment $choice */
$tmp = ['data-subtext' => $choice->getFilename() ?? 'URL'];
'filter' => 'picture',
'choice_translation_domain' => false,
'attr' => [
'class' => 'selectpicker',
],
'choice_attr' => function (Options $options) {
return function ($choice, $key, $value) use ($options) {
/** @var Attachment $choice */
$tmp = ['data-subtext' => $choice->getFilename() ?? 'URL'];
if ('picture' === $options['filter'] && ! $choice->isPicture()) {
$tmp += ['disabled' => 'disabled'];
} elseif ('3d_model' === $options['filter'] && ! $choice->is3DModel()) {
$tmp += ['disabled' => 'disabled'];
}
if ('picture' === $options['filter'] && ! $choice->isPicture()) {
$tmp += ['disabled' => 'disabled'];
} elseif ('3d_model' === $options['filter'] && ! $choice->is3DModel()) {
$tmp += ['disabled' => 'disabled'];
}
return $tmp;
};
},
'choice_label' => 'name',
'choice_loader' => function (Options $options) {
return new CallbackChoiceLoader(function () use ($options) {
$entity = $options['entity'];
if (!$entity instanceof AttachmentContainingDBElement) {
throw new \RuntimeException('$entity must have Attachments! (be of type AttachmentContainingDBElement)');
}
return $entity->getAttachments()->toArray();
});
}
]);
return $tmp;
};
},
'choice_label' => 'name',
'choice_loader' => function (Options $options) {
return new CallbackChoiceLoader(function () use ($options) {
$entity = $options['entity'];
if (! $entity instanceof AttachmentContainingDBElement) {
throw new \RuntimeException('$entity must have Attachments! (be of type AttachmentContainingDBElement)');
}
return $entity->getAttachments()->toArray();
});
},
]);
$resolver->setAllowedValues('filter', ['', 'picture', '3d_model']);
}

View file

@ -67,7 +67,7 @@ use Symfony\Component\Validator\Constraints\Choice;
class StructuralEntityType extends AbstractType
{
protected $em;
protected $options;
/**
* @var NodesListBuilder
*/
@ -82,11 +82,11 @@ class StructuralEntityType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addModelTransformer(new CallbackTransformer(
function ($value) use ($options) {
return $this->transform($value, $options);
}, function ($value) use ($options) {
return $this->reverseTransform($value, $options);
}));
function ($value) use ($options) {
return $this->transform($value, $options);
}, function ($value) use ($options) {
return $this->reverseTransform($value, $options);
}));
}
public function configureOptions(OptionsResolver $resolver): void
@ -102,11 +102,15 @@ class StructuralEntityType extends AbstractType
return $this->getEntries($options);
});
},
'choice_label' => function ($choice, $key, $value) {
return $this->generateChoiceLabels($choice, $key, $value);
'choice_label' => function (Options $options) {
return function ($choice, $key, $value) use ($options) {
return $this->generateChoiceLabels($choice, $key, $value, $options);
};
},
'choice_attr' => function ($choice, $key, $value) {
return $this->generateChoiceAttr($choice, $key, $value);
'choice_attr' => function (Options $options) {
return function ($choice, $key, $value) use ($options) {
return $this->generateChoiceAttr($choice, $key, $value, $options);
};
},
'choice_translation_domain' => false, //Don't translate the entity names
]);
@ -133,8 +137,6 @@ class StructuralEntityType extends AbstractType
*/
public function getEntries(Options $options): array
{
$this->options = $options;
return $this->builder->typeToNodesList($options['class'], null);
}
@ -240,16 +242,16 @@ class StructuralEntityType extends AbstractType
return $this->em->find($options['class'], $value->getID());
}
protected function generateChoiceAttr(AbstractStructuralDBElement $choice, $key, $value): array
protected function generateChoiceAttr(AbstractStructuralDBElement $choice, $key, $value, $options): array
{
$tmp = [];
if ($this->options['show_fullpath_in_subtext'] && null !== $choice->getParent()) {
if ($options['show_fullpath_in_subtext'] && null !== $choice->getParent()) {
$tmp += ['data-subtext' => $choice->getParent()->getFullPath()];
}
//Disable attribute if the choice is marked as not selectable
if ($this->options['disable_not_selectable'] && $choice->isNotSelectable()) {
if ($options['disable_not_selectable'] && $choice->isNotSelectable()) {
$tmp += ['disabled' => 'disabled'];
}
@ -260,15 +262,15 @@ class StructuralEntityType extends AbstractType
return $tmp;
}
protected function generateChoiceLabels(AbstractStructuralDBElement $choice, $key, $value): string
protected function generateChoiceLabels(AbstractStructuralDBElement $choice, $key, $value, $options): string
{
/** @var AbstractStructuralDBElement|null $parent */
$parent = $this->options['subentities_of'];
$parent = $options['subentities_of'];
/*** @var AbstractStructuralDBElement $choice */
$level = $choice->getLevel();
//If our base entity is not the root level, we need to change the level, to get zero position
if (null !== $this->options['subentities_of']) {
if (null !== $options['subentities_of']) {
$level -= $parent->getLevel() - 1;
}

View file

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200409130946 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE u2f_keys CHANGE key_handle key_handle VARCHAR(128) NOT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE u2f_keys CHANGE key_handle key_handle VARCHAR(64) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`');
}
}

View file

@ -50,12 +50,12 @@ class PartRepository extends NamedDBElementRepository
/**
* Gets the summed up instock of all parts (only parts without an measurent unit).
*
* @return string
* @return float
*
* @throws \Doctrine\ORM\NoResultException
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function getPartsInstockSum(): string
public function getPartsInstockSum(): float
{
$qb = new QueryBuilder($this->getEntityManager());
$qb->select('SUM(part_lot.amount)')
@ -65,7 +65,7 @@ class PartRepository extends NamedDBElementRepository
$query = $qb->getQuery();
return $query->getSingleScalarResult();
return (float) ($query->getSingleScalarResult() ?? 0.0);
}
/**
@ -86,6 +86,6 @@ class PartRepository extends NamedDBElementRepository
$query = $qb->getQuery();
return (int) $query->getSingleScalarResult();
return (int) ($query->getSingleScalarResult() ?? 0);
}
}

View file

@ -57,6 +57,18 @@ use function is_object;
class StructureVoter extends ExtendedVoter
{
protected const OBJ_PERM_MAP = [
AttachmentType::class => 'attachment_types',
Category::class => 'categories',
Device::class => 'devices',
Footprint::class => 'footprints',
Manufacturer::class => 'manufacturers',
Storelocation::class => 'storelocations',
Supplier::class => 'suppliers',
Currency::class => 'currencies',
MeasurementUnit::class => 'measurement_units',
];
/**
* Determines if the attribute and subject are supported by this voter.
*
@ -90,27 +102,18 @@ class StructureVoter extends ExtendedVoter
} else {
$class_name = $subject;
}
switch ($class_name) {
case AttachmentType::class:
return 'attachment_types';
case Category::class:
return 'categories';
case Device::class:
return 'devices';
case Footprint::class:
return 'footprints';
case Manufacturer::class:
return 'manufacturers';
case Storelocation::class:
return 'storelocations';
case Supplier::class:
return 'suppliers';
case Currency::class:
return 'currencies';
case MeasurementUnit::class:
return 'measurement_units';
//If it is existing in index, we can skip the loop
if (isset(static::OBJ_PERM_MAP[$class_name])) {
return static::OBJ_PERM_MAP[$class_name];
}
//When the class is not supported by this class return null
foreach (static::OBJ_PERM_MAP as $class => $ret) {
if (is_a($class_name, $class, true)) {
return $ret;
}
}
return null;
}

View file

@ -63,8 +63,8 @@ class AmountFormatter
* Formats the given value using the measurement unit and options.
*
* @param float|string|int $value
* @param MeasurementUnit|null $unit The measurement unit, whose unit symbol should be used for formatting.
* If set to null, it is assumed that the part amount is measured in pieces.
* @param MeasurementUnit|null $unit The measurement unit, whose unit symbol should be used for formatting.
* If set to null, it is assumed that the part amount is measured in pieces.
*
* @return string The formatted string
*

View file

@ -130,7 +130,7 @@ class AttachmentURLGenerator
throw new InvalidArgumentException('Thumbnail creation only works for picture attachments!');
}
if ($attachment->isExternal() && !empty($attachment->getURL())) {
if ($attachment->isExternal() && ! empty($attachment->getURL())) {
return $attachment->getURL();
}

View file

@ -43,10 +43,10 @@ declare(strict_types=1);
namespace App\Services\Attachments;
use App\Entity\Attachments\Attachment;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\Finder\Finder;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Cache\CacheInterface;
use Psr\Cache\InvalidArgumentException;
/**
* This service is used to find builtin attachment ressources.

View file

@ -44,7 +44,6 @@ namespace App\Services;
use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentType;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Contracts\NamedElementInterface;
use App\Entity\Devices\Device;
use App\Entity\Parameters\AbstractParameter;

View file

@ -79,7 +79,7 @@ class EntityExporter
/**
* Exports an Entity or an array of entities to multiple file formats.
*
* @param Request $request the request that should be used for option resolving
* @param Request $request the request that should be used for option resolving
* @param AbstractNamedDBElement|object[] $entity
*
* @return Response the generated response containing the exported data

View file

@ -94,7 +94,7 @@ class EntityURLGenerator
* @param mixed $entity The element for which the page should be generated
* @param string $type The page type. Currently supported: 'info', 'edit', 'create', 'clone', 'list'/'list_parts'
*
* @return null|string the link to the desired page
* @return string|null the link to the desired page
*
* @throws EntityNotSupportedException thrown if the entity is not supported for the given type
* @throws InvalidArgumentException thrown if the givent type is not existing

View file

@ -49,7 +49,6 @@ use App\Security\Interfaces\HasPermissionsInterface;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Yaml\Yaml;
class PermissionResolver
@ -70,8 +69,6 @@ class PermissionResolver
$this->is_debug = $kernel_debug;
$this->permission_structure = $this->generatePermissionStructure();
//dump($this->permission_structure);
}
public function getPermissionStructure(): array

View file

@ -174,8 +174,12 @@ class PricedetailHelper
continue;
}
$avg = bcadd($avg, $this->convertMoneyToCurrency($pricedetail->getPricePerUnit(), $pricedetail->getCurrency(), $currency), Pricedetail::PRICE_PRECISION);
++$count;
$converted = $this->convertMoneyToCurrency($pricedetail->getPricePerUnit(), $pricedetail->getCurrency(), $currency);
//Ignore price informations that can not be converted to base currency.
if (null !== $converted) {
$avg = bcadd($avg, $converted, Pricedetail::PRICE_PRECISION);
++$count;
}
}
if (0 === $count) {

View file

@ -61,12 +61,12 @@ class StatisticsHelper
/**
* Returns the summed instocked over all parts (only parts without a measurement unit).
*
* @return string
* @return float
*
* @throws \Doctrine\ORM\NoResultException
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function getPartsInstockSum(): string
public function getPartsInstockSum(): float
{
return $this->part_repo->getPartsInstockSum();
}

View file

@ -120,21 +120,12 @@
"doctrine/reflection": {
"version": "v1.0.0"
},
"easycorp/easy-log-handler": {
"version": "1.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "1.0",
"ref": "70062abc2cd58794d2a90274502f81b55cd9951b"
},
"files": [
"./config/packages/dev/easy_log_handler.yaml"
]
},
"egulias/email-validator": {
"version": "2.1.11"
},
"ekino/phpstan-banned-code": {
"version": "v0.3.1"
},
"felixfbecker/advanced-json-rpc": {
"version": "v3.0.4"
},

View file

@ -45,24 +45,22 @@
<i class="fas fa-microchip fa-fw" title="{% trans %}footprint.label{% endtrans %}"></i>
<span class="text-muted">{{ helper.structural_entity_link(part.footprint) }}</span>
</h6>
<h6>
<i class="fas fa-money-bill-alt fa-fw"></i>
<span class="text-muted">
{% set min_order_amount = pricedetail_helper.minOrderAmount(part) %}
{% set max_order_amount = pricedetail_helper.maxDiscountAmount(part) %}
{% set max_order_price = pricedetail_helper.calculateAvgPrice(part, max_order_amount, app.user.currency ?? null) %}
{% if max_order_price is not null %}
{% set min_order_amount = pricedetail_helper.minOrderAmount(part) %}
{% set max_order_amount = pricedetail_helper.maxDiscountAmount(part) %}
{% set max_order_price = pricedetail_helper.calculateAvgPrice(part, max_order_amount, app.user.currency ?? null) %}
{% if max_order_price is not null %}
<h6>
<i class="fas fa-money-bill-alt fa-fw"></i>
<span class="text-muted">
<span title="{% trans %}part.avg_price.label{% endtrans %} {{ max_order_amount | amountFormat(part.partUnit) }}">{{ max_order_price | moneyFormat(app.user.currency ?? null) }}</span>
{% if min_order_amount < max_order_amount %}
<span> - </span>
<span title="{% trans %}part.avg_price.label{% endtrans %} {{ min_order_amount | amountFormat(part.partUnit) }}">{{pricedetail_helper.calculateAvgPrice(part, min_order_amount, app.user.currency ?? null ) | moneyFormat(app.user.currency ?? null) }}</span>
{% endif %}
{% endif %}
<span> - </span>
<span title="{% trans %}part.avg_price.label{% endtrans %} {{ min_order_amount | amountFormat(part.partUnit) }}">{{pricedetail_helper.calculateAvgPrice(part, min_order_amount, app.user.currency ?? null ) | moneyFormat(app.user.currency ?? null) }}</span>
{% endif %}
</span>
</h6>
</h6>
{% endif %}
{#
{% if part.comment != "" %}
<h6 title="{% trans %}comment.label{% endtrans %}">

View file

@ -1,6 +1,6 @@
<div class="row mb-3">
<div class="col">
<a href="{{ url('part_new', url_options) }}" class="btn btn-success float-left"><i class="fas fa-plus-square fa-fw"></i>
<a href="{{ url('part_new', url_options) }}" class="btn btn-success float-left {% if not is_granted("@parts.create") or (entity is defined and entity.notSelectable) %}disabled{% endif %}"><i class="fas fa-plus-square fa-fw"></i>
{% trans%}part.create.btn{% endtrans %}</a>
</div>
</div>

View file

@ -108,6 +108,14 @@ class ApplicationAvailabilityFunctionalTest extends WebTestCase
yield ['/part/2/edit'];
yield ['/part/3/edit'];
yield ['/part/3/clone'];
yield ['/part/new'];
yield ['/part/new?category=1&footprint=1&manufacturer=1&storelocation=1&supplier=1'];
//Statistics
yield ['/statistics'];
//Typeahead
yield ['/typeahead/builtInResources/search/DIP8'];
yield ['/typeahead/tags/search/test'];

View file

@ -58,6 +58,9 @@ class UserTest extends TestCase
$this->assertSame('John Doe', $user->getFullName(false));
$this->assertSame('John Doe (@username)', $user->getFullName(true));
$user->setLastName('');
$this->assertSame('John (@username)', $user->getFullName(true));
}
public function googleAuthenticatorEnabledDataProvider(): array

View file

@ -45,7 +45,7 @@ namespace App\Tests\EventSubscriber;
use App\Entity\UserSystem\Group;
use App\Entity\UserSystem\U2FKey;
use App\Entity\UserSystem\User;
use App\EventSubscriber\PasswordChangeNeededSubscriber;
use App\EventSubscriber\UserSystem\PasswordChangeNeededSubscriber;
use PHPUnit\Framework\TestCase;
class PasswordChangeNeededSubscriberTest extends TestCase
@ -57,11 +57,11 @@ class PasswordChangeNeededSubscriberTest extends TestCase
//A user without a group must not redirect
$user->setGroup(null);
$this->assertFalse(PasswordChangeNeededSubscriber::TFARedirectNeeded($user));
$this->assertFalse(\App\EventSubscriber\UserSystem\PasswordChangeNeededSubscriber::TFARedirectNeeded($user));
//When the group does not enforce the redirect the user must not be redirected
$user->setGroup($group);
$this->assertFalse(PasswordChangeNeededSubscriber::TFARedirectNeeded($user));
$this->assertFalse(\App\EventSubscriber\UserSystem\PasswordChangeNeededSubscriber::TFARedirectNeeded($user));
//The user must be redirected if the group enforces 2FA and it does not have a method
$group->setEnforce2FA(true);

View file

@ -5974,7 +5974,7 @@ Wenn Sie dies fehlerhafterweise gemacht haben oder ein Computer nicht mehr vertr
</notes>
<segment state="translated">
<source>category.edit.default_comment.placeholder</source>
<target>e.g. Nützlich für Schaltnetzteile</target>
<target>z.B. Nützlich für Schaltnetzteile</target>
</segment>
</unit>
<unit id="n13qerD" name="tfa_backup.regenerate_codes">
@ -8147,5 +8147,113 @@ Element 3</target>
<target>__log.type.</target>
</segment>
</unit>
<unit id="Msykg.Z" name="entity.info.attachments.tab">
<segment state="translated">
<source>entity.info.attachments.tab</source>
<target>Dateianhänge</target>
</segment>
</unit>
<unit id="8VfTCPf" name="entity.info.parameters.tab">
<segment state="translated">
<source>entity.info.parameters.tab</source>
<target>Parameter</target>
</segment>
</unit>
<unit id="gWj51jS" name="attachment.preview">
<segment state="translated">
<source>attachment.preview</source>
<target>Vorschaubild</target>
</segment>
</unit>
<unit id="WjnV7iC" name="tfa_u2f.key_added_successful">
<segment state="translated">
<source>tfa_u2f.key_added_successful</source>
<target>Sicherheitsschlüssel erfolgreich hinzugefügt.</target>
</segment>
</unit>
<unit id="47ienTP" name="Username">
<segment state="translated">
<source>Username</source>
<target>Benutzername</target>
</segment>
</unit>
<unit id="dVu9PKe" name="log.type.security.google_disabled">
<segment state="translated">
<source>log.type.security.google_disabled</source>
<target>Authenticator App deaktiviert</target>
</segment>
</unit>
<unit id="HfccXTr" name="log.type.security.u2f_removed">
<segment state="translated">
<source>log.type.security.u2f_removed</source>
<target>Sicherheitsschlüssel gelöscht</target>
</segment>
</unit>
<unit id="zl1WXuM" name="log.type.security.u2f_added">
<segment state="translated">
<source>log.type.security.u2f_added</source>
<target>Sicherheitsschlüssel hinzugefügt</target>
</segment>
</unit>
<unit id="9_jzHX6" name="log.type.security.backup_keys_reset">
<segment state="translated">
<source>log.type.security.backup_keys_reset</source>
<target>Neue Backupkeys erzeugt</target>
</segment>
</unit>
<unit id="h6zwXNp" name="log.type.security.google_enabled">
<segment state="translated">
<source>log.type.security.google_enabled</source>
<target>Authenticator App aktiviert</target>
</segment>
</unit>
<unit id="XbsoHIr" name="log.type.security.password_changed">
<segment state="translated">
<source>log.type.security.password_changed</source>
<target>Passwort geändert</target>
</segment>
</unit>
<unit id="2q0_b3P" name="log.type.security.trusted_device_reset">
<segment state="translated">
<source>log.type.security.trusted_device_reset</source>
<target>Vertrauenswürdige Geräte zurückgesetzt</target>
</segment>
</unit>
<unit id="n8flY2e" name="log.type.collection_element_deleted">
<segment state="translated">
<source>log.type.collection_element_deleted</source>
<target>Kollektionselement gelöscht</target>
</segment>
</unit>
<unit id="yNm8PCN" name="log.type.security.password_reset">
<segment state="translated">
<source>log.type.security.password_reset</source>
<target>Passwort zurückgesetzt</target>
</segment>
</unit>
<unit id="CsjgnTI" name="log.type.security.2fa_admin_reset">
<segment state="translated">
<source>log.type.security.2fa_admin_reset</source>
<target>Zwei-Faktor-Authentifizierung durch Administrator zurückgesetzt</target>
</segment>
</unit>
<unit id="vlslklu" name="entity.duplicate">
<segment state="translated">
<source>entity.duplicate</source>
<target>Element duplizieren</target>
</segment>
</unit>
<unit id="bJ.EAvM" name="log.type.user_not_allowed">
<segment state="translated">
<source>log.type.user_not_allowed</source>
<target>Unerlaubter Zugriffsversuch</target>
</segment>
</unit>
<unit id="Z28oTau" name="log.database_updated.success">
<segment state="translated">
<source>log.database_updated.success</source>
<target>Erfolgreich</target>
</segment>
</unit>
</file>
</xliff>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -840,107 +840,6 @@ Les sous éléments seront déplacés vers le haut.</target>
<target>Nombre de composants avec cet élément</target>
</segment>
</unit>
<unit id="4FQqOUW" name="specifications.property">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:6</note>
<note category="file-source" priority="1">Part-DB1\templates\helper.twig:120</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:6</note>
</notes>
<segment state="initial">
<source>specifications.property</source>
<target>specifications.property</target>
</segment>
</unit>
<unit id="N4F6wz5" name="specifications.symbol">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:7</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:7</note>
</notes>
<segment state="initial">
<source>specifications.symbol</source>
<target>specifications.symbol</target>
</segment>
</unit>
<unit id="ManEcyM" name="specifications.value_min">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:8</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:8</note>
</notes>
<segment state="initial">
<source>specifications.value_min</source>
<target>specifications.value_min</target>
</segment>
</unit>
<unit id="BzRKVPC" name="specifications.value_typ">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:9</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:9</note>
</notes>
<segment state="initial">
<source>specifications.value_typ</source>
<target>specifications.value_typ</target>
</segment>
</unit>
<unit id="WLVXsOF" name="specifications.value_max">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:10</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:10</note>
</notes>
<segment state="initial">
<source>specifications.value_max</source>
<target>specifications.value_max</target>
</segment>
</unit>
<unit id="mRpl2vJ" name="specifications.unit">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:11</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:11</note>
</notes>
<segment state="initial">
<source>specifications.unit</source>
<target>specifications.unit</target>
</segment>
</unit>
<unit id="05vM0Vp" name="specifications.text">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:12</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:12</note>
</notes>
<segment state="initial">
<source>specifications.text</source>
<target>specifications.text</target>
</segment>
</unit>
<unit id="t9lgp3U" name="specifications.group">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:13</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:13</note>
</notes>
<segment state="initial">
<source>specifications.group</source>
<target>specifications.group</target>
</segment>
</unit>
<unit id="MZTH_sJ" name="specification.create">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:26</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:26</note>
</notes>
<segment state="initial">
<source>specification.create</source>
<target>specification.create</target>
</segment>
</unit>
<unit id="eEuzINH" name="parameter.delete.confirm">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\_parameters.html.twig:31</note>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\_specifications.html.twig:31</note>
</notes>
<segment state="initial">
<source>parameter.delete.confirm</source>
<target>parameter.delete.confirm</target>
</segment>
</unit>
<unit id="rpzRyMx" name="attachment.list.title">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\attachment_list.html.twig:3</note>
@ -1145,15 +1044,6 @@ Show/Hide sidebar</target>
<target>Non</target>
</segment>
</unit>
<unit id="PbJl5cf" name="specifications.value">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\helper.twig:121</note>
</notes>
<segment state="initial">
<source>specifications.value</source>
<target>specifications.value</target>
</segment>
</unit>
<unit id="Qj.Hpb." name="version.caption">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\homepage.html.twig:7</note>
@ -1553,15 +1443,6 @@ Show/Hide sidebar</target>
<target>Informations pour la commande</target>
</segment>
</unit>
<unit id="fLuFk_2" name="part.edit.tab.specifications">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\edit_part_info.html.twig:58</note>
</notes>
<segment state="initial">
<source>part.edit.tab.specifications</source>
<target>part.edit.tab.specifications</target>
</segment>
</unit>
<unit id="LgSgFFj" name="part.edit.tab.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\Parts\edit\edit_part_info.html.twig:64</note>
@ -1672,15 +1553,6 @@ Show/Hide sidebar</target>
<target>Commentaire</target>
</segment>
</unit>
<unit id="Y2.Edoh" name="part.info.specifications">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\Parts\info\show_part_info.html.twig:64</note>
</notes>
<segment state="initial">
<source>part.info.specifications</source>
<target>part.info.specifications</target>
</segment>
</unit>
<unit id="MZz0rtU" name="attachment.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\Parts\info\show_part_info.html.twig:74</note>
@ -2205,24 +2077,6 @@ Show/Hide sidebar</target>
<target>N'est plus disponible</target>
</segment>
</unit>
<unit id="PYWb1Wy" name="parameters.extracted_from_description">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\Parts\info\_specifications.html.twig:10</note>
</notes>
<segment state="initial">
<source>parameters.extracted_from_description</source>
<target>parameters.extracted_from_description</target>
</segment>
</unit>
<unit id="xuDIeTd" name="parameters.auto_extracted_from_comment">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\Parts\info\_specifications.html.twig:15</note>
</notes>
<segment state="initial">
<source>parameters.auto_extracted_from_comment</source>
<target>parameters.auto_extracted_from_comment</target>
</segment>
</unit>
<unit id="cTsojYo" name="part.edit.btn">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\Parts\info\_tools.html.twig:4</note>
@ -3628,15 +3482,6 @@ Si vous avez fait cela de manière incorrecte ou si un ordinateur n'est plus fia
<target>Nom</target>
</segment>
</unit>
<unit id="V2u6xXi" name="tags.label">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\_navbar_search.html.twig:23</note>
</notes>
<segment state="initial">
<source>tags.label</source>
<target>tags.label</target>
</segment>
</unit>
<unit id="RezjOdV" name="storelocation.label">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\_navbar_search.html.twig:27</note>
@ -4854,78 +4699,6 @@ Si vous avez fait cela de manière incorrecte ou si un ordinateur n'est plus fia
<target>Télécharger le fichier</target>
</segment>
</unit>
<unit id="o.P_V00" name="parameters.name.placeholder">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\ParameterType.php:41</note>
</notes>
<segment state="initial">
<source>parameters.name.placeholder</source>
<target>parameters.name.placeholder</target>
</segment>
</unit>
<unit id="3LWIDYM" name="parameters.symbol.placeholder">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\ParameterType.php:50</note>
</notes>
<segment state="initial">
<source>parameters.symbol.placeholder</source>
<target>parameters.symbol.placeholder</target>
</segment>
</unit>
<unit id="w7bfLKj" name="parameters.text.placeholder">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\ParameterType.php:60</note>
</notes>
<segment state="initial">
<source>parameters.text.placeholder</source>
<target>parameters.text.placeholder</target>
</segment>
</unit>
<unit id="6utToZ6" name="parameters.max.placeholder">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\ParameterType.php:71</note>
</notes>
<segment state="initial">
<source>parameters.max.placeholder</source>
<target>parameters.max.placeholder</target>
</segment>
</unit>
<unit id="BypUOrf" name="parameters.min.placeholder">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\ParameterType.php:82</note>
</notes>
<segment state="initial">
<source>parameters.min.placeholder</source>
<target>parameters.min.placeholder</target>
</segment>
</unit>
<unit id="VmYIvYF" name="parameters.typical.placeholder">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\ParameterType.php:93</note>
</notes>
<segment state="initial">
<source>parameters.typical.placeholder</source>
<target>parameters.typical.placeholder</target>
</segment>
</unit>
<unit id="kvhGoo0" name="parameters.unit.placeholder">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\ParameterType.php:103</note>
</notes>
<segment state="initial">
<source>parameters.unit.placeholder</source>
<target>parameters.unit.placeholder</target>
</segment>
</unit>
<unit id="kL5OSi8" name="parameter.group.placeholder">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\ParameterType.php:114</note>
</notes>
<segment state="initial">
<source>parameter.group.placeholder</source>
<target>parameter.group.placeholder</target>
</segment>
</unit>
<unit id="jv6wCpP" name="orderdetails.edit.supplierpartnr">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\OrderdetailType.php:75</note>
@ -5475,15 +5248,6 @@ Si vous avez fait cela de manière incorrecte ou si un ordinateur n'est plus fia
<target>Utilisateur</target>
</segment>
</unit>
<unit id="CxpVbHB" name="parameter.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:95</note>
</notes>
<segment state="initial">
<source>parameter.label</source>
<target>parameter.label</target>
</segment>
</unit>
<unit id=".nBJJBz" name="log.element_deleted.old_name.unknown">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:175</note>

View file

@ -8151,5 +8151,23 @@
<target>Тип.</target>
</segment>
</unit>
<unit id="Msykg.Z" name="entity.info.attachments.tab">
<segment state="translated">
<source>entity.info.attachments.tab</source>
<target>Вложения</target>
</segment>
</unit>
<unit id="8VfTCPf" name="entity.info.parameters.tab">
<segment state="translated">
<source>entity.info.parameters.tab</source>
<target>Параметры</target>
</segment>
</unit>
<unit id="gWj51jS" name="attachment.preview">
<segment state="translated">
<source>attachment.preview</source>
<target>Предпросмотр</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -167,5 +167,17 @@
<target>The username must contain only letters, numbers, underscores, dots, pluses or minuses.</target>
</segment>
</unit>
<unit id="lZvhKYu" name="validator.noneofitschild.self">
<segment>
<source>validator.noneofitschild.self</source>
<target>An element can not be its own parent.</target>
</segment>
</unit>
<unit id="pr07aV4" name="validator.noneofitschild.children">
<segment>
<source>validator.noneofitschild.children</source>
<target>You can not assign children element as parent (This would cause loops).</target>
</segment>
</unit>
</file>
</xliff>

155
yarn.lock
View file

@ -40,12 +40,12 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@^7.9.0":
version "7.9.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.4.tgz#12441e90c3b3c4159cdecf312075bf1a8ce2dbce"
integrity sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==
"@babel/generator@^7.9.0", "@babel/generator@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9"
integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==
dependencies:
"@babel/types" "^7.9.0"
"@babel/types" "^7.9.5"
jsesc "^2.5.1"
lodash "^4.17.13"
source-map "^0.5.0"
@ -102,14 +102,14 @@
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
"@babel/helper-function-name@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca"
integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==
"@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c"
integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==
dependencies:
"@babel/helper-get-function-arity" "^7.8.3"
"@babel/template" "^7.8.3"
"@babel/types" "^7.8.3"
"@babel/types" "^7.9.5"
"@babel/helper-get-function-arity@^7.8.3":
version "7.8.3"
@ -207,10 +207,10 @@
dependencies:
"@babel/types" "^7.8.3"
"@babel/helper-validator-identifier@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed"
integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==
"@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==
"@babel/helper-wrap-function@^7.8.3":
version "7.8.3"
@ -286,13 +286,14 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-numeric-separator" "^7.8.3"
"@babel/plugin-proposal-object-rest-spread@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.0.tgz#a28993699fc13df165995362693962ba6b061d6f"
integrity sha512-UgqBv6bjq4fDb8uku9f+wcm1J7YxJ5nT7WO/jBr0cl0PLKb7t1O6RNR1kZbjgx2LQtsDI9hwoQVmn0yhXeQyow==
"@babel/plugin-proposal-object-rest-spread@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116"
integrity sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-object-rest-spread" "^7.8.0"
"@babel/plugin-transform-parameters" "^7.9.5"
"@babel/plugin-proposal-optional-catch-binding@^7.8.3":
version "7.8.3"
@ -412,14 +413,14 @@
"@babel/helper-plugin-utils" "^7.8.3"
lodash "^4.17.13"
"@babel/plugin-transform-classes@^7.9.0":
version "7.9.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.2.tgz#8603fc3cc449e31fdbdbc257f67717536a11af8d"
integrity sha512-TC2p3bPzsfvSsqBZo0kJnuelnoK9O3welkUpqSqBQuBF6R5MN2rysopri8kNvtlGIb2jmUO7i15IooAZJjZuMQ==
"@babel/plugin-transform-classes@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c"
integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg==
dependencies:
"@babel/helper-annotate-as-pure" "^7.8.3"
"@babel/helper-define-map" "^7.8.3"
"@babel/helper-function-name" "^7.8.3"
"@babel/helper-function-name" "^7.9.5"
"@babel/helper-optimise-call-expression" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/helper-replace-supers" "^7.8.6"
@ -433,10 +434,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-destructuring@^7.8.3":
version "7.8.8"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.8.tgz#fadb2bc8e90ccaf5658de6f8d4d22ff6272a2f4b"
integrity sha512-eRJu4Vs2rmttFCdhPUM3bV0Yo/xPSdPw6ML9KHs/bjB4bLA5HXlbvYXPOD5yASodGod+krjYx21xm1QmL8dCJQ==
"@babel/plugin-transform-destructuring@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50"
integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
@ -551,10 +552,10 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/helper-replace-supers" "^7.8.3"
"@babel/plugin-transform-parameters@^7.8.7":
version "7.9.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.3.tgz#3028d0cc20ddc733166c6e9c8534559cee09f54a"
integrity sha512-fzrQFQhp7mIhOzmOtPiKffvCYQSK10NR8t6BBz2yPbeUHb9OLW8RZGtgDRBn8z2hGcwvKDL3vC7ojPTLNxmqEg==
"@babel/plugin-transform-parameters@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795"
integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA==
dependencies:
"@babel/helper-get-function-arity" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
@ -626,9 +627,9 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/preset-env@^7.4.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.0.tgz#a5fc42480e950ae8f5d9f8f2bbc03f52722df3a8"
integrity sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ==
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.5.tgz#8ddc76039bc45b774b19e2fc548f6807d8a8919f"
integrity sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ==
dependencies:
"@babel/compat-data" "^7.9.0"
"@babel/helper-compilation-targets" "^7.8.7"
@ -639,7 +640,7 @@
"@babel/plugin-proposal-json-strings" "^7.8.3"
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3"
"@babel/plugin-proposal-numeric-separator" "^7.8.3"
"@babel/plugin-proposal-object-rest-spread" "^7.9.0"
"@babel/plugin-proposal-object-rest-spread" "^7.9.5"
"@babel/plugin-proposal-optional-catch-binding" "^7.8.3"
"@babel/plugin-proposal-optional-chaining" "^7.9.0"
"@babel/plugin-proposal-unicode-property-regex" "^7.8.3"
@ -656,9 +657,9 @@
"@babel/plugin-transform-async-to-generator" "^7.8.3"
"@babel/plugin-transform-block-scoped-functions" "^7.8.3"
"@babel/plugin-transform-block-scoping" "^7.8.3"
"@babel/plugin-transform-classes" "^7.9.0"
"@babel/plugin-transform-classes" "^7.9.5"
"@babel/plugin-transform-computed-properties" "^7.8.3"
"@babel/plugin-transform-destructuring" "^7.8.3"
"@babel/plugin-transform-destructuring" "^7.9.5"
"@babel/plugin-transform-dotall-regex" "^7.8.3"
"@babel/plugin-transform-duplicate-keys" "^7.8.3"
"@babel/plugin-transform-exponentiation-operator" "^7.8.3"
@ -673,7 +674,7 @@
"@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3"
"@babel/plugin-transform-new-target" "^7.8.3"
"@babel/plugin-transform-object-super" "^7.8.3"
"@babel/plugin-transform-parameters" "^7.8.7"
"@babel/plugin-transform-parameters" "^7.9.5"
"@babel/plugin-transform-property-literals" "^7.8.3"
"@babel/plugin-transform-regenerator" "^7.8.7"
"@babel/plugin-transform-reserved-words" "^7.8.3"
@ -684,7 +685,7 @@
"@babel/plugin-transform-typeof-symbol" "^7.8.4"
"@babel/plugin-transform-unicode-regex" "^7.8.3"
"@babel/preset-modules" "^0.1.3"
"@babel/types" "^7.9.0"
"@babel/types" "^7.9.5"
browserslist "^4.9.1"
core-js-compat "^3.6.2"
invariant "^2.2.2"
@ -719,26 +720,26 @@
"@babel/types" "^7.8.6"
"@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892"
integrity sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2"
integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==
dependencies:
"@babel/code-frame" "^7.8.3"
"@babel/generator" "^7.9.0"
"@babel/helper-function-name" "^7.8.3"
"@babel/generator" "^7.9.5"
"@babel/helper-function-name" "^7.9.5"
"@babel/helper-split-export-declaration" "^7.8.3"
"@babel/parser" "^7.9.0"
"@babel/types" "^7.9.0"
"@babel/types" "^7.9.5"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.13"
"@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5"
integrity sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==
"@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444"
integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==
dependencies:
"@babel/helper-validator-identifier" "^7.9.0"
"@babel/helper-validator-identifier" "^7.9.5"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
@ -841,9 +842,9 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*":
version "13.11.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==
version "13.11.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.1.tgz#49a2a83df9d26daacead30d0ccc8762b128d53c7"
integrity sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==
"@types/q@^1.5.1":
version "1.5.2"
@ -1726,9 +1727,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001038:
version "1.0.30001039"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001039.tgz#b3814a1c38ffeb23567f8323500c09526a577bbe"
integrity sha512-SezbWCTT34eyFoWHgx8UWso7YtvtM7oosmFoXbCkdC6qJzRfBTeTgE9REtKtiuKXuMwWTZEvdnFNGAyVMorv8Q==
version "1.0.30001040"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001040.tgz#103fc8e6eb1d7397e95134cd0e996743353d58ea"
integrity sha512-Ep0tEPeI5wCvmJNrXjE3etgfI+lkl1fTDU6Y3ZH1mhrjkPlVI9W4pcKbMo+BQLpEWKVYYp2EmYaRsqpPC3k7lQ==
chalk@2.4.2, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
@ -2042,9 +2043,9 @@ core-js@^2.4.0:
integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
core-js@^3.6.4:
version "3.6.4"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647"
integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==
version "3.6.5"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a"
integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==
core-util-is@~1.0.0:
version "1.0.2"
@ -2706,9 +2707,9 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.390:
version "1.3.397"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.397.tgz#db640c2e67b08d590a504c20b56904537aa2bafa"
integrity sha512-zcUd1p/7yzTSdWkCTrqGvbnEOASy96d0RJL/lc5BDJoO23Z3G/VHd0yIPbguDU9n8QNUTCigLO7oEdtOb7fp2A==
version "1.3.402"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.402.tgz#9ad93c0c8ea2e571431739e0d76bd6bc9788a846"
integrity sha512-gaCDfX7IUH0s3JmBiHCDPrvVcdnTTP1r4WLJc2dHkYYbLmXZ2XHiJCcGQ9Balf91aKTvuCKCyu2JjJYRykoI1w==
elliptic@^6.0.0:
version "6.5.2"
@ -4199,9 +4200,9 @@ json5@^1.0.1:
minimist "^1.2.0"
json5@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.2.tgz#43ef1f0af9835dd624751a6b7fa48874fb2d608e"
integrity sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ==
version "2.1.3"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==
dependencies:
minimist "^1.2.5"
@ -5066,9 +5067,9 @@ p-limit@^1.1.0:
p-try "^1.0.0"
p-limit@^2.0.0, p-limit@^2.2.1:
version "2.2.2"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e"
integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==
version "2.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
dependencies:
p-try "^2.0.0"
@ -6607,9 +6608,9 @@ string-width@^3.0.0, string-width@^3.1.0:
strip-ansi "^5.1.0"
string.prototype.trimend@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz#ee497fd29768646d84be2c9b819e292439614373"
integrity sha512-EEJnGqa/xNfIg05SxiPSqRS7S9qwDhYts1TSLR1BQfYUfPe1stofgGKvwERK9+9yf+PpfBMlpBaCHucXGPQfUA==
version "1.0.1"
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913"
integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.17.5"
@ -6633,9 +6634,9 @@ string.prototype.trimright@^2.1.1:
string.prototype.trimend "^1.0.0"
string.prototype.trimstart@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.0.tgz#afe596a7ce9de905496919406c9734845f01a2f2"
integrity sha512-iCP8g01NFYiiBOnwG1Xc3WZLyoo+RuBymwIlWncShXDDJYWN6DbnM3odslBJdgCdRlq94B5s63NWAZlcn2CS4w==
version "1.0.1"
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54"
integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.17.5"
@ -6776,9 +6777,9 @@ terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.4.3:
worker-farm "^1.7.0"
terser@^4.1.2:
version "4.6.10"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.10.tgz#90f5bd069ff456ddbc9503b18e52f9c493d3b7c2"
integrity sha512-qbF/3UOo11Hggsbsqm2hPa6+L4w7bkr+09FNseEe8xrcVD3APGLFqE+Oz1ZKAxjYnFsj80rLOfgAtJ0LNJjtTA==
version "4.6.11"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.11.tgz#12ff99fdd62a26de2a82f508515407eb6ccd8a9f"
integrity sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==
dependencies:
commander "^2.20.0"
source-map "~0.6.1"