Skip to content

Commit

Permalink
Remove googleAccount from user's relations
Browse files Browse the repository at this point in the history
  • Loading branch information
vokomarov committed Sep 1, 2024
1 parent 3daedbd commit 2bc2a8e
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 27 deletions.
6 changes: 5 additions & 1 deletion app/src/Controller/Profile/ProfileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Database\Currency;
use App\Database\GoogleAccount;
use App\Repository\CurrencyRepository;
use App\Repository\GoogleAccountRepository;
use App\Request\CheckNickNameRequest;
use App\Request\Profile\UpdateBasicRequest;
use App\Request\Profile\UpdateLocaleRequest;
Expand All @@ -33,6 +34,7 @@ public function __construct(
protected ResponseWrapper $response,
protected CurrencyRepository $currencyRepository,
protected UserOptionsService $userOptionsService,
protected GoogleAccountRepository $googleAccountRepository,
) {
parent::__construct($auth);
}
Expand Down Expand Up @@ -121,9 +123,11 @@ public function updateLocale(UpdateLocaleRequest $request): ResponseInterface
#[Route(route: '/profile/social', name: 'profile.social', methods: 'GET', group: 'auth')]
public function socialAccounts(): ResponseInterface
{
$googleAccount = $this->googleAccountRepository->findByUser($this->user);

return $this->response->json([
'data' => [
'google' => $this->user->googleAccount instanceof GoogleAccount
'google' => $googleAccount instanceof GoogleAccount
],
]);
}
Expand Down
3 changes: 0 additions & 3 deletions app/src/Database/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,6 @@ class User implements PasswordContainerInterface
#[ORM\Relation\BelongsTo(target: Currency::class, innerKey: 'default_currency_code', cascade: true, load: 'eager')]
private Currency $defaultCurrency;

#[ORM\Relation\HasOne(target: GoogleAccount::class, outerKey: 'user_id', nullable: true, cascade: false)]
public GoogleAccount|null $googleAccount = null;

#[ORM\Column(type: 'json', name: 'options', typecast: JsonTypecast::RULE)]
public array $options = [];

Expand Down
11 changes: 11 additions & 0 deletions app/src/Repository/GoogleAccountRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,22 @@

namespace App\Repository;

use App\Database\User;
use Cycle\ORM\Select\Repository;

/**
* @extends Repository<\App\Database\GoogleAccount>
*/
class GoogleAccountRepository extends Repository
{
/**
* @param \App\Database\User $user
* @return object|null
*/
public function findByUser(User $user): object|null
{
return $this->findOne([
'user_id' => $user->id,
]);
}
}
25 changes: 18 additions & 7 deletions app/src/Service/Auth/AuthService.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
namespace App\Service\Auth;

use App\Database\Currency;
use App\Database\GoogleAccount;
use App\Database\User;
use App\Repository\CurrencyRepository;
use App\Repository\UserRepository;
use App\Security\PasswordContainerInterface;
use App\Service\GoogleAccountService;
use App\Service\UserOptionsService;
use App\Service\UserService;
use Psr\Http\Message\ServerRequestInterface;
Expand All @@ -35,6 +37,7 @@ public function __construct(
protected UserOptionsService $userOptionsService,
protected CurrencyRepository $currencyRepository,
protected RefreshTokenService $refreshTokenService,
protected GoogleAccountService $googleAccountService,
protected EmailConfirmationService $emailConfirmationService,
) {
}
Expand Down Expand Up @@ -135,13 +138,6 @@ protected function createUser(User $user, string $locale = null): User

$this->userOptionsService->setLocale($user, $locale ?? $this->translator->getLocale());

if (($googleAccount = $user->googleAccount) !== null) {
// insert user first
$user->googleAccount = null;
$this->storeUser($user);
$user->googleAccount = $googleAccount;
}

$this->storeUser($user);

if (! $user->isEmailConfirmed) {
Expand All @@ -166,6 +162,21 @@ protected function storeUser(User $user): User
}
}

protected function storeGoogleAccount(GoogleAccount $googleAccount): GoogleAccount
{
try {
return $this->googleAccountService->store($googleAccount);
} catch (\Throwable $exception) {
$this->logger->error('Error while storing googleAccount', [
'error' => get_class($exception),
'message' => $exception->getMessage(),
'code' => $exception->getCode(),
]);

throw new \RuntimeException($exception->getMessage(), (int) $exception->getCode(), $exception);
}
}

