--- title: MoreThenCms admin (RUVDS) — App_Data RX-only после scp-миграции → HTTP 500 на любой записи (delete/upload) status: fixed 2026-07-03 (Modify выдан на весь App_Data) tags: [cms, snolla, morethencms, iis, ruvds, acl, permissions, migration, assets, 500] related: [[galleries-storage-class-local-not-s3]], [[../entities/ruvds-iis-host]], [[../sources/iis-migration-to-ruvds-2026-05-23]] updated: 2026-07-03 --- # App_Data RX-only → 500 на записи из админки ## Симптом `POST /admin/assets//delete?path=/&filename=` → **HTTP 500**. В IIS-логе (`C:\inetpub\logs\LogFiles\W3SVC1\`, время в **UTC**; сервер MSK=UTC+3) — `sc-status 500 sc-substatus 0 sc-win32-status 0` = чистое managed-исключение, не IIS-уровень. В Windows **Application Event Log пусто**, файловых логов CMS нет → ASP.NET глотает исключение default-handler'ом. GET того же URL → 404 (delete только `[HttpPost]`). ## Root cause — ACL, не код и не MinIO App pool `snolla` = **ApplicationPoolIdentity** → процесс бежит как `IIS AppPool\snolla`. После scp-миграции 2026-05-23 bootstrap выдал этому аккаунту на дереве контента **только `(RX)` (Read&Execute)**, без Modify: ``` C:\sites\snolla\App_Data IIS APPPOOL\snolla:(OI)(CI)(RX) ← только чтение ...\labtools-price.pdf IIS APPPOOL\snolla:(I)(RX) ``` Провайдер `assets` в `` = `MoreThenCms.FileStorage.Local.AssetsStorage` (**локальный диск**, `App_Data\assets\\`; `basePath=""`) — см. [[galleries-storage-class-local-not-s3]]. Код-путь удаления: `AssetsController.Delete` → `AssetsService.DeleteAsset` (`MoreThenCms/Assets/Services/AssetsService.cs:84`): `FileExists` (RX-чтение ок → true) → **`DeleteFile` = `File.Delete`** под identity с RX → `UnauthorizedAccessException` → необработанное → **500**. DB-delete (строкой ниже) даже не достигается. `RX` не содержит право DELETE, и на родителе нет `DC` (delete-child) → удалять нечем. `BUILTIN\Users:(AD)(WD)` не спасает — виртуальный аккаунт пула в `IIS_IUSRS`, не в `Users`; и AD/WD — создание, не удаление. **Дифдиагностика (чем исключены NRE-версии):** в БД `mssql.kzntsv.site` подтверждены обе строки — `Folders` (root-папка owner'а, `Path='/'`, `Discriminator=AssetsFolder`) и `Files` (`StorageClient='assets'`, `StorageFilename=`), поэтому `GetFolderByPath(...).Id` и `asset.Folder` не-null, выполнение доходит именно до `File.Delete`. Единственная падающая операция — физическое удаление. **Класс проблемы шире delete:** RX-only убивает ВСЕ Local-записи из админки — upload ассетов, `contentCache`/`uploadCache`/`imageCache`, галереи, watermarks. Всё это классы Local в `App_Data`. ## Fix (применён 2026-07-03) ```powershell # на RUVDS IIS (80.64.31.36), от Administrator icacls "C:\sites\snolla\App_Data" /grant "IIS AppPool\snolla:(OI)(CI)(M)" /T /C ``` `(M)`=Modify (включает DELETE+WRITE), `(OI)(CI)`=наследование на файлы+подпапки, `/T`=протянуть на существующие. Результат: **44293 файла, 0 ошибок**. Проверка: на целевом файле теперь `IIS APPPOOL\snolla:(I)(M)`. Рестарт пула не нужен — ACL применяется на лету. Живой delete-тест намеренно НЕ гонялся (удалил бы реальный ассет); доказательство = ACL на точном таргете + протрассированный код-путь. ## Split-brain: админка ≠ боевой сайт Админка MoreThenCms живёт на **RUVDS IIS** и читает/пишет **локальный** `App_Data`. Боевой snolla-app (labtools.ru и др. на [[../entities/vds-kzntsv]]) отдаёт ассеты/галереи из **MinIO** (`minio.kzntsv.site` = books-vds, bucket `assets//`), см. [[galleries-storage-class-local-not-s3]]. Классы мигрированы в S3 (галереи 12.06, assets 13.06), но **админка на S3 не переключена** → любая правка ассета через админку меняет только локалку IIS и НЕ отражается на боевом сайте (и наоборот). Пока админка не repointed на S3 — правки зеркалить руками в оба места. Пример (2026-07-03): замена `labtools-price.pdf` (ownerId `d375c419…`) — новый файл залит **и** в MinIO (`mc cp --attr Content-Type=application/pdf … snm/assets/d375c419…/labtools-price.pdf`, ETag→`6426ddd0…`) **и** на локальный диск IIS (scp, MD5 сверен). Оба слоя = байт-в-байт с исходником. ## TODO (настоящее закрытие split-brain) Переключить админский ``-класс `assets` (и `galleries` и пр.) на S3-провайдер, указывающий на `minio.kzntsv.site` — тогда админка и боевой app работают с одним хранилищем, ручное зеркалирование и ACL на App_Data перестают быть нужны. Это код/конфиг-таска на стороне MoreThenCms.