1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LaravelでPasswordBrokerを拡張してパスワードリセットに権限チェックを追加する

Last updated at Posted at 2022-04-26

実現したいこと(抽象)

Laravelが提供しているFacadeで呼び出すクラスを差し替えたい。
処理の一部だけを変更したいのでLaravelが提供するクラスをオーバーライドしたい。

実現したいこと(具体)

Laravel Breezeを利用している。
自動生成されたパスワードリセット画面にてメールアドレスを入力して送信すると、存在チェックしてパスワードリセット用のメールを送信する。
存在チェックだけではなくて、権限チェックを追加して特定のユーザ権限の場合はエラー(メールアドレス誤りと同様に存在チェックエラー)としたい。

対応方法

app.phpでプロバイダを独自拡張のプロバイダに差し替え。

app.php
'providers' => [
        //Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        App\Providers\PasswordResetServiceProvider::class,

独自拡張のプロバイダを作成。

extends PasswordsPasswordResetServiceProviderしているので、オーバーライドしたいメソッドのみ記載。
registerPasswordBrokerメソッドのPasswordBrokerManagerを独自拡張のものに差し替える(use App\Extensions\Auth\Passwords\PasswordBrokerManagerを利用する)

App\Providers\PasswordResetServiceProvider.php
<?php

namespace App\Providers;

use App\Extensions\Auth\Passwords\PasswordBrokerManager;
use Illuminate\Auth\Passwords\PasswordResetServiceProvider as PasswordsPasswordResetServiceProvider;

class PasswordResetServiceProvider extends PasswordsPasswordResetServiceProvider
{
    /**
     * Register the password broker instance.
     *
     * @return void
     */
    protected function registerPasswordBroker()
    {
        $this->app->singleton('auth.password', function ($app) {
            return new PasswordBrokerManager($app);
        });

        $this->app->bind('auth.password.broker', function ($app) {
            return $app->make('auth.password')->broker();
        });
    }
}

プロバイダから呼び出される拡張PasswordBrokerManagerを作成

extendsするのでオーバーライドしたいメソッドのみ記載。
今回は独自のPasswordBrokerを使いたいのでresolveメソッドのみ書き換え。

App\Extensions\Auth\Passwords\PasswordBrokerManager.php
<?php

namespace App\Extensions\Auth\Passwords;

use Illuminate\Auth\Passwords\PasswordBrokerManager as PasswordsPasswordBrokerManager;
use InvalidArgumentException;

/**
 * @mixin \Illuminate\Contracts\Auth\PasswordBroker
 */
class PasswordBrokerManager extends PasswordsPasswordBrokerManager
{
    /**
     * Resolve the given broker.
     *
     * @param  string  $name
     * @return \Illuminate\Contracts\Auth\PasswordBroker
     *
     * @throws \InvalidArgumentException
     */
    protected function resolve($name)
    {
        $config = $this->getConfig($name);

        if (is_null($config)) {
            throw new InvalidArgumentException("Password resetter [{$name}] is not defined.");
        }

        // App\Extensions\Auth\Passwords配下のものでnewする
        return new PasswordBroker(
            $this->createTokenRepository($config),
            $this->app['auth']->createUserProvider($config['provider'] ?? null)
        );
    }
}

権限チェックを行う拡張PasswordBrokerを作成

やっと権限チェックを入れたいPasswordBroker。
ここも今までと同じようにextends PasswordsPasswordBrokerして、特定のメソッドのみオーバーライドする。
今回はsendResetLinkメソッドに権限チェックをして問題なければ、親のsendResetLinkを呼ぶ。(parent::sendResetLink

<?php

namespace App\Extensions\Auth\Passwords;

use Closure;
use Illuminate\Auth\Passwords\PasswordBroker as PasswordsPasswordBroker;

class PasswordBroker extends PasswordsPasswordBroker
{
    public function sendResetLink(array $credentials, Closure $callback = null)
    {
        $user = $this->getUser($credentials);

        // ここに権限チェックを追加
        if (is_null($user) || $user->is_xxx) {
            return static::INVALID_USER;
        }

        return parent::sendResetLink($credentials, $callback);
    }
}

参考

以下、ありがとうございます!

メール送信で同じようなことをしている。
https://stackoverflow.com/questions/39102483/add-a-new-transport-driver-to-laravels-mailer/39104567#39104567

ヘルパ関数で同じようなことをしている。
Extensionsディレクトリを作るのが自分もしっくりきた。
https://qiita.com/kd9951/items/46ef3559009ee575ea7d

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?