229 lines
7.9 KiB
PHP
229 lines
7.9 KiB
PHP
<?php
|
|
header('Content-Type: application/json');
|
|
|
|
// ✅ 타임존 설정 및 디버그용 메타 정보
|
|
date_default_timezone_set('Asia/Seoul');
|
|
$server_timezone = date_default_timezone_get();
|
|
$server_time = date('Y-m-d H:i:s');
|
|
|
|
// ✅ Descope Management Key
|
|
$management_key = 'P2wON5fy1K6kyia269VpeIzYP8oP:K32l5ORmzy32OvaaPvpdZsMY3JmKQb7a3vvrl10PgjlJUGk3K7EssMH3uW5VGQSbrgtEdPj';
|
|
$headers = [
|
|
"Authorization: Bearer $management_key",
|
|
"Content-Type: application/json"
|
|
];
|
|
|
|
$all_users = [];
|
|
$page = 0;
|
|
$limit = 200;
|
|
|
|
// ✅ 1) Descope 전체 유저 조회
|
|
do {
|
|
$url_users = "https://api.descope.com/v2/mgmt/user/search";
|
|
$payload = json_encode(["limit" => $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);
|
|
|
|
// ✅ 2) MySQL에서 최근 로그인 시간 병합
|
|
try {
|
|
$dbHost = getenv('G5_MYSQL_HOST') ?: getenv('MARIADB_HOST') ?: getenv('MYSQL_HOST') ?: 'localhost';
|
|
$dbName = getenv('G5_MYSQL_DB') ?: getenv('MARIADB_DATABASE') ?: getenv('MYSQL_DATABASE') ?: 'egbim';
|
|
$dbUser = getenv('G5_MYSQL_USER') ?: getenv('MARIADB_USER') ?: getenv('MYSQL_USER') ?: 'egbim';
|
|
$dbPass = getenv('G5_MYSQL_PASSWORD') ?: getenv('MARIADB_PASSWORD') ?: getenv('MYSQL_PASSWORD') ?: 'baron3840!!';
|
|
|
|
$pdo = new PDO("mysql:host={$dbHost};dbname={$dbName};charset=utf8mb4", $dbUser, $dbPass, [
|
|
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'];
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
$loginMap = [];
|
|
}
|
|
|
|
// ✅ 3) 날짜 변환 함수 (KST 환경 기준 — 이중 변환 방지)
|
|
$fmtDate = function($val) {
|
|
if (empty($val)) return null;
|
|
if (!is_numeric($val)) return null;
|
|
|
|
$ts = (float) $val;
|
|
if ($ts > 1e12) $ts = $ts / 1000; // 밀리초 → 초 변환
|
|
$ts = (int) round($ts);
|
|
if ($ts <= 0) return null;
|
|
|
|
// ✅ UTC 기준으로 그대로 출력 (PHP의 +9h 보정 방지)
|
|
return gmdate('Y-m-d H:i:s', $ts);
|
|
};
|
|
|
|
// ✅ 4) 유저 데이터 가공
|
|
foreach ($all_users as &$u) {
|
|
|
|
$u['customAttributes'] = $u['customAttributes'] ?? [];
|
|
$u['name'] = $u['name'] ?? '';
|
|
$u['email'] = $u['email'] ?? '';
|
|
$u['phone'] = $u['phone'] ?? '';
|
|
|
|
// --- 테넌트 이름 문자열화 ---
|
|
if (!empty($u['userTenants']) && is_array($u['userTenants'])) {
|
|
$tenantNames = [];
|
|
foreach ($u['userTenants'] as $t) {
|
|
$tenantNames[] = $t['tenantName'] ?? $t['tenantId'] ?? '';
|
|
}
|
|
$u['tenantText'] = implode(', ', array_filter($tenantNames));
|
|
} else {
|
|
$u['tenantText'] = '-';
|
|
}
|
|
|
|
// --- createdTime ---
|
|
if (!empty($u['createdTime'])) {
|
|
$u['createdTime'] = $fmtDate($u['createdTime']);
|
|
}
|
|
|
|
// --- egBimLExpiryDate ---
|
|
if (!empty($u['customAttributes']['egBimLExpiryDate'])) {
|
|
$u['customAttributes']['egBimLExpiryDate'] = $fmtDate($u['customAttributes']['egBimLExpiryDate']);
|
|
}
|
|
|
|
// --- lastSignInDate ---
|
|
if (!empty($u['customAttributes']['lastSignInDate'])) {
|
|
$u['customAttributes']['lastSignInDate'] = $fmtDate($u['customAttributes']['lastSignInDate']);
|
|
}
|
|
|
|
// --- serverLastLogin (EGBIM DB 병합) ---
|
|
$loginId = $u['loginIds'][0] ?? null;
|
|
if ($loginId && isset($loginMap[$loginId])) {
|
|
$u['customAttributes']['serverLastLogin'] = $loginMap[$loginId];
|
|
}
|
|
|
|
// --- completeForm 표시를 true/false → 텍스트로 ---
|
|
if (isset($u['customAttributes']['completeForm'])) {
|
|
$u['customAttributes']['completeForm'] = $u['customAttributes']['completeForm'] ? '완료' : '미완료';
|
|
}
|
|
}
|
|
unset($u);
|
|
|
|
// ✅ 5) 필터링
|
|
$start = $_GET['start'] ?? null;
|
|
$end = $_GET['end'] ?? null;
|
|
$mode = $_GET['mode'] ?? 'created';
|
|
$keyword = $_GET['keyword'] ?? '';
|
|
$tenantFilters = isset($_GET['tenants']) ? explode(',', $_GET['tenants']) : [];
|
|
|
|
function normalize_ts($val) {
|
|
$ts = (int)$val;
|
|
if ($ts > 0 && $ts < 1e12) $ts *= 1000;
|
|
return $ts;
|
|
}
|
|
|
|
// --- 기간 필터 ---
|
|
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 = strtotime($u['createdTime'] ?? '') * 1000;
|
|
} elseif ($mode === 'lastSignIn') {
|
|
$ts = strtotime($u['customAttributes']['lastSignInDate'] ?? '') * 1000;
|
|
} elseif ($mode === 'license') {
|
|
$ts = strtotime($u['customAttributes']['egBimLExpiryDate'] ?? '') * 1000;
|
|
} elseif ($mode === 'serverLogin') {
|
|
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);
|
|
}
|
|
|
|
// --- 테넌트 필터 ---
|
|
if (!empty($tenantFilters)) {
|
|
$all_users = array_filter($all_users, function($u) use ($tenantFilters) {
|
|
$txt = $u['tenantText'] ?? '';
|
|
foreach ($tenantFilters as $t) {
|
|
if (stripos($txt, $t) !== false) return true;
|
|
}
|
|
return false;
|
|
});
|
|
$all_users = array_values($all_users);
|
|
}
|
|
|
|
// --- 키워드 필터 ---
|
|
if ($keyword !== '') {
|
|
$all_users = array_filter($all_users, function($u) use ($keyword) {
|
|
$fields = [
|
|
$u['customAttributes']['familyCompany'] ?? '',
|
|
$u['customAttributes']['company'] ?? '',
|
|
$u['name'] ?? '',
|
|
$u['displayName'] ?? ''
|
|
];
|
|
foreach ($fields as $f) {
|
|
if (stripos($f, $keyword) !== false) return true;
|
|
}
|
|
return false;
|
|
});
|
|
$all_users = array_values($all_users);
|
|
}
|
|
|
|
// --- 정렬 ---
|
|
usort($all_users, function($a, $b) use ($mode) {
|
|
if ($mode === 'created') {
|
|
return strcmp($b['createdTime'] ?? '', $a['createdTime'] ?? '');
|
|
} elseif ($mode === 'lastSignIn') {
|
|
return strcmp($b['customAttributes']['lastSignInDate'] ?? '', $a['customAttributes']['lastSignInDate'] ?? '');
|
|
} elseif ($mode === 'license') {
|
|
return strcmp($b['customAttributes']['egBimLExpiryDate'] ?? '', $a['customAttributes']['egBimLExpiryDate'] ?? '');
|
|
} elseif ($mode === 'serverLogin') {
|
|
return strcmp($b['customAttributes']['serverLastLogin'] ?? '', $a['customAttributes']['serverLastLogin'] ?? '');
|
|
}
|
|
return 0;
|
|
});
|
|
|
|
|
|
// ✅ 6) 최종 응답 (타임존 정보 포함)
|
|
echo json_encode([
|
|
'status' => 'success', // ✅ "ok" 대신 "success"로
|
|
'total' => count($all_users),
|
|
'records' => $all_users,
|
|
'msg' => '', // ✅ w2ui 기본 필드 추가
|
|
'meta' => [
|
|
'timezone' => $server_timezone,
|
|
'server_time' => $server_time
|
|
]
|
|
], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
|
?>
|