feat: Flow Tester 기능 개선 및 안정화
- FlowTesterController: 테스트 실행 로직 개선 - 에러 핸들링 강화 - 응답 형식 표준화 - FlowExecutor: API 호출 실행기 개선 - 다단계 플로우 지원 강화 - 변수 바인딩 및 검증 개선 - index.blade.php: UI 개선 - 테스트 결과 표시 개선 - 사용성 향상 - routes/web.php: 라우트 정리 - composer.lock: 의존성 업데이트 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -342,73 +342,115 @@ public function runDetail(int $runId): View
|
||||
*/
|
||||
|
||||
/**
|
||||
* 현재 테넌트의 사용자 목록
|
||||
* API 서버에 직접 로그인하여 토큰 발급
|
||||
*
|
||||
* MNG에서 토큰을 발급하면 API 서버에서 인식하지 못하므로,
|
||||
* API 서버에 직접 로그인하여 토큰을 발급받습니다.
|
||||
*/
|
||||
public function users()
|
||||
public function loginToApi(Request $request)
|
||||
{
|
||||
// 현재 선택된 테넌트 ID (세션 기반)
|
||||
$tenantId = session('selected_tenant_id');
|
||||
$validated = $request->validate([
|
||||
'user_id' => 'required|string',
|
||||
'user_pwd' => 'required|string',
|
||||
]);
|
||||
|
||||
if (! $tenantId) {
|
||||
// 세션에 없으면 기본 테넌트 사용
|
||||
$currentTenant = auth()->user()->currentTenant();
|
||||
$tenantId = $currentTenant?->id;
|
||||
try {
|
||||
// API Base URL 결정
|
||||
$baseUrl = $this->getApiBaseUrl();
|
||||
|
||||
// Docker 환경에서는 내부 URL로 변환
|
||||
$requestUrl = $baseUrl.'/login';
|
||||
$headers = ['Accept' => 'application/json', 'Content-Type' => 'application/json'];
|
||||
|
||||
if ($this->isDockerEnvironment()) {
|
||||
$parsedUrl = parse_url($baseUrl);
|
||||
$host = $parsedUrl['host'] ?? '';
|
||||
|
||||
// *.sam.kr 도메인을 nginx 컨테이너로 라우팅
|
||||
if (str_ends_with($host, '.sam.kr') || $host === 'sam.kr') {
|
||||
$headers['Host'] = $host;
|
||||
$requestUrl = preg_replace('#https?://[^/]+#', 'https://nginx', $baseUrl).'/login';
|
||||
}
|
||||
}
|
||||
|
||||
// API 서버에 로그인 요청
|
||||
$response = \Illuminate\Support\Facades\Http::withHeaders($headers)
|
||||
->withoutVerifying() // Docker 내부 SSL 인증서 무시
|
||||
->timeout(10)
|
||||
->post($requestUrl, [
|
||||
'user_id' => $validated['user_id'],
|
||||
'user_pwd' => $validated['user_pwd'],
|
||||
]);
|
||||
|
||||
if (! $response->successful()) {
|
||||
$body = $response->json();
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $body['message'] ?? '로그인 실패: '.$response->status(),
|
||||
], 401);
|
||||
}
|
||||
|
||||
$body = $response->json();
|
||||
$token = $body['access_token'] ?? $body['data']['token'] ?? null;
|
||||
|
||||
if (! $token) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '토큰을 받지 못했습니다. 응답: '.json_encode($body, JSON_UNESCAPED_UNICODE),
|
||||
], 500);
|
||||
}
|
||||
|
||||
// 세션에 저장 (API Explorer와 공유)
|
||||
session([
|
||||
'api_explorer_token' => $token,
|
||||
'api_explorer_user_id' => $body['user']['id'] ?? null,
|
||||
'api_explorer_user_name' => $body['user']['name'] ?? $validated['user_id'],
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'API 서버 로그인 성공!',
|
||||
'user' => $body['user'] ?? ['name' => $validated['user_id']],
|
||||
'token_preview' => substr($token, 0, 20).'...',
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'API 서버 연결 실패: '.$e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
|
||||
if (! $tenantId) {
|
||||
return response()->json([]);
|
||||
}
|
||||
|
||||
// user_tenants 피벗 테이블을 통해 해당 테넌트의 사용자 조회
|
||||
$users = \App\Models\User::whereHas('tenants', function ($query) use ($tenantId) {
|
||||
$query->where('tenants.id', $tenantId)
|
||||
->where('user_tenants.is_active', true);
|
||||
})
|
||||
->select(['id', 'name', 'email'])
|
||||
->orderBy('name')
|
||||
->limit(100)
|
||||
->get();
|
||||
|
||||
return response()->json($users);
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 선택 (Sanctum 토큰 발급)
|
||||
* API Base URL 결정
|
||||
*/
|
||||
public function selectUser(Request $request)
|
||||
private function getApiBaseUrl(): string
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'user_id' => 'required|integer',
|
||||
]);
|
||||
|
||||
$user = \App\Models\User::find($validated['user_id']);
|
||||
|
||||
if (! $user) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '사용자를 찾을 수 없습니다.',
|
||||
], 404);
|
||||
// 환경변수 우선
|
||||
$envUrl = env('FLOW_TESTER_API_BASE_URL');
|
||||
if ($envUrl) {
|
||||
return rtrim($envUrl, '/');
|
||||
}
|
||||
|
||||
// Sanctum 토큰 발급
|
||||
$token = $user->createToken('flow-tester', ['*'])->plainTextToken;
|
||||
// config에서 로컬 환경 URL
|
||||
$environments = config('api-explorer.default_environments', []);
|
||||
foreach ($environments as $env) {
|
||||
if ($env['name'] === '로컬') {
|
||||
return rtrim($env['base_url'], '/');
|
||||
}
|
||||
}
|
||||
|
||||
// 세션에 저장 (API Explorer와 공유)
|
||||
session([
|
||||
'api_explorer_token' => $token,
|
||||
'api_explorer_user_id' => $user->id,
|
||||
]);
|
||||
// 기본값
|
||||
return 'https://api.sam.kr';
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "'{$user->name}' 사용자로 인증되었습니다.",
|
||||
'user' => [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'email' => $user->email,
|
||||
],
|
||||
'token_preview' => substr($token, 0, 20).'...',
|
||||
]);
|
||||
/**
|
||||
* Docker 환경인지 확인
|
||||
*/
|
||||
private function isDockerEnvironment(): bool
|
||||
{
|
||||
return file_exists('/.dockerenv') || (getenv('DOCKER_CONTAINER') === 'true');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user