From 593bd46bd9411a14213d0cd8a724ea5c13ce348a Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Tue, 19 Nov 2019 01:12:09 +0200 Subject: [PATCH 01/33] Lecture notes --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 86d5cadc7..c2bb3e9c8 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,11 @@ NFQ Akademija ============ +# Medžiaga + +Bus remiamasi: https://github.com/aurelijusb/kickstart/pull/140 +Namų darbai: https://github.com/aurelijusb/kickstart/pull/162 + # Intro Sveiki! Tai yra Jūsų startinis projekto "template". From 0152cd7b8257305bee55cf2338fc8b39f34c192e Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Sat, 16 Nov 2019 22:59:39 +0200 Subject: [PATCH 02/33] =?UTF-8?q?Pridedame=20Secrurity=20bibliotek=C4=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Išnaudokime Symfony teikiamas galimybes naudotojų atpažinomui ir teisių valdymui. Sugeneruota su scipts/backend.sh composer require symfony/security-bundle Per naršyklę nieko nematome, bet galima patikrinti, ar veikia su scripts/backend.sh bin/console config:dump-reference security bin/console debug:config security Sukuriamas pavyzdinis security.yaml failas. dump-reference komanda parodo galimas nustatymų reikšmes. debug:config komanda parodo apskaičiuotas reikšmes (esamus nustatymus). Dokumentacija: https://symfony.com/doc/current/security.html https://symfony.com/doc/current/reference/configuration/debug.html --- composer.json | 1 + composer.lock | 461 +++++++++++++++++++++++++++++++++- config/bundles.php | 1 + config/packages/security.yaml | 22 ++ symfony.lock | 30 +++ 5 files changed, 514 insertions(+), 1 deletion(-) create mode 100644 config/packages/security.yaml diff --git a/composer.json b/composer.json index 5e4c82c5e..88bc059b9 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "symfony/flex": "^1.3.1", "symfony/framework-bundle": "4.3.*", "symfony/orm-pack": "^1.0", + "symfony/security-bundle": "4.3.*", "symfony/twig-pack": "^1.0", "symfony/webpack-encore-bundle": "^1.7", "symfony/yaml": "4.3.*" diff --git a/composer.lock b/composer.lock index 99073b588..48f2b1fc3 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "1ef246e2c00d457122ed5e9043e91bac", + "content-hash": "c55aacf42460ba92f00b2f0e8ad76b70", "packages": [ { "name": "doctrine/annotations", @@ -2674,6 +2674,64 @@ "homepage": "https://symfony.com", "time": "2019-10-07T15:06:41+00:00" }, + { + "name": "symfony/inflector", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/inflector.git", + "reference": "f97c69c132c08e31d291689d2d77bb0878094acb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/inflector/zipball/f97c69c132c08e31d291689d2d77bb0878094acb", + "reference": "f97c69c132c08e31d291689d2d77bb0878094acb", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Inflector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Inflector Component", + "homepage": "https://symfony.com", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string", + "symfony", + "words" + ], + "time": "2019-11-05T19:58:22+00:00" + }, { "name": "symfony/mime", "version": "v4.3.5", @@ -2995,6 +3053,73 @@ ], "time": "2019-08-06T08:03:45+00:00" }, + { + "name": "symfony/property-access", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "bb0c302375ffeef60c31e72a4539611b7f787565" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/bb0c302375ffeef60c31e72a4539611b7f787565", + "reference": "bb0c302375ffeef60c31e72a4539611b7f787565", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/inflector": "~3.4|~4.0" + }, + "require-dev": { + "symfony/cache": "~3.4|~4.0" + }, + "suggest": { + "psr/cache-implementation": "To cache access methods." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PropertyAccess Component", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" + ], + "time": "2019-08-26T08:26:39+00:00" + }, { "name": "symfony/routing", "version": "v4.3.5", @@ -3071,6 +3196,340 @@ ], "time": "2019-10-04T20:57:10+00:00" }, + { + "name": "symfony/security-bundle", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-bundle.git", + "reference": "9f247c672e08385c67e3ca7cfc1484072bcc6517" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/9f247c672e08385c67e3ca7cfc1484072bcc6517", + "reference": "9f247c672e08385c67e3ca7cfc1484072bcc6517", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": "^7.1.3", + "symfony/config": "^4.2", + "symfony/dependency-injection": "^4.2", + "symfony/http-kernel": "^4.3", + "symfony/security-core": "~4.3", + "symfony/security-csrf": "~4.2", + "symfony/security-guard": "~4.2", + "symfony/security-http": "^4.3.8" + }, + "conflict": { + "symfony/browser-kit": "<4.2", + "symfony/console": "<3.4", + "symfony/framework-bundle": "<4.3.4", + "symfony/twig-bundle": "<4.2", + "symfony/var-dumper": "<3.4" + }, + "require-dev": { + "doctrine/doctrine-bundle": "~1.5", + "symfony/asset": "~3.4|~4.0", + "symfony/browser-kit": "~4.2", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/form": "~3.4|~4.0", + "symfony/framework-bundle": "^4.3.4", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "symfony/translation": "~3.4|~4.0", + "symfony/twig-bridge": "~3.4|~4.0", + "symfony/twig-bundle": "~4.2", + "symfony/validator": "~3.4|~4.0", + "symfony/var-dumper": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0", + "twig/twig": "~1.41|~2.10" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\SecurityBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony SecurityBundle", + "homepage": "https://symfony.com", + "time": "2019-11-12T13:12:56+00:00" + }, + { + "name": "symfony/security-core", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-core.git", + "reference": "8c46ea77fe0738f2495eacc08fa34e1e19ff0b0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-core/zipball/8c46ea77fe0738f2495eacc08fa34e1e19ff0b0d", + "reference": "8c46ea77fe0738f2495eacc08fa34e1e19ff0b0d", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/event-dispatcher-contracts": "^1.1", + "symfony/service-contracts": "^1.1" + }, + "conflict": { + "symfony/event-dispatcher": "<4.3", + "symfony/security-guard": "<4.3" + }, + "require-dev": { + "psr/container": "^1.0", + "psr/log": "~1.0", + "symfony/event-dispatcher": "^4.3", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/ldap": "~3.4|~4.0", + "symfony/validator": "^3.4.31|^4.3.4" + }, + "suggest": { + "psr/container-implementation": "To instantiate the Security class", + "symfony/event-dispatcher": "", + "symfony/expression-language": "For using the expression voter", + "symfony/http-foundation": "", + "symfony/ldap": "For using LDAP integration", + "symfony/validator": "For using the user password constraint" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Core\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - Core Library", + "homepage": "https://symfony.com", + "time": "2019-10-28T17:07:32+00:00" + }, + { + "name": "symfony/security-csrf", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-csrf.git", + "reference": "0760ec651ea8ff81e22097780337e43f3a795769" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/0760ec651ea8ff81e22097780337e43f3a795769", + "reference": "0760ec651ea8ff81e22097780337e43f3a795769", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/security-core": "~3.4|~4.0" + }, + "conflict": { + "symfony/http-foundation": "<3.4" + }, + "require-dev": { + "symfony/http-foundation": "~3.4|~4.0" + }, + "suggest": { + "symfony/http-foundation": "For using the class SessionTokenStorage." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Csrf\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - CSRF Library", + "homepage": "https://symfony.com", + "time": "2019-09-24T15:54:14+00:00" + }, + { + "name": "symfony/security-guard", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-guard.git", + "reference": "62cc82a384f2c1c75c58189fcf713032f6fef1e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-guard/zipball/62cc82a384f2c1c75c58189fcf713032f6fef1e9", + "reference": "62cc82a384f2c1c75c58189fcf713032f6fef1e9", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/security-core": "~3.4.22|^4.2.3", + "symfony/security-http": "^4.3" + }, + "require-dev": { + "psr/log": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Guard\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - Guard", + "homepage": "https://symfony.com", + "time": "2019-10-28T17:07:32+00:00" + }, + { + "name": "symfony/security-http", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-http.git", + "reference": "290b23a46a932746c4cf3c313d59d99f82af2a87" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-http/zipball/290b23a46a932746c4cf3c313d59d99f82af2a87", + "reference": "290b23a46a932746c4cf3c313d59d99f82af2a87", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "^4.3", + "symfony/property-access": "~3.4|~4.0", + "symfony/security-core": "^4.3" + }, + "conflict": { + "symfony/security-csrf": "<3.4.11|~4.0,<4.0.11" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/routing": "~3.4|~4.0", + "symfony/security-csrf": "^3.4.11|^4.0.11" + }, + "suggest": { + "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", + "symfony/security-csrf": "For using tokens to protect authentication/logout attempts" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Http\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - HTTP Integration", + "homepage": "https://symfony.com", + "time": "2019-11-12T13:12:56+00:00" + }, { "name": "symfony/service-contracts", "version": "v1.1.7", diff --git a/config/bundles.php b/config/bundles.php index 7b4814201..f0f48ddad 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -9,4 +9,5 @@ Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], + Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], ]; diff --git a/config/packages/security.yaml b/config/packages/security.yaml new file mode 100644 index 000000000..855f921e1 --- /dev/null +++ b/config/packages/security.yaml @@ -0,0 +1,22 @@ +security: + # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers + providers: + in_memory: { memory: null } + firewalls: + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + main: + anonymous: true + + # activate different ways to authenticate + # https://symfony.com/doc/current/security.html#firewalls-authentication + + # https://symfony.com/doc/current/security/impersonating_user.html + # switch_user: true + + # Easy way to control access for large sections of your site + # Note: Only the *first* access control that matches will be used + access_control: + # - { path: ^/admin, roles: ROLE_ADMIN } + # - { path: ^/profile, roles: ROLE_USER } diff --git a/symfony.lock b/symfony.lock index fe3f6a33e..4d059d57c 100644 --- a/symfony.lock +++ b/symfony.lock @@ -197,6 +197,9 @@ "symfony/http-kernel": { "version": "v4.3.5" }, + "symfony/inflector": { + "version": "v4.3.8" + }, "symfony/maker-bundle": { "version": "1.0", "recipe": { @@ -224,6 +227,9 @@ "symfony/polyfill-php73": { "version": "v1.12.0" }, + "symfony/property-access": { + "version": "v4.3.8" + }, "symfony/routing": { "version": "4.2", "recipe": { @@ -239,6 +245,30 @@ "config/routes.yaml" ] }, + "symfony/security-bundle": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.3", + "ref": "e5a0228251d1dd2bca4c8ef918e14423c06db625" + }, + "files": [ + "config/packages/security.yaml" + ] + }, + "symfony/security-core": { + "version": "v4.3.8" + }, + "symfony/security-csrf": { + "version": "v4.3.8" + }, + "symfony/security-guard": { + "version": "v4.3.8" + }, + "symfony/security-http": { + "version": "v4.3.8" + }, "symfony/service-contracts": { "version": "v1.1.7" }, From 625cdd8f7b8fbb2624086146fdb1041ad2da2820 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Sat, 16 Nov 2019 23:02:25 +0200 Subject: [PATCH 03/33] =?UTF-8?q?Pridedam=20profiler=20bibliotek=C4=85=20p?= =?UTF-8?q?uslapio=20informacijos=20juostai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Profiler toolbar leidžia matyti ne tik kokiu greičiu užsikrovė puslapis, bet ir koks naudotojas yra prisijungęs. Sugeneruota routes/dev konfigūracija, kad leistų užsikrauti Profiler juostai naudojant AJAX. Su savimi prideda ir kitas derinimui (angl. debug) skirtas bibliotekas. Pvz {{ dump(kintamas) }} komandą Twig'e. Sugeneruota su scripts/backend.sh composer require profiler --dev Ši biblioteka skirta tik programavimo etapui (angl. development), o ne produkcinei sistemai (žr. require-dev ir ['dev' => true, 'test' => true]) Dokumentacija: https://symfony.com/doc/current/profiler.html --- composer.json | 3 +- composer.lock | 172 ++++++++++++++++++++++++- config/bundles.php | 1 + config/packages/dev/web_profiler.yaml | 6 + config/packages/test/web_profiler.yaml | 6 + config/routes/dev/web_profiler.yaml | 7 + symfony.lock | 20 +++ 7 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 config/packages/dev/web_profiler.yaml create mode 100644 config/packages/test/web_profiler.yaml create mode 100644 config/routes/dev/web_profiler.yaml diff --git a/composer.json b/composer.json index 88bc059b9..5dbe92634 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ }, "require-dev": { "squizlabs/php_codesniffer": "^3.5", - "symfony/maker-bundle": "^1.13" + "symfony/maker-bundle": "^1.13", + "symfony/profiler-pack": "^1.0" }, "config": { "preferred-install": { diff --git a/composer.lock b/composer.lock index 48f2b1fc3..46544c02a 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "c55aacf42460ba92f00b2f0e8ad76b70", + "content-hash": "477087eecf5885d606d77829481f1e20", "packages": [ { "name": "doctrine/annotations", @@ -4478,6 +4478,176 @@ "scaffolding" ], "time": "2019-10-18T01:41:52+00:00" + }, + { + "name": "symfony/profiler-pack", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/profiler-pack.git", + "reference": "99c4370632c2a59bb0444852f92140074ef02209" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/profiler-pack/zipball/99c4370632c2a59bb0444852f92140074ef02209", + "reference": "99c4370632c2a59bb0444852f92140074ef02209", + "shasum": "" + }, + "require": { + "php": "^7.0", + "symfony/stopwatch": "*", + "symfony/twig-bundle": "*", + "symfony/web-profiler-bundle": "*" + }, + "type": "symfony-pack", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A pack for the Symfony web profiler", + "time": "2018-12-10T12:11:44+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "ea4940845535c85ff5c505e13b3205b0076d07bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/ea4940845535c85ff5c505e13b3205b0076d07bf", + "reference": "ea4940845535c85ff5c505e13b3205b0076d07bf", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php72": "~1.5" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/console": "<3.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2019-10-13T12:02:04+00:00" + }, + { + "name": "symfony/web-profiler-bundle", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-profiler-bundle.git", + "reference": "6ce12ffe97d9e26091b0e7340a9d661fba64655e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/6ce12ffe97d9e26091b0e7340a9d661fba64655e", + "reference": "6ce12ffe97d9e26091b0e7340a9d661fba64655e", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/config": "^4.2", + "symfony/http-kernel": "^4.3", + "symfony/routing": "~3.4|~4.0", + "symfony/twig-bundle": "~4.2", + "symfony/var-dumper": "~3.4|~4.0", + "twig/twig": "^1.41|^2.10" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/form": "<4.3", + "symfony/messenger": "<4.2", + "symfony/var-dumper": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\WebProfilerBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony WebProfilerBundle", + "homepage": "https://symfony.com", + "time": "2019-10-23T17:52:52+00:00" } ], "aliases": [], diff --git a/config/bundles.php b/config/bundles.php index f0f48ddad..9e7ae04b5 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -10,4 +10,5 @@ Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], ]; diff --git a/config/packages/dev/web_profiler.yaml b/config/packages/dev/web_profiler.yaml new file mode 100644 index 000000000..e92166a7f --- /dev/null +++ b/config/packages/dev/web_profiler.yaml @@ -0,0 +1,6 @@ +web_profiler: + toolbar: true + intercept_redirects: false + +framework: + profiler: { only_exceptions: false } diff --git a/config/packages/test/web_profiler.yaml b/config/packages/test/web_profiler.yaml new file mode 100644 index 000000000..03752de21 --- /dev/null +++ b/config/packages/test/web_profiler.yaml @@ -0,0 +1,6 @@ +web_profiler: + toolbar: false + intercept_redirects: false + +framework: + profiler: { collect: false } diff --git a/config/routes/dev/web_profiler.yaml b/config/routes/dev/web_profiler.yaml new file mode 100644 index 000000000..c82beff2f --- /dev/null +++ b/config/routes/dev/web_profiler.yaml @@ -0,0 +1,7 @@ +web_profiler_wdt: + resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml' + prefix: /_wdt + +web_profiler_profiler: + resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml' + prefix: /_profiler diff --git a/symfony.lock b/symfony.lock index 4d059d57c..11c77475c 100644 --- a/symfony.lock +++ b/symfony.lock @@ -227,6 +227,9 @@ "symfony/polyfill-php73": { "version": "v1.12.0" }, + "symfony/profiler-pack": { + "version": "v1.0.4" + }, "symfony/property-access": { "version": "v4.3.8" }, @@ -298,9 +301,26 @@ "symfony/twig-pack": { "version": "v1.0.0" }, + "symfony/var-dumper": { + "version": "v4.3.8" + }, "symfony/var-exporter": { "version": "v4.3.5" }, + "symfony/web-profiler-bundle": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.3", + "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6" + }, + "files": [ + "config/packages/dev/web_profiler.yaml", + "config/packages/test/web_profiler.yaml", + "config/routes/dev/web_profiler.yaml" + ] + }, "symfony/webpack-encore-bundle": { "version": "1.0", "recipe": { From 21d859f79a63206faf2bb953fc958fc2f6e94190 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Sat, 16 Nov 2019 23:06:53 +0200 Subject: [PATCH 04/33] =?UTF-8?q?Susikuriame=20naudotojo=20klas=C4=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Galima rašyti viską patiems, arba galima susigeneruoti pavyzdį. MakerBundle standartiškai klausinėja parametrų, bet dėl demonstracijos greičio tiesiog naudojama vienos eilutės komanda (no-interaction). Sugeneruota su scripts/backend.sh ./bin/console make:user User --is-entity --identity-property-name=email --with-password --use-argon2 --no-interaction Naudojami parametrai: --is-entity – duomenys bus saugomi duomenų bazėje --identity-property-name – naudotojai bus atskiriami pagal el. pašto adresą (nes pagal jį dažniausiai galima priminti slaptažodį ir įprasta, kad 1 naudotjas = 1 el. pašto adresas) --with-password – naudojamas slaptažodis --use-argon2 – naudojamas naujausias (PHP 7.3) šifravimo (hash = maišos funkcijos) algoritmas --no-interaction – neklausinėti parametrų (patogiau demostracijai) Dokumentacija: https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html --- config/packages/security.yaml | 10 ++- src/Entity/User.php | 113 ++++++++++++++++++++++++++++++ src/Repository/UserRepository.php | 50 +++++++++++++ 3 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 src/Entity/User.php create mode 100644 src/Repository/UserRepository.php diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 855f921e1..e684ee4d9 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,7 +1,15 @@ security: + encoders: + App\Entity\User: + algorithm: argon2i + # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers providers: - in_memory: { memory: null } + # used to reload user from session & other features (e.g. switch_user) + app_user_provider: + entity: + class: App\Entity\User + property: email firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ diff --git a/src/Entity/User.php b/src/Entity/User.php new file mode 100644 index 000000000..fe4a5659f --- /dev/null +++ b/src/Entity/User.php @@ -0,0 +1,113 @@ +id; + } + + public function getEmail(): ?string + { + return $this->email; + } + + public function setEmail(string $email): self + { + $this->email = $email; + + return $this; + } + + /** + * A visual identifier that represents this user. + * + * @see UserInterface + */ + public function getUsername(): string + { + return (string) $this->email; + } + + /** + * @see UserInterface + */ + public function getRoles(): array + { + $roles = $this->roles; + // guarantee every user at least has ROLE_USER + $roles[] = 'ROLE_USER'; + + return array_unique($roles); + } + + public function setRoles(array $roles): self + { + $this->roles = $roles; + + return $this; + } + + /** + * @see UserInterface + */ + public function getPassword(): string + { + return (string) $this->password; + } + + public function setPassword(string $password): self + { + $this->password = $password; + + return $this; + } + + /** + * @see UserInterface + */ + public function getSalt() + { + // not needed when using the "bcrypt" algorithm in security.yaml + } + + /** + * @see UserInterface + */ + public function eraseCredentials() + { + // If you store any temporary, sensitive data on the user, clear it here + // $this->plainPassword = null; + } +} diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php new file mode 100644 index 000000000..64f692fd3 --- /dev/null +++ b/src/Repository/UserRepository.php @@ -0,0 +1,50 @@ +createQueryBuilder('u') + ->andWhere('u.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('u.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?User + { + return $this->createQueryBuilder('u') + ->andWhere('u.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} From afdfc525b8247736739769bef152875459a2e3fc Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Sat, 16 Nov 2019 23:09:17 +0200 Subject: [PATCH 05/33] =?UTF-8?q?Atnaujiname=20duomen=C5=B3=20baz=C4=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Naudotojo modelį apsirašėme kaip Entity klasę, bet vis tiek reikia, kad duomenų bazėje būtų atitinkamos lentelės. Sugeneruota su scripts/backend.sh bin/console make:migration bin/console doctrine:migrations:migrate Patikrinimui su scripts/mysql.sh DESCRIBE symfony.user; Dokumentacija: https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html https://symfony.com/doc/master/bundles/DoctrineMigrationsBundle/index.html --- src/Migrations/Version20191116210807.php | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/Migrations/Version20191116210807.php diff --git a/src/Migrations/Version20191116210807.php b/src/Migrations/Version20191116210807.php new file mode 100644 index 000000000..8795cf7bd --- /dev/null +++ b/src/Migrations/Version20191116210807.php @@ -0,0 +1,35 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE user'); + } +} From c9268fff1dca821079c16209de0422a1f32a4dcd Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Sat, 16 Nov 2019 23:10:57 +0200 Subject: [PATCH 06/33] =?UTF-8?q?Prisidedame=20Validator=20bibliotek=C4=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ji bus reikalinga registracijos formos kūrimui (kitu atveju make:registration-form mestų klaidą) Sugeneruota su scripts/backend.sh composer require form validator Dokumentacija: https://symfony.com/doc/current/validation.html --- composer.json | 2 + composer.lock | 366 +++++++++++++++++++++++++++- config/packages/test/validator.yaml | 3 + config/packages/validator.yaml | 8 + symfony.lock | 25 ++ 5 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 config/packages/test/validator.yaml create mode 100644 config/packages/validator.yaml diff --git a/composer.json b/composer.json index 5dbe92634..6a54f20dc 100644 --- a/composer.json +++ b/composer.json @@ -9,10 +9,12 @@ "symfony/console": "4.3.*", "symfony/dotenv": "4.3.*", "symfony/flex": "^1.3.1", + "symfony/form": "4.3.*", "symfony/framework-bundle": "4.3.*", "symfony/orm-pack": "^1.0", "symfony/security-bundle": "4.3.*", "symfony/twig-pack": "^1.0", + "symfony/validator": "4.3.*", "symfony/webpack-encore-bundle": "^1.7", "symfony/yaml": "4.3.*" }, diff --git a/composer.lock b/composer.lock index 46544c02a..3a81103fd 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "477087eecf5885d606d77829481f1e20", + "content-hash": "005d0d9b4183931279872408c45a01a6", "packages": [ { "name": "doctrine/annotations", @@ -2404,6 +2404,90 @@ "description": "Composer plugin for Symfony", "time": "2019-09-19T14:55:57+00:00" }, + { + "name": "symfony/form", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/form.git", + "reference": "1134c093d6fd339ea1b8823c50940607b58349f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/form/zipball/1134c093d6fd339ea1b8823c50940607b58349f2", + "reference": "1134c093d6fd339ea1b8823c50940607b58349f2", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/event-dispatcher": "^4.3", + "symfony/intl": "^4.3", + "symfony/options-resolver": "~4.3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/property-access": "~3.4|~4.0", + "symfony/service-contracts": "~1.1" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/console": "<4.3", + "symfony/dependency-injection": "<3.4", + "symfony/doctrine-bridge": "<3.4", + "symfony/framework-bundle": "<3.4", + "symfony/http-kernel": "<4.3", + "symfony/intl": "<4.3", + "symfony/translation": "<4.2", + "symfony/twig-bridge": "<3.4.5|<4.0.5,>=4.0" + }, + "require-dev": { + "doctrine/collections": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/console": "^4.3", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "~4.3", + "symfony/security-csrf": "~3.4|~4.0", + "symfony/translation": "~4.2", + "symfony/validator": "^3.4.31|^4.3.4", + "symfony/var-dumper": "^4.3" + }, + "suggest": { + "symfony/security-csrf": "For protecting forms against CSRF attacks.", + "symfony/twig-bridge": "For templating with Twig.", + "symfony/validator": "For form validation." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Form\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Form Component", + "homepage": "https://symfony.com", + "time": "2019-10-28T17:07:32+00:00" + }, { "name": "symfony/framework-bundle", "version": "v4.3.5", @@ -2732,6 +2816,81 @@ ], "time": "2019-11-05T19:58:22+00:00" }, + { + "name": "symfony/intl", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/intl.git", + "reference": "818771ff6acef04cdce05023ddfc39b7078014bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/intl/zipball/818771ff6acef04cdce05023ddfc39b7078014bf", + "reference": "818771ff6acef04cdce05023ddfc39b7078014bf", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-intl-icu": "~1.0" + }, + "require-dev": { + "symfony/filesystem": "~3.4|~4.0" + }, + "suggest": { + "ext-intl": "to use the component with locales other than \"en\"" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Intl\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Eriksen Costa", + "email": "eriksen.costa@infranology.com.br" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A PHP replacement layer for the C intl extension that includes additional data from the ICU library.", + "homepage": "https://symfony.com", + "keywords": [ + "i18n", + "icu", + "internationalization", + "intl", + "l10n", + "localization" + ], + "time": "2019-10-04T21:18:34+00:00" + }, { "name": "symfony/mime", "version": "v4.3.5", @@ -2791,6 +2950,60 @@ ], "time": "2019-09-19T17:00:15+00:00" }, + { + "name": "symfony/options-resolver", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "f46c7fc8e207bd8a2188f54f8738f232533765a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/f46c7fc8e207bd8a2188f54f8738f232533765a4", + "reference": "f46c7fc8e207bd8a2188f54f8738f232533765a4", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2019-10-28T20:59:01+00:00" + }, { "name": "symfony/orm-pack", "version": "v1.0.7", @@ -2819,6 +3032,64 @@ "description": "A pack for the Doctrine ORM", "time": "2019-10-18T05:41:09+00:00" }, + { + "name": "symfony/polyfill-intl-icu", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "66810b9d6eb4af54d543867909d65ab9af654d7e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/66810b9d6eb4af54d543867909d65ab9af654d7e", + "reference": "66810b9d6eb4af54d543867909d65ab9af654d7e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/intl": "~2.3|~3.0|~4.0|~5.0" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's ICU-related data and classes", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "icu", + "intl", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" + }, { "name": "symfony/polyfill-intl-idn", "version": "v1.12.0", @@ -3901,6 +4172,99 @@ "description": "A Twig pack for Symfony projects", "time": "2019-10-17T05:44:22+00:00" }, + { + "name": "symfony/validator", + "version": "v4.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/validator.git", + "reference": "8062841487a1a7d95f4c7cc359e674079daf4c48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/validator/zipball/8062841487a1a7d95f4c7cc359e674079daf4c48", + "reference": "8062841487a1a7d95f4c7cc359e674079daf4c48", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^1.1" + }, + "conflict": { + "doctrine/lexer": "<1.0.2", + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/dependency-injection": "<3.4", + "symfony/http-kernel": "<3.4", + "symfony/intl": "<4.3", + "symfony/translation": "<4.2", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.0", + "egulias/email-validator": "^2.1.10", + "symfony/cache": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-client": "^4.3", + "symfony/http-foundation": "~4.1", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/intl": "^4.3", + "symfony/property-access": "~3.4|~4.0", + "symfony/property-info": "~3.4|~4.0", + "symfony/translation": "~4.2", + "symfony/var-dumper": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "egulias/email-validator": "Strict (RFC compliant) email validation", + "psr/cache-implementation": "For using the metadata cache.", + "symfony/config": "", + "symfony/expression-language": "For using the Expression validator", + "symfony/http-foundation": "", + "symfony/intl": "", + "symfony/property-access": "For accessing properties within comparison constraints", + "symfony/property-info": "To automatically add NotNull and Type constraints", + "symfony/translation": "For translating validation errors.", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Validator Component", + "homepage": "https://symfony.com", + "time": "2019-11-08T08:31:27+00:00" + }, { "name": "symfony/var-exporter", "version": "v4.3.5", diff --git a/config/packages/test/validator.yaml b/config/packages/test/validator.yaml new file mode 100644 index 000000000..1e5ab7880 --- /dev/null +++ b/config/packages/test/validator.yaml @@ -0,0 +1,3 @@ +framework: + validation: + not_compromised_password: false diff --git a/config/packages/validator.yaml b/config/packages/validator.yaml new file mode 100644 index 000000000..350786a13 --- /dev/null +++ b/config/packages/validator.yaml @@ -0,0 +1,8 @@ +framework: + validation: + email_validation_mode: html5 + + # Enables validator auto-mapping support. + # For instance, basic validation constraints will be inferred from Doctrine's metadata. + #auto_mapping: + # App\Entity\: [] diff --git a/symfony.lock b/symfony.lock index 11c77475c..db421e6be 100644 --- a/symfony.lock +++ b/symfony.lock @@ -172,6 +172,9 @@ ".env" ] }, + "symfony/form": { + "version": "v4.3.8" + }, "symfony/framework-bundle": { "version": "4.2", "recipe": { @@ -200,6 +203,9 @@ "symfony/inflector": { "version": "v4.3.8" }, + "symfony/intl": { + "version": "v4.3.8" + }, "symfony/maker-bundle": { "version": "1.0", "recipe": { @@ -212,9 +218,15 @@ "symfony/mime": { "version": "v4.3.5" }, + "symfony/options-resolver": { + "version": "v4.3.8" + }, "symfony/orm-pack": { "version": "v1.0.7" }, + "symfony/polyfill-intl-icu": { + "version": "v1.12.0" + }, "symfony/polyfill-intl-idn": { "version": "v1.12.0" }, @@ -301,6 +313,19 @@ "symfony/twig-pack": { "version": "v1.0.0" }, + "symfony/validator": { + "version": "4.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.3", + "ref": "d902da3e4952f18d3bf05aab29512eb61cabd869" + }, + "files": [ + "config/packages/test/validator.yaml", + "config/packages/validator.yaml" + ] + }, "symfony/var-dumper": { "version": "v4.3.8" }, From d96afc59a0e8f8dd6af455933245a55a92e3d621 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Sat, 16 Nov 2019 23:14:03 +0200 Subject: [PATCH 07/33] =?UTF-8?q?Susikuriame=20registracijos=20form=C4=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sugeneruota naudojant scripts/backend.sh bin/console make:registration-form Naudojant atsakymus: Do you want to add a @UniqueEntity validation annotation on your User class to make sure duplicate accounts aren't created? [yes] Do you want to automatically authenticate the user after registration? [no] What route should the user be redirected to after registration? [home] Kol nėra pilnai pabaigas prisijungimas, negalime naudoti "automatically authenticate" funkcionalumo. Po registracijos tiesiog nukreipiame į egzistuojantį route'ą (pagrindinio puslapio adresą). Laukelių suvedimui naudojamos Symfony formos. Sutikimo su sąlygomis laukelis atėjo kartu su GDPR įstatymu (duomenų apsaugos). Patikrinimui naršyklėje: http://127.0.0.1:8000/register Patikrinimui per scripts/mysql.sh SELECT * FROM symfony.user; Dokumentacija: https://symfony.com/doc/current/doctrine/registration_form.html https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html https://symfony.com/doc/current/forms.html https://gdpr-info.eu/ --- src/Controller/RegistrationController.php | 46 +++++++++++++++++++ src/Entity/User.php | 2 + src/Form/RegistrationFormType.php | 54 +++++++++++++++++++++++ templates/registration/register.html.twig | 15 +++++++ 4 files changed, 117 insertions(+) create mode 100644 src/Controller/RegistrationController.php create mode 100644 src/Form/RegistrationFormType.php create mode 100644 templates/registration/register.html.twig diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php new file mode 100644 index 000000000..5175aadb7 --- /dev/null +++ b/src/Controller/RegistrationController.php @@ -0,0 +1,46 @@ +createForm(RegistrationFormType::class, $user); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + // encode the plain password + $user->setPassword( + $passwordEncoder->encodePassword( + $user, + $form->get('plainPassword')->getData() + ) + ); + + $entityManager = $this->getDoctrine()->getManager(); + $entityManager->persist($user); + $entityManager->flush(); + + // do anything else you need here, like send an email + + return $this->redirectToRoute('home'); + } + + return $this->render('registration/register.html.twig', [ + 'registrationForm' => $form->createView(), + ]); + } +} diff --git a/src/Entity/User.php b/src/Entity/User.php index fe4a5659f..1b67f01e3 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -3,10 +3,12 @@ namespace App\Entity; use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Security\Core\User\UserInterface; /** * @ORM\Entity(repositoryClass="App\Repository\UserRepository") + * @UniqueEntity(fields={"email"}, message="There is already an account with this email") */ class User implements UserInterface { diff --git a/src/Form/RegistrationFormType.php b/src/Form/RegistrationFormType.php new file mode 100644 index 000000000..bfcacb267 --- /dev/null +++ b/src/Form/RegistrationFormType.php @@ -0,0 +1,54 @@ +add('email') + ->add('plainPassword', PasswordType::class, [ + // instead of being set onto the object directly, + // this is read and encoded in the controller + 'mapped' => false, + 'constraints' => [ + new NotBlank([ + 'message' => 'Please enter a password', + ]), + new Length([ + 'min' => 6, + 'minMessage' => 'Your password should be at least {{ limit }} characters', + // max length allowed by Symfony for security reasons + 'max' => 4096, + ]), + ], + ]) + ->add('agreeTerms', CheckboxType::class, [ + 'mapped' => false, + 'constraints' => [ + new IsTrue([ + 'message' => 'You should agree to our terms.', + ]), + ], + ]) + ; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => User::class, + ]); + } +} diff --git a/templates/registration/register.html.twig b/templates/registration/register.html.twig new file mode 100644 index 000000000..9a0afd43f --- /dev/null +++ b/templates/registration/register.html.twig @@ -0,0 +1,15 @@ +{% extends 'base.html.twig' %} + +{% block title %}Register{% endblock %} + +{% block body %} +

