getInput()->json; $token = $input->get('token', '', 'RAW'); $origin = $input->get('origin', '', 'STRING'); if (empty($token)) { $this->sendJson(401, ['error' => 'Missing token']); return; } // Validate against the core plugin's health_api_token $plugin = PluginHelper::getPlugin('system', 'mokosuite'); if (!$plugin) { $this->sendJson(503, ['error' => 'MokoSuite core plugin not found']); return; } $params = new Registry($plugin->params); $healthToken = $params->get('health_api_token', ''); if (empty($healthToken) || !hash_equals($healthToken, $token)) { $this->sendJson(401, ['error' => 'Invalid token']); return; } // Find the master user $masterUsernames = $this->getMasterUsernames($params); if (empty($masterUsernames)) { $this->sendJson(403, ['error' => 'No master user configured']); return; } // Use the first master username $masterUsername = $masterUsernames[0]; // Look up the user $db = Factory::getDbo(); $db->setQuery( $db->getQuery(true) ->select([$db->quoteName('id'), $db->quoteName('username')]) ->from($db->quoteName('#__users')) ->where($db->quoteName('username') . ' = ' . $db->quote($masterUsername)) ->where($db->quoteName('block') . ' = 0') ); $user = $db->loadObject(); if (!$user) { $this->sendJson(403, ['error' => 'Master user not found or blocked']); return; } // Generate one-time login token $otlToken = bin2hex(random_bytes(32)); $expires = time() + self::OTL_TTL; // Store in a temp file (avoids DB schema changes) $otlFile = JPATH_ADMINISTRATOR . '/cache/mokosuite_otl_' . md5($otlToken) . '.json'; file_put_contents($otlFile, json_encode([ 'token' => $otlToken, 'user_id' => (int) $user->id, 'username' => $user->username, 'expires' => $expires, 'origin' => substr($origin, 0, 100), ])); // Build login URL $loginUrl = rtrim(Uri::root(), '/') . '/administrator/index.php?mokosuite_otl=' . $otlToken; $this->sendJson(200, [ 'status' => 'ok', 'login_url' => $loginUrl, 'expires' => $expires, 'user' => $user->username, ]); } /** * Decode master usernames from plugin params. * * @param Registry $params Plugin params. * * @return array */ private function getMasterUsernames(Registry $params): array { // Use MokoSuiteHelper if available $helperFile = JPATH_PLUGINS . '/system/mokosuite/Helper/MokoSuiteHelper.php'; if (file_exists($helperFile)) { require_once $helperFile; if (method_exists(\Moko\Plugin\System\MokoSuite\Helper\MokoSuiteHelper::class, 'getMasterUsernames')) { return \Moko\Plugin\System\MokoSuite\Helper\MokoSuiteHelper::getMasterUsernames(); } } return []; } /** * Send JSON response and terminate. * * @param int $code HTTP status code. * @param array $data Response data. * * @return void */ private function sendJson(int $code, array $data): void { http_response_code($code); header('Content-Type: application/json; charset=utf-8'); echo json_encode($data, JSON_UNESCAPED_SLASHES); Factory::getApplication()->close(); } }