Skip to content

Commit

Permalink
Merge pull request #31 from ThomasLdev/feat/00-rework-auth-process
Browse files Browse the repository at this point in the history
Issue 00 - rework google auth process
  • Loading branch information
ThomasLdev authored Apr 8, 2024
2 parents b4188ec + 89d983b commit 2605a6e
Show file tree
Hide file tree
Showing 18 changed files with 313 additions and 258 deletions.
2 changes: 0 additions & 2 deletions config/packages/google_apiclient.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,3 @@ services:
# Authentication with "OAuth 2.0" using Client ID & Secret
- [setClientId, ['%env(GOOGLE_CLIENT_ID)%']]
- [setClientSecret, ['%env(GOOGLE_CLIENT_SECRET)%']]
# Authentication with "OAuth 2.0" or "Service account" using JSON
- [setAuthConfig, ['%env(resolve:GOOGLE_AUTH_CONFIG)%']]
Binary file added public/icons/instabot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions src/Controller/BaseController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/**
* @author ThomasLdev
*/

declare(strict_types=1);

namespace App\Controller;

use App\Entity\User;
use App\Entity\UserSettings;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Contracts\Translation\TranslatorInterface;

class BaseController extends AbstractController
{
protected const INDEX_ROUTE = 'app_index';
protected const SETTINGS_ROUTE = 'app_settings';

public function __construct(
private readonly TranslatorInterface $translator,
) {
}

public function flashOnRedirect(string $type, string $message, string $route): RedirectResponse
{
$this->addFlash($type, $this->translator->trans($message));

return $this->redirectToRoute($route);
}

public function translateFlash(string $translateKey): string
{
return $this->translator->trans($translateKey);
}

public function getUserSettings(): ?UserSettings
{
/** @var User $user */
$user = $this->getUser();

return $user->getSettings();
}
}
58 changes: 14 additions & 44 deletions src/Controller/DriveFilesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,70 +8,40 @@

namespace App\Controller;

use App\Entity\User;
use App\Service\Google\Drive\GoogleDriveClientService;
use Google\Service\Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Exception;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Translation\TranslatorInterface;

