diff --git a/ajax/getSupersetGuestToken.php b/ajax/getSupersetGuestToken.php new file mode 100644 index 0000000..f1dfc1d --- /dev/null +++ b/ajax/getSupersetGuestToken.php @@ -0,0 +1,92 @@ + 'Unauthorized')); + exit; +} + +$company_id = isset($_SESSION['agency_id']) ? (int)$_SESSION['agency_id'] : 1; +$user_id = (int)$_SESSION['id']; + +//$_SESSION['role_superset'] = 'manager'; + +if (isset($_SESSION['role_superset']) && !empty($_SESSION['role_superset'])) { + $user_role = $_SESSION['role_superset']; +} else { + if (!empty($_SESSION['agency']) || !empty($_SESSION['users_admin'])) { + $user_role = 'company_head'; + } elseif (!empty($_SESSION['manager'])) { + $user_role = 'manager'; + } else { + $user_role = 'agent'; + } + + $_SESSION['role_superset'] = $user_role; +} + +$dashboard_uuid = isset($_GET['dashboard_id']) ? $_GET['dashboard_id'] : ''; + +// Проверка доступа к дашборду +$dashboard_uuid_esc = mysql_real_escape_string($dashboard_uuid); +$company_id_esc = $company_id; +$user_id_esc = $user_id; + + +if ($user_id == $company_id) { + $sql_check = " + SELECT 1 FROM bi_analytics_dashboard_access + WHERE dashboard_uuid = '$dashboard_uuid_esc' + AND company_id = $company_id_esc + AND is_active = 1 + LIMIT 1 + "; +} else { + $role_level = 0; + if ($user_role == 'agent') $role_level = 1; + elseif ($user_role == 'manager') $role_level = 2; + elseif ($user_role == 'company_head') $role_level = 3; + + $sql_check = " + SELECT 1 FROM bi_analytics_dashboard_access + WHERE dashboard_uuid = '$dashboard_uuid_esc' + AND company_id = $company_id_esc + AND is_active = 1 + AND (user_id = $user_id_esc OR user_id = 0) + AND role_required <= $role_level + LIMIT 1 + "; +} + +$result_check = mysql_query($sql_check); +if (!$result_check || mysql_num_rows($result_check) == 0) { + http_response_code(403); + echo json_encode(array( + 'error' => 'Dashboard access denied', + 'role_level' => $user_role + )); + exit; +} + +// Информация о пользователе +$userInfo = array( + 'first_name' => isset($_SESSION['first_name']) ? $_SESSION['first_name'] : 'User', + 'last_name' => isset($_SESSION['last_name']) ? $_SESSION['last_name'] : (string)$user_id, + 'email' => isset($_SESSION['email']) ? $_SESSION['email'] : null, +); + +$bi = new BiAnalytics(); +$result = $bi->getGuestToken($dashboard_uuid, $company_id, $user_id, $user_role, $userInfo); + +if (isset($result['token'])) { + header('Content-Type: application/json'); + echo json_encode(array('token' => $result['token'])); +} else { + http_response_code(500); + echo json_encode(array('error' => 'Failed to get guest token', 'details' => $result['error'])); +} + +file_put_contents($_SERVER['DOCUMENT_ROOT'] . '/log/superset_guest.log', + date('Y-m-d H:i:s') . "\n" . json_encode($result) . "\n\n", FILE_APPEND); \ No newline at end of file diff --git a/bi-analytics-test.php b/bi-analytics-test.php new file mode 100644 index 0000000..7fc3492 --- /dev/null +++ b/bi-analytics-test.php @@ -0,0 +1,304 @@ + 1, 'manager' => 2, 'company_head' => 3, 'admin' => 4]; + $required_order = isset($role_order[$row['role_required']]) ? $role_order[$row['role_required']] : 1; + $user_order = isset($role_order[$user_role]) ? $role_order[$user_role] : 1; + + if ($user_order >= $required_order) { + $available_dashboards[] = $row; + } +} + +if (empty($available_dashboards)) { + echo '
+

📊 Нет доступных дашбордов

+

Для вашей компании ещё не настроены дашборды BI-аналитики.

+
'; + exit; +} + +$default_dashboard = $available_dashboards[0]; +?> + + + + + + + BI Аналитика — Тестирование + + + + +
+
+

+ 📊 BI Аналитика + Компания ID: + 🧪 Тестовый режим +

+

Тестирование дашбордов Superset

