request = $request; $this->pdm = new PersistentDataManager(); $this->userConfirmationRepository = new UserConfirmationRepository(); } public function authorize(): bool { $user = $this->request->user(); return $user !== null; } public function getAccount(): IContent { /** * @var User $user */ $user = $this->request->user(); $data = ['user' => $user->toArray()]; return new HtmlContent('account/account', $data); } public function getGoogleAuthenticateRedirect(): IRedirect { /** * @var User $user */ $user = $this->request->user(); $state = bin2hex(random_bytes(16)); $this->request->session()->set('oauth_state', $state); $oAuth = new GoogleOAuth(new Request()); $url = $oAuth->getDialogUrl( $state, $this->request->getBase() . '/' . \Container::$routeCollection->getRoute('account.googleAuthenticate-action')->generateLink(), $user->getEmail() ); return new Redirect($url, IRedirect::TEMPORARY); } public function authenticateWithGoogle(): IContent { /** * @var User $user */ $user = $this->request->user(); if ($this->request->query('state') !== $this->request->session()->get('oauth_state')) { $data = ['success' => false]; return new HtmlContent('account/google_authenticate', $data); } $oAuth = new GoogleOAuth(new Request()); $tokenData = $oAuth->getToken($this->request->query('code'), $this->request->getBase() . '/' . \Container::$routeCollection->getRoute('account.googleAuthenticate-action')->generateLink()); if (!isset($tokenData['id_token'])) { $data = ['success' => false]; return new HtmlContent('account/google_authenticate', $data); } $jwtParser = new JwtParser($tokenData['id_token']); $userData = $jwtParser->getPayload(); if ($userData['sub'] !== $user->getGoogleSub()) { $data = ['success' => false, 'errorText' => 'This Google account is not linked to your account.']; return new HtmlContent('account/google_authenticate', $data); } $authenticatedWithGoogleUntil = new DateTime('+45 seconds'); $this->request->session()->set('authenticated_with_google_until', $authenticatedWithGoogleUntil); $data = ['success' => true, 'authenticatedWithGoogleUntil' => $authenticatedWithGoogleUntil]; return new HtmlContent('account/google_authenticate', $data); } public function getDeleteAccount(): IContent { /** * @var User $user */ $user = $this->request->user(); $data = ['user' => $user->toArray()]; return new HtmlContent('account/delete', $data); } public function saveAccount(): IContent { /** * @var User $user */ $user = $this->request->user(); if (!$this->confirmUserIdentity( $user, $this->request->session()->get('authenticated_with_google_until'), $this->request->post('password'), $error )) { $data = ['error' => ['errorText' => $error]]; return new JsonContent($data); } if (strlen($this->request->post('password_new')) > 0) { if (strlen($this->request->post('password_new')) < 6) { $data = ['error' => ['errorText' => 'The given new password is too short. Please choose a password that is at least 6 characters long!']]; return new JsonContent($data); } if ($this->request->post('password_new') !== $this->request->post('password_new_confirm')) { $data = ['error' => ['errorText' => 'The given new passwords do not match.']]; return new JsonContent($data); } $user->setPlainPassword($this->request->post('password_new')); } $this->pdm->saveToDb($user); $this->request->session()->delete('authenticated_with_google_until'); $data = ['success' => true]; return new JsonContent($data); } public function deleteAccount(): IContent { /** * @var User $user */ $user = $this->request->user(); if (!$this->confirmUserIdentity( $user, $this->request->session()->get('authenticated_with_google_until'), $this->request->post('password'), $error )) { $data = ['error' => ['errorText' => $error]]; return new JsonContent($data); } \Container::$dbConnection->startTransaction(); foreach ($this->userConfirmationRepository->getByUser($user) as $userConfirmation) { $this->pdm->deleteFromDb($userConfirmation); } $this->pdm->deleteFromDb($user); \Container::$dbConnection->commit(); $this->request->session()->delete('authenticated_with_google_until'); $data = ['success' => true]; return new JsonContent($data); } private function confirmUserIdentity(User $user, ?DateTime $authenticatedWithGoogleUntil, ?string $password, &$error): bool { if ($authenticatedWithGoogleUntil !== null && $authenticatedWithGoogleUntil > new DateTime()) { return true; } if ($password !== null) { if ($user->checkPassword($password)) { return true; } $error = 'The given current password is wrong.'; return false; } $error = 'Could not confirm your identity. Please try again!'; return false; } }