diff --git a/lib/Controller/DbController.php b/lib/Controller/DbController.php index 42d19dc..d9b7f1e 100644 --- a/lib/Controller/DbController.php +++ b/lib/Controller/DbController.php @@ -6,49 +6,68 @@ use OCP\AppFramework\Controller; use OCP\IRequest; use OCP\IDBConnection; use OCP\AppFramework\Http\JSONResponse; +use OCP\IGroupManager; +use OCP\IUserSession; class DbController extends Controller { private $db; + private $groupManager; + private $userSession; - public function __construct($AppName, IRequest $request, IDBConnection $db) - { + public function __construct( + $AppName, + IRequest $request, + IDBConnection $db, + IGroupManager $groupManager, + IUserSession $userSession + ) { parent::__construct($AppName, $request); $this->db = $db; + $this->groupManager = $groupManager; + $this->userSession = $userSession; } /** * @NoCSRFRequired - * @PublicPage */ public function query() { - $sql = $this->request->getParam('sql', ''); + // Проверка прав администратора + $user = $this->userSession->getUser(); + if (!$user) { + return new JSONResponse(['error' => 'Not authenticated'], 401); + } - if (empty($sql)) { - return new JSONResponse(['error' => 'Empty query']); + if (!$this->groupManager->isAdmin($user->getUID())) { + return new JSONResponse(['error' => 'Admin privileges required'], 403); } - try { - // Разделяем запросы по точке с запятой - $queries = array_filter(array_map('trim', explode(';', $sql))); - $results = []; + $sql = $this->request->getParam('sql', ''); - foreach ($queries as $query) { - if (empty($query)) continue; - - // Пропускаем SET команды (PostgreSQL specific) - if (stripos($query, 'SET ') === 0) { - $results[] = ['query' => $query, 'type' => 'set', 'result' => 'skipped']; - continue; - } + if (empty(trim($sql))) { + return new JSONResponse(['success' => false, 'error' => 'Empty query']); + } + + // Разделяем запросы по точке с запятой. Все запросы выполняются + // последовательно на одном и том же соединении с БД (в рамках + // одного HTTP-запроса), поэтому SET сохраняет своё значение + // для current_setting() в последующих запросах пачки. + $queries = array_values(array_filter(array_map('trim', explode(';', $sql)), function ($q) { + return $q !== ''; + })); + + $results = []; + + foreach ($queries as $query) { + $isSelect = stripos($query, 'SELECT') === 0; + $isSet = stripos($query, 'SET ') === 0; + + try { + $stmt = $this->db->prepare($query); + $stmt->execute(); - // Определяем тип запроса - $isSelect = stripos($query, 'SELECT') === 0; - if ($isSelect) { - $stmt = $this->db->prepare($query); - $stmt->execute(); $rows = $stmt->fetchAll(); $results[] = [ 'query' => $query, @@ -57,25 +76,26 @@ class DbController extends Controller 'data' => $rows ]; } else { - $stmt = $this->db->prepare($query); - $stmt->execute(); $affected = $stmt->rowCount(); $results[] = [ 'query' => $query, - 'type' => 'write', + 'type' => $isSet ? 'set' : 'write', 'affected_rows' => $affected ]; } + } catch (\Exception $e) { + $results[] = [ + 'query' => $query, + 'type' => 'error', + 'error' => $e->getMessage() + ]; + // Останавливаемся на первой ошибке: не продолжаем выполнять + // оставшиеся запросы пачки (например, серию DELETE), + // если один из предыдущих шагов не выполнился. + break; } - - return new JSONResponse(['success' => true, 'results' => $results]); - - } catch (\Exception $e) { - return new JSONResponse([ - 'success' => false, - 'error' => $e->getMessage(), - 'query' => $sql - ]); } + + return new JSONResponse(['success' => true, 'results' => $results]); } }