resolveUsername(); if (PrivilegedDatabaseAccounts::isUsable($username)) { return $next($request); } // SetLocale 미실행 상태이므로 로케일을 자체 감지한다. // API/HTML 분기보다 먼저 적용해야 JSON 메시지도 활성 로케일을 반영한다. app()->setLocale($this->detectLocale($request)); if ($request->expectsJson() || $request->is('api/*')) { return response()->json([ 'success' => false, 'message' => __('database_credential.message'), ], 503); } // 확장·템플릿이 로딩되지 않은 상태이므로 템플릿 뷰나 errors/layout 을 // 쓸 수 없다. DB/JS 무의존 자체 완결 정적 페이지를 반환한다. return response()->view('database-credential-error', [ // 실제 계정명은 전달하지 않는다 — 미인증 공개 페이지이므로 정보 유출. 'reason' => PrivilegedDatabaseAccounts::isBlocked($username) ? 'blocked' : 'empty', ], 503); } /** * 현재 DB 커넥션 설정에서 사용자명을 해석합니다. * * DB::connection() 을 거치지 않고 config 배열만 읽습니다. 이 가드는 DB 설정이 * 잘못된 상황에서 동작해야 하므로, 판정을 위해 커넥션을 해석하는 것 자체가 * 새로운 실패 지점이 됩니다. read/write 우선순위 규칙은 * PrivilegedDatabaseAccounts 가 CoreServiceProvider 와 공유합니다. * * @return string|null 해석된 사용자명 (없으면 null) */ protected function resolveUsername(): ?string { $connection = config('database.default'); return PrivilegedDatabaseAccounts::resolveUsername( config("database.connections.{$connection}", []) ); } }