Register

+ + {{ form_start(registrationForm) }} + {{ form_row(registrationForm.email) }} + {{ form_row(registrationForm.plainPassword) }} + {{ form_row(registrationForm.agreeTerms) }} + + + {{ form_end(registrationForm) }} +{% endblock %} From 596e02ffc8c089b0ea0a3a5957515f7c6a97f8a4 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Sun, 17 Nov 2019 19:20:45 +0200 Subject: [PATCH 08/33] =?UTF-8?q?Sugeneruojame=20prisjungimo=20formos=20pa?= =?UTF-8?q?vyzd=C4=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Jau turėjome naudotojo klasę ir registraciją – trūko tik pačio prisijungimo. Kodas sugeneruotas su scripts/backend.sh bin/console make:auth Pasirinkti atsakymai: What style of authentication do you want? [1] The class name of the authenticator to create [AppCustomAuthenticator] Choose a name for the controller class [SecurityController] Do you want to generate a '/logout' URL? (yes/no) [yes] Yra sukuriama forma http://127.0.0.1:8000/login adresu, bet bandant prisjungti reikalauja pakeitimų: TODO: provide a valid redirect inside /code/src/Security/AppCustomAuthenticator.php Dokumentacija: https://symfony.com/doc/current/security/form_login_setup https://symfony.com/doc/current/security/guard_authentication.html#step-3-configure-the-authenticator --- config/packages/security.yaml | 7 ++ src/Controller/SecurityController.php | 36 ++++++++++ src/Security/AppCustomAuthenticator.php | 96 +++++++++++++++++++++++++ templates/security/login.html.twig | 42 +++++++++++ 4 files changed, 181 insertions(+) create mode 100644 src/Controller/SecurityController.php create mode 100644 src/Security/AppCustomAuthenticator.php create mode 100644 templates/security/login.html.twig diff --git a/config/packages/security.yaml b/config/packages/security.yaml index e684ee4d9..2146db9bf 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -16,6 +16,13 @@ security: security: false main: anonymous: true + guard: + authenticators: + - App\Security\AppCustomAuthenticator + logout: + path: app_logout + # where to redirect after logout + # target: app_any_route # activate different ways to authenticate # https://symfony.com/doc/current/security.html#firewalls-authentication diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php new file mode 100644 index 000000000..000eedc6d --- /dev/null +++ b/src/Controller/SecurityController.php @@ -0,0 +1,36 @@ +getUser()) { + // return $this->redirectToRoute('target_path'); + // } + + // get the login error if there is one + $error = $authenticationUtils->getLastAuthenticationError(); + // last username entered by the user + $lastUsername = $authenticationUtils->getLastUsername(); + + return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]); + } + + /** + * @Route("/logout", name="app_logout") + */ + public function logout() + { + throw new \Exception('This method can be blank - it will be intercepted by the logout key on your firewall'); + } +} diff --git a/src/Security/AppCustomAuthenticator.php b/src/Security/AppCustomAuthenticator.php new file mode 100644 index 000000000..60fcf130e --- /dev/null +++ b/src/Security/AppCustomAuthenticator.php @@ -0,0 +1,96 @@ +entityManager = $entityManager; + $this->urlGenerator = $urlGenerator; + $this->csrfTokenManager = $csrfTokenManager; + $this->passwordEncoder = $passwordEncoder; + } + + public function supports(Request $request) + { + return 'app_login' === $request->attributes->get('_route') + && $request->isMethod('POST'); + } + + public function getCredentials(Request $request) + { + $credentials = [ + 'email' => $request->request->get('email'), + 'password' => $request->request->get('password'), + 'csrf_token' => $request->request->get('_csrf_token'), + ]; + $request->getSession()->set( + Security::LAST_USERNAME, + $credentials['email'] + ); + + return $credentials; + } + + public function getUser($credentials, UserProviderInterface $userProvider) + { + $token = new CsrfToken('authenticate', $credentials['csrf_token']); + if (!$this->csrfTokenManager->isTokenValid($token)) { + throw new InvalidCsrfTokenException(); + } + + $user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $credentials['email']]); + + if (!$user) { + // fail authentication with a custom error + throw new CustomUserMessageAuthenticationException('Email could not be found.'); + } + + return $user; + } + + public function checkCredentials($credentials, UserInterface $user) + { + return $this->passwordEncoder->isPasswordValid($user, $credentials['password']); + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) + { + if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) { + return new RedirectResponse($targetPath); + } + + // For example : return new RedirectResponse($this->urlGenerator->generate('some_route')); + throw new \Exception('TODO: provide a valid redirect inside '.__FILE__); + } + + protected function getLoginUrl() + { + return $this->urlGenerator->generate('app_login'); + } +} diff --git a/templates/security/login.html.twig b/templates/security/login.html.twig new file mode 100644 index 000000000..5639868fe --- /dev/null +++ b/templates/security/login.html.twig @@ -0,0 +1,42 @@ +{% extends 'base.html.twig' %} + +{% block title %}Log in!{% endblock %} + +{% block body %} +
+ {% if error %} +
{{ error.messageKey|trans(error.messageData, 'security') }}
+ {% endif %} + + {% if app.user %} +
+ You are logged in as {{ app.user.username }}, Logout +
+ {% endif %} + +

