Lines 100.00% 35 / 35
Methods 100.00% 7 / 7
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 supports 100.00% 1 / 1 100.00% 1 / 1 1
 authenticate 100.00% 8 / 8 100.00% 1 / 1 1
 getGoogleClient 100.00% 1 / 1 100.00% 1 / 1 1
 getUser 100.00% 11 / 11 100.00% 1 / 1 2
 onAuthenticationSuccess 100.00% 6 / 6 100.00% 1 / 1 2
 onAuthenticationFailure 100.00% 7 / 7 100.00% 1 / 1 1
24class GoogleAuthenticator extends AbstractAuthenticator
25{
26    use TargetPathTrait;
27
28    public function __construct(
29        private readonly ClientRegistry $clientRegistry,
30        private readonly EntityManagerInterface $entityManager,
31        private readonly UserRepository $userRepository,
32        private readonly UrlGeneratorInterface $urlGenerator,
33    ) {
34    }
35
36    #[\Override]
37    public function supports(Request $request): bool
38    {
39        return '/connect/google/check' === $request->getPathInfo();
40    }
41
42    /**
43     * @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
44     */
45    #[\Override]
46    public function authenticate(Request $request): Passport
47    {
48        $token = $this->getGoogleClient()->getAccessToken();
49
50        /** @var GoogleUser $googleUser */
51        $googleUser = $this->getGoogleClient()
52            ->fetchUserFromToken($token);
53
54        $user = $this->getUser($googleUser);
55
56        return new SelfValidatingPassport(
57            new UserBadge($user->getUserIdentifier()),
58            [new RememberMeBadge()],
59        );
60    }
61
62    private function getGoogleClient(): OAuth2ClientInterface
63    {
64        return $this->clientRegistry->getClient('google');
65    }
66
67    private function getUser(GoogleUser $googleUser): User
68    {
69        $user = $this->userRepository->findOneBy(
70            ['googleId' => $googleUser->getId()]
71        );
72
73        if (null !== $user) {
74            return $user;
75        }
76
77        // Link to existing account with same email, or register a new user
78        $user = $this->userRepository->findOneBy(['identifier' => $googleUser->getEmail()])
79            ?? new User()->setIdentifier((string) $googleUser->getEmail());
80
81        $user->setGoogleId((string) $googleUser->getId());
82
83        $this->entityManager->persist($user);
84        $this->entityManager->flush();
85
86        return $user;
87    }
88
89    #[\Override]
90    public function onAuthenticationSuccess(
91        Request $request,
92        TokenInterface $token,
93        string $firewallName
94    ): RedirectResponse {
95        if ($targetPath = $this->getTargetPath(
96            $request->getSession(),
97            $firewallName
98        )
99        ) {
100            return new RedirectResponse($targetPath);
101        }
102
103        return new RedirectResponse($this->urlGenerator->generate('app_default'));
104    }
105
106    #[\Override]
107    public function onAuthenticationFailure(
108        Request $request,
109        AuthenticationException $exception,
110    ): RedirectResponse {
111        $message = \strtr(
112            $exception->getMessageKey(),
113            $exception->getMessageData()
114        );
115
116        /**
117         * @var Session $session
118         */
119        $session = $request->getSession();
120        $session->getFlashBag()->add('danger', $message);
121
122        return new RedirectResponse($this->urlGenerator->generate('app_login'));
123    }
124}