103 lines
3.3 KiB
PHP
103 lines
3.3 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Middleware;
|
||
|
||
use Closure;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\Auth;
|
||
use Carbon\Carbon;
|
||
use Symfony\Component\HttpFoundation\Response;
|
||
|
||
/**
|
||
* 定期パスワード変更チェックミドルウェア
|
||
*
|
||
* ログインしているオペレータのパスワード最後変更時刻をチェック
|
||
* 3ヶ月以上経過している場合、パスワード変更画面へ強制リダイレクト
|
||
*/
|
||
class CheckPasswordChangeRequired
|
||
{
|
||
/**
|
||
* リクエストを処理
|
||
*
|
||
* @param \Illuminate\Http\Request $request
|
||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||
* @return \Symfony\Component\HttpFoundation\Response
|
||
*/
|
||
public function handle(Request $request, Closure $next): Response
|
||
{
|
||
// ログインしていない場合はスキップ
|
||
if (!Auth::check()) {
|
||
return $next($request);
|
||
}
|
||
|
||
// 既にパスワード変更ページにいる場合はスキップ
|
||
if ($request->routeIs('password.change.show', 'password.change.update')) {
|
||
return $next($request);
|
||
}
|
||
|
||
// 現在のユーザーを取得
|
||
$ope = Auth::user();
|
||
|
||
// パスワード変更が必須か判定
|
||
if ($this->isPasswordChangeRequired($ope)) {
|
||
return redirect()->route('password.change.show');
|
||
}
|
||
|
||
return $next($request);
|
||
}
|
||
|
||
/**
|
||
* パスワード変更が必須かどうかを判定
|
||
*
|
||
* 初回ログイン時(ope_pass_changed_at が NULL)または
|
||
* 最後変更から3ヶ月以上経過している場合、TRUE を返す
|
||
*
|
||
* @param \App\Models\Ope $ope
|
||
* @return bool
|
||
*/
|
||
private function isPasswordChangeRequired($ope): bool
|
||
{
|
||
// パスワード変更日時が未設定(初回ログイン等)
|
||
if (is_null($ope->ope_pass_changed_at)) {
|
||
\Log::info('Password change required: ope_pass_changed_at is null', [
|
||
'ope_id' => $ope->ope_id,
|
||
]);
|
||
return true;
|
||
}
|
||
|
||
// パスワード変更から経過日数を計算
|
||
// ope_pass_changed_at は複数のフォーマットに対応
|
||
try {
|
||
$changedAt = Carbon::parse($ope->ope_pass_changed_at);
|
||
} catch (\Exception $e) {
|
||
// パース失敗時は強制変更
|
||
\Log::warning('Failed to parse ope_pass_changed_at', [
|
||
'ope_id' => $ope->ope_id,
|
||
'value' => $ope->ope_pass_changed_at,
|
||
'error' => $e->getMessage(),
|
||
]);
|
||
return true;
|
||
}
|
||
|
||
$now = Carbon::now();
|
||
|
||
// 3ヶ月以上経過しているか判定
|
||
// diffInMonths は絶対値ではなく符号付きなので、abs() で絶対値を取得
|
||
$monthsDiff = abs($now->diffInMonths($changedAt));
|
||
|
||
\Log::info('Password change check', [
|
||
'ope_id' => $ope->ope_id,
|
||
'changed_at' => $changedAt->format('Y-m-d H:i:s'),
|
||
'now' => $now->format('Y-m-d H:i:s'),
|
||
'months_diff' => $monthsDiff,
|
||
'is_required' => $monthsDiff >= 3,
|
||
]);
|
||
|
||
if ($monthsDiff >= 3) {
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
}
|