Slide 1

Slide 1 text

Laravel のメール認証の 内部実装を掘り下げる 2021.03.27 PHPerKaigi 2021 株式会社 M&A クラウド 濱⽥晃輔 @ hamakou108

Slide 2

Slide 2 text

⾃⼰紹介 濱⽥晃輔 ( ) 株式会社M&A クラウド Web エンジニア PHP, Laravel TypeScript, Vue.js, Nuxt.js AWS Vim @hamakou108

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

このスライドで話すこと メール認証の仕組みと構成要素 Laravel を使ったメール認証の実装⽅法 フレームワークの内部実装を理解して拡張する

Slide 7

Slide 7 text

このスライドで話さないこと メール認証のセキュリティ上の利点や⽋点 Laravel の基本的な機能の説明 Service Container, Service Provider Authentication, Authorization Middleware Routing Eloquent, Query Builder Notifications etc. トークンの⽣成ロジックなどの実装の詳細部分

Slide 8

Slide 8 text

メール認証の仕組みとその構成要素

Slide 9

Slide 9 text

メール認証とは ⼊⼒・登録されたメールアドレスを使った認証⽅法 ⼀時的に有効なトークンつき URL を記載したメールを送信し、その URL の閲 覧を以って本⼈性を担保する 他⼈のメールアドレスを⽤いた成りすましのリスクを下げる

Slide 10

Slide 10 text

シーケンス図で構成要素を洗う

Slide 11

Slide 11 text

シーケンス図で構成要素を洗う

Slide 12

Slide 12 text

シーケンス図で構成要素を洗う

Slide 13

Slide 13 text

シーケンス図で構成要素を洗う

Slide 14

Slide 14 text

その他の構成要素 認証 URL (トークン)を⽣成する ユーザーの認証情報を埋め込む トークンの有効期限を埋め込む 改ざん防⽌のため署名を埋め込む 認証 URL (トークン)へのリクエストを検証する 認証メールの再送機能を⽤意する

Slide 15

Slide 15 text

まるっと実装するのは結構⼤変そう🥺

Slide 16

Slide 16 text

Laravel を使ったメール認証の実装⽅法

Slide 17

Slide 17 text

Laravel の利⽤者がやること App User (App\Models\User) に MustVerifyEmail インターフェースを実装させる 本⼈認証が必要なページの Routing を Middleware で保護する Starter kits で Routing や Controller や view などを⽣成する

Slide 18

Slide 18 text

