From 86c80a83cf1de657ee0eb5ff914746cdad891457 Mon Sep 17 00:00:00 2001 From: vincent Date: Fri, 26 Jul 2024 16:04:16 +0200 Subject: [PATCH] ntroduction des users --- composer.json | 1 + composer.lock | 496 +++++++++++++++++++++++++++- config/bundles.php | 1 + config/packages/security.yaml | 48 +++ config/packages/twig.yaml | 2 +- config/routes/security.yaml | 3 + migrations/Version20240726120017.php | 33 ++ src/Controller/HomeController.php | 15 +- src/Entity/User.php | 101 ++++++ src/Repository/UserRepository.php | 43 +++ src/Security/OpenStreetMapAuthenticator.php | 83 +++++ symfony.lock | 13 + templates/_header.html.twig | 24 +- templates/home/index.html.twig | 11 +- 14 files changed, 862 insertions(+), 12 deletions(-) create mode 100644 config/packages/security.yaml create mode 100644 config/routes/security.yaml create mode 100644 migrations/Version20240726120017.php create mode 100644 src/Entity/User.php create mode 100644 src/Repository/UserRepository.php create mode 100644 src/Security/OpenStreetMapAuthenticator.php diff --git a/composer.json b/composer.json index 1ce90b2..cbbb31f 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,7 @@ "symfony/form": "7.1.*", "symfony/framework-bundle": "7.1.*", "symfony/runtime": "7.1.*", + "symfony/security-bundle": "7.1.*", "symfony/stimulus-bundle": "^2.18", "symfony/twig-bundle": "7.1.*", "symfony/validator": "7.1.*", diff --git a/composer.lock b/composer.lock index bc4c9a3..8c600af 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": "ab07552debf0ed36325858962a6ddb7a", + "content-hash": "d673dbc41a6c7573a7676813f6beb0c1", "packages": [ { "name": "behat/transliterator", @@ -3708,6 +3708,80 @@ "time": "2024-04-18T09:32:20+00:00" }, { + "name": "symfony/clock", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "3dfc8b084853586de51dd1441c6242c76a28cbe7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/3dfc8b084853586de51dd1441c6242c76a28cbe7", + "reference": "3dfc8b084853586de51dd1441c6242c76a28cbe7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "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": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { "name": "symfony/config", "version": "v7.1.1", "source": { @@ -5391,6 +5465,78 @@ "time": "2024-05-31T14:57:53+00:00" }, { + "name": "symfony/password-hasher", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/password-hasher.git", + "reference": "4ad96eb7cf9e2f8f133ada95f2b8021769061662" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/4ad96eb7cf9e2f8f133ada95f2b8021769061662", + "reference": "4ad96eb7cf9e2f8f133ada95f2b8021769061662", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "conflict": { + "symfony/security-core": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PasswordHasher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Robin Chalas", + "email": "robin.chalas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides password hashing utilities", + "homepage": "https://symfony.com", + "keywords": [ + "hashing", + "password" + ], + "support": { + "source": "https://github.com/symfony/password-hasher/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { "name": "symfony/polyfill-intl-grapheme", "version": "v1.30.0", "source": { @@ -6110,6 +6256,354 @@ "time": "2024-05-31T14:55:39+00:00" }, { + "name": "symfony/security-bundle", + "version": "v7.1.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-bundle.git", + "reference": "a6746372202512d2c75ba9bdbc36e15022a56c42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/a6746372202512d2c75ba9bdbc36e15022a56c42", + "reference": "a6746372202512d2c75ba9bdbc36e15022a56c42", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "ext-xml": "*", + "php": ">=8.2", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/password-hasher": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/security-csrf": "^6.4|^7.0", + "symfony/security-http": "^7.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/browser-kit": "<6.4", + "symfony/console": "<6.4", + "symfony/framework-bundle": "<6.4", + "symfony/http-client": "<6.4", + "symfony/ldap": "<6.4", + "symfony/serializer": "<6.4", + "symfony/twig-bundle": "<6.4", + "symfony/validator": "<6.4" + }, + "require-dev": { + "symfony/asset": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/ldap": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0", + "twig/twig": "^3.0.4", + "web-token/jwt-library": "^3.3.2" + }, + "type": "symfony-bundle", + "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": "Provides a tight integration of the Security component into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-bundle/tree/v7.1.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-28T10:35:32+00:00" + }, + { + "name": "symfony/security-core", + "version": "v7.1.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-core.git", + "reference": "d615960211a11913e70f8576e5c38cd05d90ec3f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-core/zipball/d615960211a11913e70f8576e5c38cd05d90ec3f", + "reference": "d615960211a11913e70f8576e5c38cd05d90ec3f", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3", + "symfony/password-hasher": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/http-foundation": "<6.4", + "symfony/ldap": "<6.4", + "symfony/translation": "<6.4.3|>=7.0,<7.0.3", + "symfony/validator": "<6.4" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "psr/container": "^1.1|^2.0", + "psr/log": "^1|^2|^3", + "symfony/cache": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/ldap": "^6.4|^7.0", + "symfony/string": "^6.4|^7.0", + "symfony/translation": "^6.4.3|^7.0.3", + "symfony/validator": "^6.4|^7.0" + }, + "type": "library", + "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", + "support": { + "source": "https://github.com/symfony/security-core/tree/v7.1.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-28T08:00:31+00:00" + }, + { + "name": "symfony/security-csrf", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-csrf.git", + "reference": "27cd1bce9d7f3457a152a6ca9790712d6954dd21" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/27cd1bce9d7f3457a152a6ca9790712d6954dd21", + "reference": "27cd1bce9d7f3457a152a6ca9790712d6954dd21", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/security-core": "^6.4|^7.0" + }, + "conflict": { + "symfony/http-foundation": "<6.4" + }, + "require-dev": { + "symfony/http-foundation": "^6.4|^7.0" + }, + "type": "library", + "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", + "support": { + "source": "https://github.com/symfony/security-csrf/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/security-http", + "version": "v7.1.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-http.git", + "reference": "e9dc3ef093dac3d4982fcd96002525aa7a1d6989" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-http/zipball/e9dc3ef093dac3d4982fcd96002525aa7a1d6989", + "reference": "e9dc3ef093dac3d4982fcd96002525aa7a1d6989", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/clock": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/http-client-contracts": "<3.0", + "symfony/security-bundle": "<6.4", + "symfony/security-csrf": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/cache": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/http-client-contracts": "^3.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/security-csrf": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "web-token/jwt-library": "^3.3.2" + }, + "type": "library", + "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", + "support": { + "source": "https://github.com/symfony/security-http/tree/v7.1.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-25T19:55:06+00:00" + }, + { "name": "symfony/service-contracts", "version": "v3.5.0", "source": { diff --git a/config/bundles.php b/config/bundles.php index b5205ba..2c82c77 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -14,4 +14,5 @@ return [ Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true], KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::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 0000000..487d2f4 --- /dev/null +++ b/config/packages/security.yaml @@ -0,0 +1,48 @@ +security: + # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords + password_hashers: + Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' + # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider + providers: + # used to reload user from session & other features (e.g. switch_user) + app_user_provider: + entity: + class: App\Entity\User + property: username + firewalls: + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + main: + lazy: true + provider: app_user_provider + custom_authenticators: + - App\Security\OpenStreetMapAuthenticator + logout: + path: /osm/logout + target: app_home + + # activate different ways to authenticate + # https://symfony.com/doc/current/security.html#the-firewall + + # 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 } + +when@test: + security: + password_hashers: + # By default, password hashers are resource intensive and take time. This is + # important to generate secure password hashes. In tests however, secure hashes + # are not important, waste resources and increase test times. The following + # reduces the work factor to the lowest possible values. + Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: + algorithm: auto + cost: 4 # Lowest possible value for bcrypt + time_cost: 3 # Lowest possible value for argon + memory_cost: 10 # Lowest possible value for argon diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index 1cb977e..2b0eab2 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -5,7 +5,7 @@ twig: title: Gestionnaire de tâches simple menu: header: - - { route: 'app_project', label: 'Projets' } + - { route: 'app_project', label: 'Projets', icon: '' } taskLifecycleManager: '@App\Service\TaskLifecycleManager' geoJsonManager: '@App\Service\GeoJsonManager' diff --git a/config/routes/security.yaml b/config/routes/security.yaml new file mode 100644 index 0000000..f853be1 --- /dev/null +++ b/config/routes/security.yaml @@ -0,0 +1,3 @@ +_security_logout: + resource: security.route_loader.logout + type: service diff --git a/migrations/Version20240726120017.php b/migrations/Version20240726120017.php new file mode 100644 index 0000000..d86b096 --- /dev/null +++ b/migrations/Version20240726120017.php @@ -0,0 +1,33 @@ +addSql('CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(180) NOT NULL, roles CLOB NOT NULL --(DC2Type:json) + , osm_id INTEGER NOT NULL)'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_USERNAME ON user (username)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP TABLE user'); + } +} diff --git a/src/Controller/HomeController.php b/src/Controller/HomeController.php index ce58eb8..5dbae99 100644 --- a/src/Controller/HomeController.php +++ b/src/Controller/HomeController.php @@ -5,11 +5,11 @@ namespace App\Controller; use KnpU\OAuth2ClientBundle\Client\ClientRegistry; use League\OAuth2\Client\Provider\Exception\IdentityProviderException; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; - class HomeController extends AbstractController { #[Route('/', name: 'app_home')] @@ -36,16 +36,19 @@ class HomeController extends AbstractController try { $resourceOwner = $client->fetchUser(); - dump( - $resourceOwner->getId(), - $resourceOwner->getDisplayName() - ); $this->addFlash('success', 'Authentification OSM réussie !'); } catch (IdentityProviderException $exception) { - $this->addFlash('success', 'Échec de l’authentification OSM !'); + $this->addFlash('danger', 'Échec de l’authentification OSM !'); } return $this->redirectToRoute('app_home'); } + #[Route('/osm/logout', name: 'app_osm_logout')] + public function osmLogout(Security $security): Response + { + return $security->logout(); + } + + } diff --git a/src/Entity/User.php b/src/Entity/User.php new file mode 100644 index 0000000..4052829 --- /dev/null +++ b/src/Entity/User.php @@ -0,0 +1,101 @@ + The user roles + */ + #[ORM\Column] + private array $roles = []; + + #[ORM\Column] + private ?int $osmId = null; + + public function getId(): ?int + { + return $this->id; + } + + public function getUsername(): ?string + { + return $this->username; + } + + public function setUsername(string $username): static + { + $this->username = $username; + + return $this; + } + + /** + * A visual identifier that represents this user. + * + * @see UserInterface + */ + public function getUserIdentifier(): string + { + return (string) $this->username; + } + + /** + * @see UserInterface + * + * @return list + */ + public function getRoles(): array + { + $roles = $this->roles; + // guarantee every user at least has ROLE_USER + $roles[] = 'ROLE_USER'; + + return array_unique($roles); + } + + /** + * @param list $roles + */ + public function setRoles(array $roles): static + { + $this->roles = $roles; + + return $this; + } + + /** + * @see UserInterface + */ + public function eraseCredentials(): void + { + // If you store any temporary, sensitive data on the user, clear it here + // $this->plainPassword = null; + } + + public function getOsmId(): ?int + { + return $this->osmId; + } + + public function setOsmId(int $osmId): static + { + $this->osmId = $osmId; + + return $this; + } +} diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php new file mode 100644 index 0000000..b29153b --- /dev/null +++ b/src/Repository/UserRepository.php @@ -0,0 +1,43 @@ + + */ +class UserRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, User::class); + } + + // /** + // * @return User[] Returns an array of User objects + // */ + // public function findByExampleField($value): array + // { + // return $this->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() + // ; + // } +} diff --git a/src/Security/OpenStreetMapAuthenticator.php b/src/Security/OpenStreetMapAuthenticator.php new file mode 100644 index 0000000..b40011a --- /dev/null +++ b/src/Security/OpenStreetMapAuthenticator.php @@ -0,0 +1,83 @@ +clientRegistry = $clientRegistry; + $this->entityManager = $entityManager; + $this->router = $router; + } + + public function supports(Request $request): ?bool + { + return $request->attributes->get('_route') === 'app_osm_callback'; + } + + public function authenticate(Request $request): Passport + { + $client = $this->clientRegistry->getClient('openstreetmap'); + $accessToken = $this->fetchAccessToken($client); + + return new SelfValidatingPassport( + new UserBadge($accessToken->getToken(), function() use ($accessToken, $client) { + $resourceOwner = $client->fetchUserFromToken($accessToken); + + $existingUser = $this->entityManager->getRepository(User::class)->findOneBy(['osmId' => $resourceOwner->getId()]); + + if ($existingUser) { + return $existingUser; + } + + $user = new User(); + + $user->setOsmId($resourceOwner->getId()); + $user->setUsername($resourceOwner->getDisplayName()); + + $this->entityManager->persist($user); + $this->entityManager->flush(); + + return $user; + }) + ); + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response + { + return null; + } + + public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response + { + return null; + } + + public function start(Request $request, AuthenticationException $authException = null): Response + { + return new RedirectResponse( + '/', + Response::HTTP_TEMPORARY_REDIRECT + ); + } +} diff --git a/symfony.lock b/symfony.lock index 74a9920..7a65556 100644 --- a/symfony.lock +++ b/symfony.lock @@ -157,6 +157,19 @@ "config/routes.yaml" ] }, + "symfony/security-bundle": { + "version": "7.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.4", + "ref": "2ae08430db28c8eb4476605894296c82a642028f" + }, + "files": [ + "config/packages/security.yaml", + "config/routes/security.yaml" + ] + }, "symfony/stimulus-bundle": { "version": "2.18", "recipe": { diff --git a/templates/_header.html.twig b/templates/_header.html.twig index ab5e89e..96ad3a5 100644 --- a/templates/_header.html.twig +++ b/templates/_header.html.twig @@ -9,9 +9,31 @@ diff --git a/templates/home/index.html.twig b/templates/home/index.html.twig index c3a5204..80fbe28 100644 --- a/templates/home/index.html.twig +++ b/templates/home/index.html.twig @@ -1,9 +1,14 @@ {% extends 'base.html.twig' %} {% block page_content %} -
-
- S’authentifier avec OSM +
+

Gestionnaire de tâches simple

+
+

L’idée c’est d’avoir un petit outil collaboratif simple et facile à administrer/utiliser pour mapper des trucs de façon coordonnée à un endroit.

+
+
{% endblock %}