class DriveFilesController extends AbstractController
class DriveFilesController extends BaseController
{
private const LOGIN_ROUTE = 'app_login';
private const SETTINGS_ROUTE = 'app_settings';

public function __construct(
private readonly TranslatorInterface $translator,
private readonly LoggerInterface $logger,
) {
}

/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Exception
*/
#[Route('/drive/files', name: 'app_drive_files')]
public function index(
GoogleDriveClientService $driveService,
): Response|RedirectResponse {
$user = $this->getUser();

if (false === $user instanceof User) {
return $this->redirectOnError('errors.controller.user.not_logged', self::LOGIN_ROUTE);
}
public function index(GoogleDriveClientService $driveService): Response|RedirectResponse
{
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');

$settings = $user->getSettings();
$settings = $this->getUserSettings();

if (null === $settings) {
return $this->redirectOnError('errors.controller.user.no_settings', self::SETTINGS_ROUTE);
return $this->flashOnRedirect(
'error',
'errors.controller.drive.no_settings',
self::SETTINGS_ROUTE
);
}

try {
$response = $driveService->getFilesForUser($settings);
} catch (Exception $e) {
$this->logger->error($e->getMessage());

return $this->redirectOnError('errors.drive.general', self::SETTINGS_ROUTE);
}
$response = $driveService->getFilesForUser($settings);

if (false === $response->getSuccess()) {
return $this->redirectOnError($response->getMessage(), self::SETTINGS_ROUTE);
return $this->flashOnRedirect('error', $response->getMessage(), self::SETTINGS_ROUTE);
}

return $this->render('drive_files/index.html.twig', [
'files' => $response->getFiles(),
]);
}

private function redirectOnError(string $message, string $route): RedirectResponse
{
$this->addFlash('error', $this->translator->trans($message));

return $this->redirectToRoute($route);
}
}
134 changes: 63 additions & 71 deletions src/Controller/GoogleAuthorizeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,41 @@

namespace App\Controller;

use App\Entity\User;
use App\Entity\UserSettings;
use App\Service\Google\GoogleClientService;
use App\Service\Security\EncryptionService;
use App\Service\Google\OAuth\GoogleOAuthTokenService;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Random\RandomException;
use SodiumException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;

class GoogleAuthorizeController extends AbstractController
class GoogleAuthorizeController extends BaseController
{
#[Route('/google/authorize-request', name: 'app_google_authorize_request')]
public function index(GoogleClientService $clientService): RedirectResponse
{
$user = $this->getUser();
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');

if (false === $user instanceof User) {
$this->addFlash('error', 'errors.controller.user.not_logged');
$settings = $this->getUserSettings();

return $this->redirectToRoute('app_index');
if (null === $settings) {
return $this->flashOnRedirect(
'error',
'errors.controller.drive.no_settings',
self::SETTINGS_ROUTE
);
}

/** @var UserSettings $settings */
$settings = $user->getSettings();

try {
$client = $clientService->getClientForUser($settings);
} catch (NotFoundExceptionInterface | ContainerExceptionInterface | Exception $e) {
$this->addFlash('error', 'errors.controller.google.authorization_failed');

return $this->redirectToRoute('app_settings');
}

if (null === $client) {
$this->addFlash('error', 'errors.controller.google.authorization_failed');

return $this->redirectToRoute('app_settings');
} catch (Exception $e) {
return $this->flashOnRedirect(
'error',
'errors.controller.google.authorization_failed',
BaseController::SETTINGS_ROUTE
);
}

return $this->redirect($client->createAuthUrl());
Expand All @@ -61,72 +53,72 @@ public function index(GoogleClientService $clientService): RedirectResponse
* @throws SodiumException
*/
#[Route('/google/authorize-response', name: 'app_google_authorize_response')]
public function response(
Request $request,
EncryptionService $tokenService,
EntityManagerInterface $entityManager
): RedirectResponse {
public function response(Request $request, GoogleOAuthTokenService $tokenService): RedirectResponse
{
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');

$settings = $this->getUserSettings();

if (null === $settings) {
return $this->flashOnRedirect(
'error',
'errors.controller.drive.no_settings',
self::SETTINGS_ROUTE
);
}

$authCode = $request->query->get('code');

if (false === is_string($authCode)) {
$this->addFlash('error', 'errors.controller.google.no_code');
return $this->flashOnRedirect(
'error',
'errors.controller.google.no_code',
BaseController::SETTINGS_ROUTE
);
}

/** @var string $authCode */
$response = $tokenService->storeAuthCodeForUser($settings, $authCode);

return $this->redirectToRoute('app_settings');
if (false === $response->getSuccess()) {
return $this->flashOnRedirect(
'error',
'errors.controller.google.authorization_failed',
BaseController::INDEX_ROUTE
);
}

return $this->storeAuthCodeForUser($authCode, $tokenService, $entityManager);
return $this->flashOnRedirect(
'success',
'errors.controller.google.authorization_success',
BaseController::INDEX_ROUTE
);
}

#[Route('/google/revoke-access', name: 'app_google_revoke_access')]
public function revokeAuthCodeForUser(EntityManagerInterface $entityManager): RedirectResponse
{
$user = $this->getUser();
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');

if (false === $user instanceof User) {
$this->addFlash('error', 'errors.controller.user.not_logged');
$settings = $this->getUserSettings();

return $this->redirectToRoute('app_index');
if (null === $settings) {
return $this->flashOnRedirect(
'error',
'errors.controller.drive.no_settings',
self::SETTINGS_ROUTE
);
}

/** @var UserSettings $settings */
$settings = $user->getSettings();

$settings->setGoogleDriveAuthCode(null);
$settings->setGoogleDriveToken(null);

$this->addFlash('success', 'form.update.token.revoke');

$entityManager->flush();

return $this->redirectToRoute('app_settings');
}

/**
* @throws RandomException
* @throws SodiumException
*/
private function storeAuthCodeForUser(
string $authCode,
EncryptionService $tokenService,
EntityManagerInterface $entityManager
): RedirectResponse {
$user = $this->getUser();

if (false === $user instanceof User) {
$this->addFlash('error', 'errors.controller.user.not_logged');

return $this->redirectToRoute('app_index');
}

/** @var UserSettings $settings */
$settings = $user->getSettings();

$settings->setGoogleDriveAuthCode($tokenService->encrypt($authCode));

$this->addFlash('success', 'form.update.token.granted');

$entityManager->flush();

return $this->redirectToRoute('app_settings');
return $this->flashOnRedirect(
'success',
'form.update.token.revoke',
BaseController::SETTINGS_ROUTE
);
}
}
3 changes: 1 addition & 2 deletions src/Controller/RegistrationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ public function register(
Request $request,
UserPasswordHasherInterface $userPasswordHasher,
EntityManagerInterface $entityManager
): Response
{
): Response {
$user = new User();
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
Expand Down
Loading

0 comments on commit 2605a6e

Please sign in to comment.