Files
sam-manage/app/Http/Middleware/SetTenantContext.php
강영보 d03c7ed870 feat: [bending] 절곡품 관리 MNG 화면
- 기초관리: 목록(13컬럼) + 폼(기본정보 + 케이스전용 + 절곡테이블 + 이미지)
- 절곡품: 가이드레일/케이스/하단마감재 타입별 목록 + 폼
- 부품 추가(기초관리 검색 모달) + 삭제 + 수량/품명/재질 편집
- 절곡테이블 inline 편집 + 재질별 폭합 자동계산
- 작업지시서 레거시 포맷 인쇄 모달
- 원본수정 버튼 sam_item_id 직접 링크
- DB 메뉴 등록 (기초관리 + 절곡품 + 케이스 + 하단마감재)
2026-03-19 21:08:57 +09:00

132 lines
4.2 KiB
PHP

<?php
namespace App\Http\Middleware;
use App\Models\Tenants\Tenant;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class SetTenantContext
{
/**
* 테넌트 콘솔 새창에서 URL의 tenantId를 컨텍스트로 설정
* 메인 창의 세션에는 영향을 주지 않음
* 리다이렉트/JSON 응답의 URL을 tenant-console 경로로 자동 재작성
*/
public function handle(Request $request, Closure $next): Response
{
$tenantId = $request->route('tenantId');
if (! $tenantId) {
abort(404, '테넌트 ID가 필요합니다.');
}
$tenant = Tenant::find($tenantId);
if (! $tenant) {
abort(404, '테넌트를 찾을 수 없습니다.');
}
// 요청 범위에서만 테넌트 컨텍스트 설정 (세션 변경 없음)
$request->attributes->set('tenant_console_id', $tenantId);
$request->attributes->set('tenant_console', $tenant);
$request->attributes->set('tenant_id', (int) $tenantId);
// 뷰에서 사용할 수 있도록 공유
view()->share('consoleTenant', $tenant);
view()->share('consoleTenantId', $tenantId);
view()->share('isTenantConsole', true);
// layouts.app → layouts.tenant-console 자동 전환
// tenant-override 디렉토리를 뷰 경로 최우선으로 추가
app('view')->getFinder()->prependLocation(resource_path('views/tenant-override'));
$response = $next($request);
// 리다이렉트 응답: URL을 tenant-console 경로로 재작성
if ($response instanceof RedirectResponse) {
$response = $this->rewriteRedirect($response, $tenantId);
}
// JSON 응답: redirect 키의 URL 재작성
if ($response instanceof JsonResponse) {
$response = $this->rewriteJsonRedirect($response, $tenantId);
}
// HX-Redirect 헤더 재작성
if ($response->headers->has('HX-Redirect')) {
$hxUrl = $response->headers->get('HX-Redirect');
$response->headers->set('HX-Redirect', $this->prefixUrl($hxUrl, $tenantId));
}
return $response;
}
/**
* 리다이렉트 URL에 tenant-console 프리픽스 추가
*/
private function rewriteRedirect(RedirectResponse $response, int $tenantId): RedirectResponse
{
$targetUrl = $response->getTargetUrl();
$response->setTargetUrl($this->prefixUrl($targetUrl, $tenantId));
return $response;
}
/**
* JSON 응답의 redirect 키 URL 재작성
*/
private function rewriteJsonRedirect(JsonResponse $response, int $tenantId): JsonResponse
{
$data = $response->getData(true);
if (isset($data['redirect']) && is_string($data['redirect'])) {
$data['redirect'] = $this->prefixUrl($data['redirect'], $tenantId);
$response->setData($data);
}
return $response;
}
/**
* URL에 /tenant-console/{tenantId} 프리픽스 추가
* 이미 tenant-console 경로면 그대로 반환
*/
private function prefixUrl(string $url, int $tenantId): string
{
$consolePrefix = "/tenant-console/{$tenantId}";
// 이미 tenant-console 경로면 그대로
if (str_contains($url, '/tenant-console/')) {
return $url;
}
// 절대 URL (https://...) 에서 path 추출
$parsed = parse_url($url);
$path = $parsed['path'] ?? '/';
// /api/ 경로는 재작성하지 않음
if (str_starts_with($path, '/api/')) {
return $url;
}
// 프리픽스 추가
$newPath = $consolePrefix . $path;
$query = isset($parsed['query']) ? '?' . $parsed['query'] : '';
$fragment = isset($parsed['fragment']) ? '#' . $parsed['fragment'] : '';
// 호스트가 있으면 포함
if (isset($parsed['scheme'])) {
$host = $parsed['scheme'] . '://' . $parsed['host'];
$port = isset($parsed['port']) ? ':' . $parsed['port'] : '';
return $host . $port . $newPath . $query . $fragment;
}
return $newPath . $query . $fragment;
}
}