5 Commits

Author SHA1 Message Date
dillard 040743d351 Credit fanategorius and Git-Usr123 forks in README 2026-09-11 17:52:59 +02:00
dillard 85890e12db Update README to reflect active fork status, drop stale Russian translation
Also backport OccController's getConfig() -> IConfig::class fix (deprecated
internal API -> stable OCP interface), spotted while comparing against
Git-Usr123/occweb.
2026-09-11 17:40:12 +02:00
dillard cd01a2fa17 Merge branch 'fix/fetch-return-type-php81' into deploy-nc01 2026-08-09 13:06:32 +02:00
dillard a4a8f9a4eb Fix missing admin check on OccController routes (security)
index(), cmd() and list() were accessible to any logged-in user.
The navigation menu already restricts visibility to admins, but the
routes themselves were unprotected — any authenticated user who knows
the URL could execute occ commands or list all available commands.

Fix: inject IGroupManager + IUserSession, add requireAdmin() helper,
call it at the start of all three public methods. Matches the pattern
already used in DbController.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 22:04:05 +02:00
dillard f681caca35 Fix OccOutput::fetch() return type for PHP 8.1+ compatibility
BufferedOutput::fetch() declares a string return type in Symfony 5+.
PHP 8.1 enforces return type compatibility with parent methods, causing
a fatal 500 error when the occweb page loads.

