v7.0.0 release
This commit is contained in:
1 parent
0e7fa04b03
commit
c4ea9a6cd1
3582 files changed
+626189
-160151
No files matched your search
+62
-22
@@ -1,9 +1,30 @@
|
||||
<?php
|
||||
|
||||
use App\Exceptions\CoreVersionMismatchException;
|
||||
use App\Exceptions\IdentityVerificationRequiredException;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Http\Middleware\AdminMiddleware;
|
||||
use App\Http\Middleware\CheckTemplateDependencies;
|
||||
use App\Http\Middleware\CheckUserStatus;
|
||||
use App\Http\Middleware\EnforceIdentityPolicy;
|
||||
use App\Http\Middleware\GzipEncodeResponse;
|
||||
use App\Http\Middleware\MaintenanceModePage;
|
||||
use App\Http\Middleware\OptionalSanctumMiddleware;
|
||||
use App\Http\Middleware\PermissionMiddleware;
|
||||
use App\Http\Middleware\RefreshTokenExpiration;
|
||||
use App\Http\Middleware\RoleMiddleware;
|
||||
use App\Http\Middleware\SetLocale;
|
||||
use App\Http\Middleware\SetTimezone;
|
||||
use App\Http\Middleware\StartApiSession;
|
||||
use App\Http\Middleware\SyncBoostWithDebugMode;
|
||||
use App\Seo\SeoMiddleware;
|
||||
use App\Support\UmaskHelper;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Foundation\Configuration\Exceptions;
|
||||
use Illuminate\Foundation\Configuration\Middleware;
|
||||
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Env;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
@@ -53,70 +74,89 @@ $app = Application::configure(basePath: dirname(__DIR__))
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware): void {
|
||||
// Laravel 기본 메인터넌스 미들웨어 제거 (커스텀 MaintenanceModePage로 대체)
|
||||
$middleware->remove(\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::class);
|
||||
$middleware->remove(PreventRequestsDuringMaintenance::class);
|
||||
|
||||
// Maintenance 모드 전용 페이지 미들웨어 (인증 불필요, 최우선 실행)
|
||||
$middleware->prepend(\App\Http\Middleware\MaintenanceModePage::class);
|
||||
$middleware->prepend(MaintenanceModePage::class);
|
||||
|
||||
// Laravel Boost browser-logs를 G7 디버그 모드와 연동
|
||||
// InjectBoost 미들웨어보다 먼저 실행되어야 하므로 최상단에 추가
|
||||
$middleware->prependToGroup('web', \App\Http\Middleware\SyncBoostWithDebugMode::class);
|
||||
$middleware->prependToGroup('web', SyncBoostWithDebugMode::class);
|
||||
|
||||
// SetLocale, SetTimezone은 인증 후 실행되어야 사용자 설정을 읽을 수 있음
|
||||
$localeTimezoneMiddleware = [
|
||||
\App\Http\Middleware\SetLocale::class,
|
||||
\App\Http\Middleware\SetTimezone::class,
|
||||
SetLocale::class,
|
||||
SetTimezone::class,
|
||||
];
|
||||
$middleware->appendToGroup('web', $localeTimezoneMiddleware);
|
||||
$middleware->appendToGroup('api', $localeTimezoneMiddleware);
|
||||
|
||||
// Gzip 압축 미들웨어 (웹서버 설정 없이 애플리케이션 레벨에서 압축)
|
||||
$middleware->append(\App\Http\Middleware\GzipEncodeResponse::class);
|
||||
$middleware->append(GzipEncodeResponse::class);
|
||||
|
||||
// 토큰 만료 시간 슬라이딩 갱신 미들웨어 (API 요청 시 토큰 만료 시간 자동 연장)
|
||||
$middleware->appendToGroup('api', [
|
||||
\App\Http\Middleware\RefreshTokenExpiration::class,
|
||||
RefreshTokenExpiration::class,
|
||||
]);
|
||||
|
||||
// IDV 정책 자동 매핑 — 모든 API 라우트에서 라우트 이름과 매칭되는 scope='route' 정책을 자동 enforce.
|
||||
// 정책 DB 토글만으로 즉시 효과 (라우트 코드 수정 불필요). hook scope 정책의 동적 구독과 동일 모델.
|
||||
// 캐시된 인덱스 lookup → 무매칭 라우트는 O(1) 통과.
|
||||
$middleware->appendToGroup('api', [
|
||||
\App\Http\Middleware\EnforceIdentityPolicy::class,
|
||||
EnforceIdentityPolicy::class,
|
||||
]);
|
||||
|
||||
// 비인증 게스트 redirect 경로 가드 (공개#39).
|
||||
// Laravel 12 기본값은 `redirectGuestsTo(fn () => route('login'))` 인데,
|
||||
// 이 프로젝트엔 'login' 이름 라우트가 없어 Accept 헤더 없는 /api/* 비인증 요청이
|
||||
// Authenticate::unauthenticated() 의 redirectTo() 평가 단계에서 route('login')
|
||||
// → RouteNotFoundException(HTTP 500) 으로 떨어진다.
|
||||
// API 경로는 redirect 대상을 null 로 반환해 RouteNotFoundException 을 차단하고,
|
||||
// withExceptions 의 AuthenticationException 핸들러가 401 JSON 으로 응답하도록 위임한다.
|
||||
$middleware->redirectGuestsTo(function (Request $request) {
|
||||
// API 경로는 redirect 하지 않음 → AuthenticationException 으로 propagate → 401 JSON.
|
||||
if ($request->expectsJson() || $request->is('api/*')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// web 경로는 'login' 이름 라우트가 정의된 경우에만 redirect (현재 프로젝트엔 없음 → null).
|
||||
return Route::has('login') ? route('login') : null;
|
||||
});
|
||||
|
||||
// 권한 관련 미들웨어 등록
|
||||
$middleware->alias([
|
||||
'admin' => \App\Http\Middleware\AdminMiddleware::class,
|
||||
'check.user_status' => \App\Http\Middleware\CheckUserStatus::class,
|
||||
'permission' => \App\Http\Middleware\PermissionMiddleware::class,
|
||||
'role' => \App\Http\Middleware\RoleMiddleware::class,
|
||||
'template.dependencies' => \App\Http\Middleware\CheckTemplateDependencies::class,
|
||||
'optional.sanctum' => \App\Http\Middleware\OptionalSanctumMiddleware::class,
|
||||
'start.api.session' => \App\Http\Middleware\StartApiSession::class,
|
||||
'seo' => \App\Seo\SeoMiddleware::class,
|
||||
'identity.policy' => \App\Http\Middleware\EnforceIdentityPolicy::class,
|
||||
'admin' => AdminMiddleware::class,
|
||||
'check.user_status' => CheckUserStatus::class,
|
||||
'permission' => PermissionMiddleware::class,
|
||||
'role' => RoleMiddleware::class,
|
||||
'template.dependencies' => CheckTemplateDependencies::class,
|
||||
'optional.sanctum' => OptionalSanctumMiddleware::class,
|
||||
'start.api.session' => StartApiSession::class,
|
||||
'seo' => SeoMiddleware::class,
|
||||
'identity.policy' => EnforceIdentityPolicy::class,
|
||||
]);
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions): void {
|
||||
// API 401 응답 시 잔존 세션 쿠키 정리
|
||||
$exceptions->render(function (\Illuminate\Auth\AuthenticationException $e, \Illuminate\Http\Request $request) {
|
||||
if ($request->expectsJson()) {
|
||||
$exceptions->render(function (AuthenticationException $e, Request $request) {
|
||||
// API 경로는 Accept 헤더 유무와 무관하게 항상 JSON 401 (web redirect/route('login') 폴백 차단).
|
||||
// 동일 파일의 IDV/CoreVersionMismatch 핸들러와 같은 가드 패턴.
|
||||
if ($request->expectsJson() || $request->is('api/*')) {
|
||||
return response()->json(['message' => __('auth.unauthenticated')], 401)
|
||||
->withCookie(cookie()->forget(config('session.cookie')));
|
||||
}
|
||||
});
|
||||
|
||||
// IDV 정책 위반 → HTTP 428 (Precondition Required) + verification payload
|
||||
$exceptions->render(function (\App\Exceptions\IdentityVerificationRequiredException $e, \Illuminate\Http\Request $request) {
|
||||
$exceptions->render(function (IdentityVerificationRequiredException $e, Request $request) {
|
||||
if ($request->expectsJson() || $request->is('api/*')) {
|
||||
return \App\Helpers\ResponseHelper::identityRequired($e->getPayload());
|
||||
return ResponseHelper::identityRequired($e->getPayload());
|
||||
}
|
||||
});
|
||||
|
||||
// 확장 코어 버전 호환성 검사 실패 → HTTP 422 + error_code: 'core_version_mismatch'
|
||||
// (extension update/activate/recovery 등 사전 검증 진입 지점에서 throw)
|
||||
$exceptions->render(function (\App\Exceptions\CoreVersionMismatchException $e, \Illuminate\Http\Request $request) {
|
||||
$exceptions->render(function (CoreVersionMismatchException $e, Request $request) {
|
||||
if ($request->expectsJson() || $request->is('api/*')) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
|
||||
Reference in new issue
Block a user