Please sign in

+ + + + + + + + {# + Uncomment this section and add a remember_me option below your firewall to activate remember me functionality. + See https://symfony.com/doc/current/security/remember_me.html + +
+ +
+ #} + + +
+{% endblock %} From 286af37f0b8ab532ff3a34b3a7e5d04bf7cb8899 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Mon, 6 May 2019 12:11:46 +0300 Subject: [PATCH 09/33] =?UTF-8?q?Pataisome=20nukreipim=C4=85=20po=20prisij?= =?UTF-8?q?ungimo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nukreipiame prisjungusį naudotoją į pagrindinį puslapį. Survarkome eilutes, kad atitiktų kodo stilių. Prisijungimas veikia, bet nėra nei Atsijungti mygtuko, nei automatinio prisjungimo po registracijos. Dokumentacija: https://symfony.com/doc/current/security/form_login_setup#finishing-the-login-form --- src/Security/AppCustomAuthenticator.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Security/AppCustomAuthenticator.php b/src/Security/AppCustomAuthenticator.php index 60fcf130e..0b81d1c09 100644 --- a/src/Security/AppCustomAuthenticator.php +++ b/src/Security/AppCustomAuthenticator.php @@ -28,8 +28,12 @@ class AppCustomAuthenticator extends AbstractFormLoginAuthenticator private $csrfTokenManager; private $passwordEncoder; - public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder) - { + public function __construct( + EntityManagerInterface $entityManager, + UrlGeneratorInterface $urlGenerator, + CsrfTokenManagerInterface $csrfTokenManager, + UserPasswordEncoderInterface $passwordEncoder + ) { $this->entityManager = $entityManager; $this->urlGenerator = $urlGenerator; $this->csrfTokenManager = $csrfTokenManager; @@ -85,8 +89,7 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token, return new RedirectResponse($targetPath); } - // For example : return new RedirectResponse($this->urlGenerator->generate('some_route')); - throw new \Exception('TODO: provide a valid redirect inside '.__FILE__); + return new RedirectResponse($this->urlGenerator->generate('home')); } protected function getLoginUrl() From c070a4d28d933c8af788126109b9cc89ded2bace Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Mon, 6 May 2019 12:54:15 +0300 Subject: [PATCH 10/33] =?UTF-8?q?Naudotojo=20objekto=20pasiekimas=20i?= =?UTF-8?q?=C5=A1=20Twig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Twig šablonose yra specialus kintamasis "app", kurio vienas iš elementų ir yra "user". Kai nėra prisijungta – "app.user" yra null. Kai prisijungiama, Symfony pakeičia kintamąjį į konkretų naudotoją. Twige getter'iai pasiekiami ir bet get žodelio (pvz. $user->getUserName -> user.username, $user->getRoles -> user.roles) Užmiršus, kokie adresai naudojami, pasitikrinti galima per scripts/backend.sh bin/console debug:route Dokumentacija: https://symfony.com/doc/master/templating/app_variable.html http://api.symfony.com/master/Symfony/Component/Security/Core/User/UserInterface.html https://getbootstrap.com/docs/4.0/components/navbar/ --- templates/base.html.twig | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/templates/base.html.twig b/templates/base.html.twig index e06313d52..2ca7bc4d7 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -10,6 +10,43 @@ {% endblock %} + + {% block body %}{% endblock %} {% block javascripts %} {{ encore_entry_script_tags('app') }} From 5dd11592db61d58e2dd6cf465cd7a70641dfa733 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Mon, 6 May 2019 13:55:38 +0300 Subject: [PATCH 11/33] =?UTF-8?q?Naudotojo=20objekto=20pasiekimas=20i?= =?UTF-8?q?=C5=A1=20Controller'io?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patogu, jei norima nukreipti į Prisijungimą arba neužtenka standartinių Security konfiguracijos galimybių. Naudotojo objektas įdedamas į kontrolerio metodą (analogiškai kaip Service'ams). Alternatyva būtų naudoti "$this->getUser()", bet naudojant per argumentus – lengviau bus perkeleti į kitą projektą (ar paruošti testams). Nors pavyzdžiuose yra Security $security, $security->getUser(), bet praktikoje kitos funkcijos (credentials, attributes) rečiau naudojamas nei tiesiogiai kviečiamas UserInterface. Jei naudotojas(-a) neprisijungęs, reikia "UserInterface $user = null", kitaip Symfony nežinos ką daryti su null (neprisijungęs), kurio negalima paversti į UserInterface objektą. Pastaba: AccessDeniedException yra standartinis atsakymas, kai neprisiregistruojama, bet tada grąžinas HTTP 500 statusas. Produkcinėje aplinkoje reikėtų reaguoti į kernel.exception arba užsidėti templates/bundles/TwigBundle/Exception/error.html.twig žmogiškai klaidos žinutei Dokumentacija: https://symfony.com/doc/current/security.html#b-fetching-the-user-from-a-service https://symfony.com/doc/current/controller.html#redirecting https://symfony.com/blog/new-in-symfony-3-2-user-value-resolver-for-controllers https://symfony.com/doc/current/security.html#securing-controllers-and-other-code --- src/Controller/SecurityController.php | 27 +++++++++++++++++++++++++++ templates/base.html.twig | 6 +++--- templates/security/profile.html.twig | 13 +++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 templates/security/profile.html.twig diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php index 000eedc6d..438d36bc1 100644 --- a/src/Controller/SecurityController.php +++ b/src/Controller/SecurityController.php @@ -2,9 +2,13 @@ namespace App\Controller; +use App\Entity\User; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; class SecurityController extends AbstractController @@ -33,4 +37,27 @@ public function logout() { throw new \Exception('This method can be blank - it will be intercepted by the logout key on your firewall'); } + + /** + * @Route("/profile", name="profile") + */ + public function profile(UrlGeneratorInterface $urlGenerator, UserInterface $user = null) + { + if ($user instanceof User) { + return $this->render('security/profile.html.twig', [ + 'user' => $user, + 'userId' => $user->getId(), + 'roles' => $this->roleNames($user->getRoles()), + ]); + } + // Redirect for not logged in users (or different kind) + return new RedirectResponse($urlGenerator->generate('app_login')); + } + + private function roleNames(array $userRoles) + { + foreach ($userRoles as $role) { + yield str_replace('ROLE_', '', $role); + } + } } diff --git a/templates/base.html.twig b/templates/base.html.twig index 2ca7bc4d7..bf91b2914 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -24,9 +24,9 @@ {% if app.user %} + {% else %} From d88aba2f0800bba2f1097f900df3756a0ccdd568 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Sun, 17 Nov 2019 20:25:56 +0200 Subject: [PATCH 15/33] =?UTF-8?q?Sukuriam=20Console's=20komand=C4=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ją naudosime pasikeisti administratoriaus rolei. Daroma prielaida, kad prisijungimas prie serverio yra labiau apsaugotas nei naršyklė ir tai yra intuityviau nei keisti kažką per duomenų bazę. Sugeneruota per scripts/backend.sh bin/console make:command app:promote-user Patikrinimui per scripts/backend.sh bin/console list app bin/console app:promote-user Dokumentacija: https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html https://symfony.com/doc/current/components/console.html --- src/Command/PromoteUserCommand.php | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/Command/PromoteUserCommand.php diff --git a/src/Command/PromoteUserCommand.php b/src/Command/PromoteUserCommand.php new file mode 100644 index 000000000..025eb6ec0 --- /dev/null +++ b/src/Command/PromoteUserCommand.php @@ -0,0 +1,40 @@ +setDescription('Add a short description for your command') + ->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description') + ->addOption('option1', null, InputOption::VALUE_NONE, 'Option description') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + $arg1 = $input->getArgument('arg1'); + + if ($arg1) { + $io->note(sprintf('You passed an argument: %s', $arg1)); + } + + if ($input->getOption('option1')) { + // ... + } + + $io->success('You have a new command! Now make it your own! Pass --help to see your options.'); + } +} From 85b23ab650eaca3f98f3c62025d678ade5faaa53 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Mon, 6 May 2019 15:51:51 +0300 Subject: [PATCH 16/33] =?UTF-8?q?=C4=AEgyvendinam=20komand=C4=85=20rolei?= =?UTF-8?q?=20pakelti?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per komandinę eilutę pridedame ROLE_ADMIN rolę registruotam naudotojui – taip apsaugome administravimo panelę nuo įsilaužėlių. UserRepository klasėje pasidarome papildomą metodą, kad būtų patogiau ieškoti elemento (duomenų bazės įžanga). Patikrinimui per scripts/backend.sh bin/console app:promote-user --help bin/console app:promote-user aurelijus@banelis.lt Ir tada bandome užeiti į http://127.0.0.1:8000/admin Pakeitus rolę – gali reikėti iš naujo prisijungti, nes naudotojo pasikeitimas tikrinamas pagal serialize metodą su išsaugota versija Sesijoje. Dokumentacija: https://symfony.com/doc/current/components/console.html https://symfony.com/doc/3.4/doctrine/repository.html https://symfony.com/doc/current/security.html#roles https://symfony.com/doc/current/security/user_provider.html#understanding-how-users-are-refreshed-from-the-session --- config/packages/security.yaml | 2 +- src/Command/PromoteUserCommand.php | 71 +++++++++++++++++++++++++----- src/Repository/UserRepository.php | 15 +++++++ 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 373b66409..2986628c4 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -33,5 +33,5 @@ security: # Easy way to control access for large sections of your site # Note: Only the *first* access control that matches will be used access_control: - - { path: ^/admin, roles: ROLE_USER } + - { path: ^/admin, roles: ROLE_ADMIN } # - { path: ^/profile, roles: ROLE_USER } diff --git a/src/Command/PromoteUserCommand.php b/src/Command/PromoteUserCommand.php index 025eb6ec0..404ccfbad 100644 --- a/src/Command/PromoteUserCommand.php +++ b/src/Command/PromoteUserCommand.php @@ -2,39 +2,88 @@ namespace App\Command; +use App\Entity\User; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Security\Core\User\UserInterface; class PromoteUserCommand extends Command { protected static $defaultName = 'app:promote-user'; + /** @var EntityManagerInterface */ + private $entityManager; + private $adminRole; + + /** + * PromoteUserCommand constructor. + * @param EntityManagerInterface $entityManager + */ + public function __construct(EntityManagerInterface $entityManager, $adminRole = 'ROLE_ADMIN') + { + $this->entityManager = $entityManager; + $this->adminRole = $adminRole; + + parent::__construct(); + } + protected function configure() { $this - ->setDescription('Add a short description for your command') - ->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description') - ->addOption('option1', null, InputOption::VALUE_NONE, 'Option description') - ; + ->setDescription('Make user admin') + ->addArgument('email', InputArgument::REQUIRED, 'E-mail address of existing user'); } + /** + * @throws \Doctrine\ORM\NonUniqueResultException + */ protected function execute(InputInterface $input, OutputInterface $output) { + // Parsing input $io = new SymfonyStyle($input, $output); - $arg1 = $input->getArgument('arg1'); + $email = $input->getArgument('email'); - if ($arg1) { - $io->note(sprintf('You passed an argument: %s', $arg1)); + // Getting user + $this->info("Searching for user", $email, $io); + $user = $this->entityManager->getRepository(User::class)->findByEmail($email); + if (!$user) { + $io->error("Cannot find user by e-mail: " . $email); + return; } - if ($input->getOption('option1')) { - // ... + if (in_array($this->adminRole, $user->getRoles())) { + $this->printUserRoles($user, $io); + $io->success('Admin role already exists'); + return; } - $io->success('You have a new command! Now make it your own! Pass --help to see your options.'); + // Adding admin role + $this->info("Adding role: ", $this->adminRole, $io); + $roles = $user->getRoles(); + $roles[] = $this->adminRole; + $user->setRoles(array_unique($roles)); + + // Storing user + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $this->printUserRoles($user, $output); + $io->success('Admin role successfully added'); + } + + private function info($message, $value, OutputInterface $io) + { + $io->writeln(sprintf('%s: %s', $message, $value)); + } + + private function printUserRoles(UserInterface $user, OutputInterface $io) + { + $io->writeln( + "User roles: " . join(', ', $user->getRoles()) . '' + ); } } diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 64f692fd3..149bac63d 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -19,6 +19,21 @@ public function __construct(ManagerRegistry $registry) parent::__construct($registry, User::class); } + /** + * @param string $email + * @return User|null + * @throws \Doctrine\ORM\NonUniqueResultException + */ + public function findByEmail($email): ?User + { + return $this->createQueryBuilder('u') + ->andWhere('u.email = :email') + ->setParameter('email', $email) + ->getQuery() + ->getOneOrNullResult() + ; + } + // /** // * @return User[] Returns an array of User objects // */ From e45476150a0edb5724d07c8bbee40f66135760de Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Mon, 6 May 2019 16:45:41 +0300 Subject: [PATCH 17/33] =?UTF-8?q?Praple=C4=8Diame=20TwigBundle=20klaid?= =?UTF-8?q?=C5=B3=20=C5=A1ablon=C4=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Jei prisjungtume naudotoju, kuris turi ne tą rolę, Symfony duoda 403 Forbidden klaidą. Jei naudotojas iš viso nėra prisijungęs – Symfony yra pakankamai protingas, kad nukreiptų į prisijungimo adresą. Kadangi jau yra gražus šablonas, tai galima naudoti AccessDeniedException klaidą, kuri sugeneruos 403 klaidos puslapį. Kai APP_ENV=dev (paleidus scripts/install-dev.sh) atvaizdavimą šablonas matomas per: http://127.0.0.1:8000/_error/403.html Kai APP_ENV=prod (paleidus scripts/install-prod.sh) ši klaida bus rodoma per: http://127.0.0.1:8000/admin/ Kai naudotojas yra prisijungęs, bet neturi ROLE_ADMIN teisių Dokumentacija: https://symfony.com/doc/current/controller/error_pages.html https://symfony.com/doc/current/bundles/override.html#templates --- templates/bundles/TwigBundle/Exception/error403.html.twig | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 templates/bundles/TwigBundle/Exception/error403.html.twig diff --git a/templates/bundles/TwigBundle/Exception/error403.html.twig b/templates/bundles/TwigBundle/Exception/error403.html.twig new file mode 100644 index 000000000..0eb714965 --- /dev/null +++ b/templates/bundles/TwigBundle/Exception/error403.html.twig @@ -0,0 +1,7 @@ +{% extends 'base.html.twig' %} + +{% block body %} +

Neturite teisių

+ + Prisijungti kitu naudotoju +{% endblock %} \ No newline at end of file From 7bffea53f9fd1e01fb1c72a7bea41170f61fd3e3 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Mon, 6 May 2019 17:02:32 +0300 Subject: [PATCH 18/33] =?UTF-8?q?Praple=C4=8Diame=20EasyAdmin=20=C5=A1ablo?= =?UTF-8?q?n=C4=85:=20Surandame=20original=C5=B3=20=C5=A1ablon=C4=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Profiler Toolbar -> Twig -> Rendering Call Graph randame mus domintančią dalį. Per Profiler Toolbar -> Configuration -> Enabled Bundles randame Bundle pavadinimą ir atitikmenį failų sistemoje. Nukopijuojame turinį į templates/bundles/BUNDLE_PAVADINIMAS/ORIGINAL_ADRESAS Atkreipkite dėmesį, kad pavadinimas gali būti EasyAdminBundle, o ne EasyAdmin! Jei nepasikeičia, gali prireikti: bin/console cache:clear Dokumentacija: https://symfony.com/doc/current/bundles/override.html#templates --- .../EasyAdminBundle/default/layout.html.twig | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 templates/bundles/EasyAdminBundle/default/layout.html.twig diff --git a/templates/bundles/EasyAdminBundle/default/layout.html.twig b/templates/bundles/EasyAdminBundle/default/layout.html.twig new file mode 100644 index 000000000..7c10b0452 --- /dev/null +++ b/templates/bundles/EasyAdminBundle/default/layout.html.twig @@ -0,0 +1,172 @@ + + + + + + + + + {% block page_title %}{{ block('content_title')|striptags|raw }}{% endblock %} + {% block head_stylesheets %} + + {% endblock %} + {% block head_custom_stylesheets %} + {% for css_asset in easyadmin_config('design.assets.css') %} + + {% endfor %} + {% endblock head_custom_stylesheets %} + {% if easyadmin_config('design.brand_color') != 'hsl(230, 55%, 60%)' %} + + {% endif %} + {% block head_favicon %} + {% set favicon = easyadmin_config('design.assets.favicon') %} + + {% endblock %} + {% block head_javascript %} + + {% endblock head_javascript %} + {% if easyadmin_config('design.rtl') %} + + + {% endif %} + +{% block body %} + + + {% block wrapper_wrapper %} +
+ {% block wrapper %} +
+ {% block header %} + + {% set _user_name = easyadmin_read_property(app.user, easyadmin_config('user.name_property_path'))|default('user.unnamed'|trans(domain = 'EasyAdminBundle')) %} + {% set _logout_path = easyadmin_logout_path() %} + {% set _user_has_logout = _logout_path is not empty %} + {% set _user_is_impersonated = is_granted('ROLE_PREVIOUS_ADMIN') %} + {% set _user_menu_content %} +
+

{{ 'user.logged_in_as'|trans(domain = 'EasyAdminBundle') }}

+

+ {% if app.user|default(false) == false %} + {{ 'user.anonymous'|trans(domain = 'EasyAdminBundle') }} + {% else %} + {{ _user_name }} + {% endif %} +

+
+ {% block user_menu %} + {% if _user_has_logout or _user_is_impersonated %} +
+ {% if _user_has_logout %} + {{ 'user.signout'|trans(domain = 'EasyAdminBundle') }} + {% endif %} + {% if _user_is_impersonated %} + {{ 'user.exit_impersonation'|trans(domain = 'EasyAdminBundle') }} + {% endif %} +
+ {% endif %} + {% endblock user_menu %} + {% endset %} + + {% endblock header %} +
+ +
+ {% block flash_messages %} + {{ include(_entity_config is defined ? _entity_config.templates.flash_messages : '@EasyAdmin/default/flash_messages.html.twig') }} + {% endblock flash_messages %} + + {% block content %} +
+ {% block content_header_wrapper %} + {% set _has_content_help = _entity_config is defined and _entity_config[app.request.query.get('action')]['help']|default(false) %} +
+ {% block content_header %} +
+
+

{% block content_title %}{% endblock %}

+
+ {% block global_actions_wrapper %} +
{% block global_actions %}{% endblock %}
+ {% endblock %} +
+ {% block content_help %} + {% if _entity_config is defined and _entity_config[app.request.query.get('action')]['help']|default(false) %} +
+ {{ _entity_config[app.request.query.get('action')]['help']|trans(domain = _entity_config.translation_domain)|raw }} +
+ {% endif %} + {% endblock content_help %} + {% endblock content_header %} +
+ {% endblock content_header_wrapper %} +
+ {% block main %}{% endblock %} +
+ {% block content_footer_wrapper %} + + {% endblock %} +
+ {% endblock content %} +
+
+ {% endblock wrapper %} +
+ {% endblock wrapper_wrapper %} + {% block body_javascript %}{% endblock body_javascript %} + {% block body_custom_javascript %} + {% for js_asset in easyadmin_config('design.assets.js') %} + + {% endfor %} + {% endblock body_custom_javascript %} + +{% endblock body %} + From ed87245b1f472acf2ed6df01ce6a6c00f5042824 Mon Sep 17 00:00:00 2001 From: Aurelijus Banelis Date: Sun, 17 Nov 2019 21:02:13 +0200 Subject: [PATCH 19/33] =?UTF-8?q?Praple=C4=8Diame=20EasyAdmin=20=C5=A1ablo?= =?UTF-8?q?n=C4=85:=20pakei=C4=8Diam=20turin=C4=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pritaikome layout.html.twig šabloną, kad jis naudotų mūsų projekto base.html.twig tėvinį šabloną. Reikia daryti atsargiai, nes lengva pralesiti kokią nors CSS/JavaScript dalį ir biblioteka nebeveiks. Dokumentacija: https://symfony.com/doc/current/bundles/override.html#templates https://twig.symfony.com/doc/3.x/tags/extends.html --- templates/base.html.twig | 3 ++- .../EasyAdminBundle/default/layout.html.twig | 20 +++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/templates/base.html.twig b/templates/base.html.twig index 0ccc52f7c..eb61ed532 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -8,8 +8,9 @@ {% block stylesheets %} {{ encore_entry_link_tags('app') }} {% endblock %} + {% block head %}{% endblock %} - +