From 2bc2a8ec798bef0c8e16a9f540583629e5840d1a Mon Sep 17 00:00:00 2001 From: vokomarov Date: Sun, 1 Sep 2024 15:37:22 +0300 Subject: [PATCH] Remove googleAccount from user's relations --- .../Controller/Profile/ProfileController.php | 6 ++- app/src/Database/User.php | 3 -- .../Repository/GoogleAccountRepository.php | 11 ++++++ app/src/Service/Auth/AuthService.php | 25 ++++++++---- app/src/Service/Auth/GoogleAuthService.php | 38 +++++++++++-------- app/src/Service/GoogleAccountService.php | 24 ++++++++++++ 6 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 app/src/Service/GoogleAccountService.php diff --git a/app/src/Controller/Profile/ProfileController.php b/app/src/Controller/Profile/ProfileController.php index 98b602f..36c0bd1 100644 --- a/app/src/Controller/Profile/ProfileController.php +++ b/app/src/Controller/Profile/ProfileController.php @@ -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; @@ -33,6 +34,7 @@ public function __construct( protected ResponseWrapper $response, protected CurrencyRepository $currencyRepository, protected UserOptionsService $userOptionsService, + protected GoogleAccountRepository $googleAccountRepository, ) { parent::__construct($auth); } @@ -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 ], ]); } diff --git a/app/src/Database/User.php b/app/src/Database/User.php index 85f91bc..a802b95 100644 --- a/app/src/Database/User.php +++ b/app/src/Database/User.php @@ -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 = []; diff --git a/app/src/Repository/GoogleAccountRepository.php b/app/src/Repository/GoogleAccountRepository.php index 839d242..7f9db78 100644 --- a/app/src/Repository/GoogleAccountRepository.php +++ b/app/src/Repository/GoogleAccountRepository.php @@ -4,6 +4,7 @@ namespace App\Repository; +use App\Database\User; use Cycle\ORM\Select\Repository; /** @@ -11,4 +12,14 @@ */ 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, + ]); + } } diff --git a/app/src/Service/Auth/AuthService.php b/app/src/Service/Auth/AuthService.php index ebe0315..a4f9f6e 100644 --- a/app/src/Service/Auth/AuthService.php +++ b/app/src/Service/Auth/AuthService.php @@ -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; @@ -35,6 +37,7 @@ public function __construct( protected UserOptionsService $userOptionsService, protected CurrencyRepository $currencyRepository, protected RefreshTokenService $refreshTokenService, + protected GoogleAccountService $googleAccountService, protected EmailConfirmationService $emailConfirmationService, ) { } @@ -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) { @@ -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 { diff --git a/app/src/Service/Auth/GoogleAuthService.php b/app/src/Service/Auth/GoogleAuthService.php index 795294f..5b4cf33 100644 --- a/app/src/Service/Auth/GoogleAuthService.php +++ b/app/src/Service/Auth/GoogleAuthService.php @@ -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; @@ -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, @@ -48,6 +52,7 @@ public function __construct( $this->userOptionsService, $this->currencyRepository, $this->refreshTokenService, + $this->googleAccountService, $this->emailConfirmationService, ); } @@ -126,25 +131,23 @@ 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']); @@ -152,10 +155,13 @@ public function loginOrRegister(string $idToken): Authentication } $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']); } @@ -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); diff --git a/app/src/Service/GoogleAccountService.php b/app/src/Service/GoogleAccountService.php new file mode 100644 index 0000000..4adeebf --- /dev/null +++ b/app/src/Service/GoogleAccountService.php @@ -0,0 +1,24 @@ +tr->persist($googleAccount); + $this->tr->run(); + + return $googleAccount; + } +}