. * * This software is licensed under the terms of the MIT license. * https://opensource.org/licenses/MIT */ namespace Pterodactyl\Services\Users; use Pterodactyl\Models\User; use PragmaRX\Google2FA\Google2FA; use Illuminate\Support\Collection; use Illuminate\Contracts\Encryption\Encrypter; use Pterodactyl\Contracts\Repository\UserRepositoryInterface; class TwoFactorSetupService { /** * @var \Illuminate\Contracts\Encryption\Encrypter */ private $encrypter; /** * @var \PragmaRX\Google2FA\Google2FA */ private $google2FA; /** * @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface */ private $repository; /** * TwoFactorSetupService constructor. * * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter * @param \PragmaRX\Google2FA\Google2FA $google2FA * @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $repository */ public function __construct( Encrypter $encrypter, Google2FA $google2FA, UserRepositoryInterface $repository ) { $this->encrypter = $encrypter; $this->google2FA = $google2FA; $this->repository = $repository; } /** * Generate a 2FA token and store it in the database before returning the * QR code image. * * @param \Pterodactyl\Models\User $user * @return \Illuminate\Support\Collection * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ public function handle(User $user): Collection { $secret = $this->google2FA->generateSecretKey(config('pterodactyl.auth.2fa.bytes')); $image = $this->google2FA->getQRCodeGoogleUrl(config('app.name'), $user->email, $secret); $this->repository->withoutFreshModel()->update($user->id, [ 'totp_secret' => $this->encrypter->encrypt($secret), ]); return new Collection([ 'image' => $image, 'secret' => $secret, ]); } }