- DemoLimitMiddleware: 쇼케이스 읽기전용, 만료 체크, 외부연동 차단 - DemoTenantService: 파트너/체험 테넌트 생성, 기간 연장, 정식 전환 - ResetDemoShowcaseCommand: 매일 자정 데이터 리셋 + 샘플 재시드 - ManufacturingPresetSeeder: 부서/거래처/품목/견적/수주 샘플 데이터 - 스케줄러 등록 (00:00 demo:reset-showcase --seed) - 미들웨어 별칭 등록 (demo.limit)
94 lines
3.0 KiB
PHP
94 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use App\Models\Tenants\Tenant;
|
|
use Closure;
|
|
use Illuminate\Http\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
/**
|
|
* 데모 테넌트 제한 미들웨어
|
|
*
|
|
* - DEMO_SHOWCASE: 모든 쓰기 작업 차단 (읽기 전용)
|
|
* - DEMO_PARTNER / DEMO_TRIAL: 만료 체크 + 차단 기능 체크
|
|
*
|
|
* 기존 코드 영향 없음: 프로덕션 테넌트(STD/TPL/HQ)는 즉시 통과
|
|
*
|
|
* @see docs/features/sales/demo-tenant-policy.md
|
|
*/
|
|
class DemoLimitMiddleware
|
|
{
|
|
/**
|
|
* 데모에서 차단하는 라우트 프리픽스 (외부 시스템 연동)
|
|
*/
|
|
private const BLOCKED_ROUTE_PREFIXES = [
|
|
'api/v1/barobill',
|
|
'api/v1/ecount',
|
|
];
|
|
|
|
public function handle(Request $request, Closure $next): Response
|
|
{
|
|
$tenantId = app('tenant_id');
|
|
if (! $tenantId) {
|
|
return $next($request);
|
|
}
|
|
|
|
$tenant = Tenant::withoutGlobalScopes()->find($tenantId);
|
|
if (! $tenant || ! $tenant->isDemoTenant()) {
|
|
// 프로덕션 테넌트 → 즉시 통과 (기존 동작 유지)
|
|
return $next($request);
|
|
}
|
|
|
|
// 1. 만료 체크 (파트너 데모, 고객 체험)
|
|
if ($tenant->isDemoExpired()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '체험 기간이 만료되었습니다. 정식 계약을 진행해 주세요.',
|
|
'error_code' => 'DEMO_EXPIRED',
|
|
], 403);
|
|
}
|
|
|
|
// 2. 쇼케이스 → 읽기 전용 (GET, HEAD, OPTIONS만 허용)
|
|
if ($tenant->isDemoShowcase() && ! $request->isMethodSafe()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '데모 환경에서는 조회만 가능합니다.',
|
|
'error_code' => 'DEMO_READ_ONLY',
|
|
], 403);
|
|
}
|
|
|
|
// 3. 읽기전용 옵션이 설정된 데모 테넌트
|
|
if ($tenant->isDemoReadOnly() && ! $request->isMethodSafe()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '데모 환경에서는 조회만 가능합니다.',
|
|
'error_code' => 'DEMO_READ_ONLY',
|
|
], 403);
|
|
}
|
|
|
|
// 4. 차단 기능 체크 (바로빌, 이카운트 등 외부 연동)
|
|
if ($this->isBlockedRoute($request)) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '데모 환경에서 사용할 수 없는 기능입니다. 정식 계약 후 이용 가능합니다.',
|
|
'error_code' => 'DEMO_FEATURE_BLOCKED',
|
|
], 403);
|
|
}
|
|
|
|
return $next($request);
|
|
}
|
|
|
|
private function isBlockedRoute(Request $request): bool
|
|
{
|
|
$path = $request->path();
|
|
foreach (self::BLOCKED_ROUTE_PREFIXES as $prefix) {
|
|
if (str_starts_with($path, $prefix)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|