Update index.js
This commit is contained in:
+92
-83
@@ -1,92 +1,101 @@
|
|||||||
(function(OC, window, $, undefined) {
|
<?php
|
||||||
'use strict';
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
namespace OCA\OCCWeb\Controller;
|
||||||
var sqlMode = false;
|
|
||||||
|
use OCP\AppFramework\Controller;
|
||||||
var term = $('body').terminal(function(command, term) {
|
use OCP\IRequest;
|
||||||
if (command === '') {
|
use OCP\IDBConnection;
|
||||||
return;
|
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,
|
||||||
|
IGroupManager $groupManager,
|
||||||
|
IUserSession $userSession
|
||||||
|
) {
|
||||||
|
parent::__construct($AppName, $request);
|
||||||
|
$this->db = $db;
|
||||||
|
$this->groupManager = $groupManager;
|
||||||
|
$this->userSession = $userSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoCSRFRequired
|
||||||
|
*/
|
||||||
|
public function query()
|
||||||
|
{
|
||||||
|
// Проверка прав администратора
|
||||||
|
$user = $this->userSession->getUser();
|
||||||
|
if (!$user) {
|
||||||
|
return new JSONResponse(['error' => 'Not authenticated'], 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Команды переключения режимов
|
if (!$this->groupManager->isAdmin($user->getUID())) {
|
||||||
if (command === ':sql') {
|
return new JSONResponse(['error' => 'Admin privileges required'], 403);
|
||||||
sqlMode = true;
|
|
||||||
term.set_prompt('sql $ ');
|
|
||||||
term.echo('SQL mode enabled. Type :occ to return to OCC mode.');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command === ':occ') {
|
$sql = $this->request->getParam('sql', '');
|
||||||
sqlMode = false;
|
|
||||||
term.set_prompt('occ $ ');
|
if (empty(trim($sql))) {
|
||||||
term.echo('OCC mode enabled.');
|
return new JSONResponse(['success' => false, 'error' => 'Empty query']);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command === ':help') {
|
// Разделяем запросы по точке с запятой. Все запросы выполняются
|
||||||
term.echo('Available commands:');
|
// последовательно на одном и том же соединении с БД (в рамках
|
||||||
term.echo(' :sql - Switch to SQL mode');
|
// одного HTTP-запроса), поэтому SET сохраняет своё значение
|
||||||
term.echo(' :occ - Switch to OCC mode');
|
// для current_setting() в последующих запросах пачки.
|
||||||
term.echo(' :help - Show this help');
|
$queries = array_values(array_filter(array_map('trim', explode(';', $sql)), function ($q) {
|
||||||
term.echo('');
|
return $q !== '';
|
||||||
term.echo('In OCC mode: execute Nextcloud occ commands');
|
}));
|
||||||
term.echo('In SQL mode: execute SQL queries directly');
|
|
||||||
return;
|
$results = [];
|
||||||
}
|
|
||||||
|
foreach ($queries as $query) {
|
||||||
term.pause();
|
$isSelect = stripos($query, 'SELECT') === 0;
|
||||||
|
$isSet = stripos($query, 'SET ') === 0;
|
||||||
if (sqlMode) {
|
|
||||||
// SQL режим
|
try {
|
||||||
$.post(OC.generateUrl('/apps/occweb/db/query'), {
|
$stmt = $this->db->prepare($query);
|
||||||
sql: command
|
$stmt->execute();
|
||||||
}, function(response) {
|
|
||||||
if (response.success) {
|
if ($isSelect) {
|
||||||
response.results.forEach(function(result) {
|
$rows = $stmt->fetchAll();
|
||||||
if (result.type === 'select') {
|
$results[] = [
|
||||||
term.echo('Query: ' + result.query);
|
'query' => $query,
|
||||||
term.echo('Rows: ' + result.count);
|
'type' => 'select',
|
||||||
if (result.data.length > 0) {
|
'count' => count($rows),
|
||||||
term.echo(JSON.stringify(result.data, null, 2));
|
'data' => $rows
|
||||||
} else {
|
];
|
||||||
term.echo('(no results)');
|
|
||||||
}
|
|
||||||
} else if (result.type === 'write') {
|
|
||||||
term.echo('Query: ' + result.query);
|
|
||||||
term.echo('Affected rows: ' + result.affected_rows);
|
|
||||||
} else if (result.type === 'set') {
|
|
||||||
term.echo('Skipped: ' + result.query);
|
|
||||||
}
|
|
||||||
term.echo('');
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
term.echo('ERROR: ' + response.error);
|
$affected = $stmt->rowCount();
|
||||||
|
$results[] = [
|
||||||
|
'query' => $query,
|
||||||
|
'type' => $isSet ? 'set' : 'write',
|
||||||
|
'affected_rows' => $affected
|
||||||
|
];
|
||||||
}
|
}
|
||||||
term.resume();
|
} catch (\Exception $e) {
|
||||||
}).fail(function(xhr, status, error) {
|
$results[] = [
|
||||||
term.echo('ERROR: Request failed - ' + error);
|
'query' => $query,
|
||||||
term.resume();
|
'type' => 'error',
|
||||||
});
|
'error' => $e->getMessage()
|
||||||
} else {
|
];
|
||||||
// OCC режим
|
// Останавливаемся на первой ошибке: не продолжаем выполнять
|
||||||
$.post(OC.generateUrl('/apps/occweb/cmd'), {
|
// оставшиеся запросы пачки (например, серию DELETE),
|
||||||
command: command
|
// если один из предыдущих шагов не выполнился.
|
||||||
}, function(response) {
|
break;
|
||||||
term.echo('\n' + response).resume();
|
}
|
||||||
}).fail(function(xhr, status, error) {
|
|
||||||
term.echo('ERROR: Request failed - ' + error);
|
|
||||||
term.resume();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, {
|
|
||||||
prompt: 'occ $ ',
|
|
||||||
name: 'occweb',
|
|
||||||
greetings: 'Nextcloud OCC Web Terminal\nType :help for available commands\n',
|
|
||||||
onBlur: function() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
})(OC, window, jQuery);
|
return new JSONResponse(['success' => true, 'results' => $results]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user