Fix: add ': string' return type to OccOutput::fetch().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 21:25:56 +02:00
4 changed files with 48 additions and 135 deletions
+26 -7
View File
@@ -1,15 +1,34 @@
# ⚠️ Deprecated ⚠️ OCCWeb terminal # OCCWeb terminal (maintained fork)
*Читать на [русском](README.ru.md).*
### A web terminal for admins to launch Nextcloud's occ commands ### A web terminal for admins to launch Nextcloud's occ commands
![occweb](https://github.com/Adphi/OCCWeb/raw/main/appinfo/screenshot.png) ![occweb](https://github.com/Adphi/OCCWeb/raw/main/appinfo/screenshot.png)
## About this fork
## ⚠️ Deprecated ⚠️ The original [Adphi/occweb](https://github.com/Adphi/occweb) was marked deprecated by its
As nextcloudd has no native support for asynchronous operations, due to the use of php, this aplication is deprecated, and will no longer support the Nextcloud' future versions (19+). I did not find a way to implemement true support for interactive and long running occ tasks in a web terminal whitout introducing addtional dependencies (through websockets, for example), the lack of true asynchronous occ operations can lead to serious alterations of voluminous instances. author and is unmaintained. This fork tracks [fanategorius/occweb](https://github.com/fanategorius/occweb),
[This issue](https://github.com/nextcloud/server/issues/16726) may give some hints on why I decided to not support this application anymore. which picked up compatibility maintenance where Adphi left off, and adds SQL query mode,
security hardening (admin checks, CSRF/confirmation flows, transactional batches), and PHP
8.1+ compatibility fixes on top.
### Credits
- [Adphi/occweb](https://github.com/Adphi/occweb) — original author/project.
- [fanategorius/occweb](https://github.com/fanategorius/occweb) — the actively maintained
fork this repo is based on and tracks.
- [Git-Usr123/occweb](https://github.com/Git-Usr123/occweb) — independent fork; the
`OC::$server->getConfig()` → `OC::$server->get(\OCP\IConfig::class)` fix in
`OccController.php` was spotted there and backported here.
**This tool is still not the right place for big/risky operations.** It has no support for
asynchronous or long-running tasks — every command runs synchronously inside a single PHP
web request, so anything that takes a while (`occ files:scan` on a large instance, a Nextcloud
major-version `occ upgrade`, `occ maintenance:mode --on` workflows) can time out mid-operation
with no way to recover cleanly. Use a real shell (SSH + `occ` directly, or the guest-agent/
console) for major upgrades and other long-running or high-blast-radius operations; reserve
this terminal for routine day-to-day occ/SQL admin tasks. [This issue](https://github.com/nextcloud/server/issues/16726)
has background on why Nextcloud has no native async support for occ tasks.
## Install ## Install
@@ -110,4 +129,4 @@ This does not apply on a fresh `occ app:enable` install — that command sets
`installed_version` correctly on its own. `installed_version` correctly on its own.
## TODOs: ## TODOs:
See [open issues](https://github.com/Adphi/occweb/issues) See [open issues](https://github.com/dillardblom/occweb/issues)
-126
View File
@@ -1,126 +0,0 @@
# ⚠️ Устарело ⚠️ OCCWeb terminal
*Read in [English](README.md).*
### Веб-терминал для администраторов для запуска occ-команд Nextcloud
![occweb](https://github.com/Adphi/OCCWeb/raw/main/appinfo/screenshot.png)
## ⚠️ Устарело ⚠️
Поскольку Nextcloud не имеет встроенной поддержки асинхронных операций
(из-за использования PHP), это приложение считается устаревшим и больше не
будет поддерживать будущие версии Nextcloud (19+). Автору не удалось найти
способ реализовать полноценную поддержку интерактивных и долгих occ-задач в
веб-терминале без введения дополнительных зависимостей (например, через
websockets), а отсутствие настоящей асинхронности может привести к серьёзным
проблемам на больших инсталляциях.
[Этот issue](https://github.com/nextcloud/server/issues/16726) объясняет,
почему разработчик решил больше не поддерживать это приложение.
## Установка
Сборка не нужна (чистый PHP + vanilla JS). Клонируйте прямо в `apps/`
целевого сервера и запустите установочный скрипт:
```bash
cd /var/www/nextcloud/apps
git clone https://github.com/fanategorius/occweb.git
bash occweb/install.sh
```
`install.sh` удаляет dev/CI-файлы, не нужные для работающей установки
(`tests/`, `.travis.yml`, `phpunit*.xml`, `composer.json`, `composer.lock`,
`Makefile`), выставляет `chown -R` на пользователя веб-сервера и выполняет
`occ app:enable`. По умолчанию считает, что Nextcloud лежит в
`/var/www/nextcloud`, а пользователь веб-сервера — `www-data`; если у вас
иначе, передайте своими аргументами:
```bash
bash occweb/install.sh /path/to/nextcloud custom-web-user
```
`occ app:enable` сам корректно проставит версию приложения в базе, поэтому
оговорки из раздела «Обновление кода на сервере» ниже к свежей установке не
относятся — они актуальны только когда приложение уже включено и вы
обновляете его на месте.
Перед установкой сверьте версию вашего Nextcloud с диапазоном в
`appinfo/info.xml` (`dependencies/nextcloud`, `min-version`/`max-version`)
— `occ app:enable` откажется включать приложение вне этого диапазона.
Учтите: `install.sh` удаляет файлы, отслеживаемые в git. Если планируете
дальше обновлять эту установку через `git pull`, а не пере-клонированием —
имейте в виду, что будущее изменение одного из удалённых файлов в апстриме
может привести к отказу `git pull` смёржить изменения. Git сам сообщит об
этом, и файл можно вернуть командой `git checkout -- <file>`.
## Режим SQL-запросов
Введите `sql` в терминале, чтобы переключиться в режим SQL-запросов и
выполнять произвольные SQL-запросы напрямую к базе данных Nextcloud (только
для администраторов). Запросы разделяются `;`. Используйте **Shift+Enter**
для перехода на новую строку и **Enter**, чтобы отправить весь блок одним
запросом — это важно для скриптов вида
`SET vars.x = 'value'; SELECT current_setting('vars.x');`, так как все
запросы, отправленные одним блоком, выполняются в рамках одного соединения
(сессии) с базой данных. Введите `occ`, чтобы вернуться в обычный режим
occ-команд.
⚠️ Для `DELETE`/`UPDATE` нет отмены — внимательно проверяйте, что вы
собираетесь выполнить, желательно сначала на некритичной записи/пользователе.
## ⚠️ Предупреждения ⚠️
- Это приложение не является настоящим интерактивным терминалом и не
поддерживает долгие задачи.
Поэтому на крупных инсталляциях команды вроде `occ files:scan` могут
завершаться по таймауту с ошибкой.
- Не используйте `occ maintenance:mode --on`, это очевидно...
- Шаблон `rename-user` — это **best-effort**, а не официально поддерживаемая
Nextcloud операция. Он обновляет только известные таблицы ядра
(`oc_users`, `oc_preferences`, `oc_group_user`, `oc_group_admin`,
`oc_ldap_user_mapping`, `oc_share`, `oc_mounts`, `oc_storages`), но **не**
трогает таблицы сторонних приложений (Talk, Calendar, Contacts, Mail,
двухфакторная аутентификация/WebAuthn и т.д.). Дополнительно нужно вручную
переименовать каталог данных пользователя на диске (`data/<старый> ->
data/<новый>`) при остановленном веб-сервере или в режиме обслуживания, а
затем выполнить `occ files:scan --all`. Сначала сделайте бэкап базы и
протестируйте на некритичном аккаунте.
## Обновление кода на сервере
После того как новый код скопирован/спуллен в `nextcloud/apps/occweb/`,
обязательно перезапустите PHP, иначе изменения не применятся. `occ
app:disable`/`app:enable` **не помогает** — эта команда не сбрасывает
opcode-кэш PHP, из-за чего может продолжать работать старая закэшированная
версия кода (характерный симптом — маршруты внезапно отвечают 404).
Перезапустите сам процесс PHP, например:
```bash
sudo systemctl restart php8.3-fpm # укажите свою версию PHP
sudo systemctl restart apache2 # если PHP работает как модуль Apache
```
### Если меняете `<version>` в `appinfo/info.xml`
Nextcloud хранит установленную версию каждого приложения в базе
(`installed_version` в `oc_appconfig`) отдельно от `<version>` в
`info.xml`. Если вы правите файлы на месте (копированием/`git pull`), а не
через App Store или `occ upgrade`, эти два значения расходятся — и
Nextcloud считает, что «инстансу нужен апгрейд», блокируя большинство
`occ`-команд за CLI-визардом обновления, хотя само ядро Nextcloud никак не
менялось. После бампа версии синхронизируйте её вручную:
```bash
sudo -u www-data php /var/www/nextcloud/occ config:app:set occweb installed_version --value="X.Y.Z"
```
(то же значение `X.Y.Z`, что и в новом `<version>`), затем перезапустите
PHP, как описано выше. На свежую установку через `occ app:enable` это не
распространяется — там версия проставляется корректно автоматически.
## Планы (TODO):
См. [открытые issues](https://github.com/Adphi/occweb/issues)
+21 -1
View File
@@ -9,6 +9,7 @@ use OC\MemoryInfo;
use OCP\IRequest; use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -31,7 +32,7 @@ class OccController extends Controller
$this->application = new Application( $this->application = new Application(
OC::$server->get(\OCP\ServerVersion::class), OC::$server->get(\OCP\ServerVersion::class),
OC::$server->getConfig(), OC::$server->get(\OCP\IConfig::class),
OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class), OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class),
new FakeRequest(), new FakeRequest(),
$this->logger, $this->logger,
@@ -47,11 +48,28 @@ class OccController extends Controller
$this->symphonyApplication = $reflectionProperty->getValue($this->application); $this->symphonyApplication = $reflectionProperty->getValue($this->application);
} }
private function requireAdmin(): ?JSONResponse
{
// Services via OC::$server zodat de constructor-signatuur ongewijzigd blijft
// en NC's DI-container (zonder application.php) de class kan resolven.
$userSession = OC::$server->get(\OCP\IUserSession::class);
$user = $userSession->getUser();
if ($user === null) {
return new JSONResponse(['error' => 'Not authenticated'], 401);
}
$groupManager = OC::$server->get(\OCP\IGroupManager::class);
if (!$groupManager->isAdmin($user->getUID())) {
return new JSONResponse(['error' => 'Admin privileges required'], 403);
}
return null;
}
/** /**
* @NoCSRFRequired * @NoCSRFRequired
*/ */
public function index() public function index()
{ {
if ($err = $this->requireAdmin()) return $err;
return new TemplateResponse('occweb', 'index'); return new TemplateResponse('occweb', 'index');
} }
@@ -76,6 +94,7 @@ class OccController extends Controller
*/ */
public function cmd($command) public function cmd($command)
{ {
if ($err = $this->requireAdmin()) return $err;
$this->logger->debug($command); $this->logger->debug($command);
$input = new StringInput($command); $input = new StringInput($command);
$response = $this->run($input); $response = $this->run($input);
@@ -84,6 +103,7 @@ class OccController extends Controller
} }
public function list() { public function list() {
if ($err = $this->requireAdmin()) return $err;
$defs = $this->symphonyApplication->all(); $defs = $this->symphonyApplication->all();
$cmds = array(); $cmds = array();
foreach ($defs as $d) { foreach ($defs as $d) {
+1 -1
View File
@@ -35,7 +35,7 @@ class OccOutput extends BufferedOutput implements ConsoleOutputInterface
); );
} }
public function fetch() public function fetch(): string
{ {
// Получаем основной буфер // Получаем основной буфер
$content = parent::fetch(); $content = parent::fetch();