$limit, // "page" => $page // ]); // $ch = curl_init($url_users); // curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); // curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // $response = curl_exec($ch); // $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); // curl_close($ch); // if ($http_code !== 200) { // echo json_encode(['status' => 'fail', 'step' => 'user_search', 'code' => $http_code, 'raw' => $response]); // exit; // } // $res = json_decode($response, true); // $users = $res['users'] ?? []; // $all_users = array_merge($all_users, $users); // $fetched = count($users); // $page++; // } while ($fetched === $limit); // limit만큼 꽉 찼으면 다음 페이지 있음 // // === 2) 테넌트 이름 매핑 === // // 유저들에서 tenantId 수집 // $tenantIds = []; // foreach ($all_users as $u) { // if (!empty($u['tenants'])) { // foreach ($u['tenants'] as $t) { // if (!in_array($t['tenantId'], $tenantIds)) { // $tenantIds[] = $t['tenantId']; // } // } // } // } // // 테넌트 이름 가져오기 // $tenant_map = []; // if (!empty($tenantIds)) { // $url_tenants = "https://api.descope.com/v1/mgmt/tenant/search"; // $payload_tenant = json_encode([ // "tenantIds" => $tenantIds // ]); // $ch2 = curl_init($url_tenants); // curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true); // curl_setopt($ch2, CURLOPT_POSTFIELDS, $payload_tenant); // curl_setopt($ch2, CURLOPT_HTTPHEADER, $headers); // $response_tenants = curl_exec($ch2); // $http_code_tenants = curl_getinfo($ch2, CURLINFO_HTTP_CODE); // curl_close($ch2); // if ($http_code_tenants === 200) { // $res_tenants = json_decode($response_tenants, true); // if (!empty($res_tenants['tenants'])) { // foreach ($res_tenants['tenants'] as $t) { // $tenant_map[$t['id']] = $t['name']; // } // } // } // } // // === 3) 각 유저에 tenantName 붙이기 === // foreach ($all_users as &$user) { // $user['name'] = $user['name'] ?? ''; // $user['phone'] = $user['phone'] ?? ''; // $user['customAttributes'] = $user['customAttributes'] ?? []; // if (!empty($user['tenants'])) { // foreach ($user['tenants'] as &$ten) { // $ten['tenantName'] = $tenant_map[$ten['tenantId']] ?? $ten['tenantId']; // } // } // } // // === 4) 최종 응답 === // echo json_encode([ // 'status' => 'ok', // 'count' => count($all_users), // 'users' => $all_users // ]); ?> $limit, "page" => $page]); $ch = curl_init($url_users); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($http_code !== 200) { echo json_encode(['status' => 'fail', 'step' => 'user_search', 'code' => $http_code, 'raw' => $response]); exit; } $res = json_decode($response, true); $users = $res['users'] ?? []; $all_users = array_merge($all_users, $users); $page++; } while (count($users) === $limit); // ✅ timestamp 보정 function normalize_ts($val) { $ts = (int) $val; if ($ts > 0 && $ts < 1e12) $ts *= 1000; return $ts; } // ====== ✅ DB에서 최근 로그인 시간 가져오기 ====== try { $pdo = new PDO("mysql:host=localhost;dbname=egbim;charset=utf8mb4", "egbim", "baron3840!!", [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]); $stmt = $pdo->query(" SELECT login_id, MAX(user_login_time) AS last_login_time FROM user_program_info WHERE user_login_time IS NOT NULL AND user_login_time <> '' GROUP BY login_id "); $loginMap = []; while ($row = $stmt->fetch()) { $loginMap[$row['login_id']] = $row['last_login_time']; } // Descope 유저 리스트와 merge foreach ($all_users as &$u) { $loginId = $u['loginIds'][0] ?? null; $u['customAttributes']['serverLastLogin'] = ($loginId && isset($loginMap[$loginId])) ? $loginMap[$loginId] : null; } unset($u); } catch (Exception $e) { // DB 오류 시 무시하고 진행 } // ✅ 기간 필터 $start = $_GET['start'] ?? null; $end = $_GET['end'] ?? null; $mode = $_GET['mode'] ?? 'created'; if ($start || $end) { $startTs = $start ? strtotime($start . " 00:00:00") * 1000 : null; $endTs = $end ? strtotime($end . " 23:59:59") * 1000 : null; $all_users = array_filter($all_users, function($u) use ($startTs, $endTs, $mode) { // 기본값 $ts = 0; if ($mode === 'created') { $ts = normalize_ts($u['createdTime'] ?? 0); } elseif ($mode === 'lastSignIn') { $ts = normalize_ts($u['customAttributes']['lastSignInDate'] ?? 0); } elseif ($mode === 'license') { $ts = normalize_ts($u['customAttributes']['egBimLExpiryDate'] ?? 0); } elseif ($mode === 'serverLogin') { // ✅ EGBIM 최근 로그인 (DB에서 가져온 값은 문자열로 가정) if (!empty($u['customAttributes']['serverLastLogin'])) { $ts = strtotime($u['customAttributes']['serverLastLogin']) * 1000; } } if (!$ts) return false; if ($startTs && $ts < $startTs) return false; if ($endTs && $ts > $endTs) return false; return true; }); $all_users = array_values($all_users); } // ✅ 테넌트 필터 $tenantFilters = isset($_GET['tenants']) ? explode(',', $_GET['tenants']) : []; if (!empty($tenantFilters)) { $all_users = array_filter($all_users, function($u) use ($tenantFilters) { if (!empty($u['userTenants']) && is_array($u['userTenants'])) { foreach ($u['userTenants'] as $t) { $tName = $t['tenantName'] ?? ''; foreach ($tenantFilters as $f) { if (strcasecmp($tName, $f) === 0) return true; } } } return false; }); $all_users = array_values($all_users); } // ✅ 키워드 검색 (소속 가족사 / 외부회사 / 이름 / DisplayName) $keyword = $_GET['keyword'] ?? ''; if ($keyword !== '') { $all_users = array_filter($all_users, function($u) use ($keyword) { $fc = $u['customAttributes']['familyCompany'] ?? ''; $comp = $u['customAttributes']['company'] ?? ''; $name = $u['name'] ?? ''; $disp = $u['displayName'] ?? ''; return ( stripos($fc, $keyword) !== false || stripos($comp, $keyword) !== false || stripos($name, $keyword) !== false || stripos($disp, $keyword) !== false ); }); $all_users = array_values($all_users); } // ✅ 정렬 (최신순) usort($all_users, function($a, $b) use ($mode) { if ($mode === 'created') { return ($b['createdTime'] ?? 0) <=> ($a['createdTime'] ?? 0); } elseif ($mode === 'lastSignIn') { return ($b['customAttributes']['lastSignInDate'] ?? 0) <=> ($a['customAttributes']['lastSignInDate'] ?? 0); } elseif ($mode === 'license') { return ($b['customAttributes']['egBimLExpiryDate'] ?? 0) <=> ($a['customAttributes']['egBimLExpiryDate'] ?? 0); } elseif ($mode === 'serverLogin') { $aTs = !empty($a['customAttributes']['serverLastLogin']) ? strtotime($a['customAttributes']['serverLastLogin']) : 0; $bTs = !empty($b['customAttributes']['serverLastLogin']) ? strtotime($b['customAttributes']['serverLastLogin']) : 0; return $bTs <=> $aTs; } return 0; }); // ✅ 최종 응답 echo json_encode([ 'status' => 'ok', 'count' => count($all_users), 'users' => $all_users, 'filters'=> [ 'start' => $start, 'end' => $end, 'mode' => $mode, 'keyword' => $keyword ] ], JSON_UNESCAPED_UNICODE);