====== Initialiser un projet Symfony 4 ====== ===== Logiciels requis ===== De manière obligatoire : * PHP >= 7.1.3 * [[https://getcomposer.org/|Composer]] Il est impératif que la commande php pointe vers la bonne version de php ! Pour avoir votre version de php tapez ''php -v'' dans le terminal. De manière facultative : * [[https://nodejs.org/en/|Node.js]] Uniquement si le projet utilise webpack Webpack sert à gérer les librairies et dépendances javascript de manière plus simple. C'est utile si le projet utilise beaucoup de javascript. (Appli front par exemple, mais pas seulement. Webpack est utilisé sur MyCA) De plus il faudra un serveur MySQL sur la machine (Laragon fera l'affaire pour windows, MAMP pour Mac, et pour linux installer un serveur mysql est assez simple) ===== Initialisation du projet ===== ==== Symfony et les dépendances de base ==== Créer un nouveau dossier qui va contenir le projet, et lancer la commande suivante à l'intérieur : composer create-project symfony/website-skeleton . "4.4.*" ==== Installation de Webpack ==== A faire uniquement si le projet va utiliser Webpack ! Lancer la commande suivante pour installer **Webpack Encore** : composer require symfony/webpack-encore-bundle Pour les dépendances front : npm install --save-dev @symfony/webpack-encore ==== Installation de FOSUserBundle ==== A ne pas installer pour les projets claqués, vous gérerez les utilisateurs comme dans la fabuleuse vidéo de Lior [[https://www.youtube.com/watch?v=_GjHWa9hQic&ab_channel=LiorCHAMLA | COMPRENDRE L'AUTHENTIFICATION !]] A faire si le site nécessite une gestion d'utilisateurs. (99% des cas) Le module utilisé FOSUserBundle est un module couramment utilisé avec symfony pour cette utilisation. === Modules nécessaires === composer require swiftmailer-bundle composer require symfony/translation composer require friendsofsymfony/user-bundle "~2.0" Une erreur apparaît à la fin de l'installation de ce dernier module mais c'est normal. === Création de l'entité User === Le code est ici très basique. On pourra rajouter des champs notamment avec la commande ''php bin/console make:entity'' en précisant l'entité User. === Configuration === Modifier le fichier security.yaml : security: encoders: FOS\UserBundle\Model\UserInterface: bcrypt role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: ROLE_ADMIN # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers providers: fos_userbundle: id: fos_user.user_provider.username firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false main: pattern: ^/ form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager logout: true anonymous: 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: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin/, role: ROLE_ADMIN } Ensuite il faut créer le fichier de configuration de FOSUser fos_user: db_driver: orm # other valid values are 'mongodb' and 'couchdb' firewall_name: main user_class: App\Entity\User from_email: address: "change@me" sender_name: "change@me" Et enfin ajouter un paramètre au fichier framework.yaml : framework: templating: engines: ['twig', 'php'] === Création du schéma === Après avoir éventuellement ajouté des champs à l'entité User, il faut créer ou mettre à jour la base de données : php bin/console make:migration php bin/console doctrine:migrations:migrate === Connexion via MyCentraleAssos === Pour rajouter une connexion via MyCA, il faut avoir un jeu de clés OAUTH_ID et OAUTH_SECRET. Il faut un module pour gérer la communication via le protocol OAuth2 : composer require adoy/oauth2 On va modifier le .env pour rajouter les attributs nécessaires : OAUTH_ID= OAUTH_SECRET= OAUTH_BASE=https://my.centrale-assos.fr Ensuite le fichier services.yaml pour rajouter ces paramètres d'environnement en parameter de symfony : parameters: locale: 'fr' oauth_id: '%env(OAUTH_ID)%' oauth_secret: '%env(OAUTH_SECRET)%' oauth_base: '%env(OAUTH_BASE)%' Enfin il faut créer un controller qui va gérer la connexion ! Si vous utilisez FOSUserBundle : getParameter('oauth_id'); $secret = $this->getParameter('oauth_secret'); $base = $this->getParameter('oauth_base'); $client = new \OAuth2\Client($id, $secret); if(!$request->query->has('code')){ $url = $client->getAuthenticationUrl($base.'/oauth/v2/auth', $this->generateUrl('user_login', [],UrlGeneratorInterface::ABSOLUTE_URL)); return $this->redirect($url); }else{ $params = ['code' => $request->query->get('code'), 'redirect_uri' => $this->generateUrl('user_login', [],UrlGeneratorInterface::ABSOLUTE_URL)]; $resp = $client->getAccessToken($base.'/oauth/v2/token', 'authorization_code', $params); if(isset($resp['result']) && isset($resp['result']['access_token'])){ $info = $resp['result']; $client->setAccessTokenType(\OAuth2\Client::ACCESS_TOKEN_BEARER); $client->setAccessToken($info['access_token']); $response = $client->fetch($base.'/api/user/me'); $data = $response['result']; $username = $data['username']; $user = $userManager->findUserByUsername($username); if($user === null){ // Création de l'utilisateur s'il n'existe pas $user = $userManager->createUser(); $user->setUsername($username); $user->setPlainPassword(sha1(uniqid())); $user->setEnabled(true); $user->setEmail($data['email']); $user->setNom($data['nom']); $user->setPrenom($data['prenom']); $userManager->updateUser($user); } // Connexion effective de l'utilisateur $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); $tokenStorage->setToken($token); $session->set('_security_main', serialize($token)); $event = new InteractiveLoginEvent($request, $token); $dispatcher->dispatch("security.interactive_login", $event); } // Redirection vers l'accueil return $this->redirectToRoute('default'); } } } Si vous n'utilisez pas FOS : isGranted('ROLE_USER')){ return $this->redirectToRoute('home'); } $id = $this->getParameter('oauth_id'); $secret = $this->getParameter('oauth_secret'); $base = $this->getParameter('oauth_base'); $client = new \OAuth2\Client($id, $secret); if(!$request->query->has('code')){ $url = $client->getAuthenticationUrl($base.'/oauth/v2/auth', $this->generateUrl('user_login', [],UrlGeneratorInterface::ABSOLUTE_URL)); return $this->redirect($url); }else{ $params = ['code' => $request->query->get('code'), 'redirect_uri' => $this->generateUrl('user_login', [],UrlGeneratorInterface::ABSOLUTE_URL)]; $resp = $client->getAccessToken($base.'/oauth/v2/token', 'authorization_code', $params); if(isset($resp['result']) && isset($resp['result']['access_token'])){ $info = $resp['result']; $client->setAccessTokenType(\OAuth2\Client::ACCESS_TOKEN_BEARER); $client->setAccessToken($info['access_token']); $response = $client->fetch($base.'/api/user/me'); $data = $response['result']; $username = $data['username']; $user = $this->getDoctrine()->getRepository(User::class)->findOneBy(['username'=>$username]); if($user === null){ // Création de l'utilisateur s'il n'existe pas $user = new User; $user->setUsername($username); $user->setPassword(sha1(uniqid())); $user->setEmail($data['email']); $user->setLastName($data['nom']); $user->setFirstName($data['prenom']); $manager->persist($user); $manager->flush(); } // Connexion effective de l'utilisateur $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); $tokenStorage->setToken($token); $session->set('_security_main', serialize($token)); $event = new InteractiveLoginEvent($request, $token); $dispatcher->dispatch("security.interactive_login", $event); } // Redirection vers l'accueil return $this->redirectToRoute('default'); } } }