protected function initiateEmailConfirmation(User $user): void
{
try {
Expand Down
38 changes: 22 additions & 16 deletions app/src/Service/Auth/GoogleAuthService.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
use App\Database\GoogleAccount;
use App\Database\User;
use App\Repository\CurrencyRepository;
use App\Repository\GoogleAccountRepository;
use App\Repository\UserRepository;
use App\Service\Auth\Exception\InvalidTokenException;
use App\Service\GoogleAccountService;
use App\Service\PhotoStorageService;
use App\Service\UserOptionsService;
use App\Service\UserService;
Expand All @@ -36,7 +38,9 @@ public function __construct(
protected CurrencyRepository $currencyRepository,
protected PhotoStorageService $photoStorageService,
protected RefreshTokenService $refreshTokenService,
protected GoogleAccountService $googleAccountService,
protected EmailConfirmationService $emailConfirmationService,
protected readonly GoogleAccountRepository $googleAccountRepository,
) {
parent::__construct(
$this->auth,
Expand All @@ -48,6 +52,7 @@ public function __construct(
$this->userOptionsService,
$this->currencyRepository,
$this->refreshTokenService,
$this->googleAccountService,
$this->emailConfirmationService,
);
}
Expand Down Expand Up @@ -126,36 +131,37 @@ public function loginOrRegister(string $idToken): Authentication
throw new InvalidTokenException($this->say('google_auth_account_not_verified'));
}

if (
$user instanceof User &&
$user->googleAccount !== null &&
$user->googleAccount->accountId !== (string) ($data['sub'] ?? '')
) {
$this->logger->error('Unable to attach Google Account to existing user, Google account ID is already attached and different from actual.', [
'data' => json_encode($data),
]);
if ($user instanceof User) {
$googleAccount = $this->googleAccountRepository->findByUser($user);

throw new InvalidTokenException($this->say('google_auth_email_already_claimed'));
}
if ($googleAccount instanceof GoogleAccount && $googleAccount->accountId !== (string) ($data['sub'] ?? '')) {
$this->logger->error('Unable to attach Google Account to existing user, Google account ID is already attached and different from actual.', [
'data' => json_encode($data),
]);

if ($user instanceof User) {
if ($user->googleAccount instanceof GoogleAccount) {
throw new InvalidTokenException($this->say('google_auth_email_already_claimed'));
}

if ($googleAccount instanceof GoogleAccount) {
// Update existing Google Account data
$user->googleAccount->setData($data);
$googleAccount->setData($data);
} else {
// attach existing user to the new Google Account
$user->googleAccount = $this->makeGoogleAccount($data);
$googleAccount = $this->makeGoogleAccount($user, $data);

if ($user->photo === null) {
$this->photoStorageService->queueDownloadProfilePhoto((int) $user->id, $data['picture']);
}
}

$this->storeUser($user);
$this->storeGoogleAccount($googleAccount);
} else {
// new user
$user = $this->makeUser($data);
$user = $this->createUser($user);
$googleAccount = $this->makeGoogleAccount($user, $data);
$this->storeGoogleAccount($googleAccount);
$this->photoStorageService->queueDownloadProfilePhoto((int) $user->id, $data['picture']);
}

Expand All @@ -171,14 +177,14 @@ protected function makeUser(array $data): User
$user->email = $data['email'] ?? null;
$user->defaultCurrencyCode = Currency::DEFAULT_CURRENCY_CODE;
$user->isEmailConfirmed = (bool) ($data['email_verified'] ?? false);
$user->googleAccount = $this->makeGoogleAccount($data);

return $user;
}

protected function makeGoogleAccount(array $data): GoogleAccount
protected function makeGoogleAccount(User $user, array $data): GoogleAccount
{
$account = new GoogleAccount();
$account->userId = $user->id;
$account->accountId = $data['sub'] ?? null;
$account->pictureUrl = $data['picture'] ?? null;
$account->setData($data);
Expand Down
24 changes: 24 additions & 0 deletions app/src/Service/GoogleAccountService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace App\Service;

use App\Database\GoogleAccount;
use Cycle\ORM\EntityManagerInterface;

class GoogleAccountService
{
public function __construct(
private readonly EntityManagerInterface $tr,
) {
}

public function store(GoogleAccount $googleAccount): GoogleAccount
{
$this->tr->persist($googleAccount);
$this->tr->run();

return $googleAccount;
}
}

0 comments on commit 2bc2a8e

Please sign in to comment.