App User App\Models\User MustVerifyEmail を実装する = メール認証の有効化 ユーザー登録時に認証メールを送信する 認証 URL へのリクエストを検証する 認証⽇時を保存する ユーザー認証済みかどうかを検証する use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements MustVerifyEmail { use Notifiable; // ... } 1 2 3 4 5 6 7 8 9

Slide 19

Slide 19 text

App User App\Models\User MustVerifyEmail を実装する = メール認証の有効化 ユーザー登録時に認証メールを送信する 認証 URL へのリクエストを検証する 認証⽇時を保存する ユーザー認証済みかどうかを検証する use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements MustVerifyEmail { use Notifiable; // ... } 1 2 3 4 5 6 7 8 9 class User extends Authenticatable implements MustVerifyEmail use Illuminate\Contracts\Auth\MustVerifyEmail; 1 use Illuminate\Foundation\Auth\User as Authenticatable; 2 3 4 { 5 use Notifiable; 6 7 // ... 8 } 9

Slide 20

Slide 20 text

Routing の保護 Kernel の $routeMiddleware に verified という名前で登録されている。 Route::get('profile', function () { // Only verified users may enter... })->middleware('verified'); 1 2 3

Slide 21

Slide 21 text

Starter kits (Laravel Breeze) を使うと さらに実装量が減る ├── app │ ├── Models │ ├── Http │ │ ├── Controllers │ │ └── Middleware │ └── Providers ├── routes ├── resources │ ├── css │ ├── js │ └── views ├── database │ └── migrations └── tests 1 2 3 4 5 6 7 8 9 10 11 12 13 14

Slide 22

Slide 22 text

Starter kits (Laravel Breeze) を使うと さらに実装量が減る ├── app │ ├── Models │ ├── Http │ │ ├── Controllers │ │ └── Middleware │ └── Providers ├── routes ├── resources │ ├── css │ ├── js │ └── views ├── database │ └── migrations └── tests 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ├── app │ ├── Models │ ├── Http │ │ ├── Controllers ├── routes ├── resources │ ├── css │ ├── js │ └── views └── tests 1 2 3 4 │ │ └── Middleware 5 │ └── Providers 6 7 8 9 10 11 ├── database 12 │ └── migrations 13 14

Slide 23

Slide 23 text

Starter kits (Laravel Breeze) を使うと さらに実装量が減る ├── app │ ├── Models │ ├── Http │ │ ├── Controllers │ │ └── Middleware │ └── Providers ├── routes ├── resources │ ├── css │ ├── js │ └── views ├── database │ └── migrations └── tests 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ├── app │ ├── Models │ ├── Http │ │ ├── Controllers ├── routes ├── resources │ ├── css │ ├── js │ └── views └── tests 1 2 3 4 │ │ └── Middleware 5 │ └── Providers 6 7 8 9 10 11 ├── database 12 │ └── migrations 13 14 ├── app │ ├── Models ├── routes 1 2 │ ├── Http 3 │ │ ├── Controllers 4 │ │ └── Middleware 5 │ └── Providers 6 7 ├── resources 8 │ ├── css 9 │ ├── js 10 │ └── views 11 ├── database 12 │ └── migrations 13 └── tests 14

Slide 24

Slide 24 text

Starter kits (Laravel Breeze) を使うと さらに実装量が減る ├── app │ ├── Models <- MustVerifyEmail を実装するだけ ├── routes <- middleware('verified') を追加するだけ 1 2 │ ├── Http 3 │ │ ├── Controllers 4 │ │ └── Middleware 5 │ └── Providers 6 7 ├── resources 8 │ ├── css 9 │ ├── js 10 │ └── views 11 ├── database 12 │ └── migrations 13 └── tests 14

Slide 25

Slide 25 text

Laravel の機能やツールを活⽤すれば 少ない⼿数でメール認証を実装できる 😃

Slide 26

Slide 26 text

フレームワークの内部実装を理解して拡張する

Slide 27

Slide 27 text

Laravel のメール認証は便利だが ... フレームワーク内部で何をしているかよく分からない ドキュメントには必要最低限の拡張⽅法しか書かれていない 例えば RDB を NoSQL に差し替えたい場合はどうする?

Slide 28

Slide 28 text

App User (再掲) App\Models\User use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements MustVerifyEmail { use Notifiable; // ... } 1 2 3 4 5 6 7 8 9

Slide 29

Slide 29 text

依存先が⾒えるように書き直してみる Auth 関連の Contract とトレイト、 Eloquent Model 、 Notifiable に依存してい る use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Notifiable, Authenticatable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Slide 30

Slide 30 text

依存先が⾒えるように書き直してみる Auth 関連の Contract とトレイト、 Eloquent Model 、 Notifiable に依存してい る use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Notifiable, Authenticatable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Database\Eloquent\Model; 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 class User extends Model implements 12 13 14 15 16 { 17 use Notifiable, 18 19 20 21 22 } 23

Slide 31

Slide 31 text

依存先が⾒えるように書き直してみる Auth 関連の Contract とトレイト、 Eloquent Model 、 Notifiable に依存してい る use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Notifiable, Authenticatable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract Authenticatable use Illuminate\Auth\Authenticatable; 1 use Illuminate\Auth\MustVerifyEmail; 2 use Illuminate\Auth\Passwords\CanResetPassword; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Database\Eloquent\Model; 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 class User extends Model implements 12 13 14 15 16 { 17 use Notifiable, 18 19 use Illuminate\Database\Eloquent\Model; class User extends Model implements use Illuminate\Auth\Authenticatable; 1 use Illuminate\Auth\MustVerifyEmail; 2 use Illuminate\Auth\Passwords\CanResetPassword; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 12 AuthenticatableContract, 13 AuthorizableContract, 14 CanResetPasswordContract, 15 MustVerifyEmailContract 16 { 17 use Notifiable, 18 Authenticatable, 19

Slide 32

Slide 32 text

依存先が⾒えるように書き直してみる Auth 関連の Contract とトレイト、 Eloquent Model 、 Notifiable に依存してい る use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Notifiable, Authenticatable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract Authenticatable use Illuminate\Auth\Authenticatable; 1 use Illuminate\Auth\MustVerifyEmail; 2 use Illuminate\Auth\Passwords\CanResetPassword; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Database\Eloquent\Model; 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 class User extends Model implements 12 13 14 15 16 { 17 use Notifiable, 18 19 use Illuminate\Database\Eloquent\Model; class User extends Model implements use Illuminate\Auth\Authenticatable; 1 use Illuminate\Auth\MustVerifyEmail; 2 use Illuminate\Auth\Passwords\CanResetPassword; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 12 AuthenticatableContract, 13 AuthorizableContract, 14 CanResetPasswordContract, 15 MustVerifyEmailContract 16 { 17 use Notifiable, 18 Authenticatable 19 use Illuminate\Notifications\Notifiable; use Notifiable, use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Database\Eloquent\Model; 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 10 11 class User extends Model implements 12 AuthenticatableContract, 13 AuthorizableContract, 14 CanResetPasswordContract, 15 MustVerifyEmailContract 16 { 17 18 Authenticatable, 19 Authorizable, 20 CanResetPassword, 21 MustVerifyEmail; 22 } 23

Slide 33

Slide 33 text

Auth 関連のトレイトの依存先 Illuminate\Auth\MustVerifyEmail Auth 関連の機能は App User を通して Eloquent と Notifiable に複雑に依存して いる trait MustVerifyEmail { /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } // ... /** * Send the email verification notification. * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Slide 34

Slide 34 text

Auth 関連のトレイトの依存先 Illuminate\Auth\MustVerifyEmail Auth 関連の機能は App User を通して Eloquent と Notifiable に複雑に依存して いる trait MustVerifyEmail { /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } // ... /** * Send the email verification notification. * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } trait MustVerifyEmail 1 { 2 3 4 5 6 7 8 9 10 11 12 13 14 // ... 15 16 /** 17 * Send the email verification notification. 18 * 19

Slide 35

Slide 35 text

Auth 関連のトレイトの依存先 Illuminate\Auth\MustVerifyEmail Auth 関連の機能は App User を通して Eloquent と Notifiable に複雑に依存して いる trait MustVerifyEmail { /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } // ... /** * Send the email verification notification. * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } trait MustVerifyEmail 1 { 2 3 4 5 6 7 8 9 10 11 12 13 14 // ... 15 16 /** 17 * Send the email verification notification. 18 * 19 /** * Send the email verification notification. * * @return void */ public function sendEmailVerificationNotification() { $this->notify(new VerifyEmail); } return $this->forceFill([ 10 'email_verified_at' => $this->freshTimestamp(), 11 ])->save(); 12 } 13 14 // ... 15 16 17 18 19 20 21 22 23 24 25 26 // ... 27 } 28

Slide 36

Slide 36 text

App User の責務が多すぎる Auth 系の機能を使うための I/F を提供する DB を通して認証情報を取得、保存する (=> Eloquent Model) ユーザーにメールを送信する (=> Notifiable)

Slide 37

Slide 37 text

App User の責務が多すぎる Auth 系の機能を使うための I/F を提供する DB を通して認証情報を取得、保存する (=> Eloquent Model) ユーザーにメールを送信する (=> Notifiable)

Slide 38

Slide 38 text

Repository パターンを利⽤して App User の責務を切り離す

Slide 39

Slide 39 text

クラス図(変更前)

Slide 40

Slide 40 text

クラス図(変更後)

Slide 41

Slide 41 text

⚠ この先、幾つかの User が出てきます 呼称 役割 App User 認証に⽤いる I/F を提供する Domain User ドメインのコアロジックを提供する Eloquent User User を永続化するための機能を提供する Notifiable User User に通知を送るための機能を提供する ※ 公式の呼称ではありません。

Slide 42

Slide 42 text

Domain Repository Domain\User\UserRepository interface UserRepository { public function markEmailAsVerified(UserId $id): bool; // ... } 1 2 3 4 5 6

Slide 43

Slide 43 text

Infra Repository Infra\Repository\Eloquent\UserRepository use Domain\User\UserRepository as UserRepositoryInterface; use Infra\Model\Eloquent\User as UserModel; class UserRepository implements UserRepositoryInterface { public function markEmailAsVerified(UserId $id): bool { return UserModel::where('id', $id->rawValue()) ->whereNull('email_verified_at') ->update([ 'email_verified_at' => Date::now(), ]); } // ... } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Slide 44

Slide 44 text

Infra Repository Infra\Repository\Eloquent\UserRepository use Domain\User\UserRepository as UserRepositoryInterface; use Infra\Model\Eloquent\User as UserModel; class UserRepository implements UserRepositoryInterface { public function markEmailAsVerified(UserId $id): bool { return UserModel::where('id', $id->rawValue()) ->whereNull('email_verified_at') ->update([ 'email_verified_at' => Date::now(), ]); } // ... } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class UserRepository implements UserRepositoryInterface use Domain\User\UserRepository as UserRepositoryInterface; 1 use Infra\Model\Eloquent\User as UserModel; 2 3 4 { 5 public function markEmailAsVerified(UserId $id): bool 6 { 7 return UserModel::where('id', $id->rawValue()) 8 ->whereNull('email_verified_at') 9 ->update([ 10 'email_verified_at' => Date::now(), 11 ]); 12 } 13 14 // ... 15 } 16

Slide 45

Slide 45 text

Infra Repository Infra\Repository\Eloquent\UserRepository use Domain\User\UserRepository as UserRepositoryInterface; use Infra\Model\Eloquent\User as UserModel; class UserRepository implements UserRepositoryInterface { public function markEmailAsVerified(UserId $id): bool { return UserModel::where('id', $id->rawValue()) ->whereNull('email_verified_at') ->update([ 'email_verified_at' => Date::now(), ]); } // ... } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class UserRepository implements UserRepositoryInterface use Domain\User\UserRepository as UserRepositoryInterface; 1 use Infra\Model\Eloquent\User as UserModel; 2 3 4 { 5 public function markEmailAsVerified(UserId $id): bool 6 { 7 return UserModel::where('id', $id->rawValue()) 8 ->whereNull('email_verified_at') 9 ->update([ 10 'email_verified_at' => Date::now(), 11 ]); 12 } 13 14 // ... 15 } 16 public function markEmailAsVerified(UserId $id): bool { return UserModel::where('id', $id->rawValue()) ->whereNull('email_verified_at') ->update([ 'email_verified_at' => Date::now(), ]); } use Domain\User\UserRepository as UserRepositoryInterface; 1 use Infra\Model\Eloquent\User as UserModel; 2 3 class UserRepository implements UserRepositoryInterface 4 { 5 6 7 8 9 10 11 12 13 14 // ... 15 } 16

Slide 46

Slide 46 text

RepositoryServiceProvider App\Providers\RepositoryServiceProvider インフラが変わる場合は Infra の UserRepository を差し替えれば良いだけにな った! use Domain\User\UserRepository; use Infra\Repository\Eloquent\UserRepository as EloquentUserRepository; class RepositoryServiceProvider extends ServiceProvider { public function register() { $this->app->bind( UserRepository::class, EloquentUserRepository::class ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13

Slide 47

Slide 47 text

RepositoryServiceProvider App\Providers\RepositoryServiceProvider インフラが変わる場合は Infra の UserRepository を差し替えれば良いだけにな った! use Domain\User\UserRepository; use Infra\Repository\Eloquent\UserRepository as EloquentUserRepository; class RepositoryServiceProvider extends ServiceProvider { public function register() { $this->app->bind( UserRepository::class, EloquentUserRepository::class ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 $this->app->bind( UserRepository::class, EloquentUserRepository::class ); use Domain\User\UserRepository; 1 use Infra\Repository\Eloquent\UserRepository as EloquentUserRepository; 2 3 class RepositoryServiceProvider extends ServiceProvider 4 { 5 public function register() 6 { 7 8 9 10 11 } 12 } 13

Slide 48

Slide 48 text

Domain Notifier Domain\User\UserNotifier interface UserNotifier { public function sendEmailVerificationNotification( User $user, string $url ): void; } 1 2 3 4 5 6 7

Slide 49

Slide 49 text

Infra Notifier Infra\Notifier\Illuminate\UserNotifier use Domain\User\User; use Domain\User\UserNotifier as UserNotifierInterface; use Illuminate\Auth\Notifications\VerifyEmail; use Infra\Notifiable\User as NotifiableUser; use Infra\Notifications\VerifyEmail; class UserNotifier implements UserNotifierInterface { private Dispatcher $dispatcher; public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function sendEmailVerificationNotification( User $user, string $url ): void { $this >dispatcher >send( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Slide 50

Slide 50 text

Infra Notifier Infra\Notifier\Illuminate\UserNotifier use Domain\User\User; use Domain\User\UserNotifier as UserNotifierInterface; use Illuminate\Auth\Notifications\VerifyEmail; use Infra\Notifiable\User as NotifiableUser; use Infra\Notifications\VerifyEmail; class UserNotifier implements UserNotifierInterface { private Dispatcher $dispatcher; public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function sendEmailVerificationNotification( User $user, string $url ): void { $this >dispatcher >send( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class UserNotifier implements UserNotifierInterface use Domain\User\User; 1 use Domain\User\UserNotifier as UserNotifierInterface; 2 use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 7 { 8 private Dispatcher $dispatcher; 9 10 public function __construct(Dispatcher $dispatcher) { 11 $this->dispatcher = $dispatcher; 12 } 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this >dispatcher >send( 19

Slide 51

Slide 51 text

Infra Notifier Infra\Notifier\Illuminate\UserNotifier use Domain\User\User; use Domain\User\UserNotifier as UserNotifierInterface; use Illuminate\Auth\Notifications\VerifyEmail; use Infra\Notifiable\User as NotifiableUser; use Infra\Notifications\VerifyEmail; class UserNotifier implements UserNotifierInterface { private Dispatcher $dispatcher; public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function sendEmailVerificationNotification( User $user, string $url ): void { $this >dispatcher >send( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class UserNotifier implements UserNotifierInterface use Domain\User\User; 1 use Domain\User\UserNotifier as UserNotifierInterface; 2 use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 7 { 8 private Dispatcher $dispatcher; 9 10 public function __construct(Dispatcher $dispatcher) { 11 $this->dispatcher = $dispatcher; 12 } 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this >dispatcher >send( 19 public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 class UserNotifier implements UserNotifierInterface 7 { 8 private Dispatcher $dispatcher; 9 10 11 12 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this->dispatcher->send( 19 new NotifiableUser($user), 20 new VerifyEmail($url) 21

Slide 52

Slide 52 text

Infra Notifier Infra\Notifier\Illuminate\UserNotifier use Domain\User\User; use Domain\User\UserNotifier as UserNotifierInterface; use Illuminate\Auth\Notifications\VerifyEmail; use Infra\Notifiable\User as NotifiableUser; use Infra\Notifications\VerifyEmail; class UserNotifier implements UserNotifierInterface { private Dispatcher $dispatcher; public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function sendEmailVerificationNotification( User $user, string $url ): void { $this >dispatcher >send( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class UserNotifier implements UserNotifierInterface use Domain\User\User; 1 use Domain\User\UserNotifier as UserNotifierInterface; 2 use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 7 { 8 private Dispatcher $dispatcher; 9 10 public function __construct(Dispatcher $dispatcher) { 11 $this->dispatcher = $dispatcher; 12 } 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this >dispatcher >send( 19 public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } use Domain\User\User; 1 use Domain\User\UserNotifier as UserNotifierInterface; 2 use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 class UserNotifier implements UserNotifierInterface 7 { 8 private Dispatcher $dispatcher; 9 10 11 12 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this >dispatcher >send( 19 public function sendEmailVerificationNotification( User $user, string $url ): void { $this->dispatcher->send( new NotifiableUser($user), new VerifyEmail($url) ); } 6 class UserNotifier implements UserNotifierInterface 7 { 8 private Dispatcher $dispatcher; 9 10 public function __construct(Dispatcher $dispatcher) { 11 $this->dispatcher = $dispatcher; 12 } 13 14 15 16 17 18 19 20 21 22 23 } 24

Slide 53

Slide 53 text

Notifiable Infra\Notifiable\User use Domain\User\User as DomainUser; use Illuminate\Notifications\Notifiable; class User { use Notifiable; private DomainUser $user; public function __construct(DomainUser $user) { $this->user = $user; } public function routeNotificationForMail() { return $this->user->getRawEmail(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Slide 54

Slide 54 text

Notifiable Infra\Notifiable\User use Domain\User\User as DomainUser; use Illuminate\Notifications\Notifiable; class User { use Notifiable; private DomainUser $user; public function __construct(DomainUser $user) { $this->user = $user; } public function routeNotificationForMail() { return $this->user->getRawEmail(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use Notifiable; use Domain\User\User as DomainUser; 1 use Illuminate\Notifications\Notifiable; 2 3 class User 4 { 5 6 7 private DomainUser $user; 8 9 public function __construct(DomainUser $user) 10 { 11 $this->user = $user; 12 } 13 14 public function routeNotificationForMail() 15 { 16 return $this->user->getRawEmail(); 17 } 18 } 19

Slide 55

Slide 55 text

Notification Infra\Notifications\VerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; class VerifyEmail extends IlluminateVerifyEmail { private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Slide 56

Slide 56 text

Notification Infra\Notifications\VerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; class VerifyEmail extends IlluminateVerifyEmail { private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class VerifyEmail extends IlluminateVerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 3 { 4 private string $verificationUrl; 5 6 public function __construct(string $verificationUrl) 7 { 8 $this->verificationUrl = $verificationUrl; 9 } 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19

Slide 57

Slide 57 text

Notification Infra\Notifications\VerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; class VerifyEmail extends IlluminateVerifyEmail { private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class VerifyEmail extends IlluminateVerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 3 { 4 private string $verificationUrl; 5 6 public function __construct(string $verificationUrl) 7 { 8 $this->verificationUrl = $verificationUrl; 9 } 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19 private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 class VerifyEmail extends IlluminateVerifyEmail 3 { 4 5 6 7 8 9 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19

Slide 58

Slide 58 text

Notification Infra\Notifications\VerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; class VerifyEmail extends IlluminateVerifyEmail { private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class VerifyEmail extends IlluminateVerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 3 { 4 private string $verificationUrl; 5 6 public function __construct(string $verificationUrl) 7 { 8 $this->verificationUrl = $verificationUrl; 9 } 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19 private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 class VerifyEmail extends IlluminateVerifyEmail 3 { 4 5 6 7 8 9 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19 /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 class VerifyEmail extends IlluminateVerifyEmail 3 { 4 private string $verificationUrl; 5 6 public function __construct(string $verificationUrl) 7 { 8 $this->verificationUrl = $verificationUrl; 9 } 10 11 12 13 14 15 16 17 18 } 19

Slide 59

Slide 59 text

認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証 URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Slide 60

Slide 60 text

認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証 URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } return $this->buildMailMessage($verificationUrl); } // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // 24

Slide 61

Slide 61 text

認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証 URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 20 return $this->buildMailMessage($verificationUrl); 21 } 22 23 // ... 24

Slide 62

Slide 62 text

認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証 URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 // ... /** * Get the verification URL for the given notifiable. * * @param mixed $notifiable * @return string */ protected function verificationUrl($notifiable) { if (static::$createUrlCallback) { return call_user_func(static::$createUrlCallback, $notifiable); } return URL::temporarySignedRoute( 'verification.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' $ tifi bl t () 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

Slide 63

Slide 63 text

認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証 URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 return URL::temporarySignedRoute( 'verification.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' => $notifiable->getKey(), 'hash' => sha1($notifiable->getEmailForVerification()), ] ); */ 31 protected function verificationUrl($notifiable) 32 { 33 if (static::$createUrlCallback) { 34 return call_user_func(static::$createUrlCallback, $notifiable); 35 } 36 37 38 39 40 41 42 43 44 45 } 46 47 // ... 48 } 49

Slide 64

Slide 64 text

認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証 URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 [ 'id' => $notifiable->getKey(), 'hash' => sha1($notifiable->getEmailForVerification()), ] */ 31 protected function verificationUrl($notifiable) 32 { 33 if (static::$createUrlCallback) { 34 return call_user_func(static::$createUrlCallback, $notifiable); 35 } 36 37 return URL::temporarySignedRoute( 38 'verification.verify', 39 Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), 40 41 42 43 44 ); 45 } 46 47 // ... 48 } 49

Slide 65

Slide 65 text

認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証 URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 'id' => $notifiable->getKey(), */ 31 protected function verificationUrl($notifiable) 32 { 33 if (static::$createUrlCallback) { 34 return call_user_func(static::$createUrlCallback, $notifiable); 35 } 36 37 return URL::temporarySignedRoute( 38 'verification.verify', 39 Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), 40 [ 41 42 'hash' => sha1($notifiable->getEmailForVerification()), 43 ] 44 ); 45 } 46 47 // ... 48 } 49

Slide 66

Slide 66 text

App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Slide 67

Slide 67 text

App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserNotifier $notifier; 20 21

Slide 68

Slide 68 text

App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; private UserNotifier $notifier; public function __construct( UserId $id, UserRepository $repository, UserNotifier $notifier ) { $this->id = $id; $this->repository = $repository; $this->notifier = $notifier; } { 15 use Authorizable; 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // ... 32 33

Slide 69

Slide 69 text

App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 18 19 /** * @inheritDoc */ public function markEmailAsVerified() { return $this->repository->markEmailAsVerified($this->id); } $this->repository = $repository; 28 $this->notifier = $notifier; 29 } 30 31 // ... 32 33 34 35 36 37 38 39 40 41 /** 42 * @inheritDoc 43 */ 44 public function sendEmailVerificationNotification() 45 { 46

Slide 70

Slide 70 text

App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 18 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 /** * @inheritDoc */ public function sendEmailVerificationNotification() { $user = $this->repository->get($this->id); $url = $this->createVerificationUrl(); $this->notifier->sendEmailVerificationNotification($user, $url); } public function markEmailAsVerified() 37 { 38 return $this->repository->markEmailAsVerified($this->id); 39 } 40 41 42 43 44 45 46 47 48 49 50 51 52 private function createVerificationUrl(): string 53 { 54 return URL::temporarySignedRoute( 55

Slide 71

Slide 71 text

App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 18 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private function createVerificationUrl(): string { return URL::temporarySignedRoute( 'verification.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' => $this->id->rawValue(), 'hash' => sha1($this->getEmailForVerification()), ] ); } { 46 $user = $this->repository->get($this->id); 47 $url = $this->createVerificationUrl(); 48 49 $this->notifier->sendEmailVerificationNotification($user, $url); 50 } 51 52 53 54 55 56 57 58 59 60 61 62 63

Slide 72

Slide 72 text

App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 18 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 'id' => $this->id->rawValue(), { 46 $user = $this->repository->get($this->id); 47 $url = $this->createVerificationUrl(); 48 49 $this->notifier->sendEmailVerificationNotification($user, $url); 50 } 51 52 private function createVerificationUrl(): string 53 { 54 return URL::temporarySignedRoute( 55 'verification.verify', 56 Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), 57 [ 58 59 'hash' => sha1($this->getEmailForVerification()), 60 ] 61 ); 62 } 63

Slide 73

Slide 73 text

まとめ メール認証の実装では検討すべき事項が多く、マニュアル実装するのは結構 ⼤変 Laravel は少ない⼿数でメール認証を実装する⼿段を⽤意してくれている 内部実装を理解して依存関係を紐解くことで、保守性・拡張性の⾼いアーキ テクチャに組み替えることができる

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

ありがとうございました!🤲