diff --git a/src/Auth/Passwords/LaravelTwelveTokenRepository.php b/src/Auth/Passwords/LaravelTwelveTokenRepository.php new file mode 100644 index 0000000000..17b2891cc2 --- /dev/null +++ b/src/Auth/Passwords/LaravelTwelveTokenRepository.php @@ -0,0 +1,98 @@ +path = storage_path("statamic/password_resets/$table.yaml"); + } + + public function create(CanResetPasswordContract $user) + { + $email = $user->getEmailForPasswordReset(); + + $token = $this->createNewToken(); + + $this->insert($this->getPayload($email, $token)); + + return $token; + } + + protected function insert($payload) + { + $resets = $this->getResets(); + + $resets[$payload['email']] = [ + 'token' => $payload['token'], + 'created_at' => $payload['created_at']->timestamp, + ]; + + $this->putResets($resets); + } + + public function delete(CanResetPasswordContract $user) + { + $this->putResets( + $this->getResets()->forget($user->email()) + ); + } + + public function deleteExpired() + { + $this->putResets($this->getResets()->reject(function ($item, $email) { + return $this->tokenExpired($item['created_at']); + })); + } + + public function exists(CanResetPasswordContract $user, $token) + { + $record = $this->getResets()->get($user->email()); + + return $record && + ! $this->tokenExpired(Carbon::createFromTimestamp($record['created_at'], config('app.timezone'))) + && $this->hasher->check($token, $record['token']); + } + + public function recentlyCreatedToken(CanResetPasswordContract $user) + { + $record = $this->getResets()->get($user->email()); + + return $record && parent::tokenRecentlyCreated($record['created_at']); + } + + protected function getResets() + { + if (! $this->files->exists($this->path)) { + return collect(); + } + + return collect(YAML::parse($this->files->get($this->path))); + } + + protected function putResets($resets) + { + if (! $this->files->isDirectory($dir = dirname($this->path))) { + $this->files->makeDirectory($dir); + } + + $this->files->put($this->path, YAML::dump($resets->all())); + } +} diff --git a/src/Auth/Passwords/PasswordBrokerManager.php b/src/Auth/Passwords/PasswordBrokerManager.php index 59864a31c1..0267a1e2ac 100644 --- a/src/Auth/Passwords/PasswordBrokerManager.php +++ b/src/Auth/Passwords/PasswordBrokerManager.php @@ -15,7 +15,18 @@ protected function createTokenRepository(array $config) $key = base64_decode(substr($key, 7)); } - return new TokenRepository( + if (version_compare(app()->version(), '12', '<')) { + return new TokenRepository( + $this->app['files'], + $this->app['hash'], + $config['table'], + $key, + $config['expire'], + $config['throttle'] ?? 0 + ); + } + + return new LaravelTwelveTokenRepository( $this->app['files'], $this->app['hash'], $config['table'], diff --git a/src/Auth/Passwords/TokenRepository.php b/src/Auth/Passwords/TokenRepository.php index aa6e9e132b..0a717929fb 100644 --- a/src/Auth/Passwords/TokenRepository.php +++ b/src/Auth/Passwords/TokenRepository.php @@ -11,16 +11,20 @@ class TokenRepository extends DatabaseTokenRepository { + protected $files; + protected $hasher; + protected $hashKey; + protected $expires; protected $path; - public function __construct( - protected Filesystem $files, - protected HasherContract $hasher, - protected string $table, - protected string $hashKey, - protected int $expires = 3600, - protected int $throttle = 60 - ) { + public function __construct(Filesystem $files, HasherContract $hasher, $table, $hashKey, $expires = 60, $throttle = 60) + { + $this->files = $files; + $this->hasher = $hasher; + $this->hashKey = $hashKey; + $this->expires = $expires * 60; + $this->throttle = $throttle; + $this->path = storage_path("statamic/password_resets/$table.yaml"); }