+
+ + 1): ?> +
+ + + +
+ + +
+
+
+ + Загрузка дашборда... +
+
+
+ + +
+ + + + \ No newline at end of file diff --git a/engine/classes/BiAnalytics.php b/engine/classes/BiAnalytics.php new file mode 100644 index 0000000..87c9d1b --- /dev/null +++ b/engine/classes/BiAnalytics.php @@ -0,0 +1,184 @@ +supersetDomain = trim('http://10.91.76.110'); + $this->loginEndpoint = $this->supersetDomain . '/api/v1/security/login'; + $this->guestTokenEndpoint = $this->supersetDomain . '/api/v1/security/guest_token/'; + $this->adminUsername = 'admin'; + $this->adminPassword = '6a6a78543e215c5adce1b828c9a30ef5'; + } + + public static function getAvailableUserIds($userId, $role) + { + if ($role === 'company_head') { + return null; + } + if ($role === 'agent') { + return array($userId); + } + if ($role === 'manager') { + $subordinates = self::getAllSubordinateIds($userId); + $subordinates[] = $userId; + return array_unique($subordinates); + } + return array($userId); + } + + private static function getAllSubordinateIds($managerId) + { + $sql = "SELECT id FROM users WHERE id_manager = " . intval($managerId) . " AND blocked = 0"; + $result = mysql_query($sql); + if (!$result) { + return array(); + } + $subIds = array(); + while ($row = mysql_fetch_assoc($result)) { + $subId = (int)$row['id']; + $subIds[] = $subId; + $subSubIds = self::getAllSubordinateIds($subId); + $subIds = array_merge($subIds, $subSubIds); + } + return $subIds; + } + + public static function buildRlsRules($companyId, $userId, $role) + { + $tables = array( + 'cur.clients_base', + 'bi.client_kpi_daily', + 'logs.client_events', + 'cur.requisitions_base', + 'bi.requisition_kpi_daily', + 'logs.requisition_events' + ); + + $availableUserIds = self::getAvailableUserIds($userId, $role); + $rules = array(); + + // Одно правило company_id на все таблицы (без dataset_name — Superset применит ко всем) + $rules[] = array( + 'clause' => "company_id = {$companyId}" + ); + + // Если не company_head — добавляем фильтр по who_work + if ($availableUserIds !== null) { + $userIdsString = implode(',', $availableUserIds); + $rules[] = array( + 'clause' => "(who_work IN ({$userIdsString}) OR who_work = 0)" + ); + } + + return $rules; + } + + public function getGuestToken($dashboardUuid, $companyId, $userId, $userRole, $userInfo = array()) + { + try { + $accessToken = $this->getAdminAccessToken(); + if (!$accessToken) { + return array('error' => 'Failed to obtain admin access token'); + } + + $rlsRules = self::buildRlsRules($companyId, $userId, $userRole); + + $guestTokenData = array( + 'resources' => array( + array( + 'type' => 'dashboard', + 'id' => $dashboardUuid + ) + ), + 'rls' => $rlsRules, + 'ui_config' => array( + 'show_sql' => in_array($userRole, array('manager', 'company_head', 'admin', 'agent')), + 'url_params' => array( + 'filter_company_id' => (string)$companyId + ) + ), + 'user' => array( + 'username' => 'joywork_user_' . $userId, + 'first_name' => isset($userInfo['first_name']) ? $userInfo['first_name'] : 'User', + 'last_name' => isset($userInfo['last_name']) ? $userInfo['last_name'] : (string)$userId, + 'email' => isset($userInfo['email']) ? $userInfo['email'] : null, + ), + 'attributes' => array( + 'company_id' => $companyId, + 'available_user_ids' => self::getAvailableUserIds($userId, $userRole), + ), + ); + + $response = $this->makeRequest($this->guestTokenEndpoint, $guestTokenData, $accessToken); + if (isset($response['token'])) { + return array('token' => $response['token']); + } else { + return array('error' => 'Guest token not returned', 'details' => $response); + } + } catch (Exception $e) { + return array('error' => $e->getMessage()); + } + } + + private function getAdminAccessToken() + { + $loginData = array( + 'username' => $this->adminUsername, + 'password' => $this->adminPassword, + 'provider' => 'db', + 'refresh' => true, + ); + + $response = $this->makeRequest($this->loginEndpoint, $loginData); + if (isset($response['access_token'])) { + return $response['access_token']; + } + return null; + } + + private function makeRequest($url, $postData, $accessToken = null) + { + $ch = curl_init(); + curl_setopt_array($ch, array( + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode($postData), + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'Accept: application/json', + ), + CURLOPT_SSL_VERIFYPEER => false, + )); + + if ($accessToken) { + $headers = array( + 'Content-Type: application/json', + 'Accept: application/json', + 'Authorization: Bearer ' . $accessToken, + ); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + } + + $responseBody = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($httpCode !== 200) { + throw new Exception("API request failed. HTTP code: $httpCode. Response: $responseBody"); + } + + $decoded = json_decode($responseBody, true); + if (json_last_error() !== JSON_ERROR_NONE) { + throw new Exception("Invalid JSON response: " . json_last_error_msg()); + } + return $decoded; + } +} \ No newline at end of file