<?php
namespace App\Controller;
use App\Entity\User;
use App\Security\AppAuthenticator;
use GuzzleHttp\Client;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\LinkedIn;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class LinkedinController extends AbstractController
{
private LinkedIn $login_provider;
private LinkedIn $register_provider;
public function __construct()
{
$this->login_provider = new LinkedIn([
'clientId' => $_ENV['LINKEDIN_ID'],
'clientSecret' => $_ENV['LINKEDIN_SECRET'],
'redirectUri' => $_ENV['LINKEDIN_CALLBACK']
]);
$this->register_provider = new LinkedIn([
'clientId' => $_ENV['LINKEDIN_ID'],
'clientSecret' => $_ENV['LINKEDIN_SECRET'],
'redirectUri' => $_ENV['LINKEDIN_CALLBACK_REGISTER']
]);
}
/**
* @Route("/linkedin-login", name="linkedin_login")
*/
public function linkedinLogin(): Response
{
$options = [
'scope' => ['openid', 'profile', 'email'] // array or string
];
$helper_url = $this->login_provider->getAuthorizationUrl($options);
return $this->redirect($helper_url);
}
/**
* @Route("/linkedin-save/register", name="linkedin_save")
*/
public function linkedinRegister(): Response
{
$options = [
'scope' => ['openid', 'profile', 'email'] // array or string
];
$helper_url = $this->register_provider->getAuthorizationUrl($options);
return $this->redirect($helper_url);
}
/**
* @Route("/linkedin-callback", name="linkedin_callback")
* @throws IdentityProviderException
*/
public function linkedinCallBack(
EntityManagerInterface $manager,
UserAuthenticatorInterface $userAuthenticator,
AppAuthenticator $authenticator,
Request $request,
HttpClientInterface $client
): Response {
//Récupérer le token
$token = $this->login_provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
try {
//Récupérer les informations de l'utilisateur
// Options de la requête
$options = [
'headers' => [
'Authorization' => 'Bearer ' . $token, // Ajout du jeton Bearer dans l'en-tête
'Content-Type' => 'application/json', // Spécification du type de contenu
],
];
// Exemple de requête GET avec les options spécifiées
$response = $client->request('GET', "https://api.linkedin.com/v2/userinfo", array_merge($options, [
'timeout' => 5,
]))->getContent();
$user = json_decode($response);
$email = $user->email;
//Vérifier si l'utilisateur existe dans la base des données
$user_exist = $manager->getRepository(User::class)->findOneBy(
[
'email' => $email
]
);
if ($user_exist) {
if (!empty($user->picture)) {
$urlPhoto = $this->downloadAndSaveAvatar($user->picture);
$user_exist->setPhoto($urlPhoto);
if ($user_exist->isFreelance()) {
$user_exist->getUniqueProfile()->setPhoto($urlPhoto);
}
}
return $userAuthenticator->authenticateUser(
$user_exist,
$authenticator,
$request
);
} else {
$this->addFlash('error-google', "Votre compte linkedIn n'est pas associé à cette application.\n Veuillez vous inscrire! ");
return $this->redirectToRoute('login');
}
} catch (\Throwable $th) {
//throw $th;
return new Response($th->getMessage());
}
}
/**
* @Route("/linkedin-callback-register", name="linkedin_callback_register")
*
* @throws IdentityProviderException
*/
public function linkedinCallBackRegister(
EntityManagerInterface $manager,
UserAuthenticatorInterface $userAuthenticator,
AppAuthenticator $authenticator,
Request $request,
HttpClientInterface $client
): Response {
//Récupérer le token
$token = $this->register_provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
try {
//Récupérer les informations de l'utilisateur
$options = [
'headers' => [
'Authorization' => 'Bearer ' . $token, // Ajout du jeton Bearer dans l'en-tête
'Content-Type' => 'application/json', // Spécification du type de contenu
],
];
$response = $client->request('GET', "https://api.linkedin.com/v2/userinfo", array_merge($options, [
'timeout' => 5,
]))->getContent();
$linkedinUser = json_decode($response);
$email = $linkedinUser->email;
//Vérifier si l'utilisateur existe dans la base des données
$user_exist = $manager->getRepository(User::class)->findOneBy(
[
'email' => $email
]
);
if ($user_exist) {
return $userAuthenticator->authenticateUser(
$user_exist,
$authenticator,
$request
);
} else {
$user = new User();
$user->setCreatedAt(new \DateTime());
$user->setRoles(['ROLE_FREELANCE']);
$user->setType('freelance');
$user->setPhone('');
// ADDED INFO
$user->setEmail($linkedinUser->email);
$user->setPassword('__LINKEDIN__AUTH__');
$user->setLastname($linkedinUser->family_name);
$user->setFirstname($linkedinUser->given_name);
$user->setGoogleSubId($linkedinUser->sub);
$user->setIsVerified(true);
if (!empty($linkedinUser->picture)) {
$urlPhoto = $this->downloadAndSaveAvatar($linkedinUser->picture);
// dd($urlPhoto);
$user->setPhoto($urlPhoto);
$user->getUniqueProfile()->setPhoto($urlPhoto);
}
$manager->persist($user);
$manager->flush();
$user->setPassword($user->getId() . '__LINKEDIN__AUTH__');
$manager->persist($user);
$manager->flush();
return $userAuthenticator->authenticateUser(
$user,
$authenticator,
$request
);
}
} catch (\Throwable $th) {
//throw $th;
return new Response($th->getMessage());
}
}
private function downloadAndSaveAvatar(string $imageUrl): ?string
{
$client = new Client();
$publicDir = $this->getParameter('avatar_directory') . '/';
try {
// Faire une requête GET pour télécharger l'image avec un timeout
$response = $client->get($imageUrl, [
'timeout' => 5,
'connect_timeout' => 2,
]);
$contentType = $response->getHeader('Content-Type')[0];
// Vérifier si c'est une image
if (strpos($contentType, 'image/') !== 0) {
throw new \Exception("Ce n'est pas une image valide.");
}
// Déterminer l'extension de l'image
$extension = explode('/', $contentType)[1]; // par exemple "jpeg" ou "png"
// Générer un nom unique pour l'image
$uniqueFileName = 'avatar-' . uniqid() . '.' . $extension;
// Chemin complet pour enregistrer l'image
$filePath = $publicDir . $uniqueFileName;
// Enregistrer l'image localement
file_put_contents($filePath, $response->getBody());
return $uniqueFileName; // Retourner le nom du fichier enregistré
} catch (\Exception $e) {
// Gérer l'erreur
return null;
}
}
}