docs(.wiki,.tasks): cms-admin-assets-root-folders-seed — DB seed 15 missing root rows
Admin /admin/assets/<siteId>/getList?path= крашился 500 NullReferenceException в AssetsJsonViewModelBuilder.cs:22 (model.ParentPath на null) для 15 sites без root AssetsFolder в Folders table (emspb.ru, pilorama98.ru, labtools.pro, kupimknigi.spb.ru, sestech.ru, aquamax.spb.ru, artmone.pro, priemka-kvartiry.ru, profund.spb.ru, ics-artmaterials.com, _voda-indigo.ru + 4 sites с NULL Domain). Root создавался lazy при first upload — sites которые никогда не использовали admin assets UI остались без root. Frontend (AssetsAppFunc.cs:66-86) делает proper null-check → 404, только admin view-model builder упустил. Fix: idempotent SQL seed (WHERE NOT EXISTS), 15 rows inserted. Inserted FolderId/OwnerId captured в .tasks/...inserted-rows.txt для atomic revert. Browser-verified user'ом на pilorama98/emspb. Долгосрочный TODO: null-guard в AssetsJsonViewModelBuilder.Build (CMS code), требует recompile DLL — отложено до восстановления build env (vds-kzntsv-bootstrap). snapshot open issue #8 → resolved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
# Task Board
|
||||
_Updated: 2026-05-19_
|
||||
|
||||
## 🟢 [cms-admin-assets-root-folders-seed] — seed 15 missing root AssetsFolder rows в DB, admin assets открывается
|
||||
**Status:** done (2026-05-19 вечер). Browser-verified user'ом на pilorama98/emspb. Detail в [[cms-admin-assets-root-folder-seed]].
|
||||
**Result:** 15 rows inserted (idempotent NOT EXISTS query). Affected: emspb.ru, pilorama98.ru, labtools.pro, kupimknigi.spb.ru, sestech.ru, aquamax.spb.ru, artmone.pro, priemka-kvartiry.ru, profund.spb.ru, ics-artmaterials.com, _voda-indigo.ru + 4 sites с NULL PrimaryDomain. Inserted FolderId/OwnerId captured в `.tasks/cms-admin-assets-root-folders-seed.inserted-rows.txt` для atomic revert.
|
||||
**Long-term TODO (deferred):** null-guard в `AssetsJsonViewModelBuilder.Build` (CMS code) — defensive fix чтобы не crash'ить если root missing. Требует recompile `MoreThenCms.Admin.dll`, ждёт build env (`vds-kzntsv-bootstrap`).
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## 🟢 [cms-port-leak-fix] — утечка `:8089`/`:4443` в admin URLs закрыта через URL Rewrite serverVariables
|
||||
**Status:** done (2026-05-19 вечер; verified user-side в браузере, остальные 10 cms работают). Detailed wiki concept — [[cms-server-port-leak-fix]].
|
||||
**Root cause:** `MoreThenCms.Admin\Mis\Web\Mvc\UrlHelpers\UrlHelpers.cs:14-37` `Url.SiteRoot()` читает `SERVER_PORT`/`SERVER_PORT_SECURE` из server vars, и в attempt2-host setup `SERVER_PORT=8089` → leak. Десятки .cshtml файлов (admin views + `_Layout`/`_LogInLayout`) рендерят это в `mis.siteRoot` и `<style background: url(...)>`. На VM работало просто потому что `SERVER_PORT=80` (см. SSH probe VM IIS bind = `*:80`).
|
||||
|
||||
21
cms-admin-assets-root-folders-seed.inserted-rows.txt
Normal file
21
cms-admin-assets-root-folders-seed.inserted-rows.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
(15 rows affected)
|
||||
Tag,FolderId,OwnerId
|
||||
---,--------,-------
|
||||
INSERTED-ROW,580369C8-DB8B-4352-97EB-4F525C989A7C,07E0290C-8735-474E-B494-1230C1E259B3
|
||||
INSERTED-ROW,52A0DE78-BF1C-4F6D-BE2E-7C401D64F690,96EBC481-D26A-47BE-B660-13D49E7D0A61
|
||||
INSERTED-ROW,465E2F07-525B-4772-BBEB-F7965F605966,81B2461F-78C0-40DF-9B13-2B255DE502FC
|
||||
INSERTED-ROW,03150541-5278-4FB5-B815-630A17611B3D,E924A354-0377-4E1E-80C6-2EB0194AA55F
|
||||
INSERTED-ROW,228DDFE9-112E-42BB-8B61-CF88163B94AA,C3B1FD79-663D-4271-A251-380E8B74EB7F
|
||||
INSERTED-ROW,775F159A-72B7-4B2C-BF13-E57F84BDFCCE,2C82EF33-009E-4779-A51E-389C65D4A3D4
|
||||
INSERTED-ROW,0E6B2936-0522-4897-814E-B16FB4091B4C,663F9410-A6CC-4651-9A5C-62844A313957
|
||||
INSERTED-ROW,4BD7784F-7BA4-431B-952A-33D422161191,F8FBBF59-8F34-4327-96CA-63A8103D8EE6
|
||||
INSERTED-ROW,878D64DF-07B5-4973-BAA4-BC7DA4C7C8BE,4DC7E9E4-8D5D-4ECC-9459-84F7A1BF1759
|
||||
INSERTED-ROW,9F368D86-9CB0-48FD-A871-1AA565808BE8,D8E84734-9E35-414D-9342-862A63AD87FB
|
||||
INSERTED-ROW,542AFFDC-4632-4080-B6C6-19611FB2CEA2,592D399B-31C0-4150-9BFD-880CF7A244C5
|
||||
INSERTED-ROW,A7B028C1-D6BD-49FA-8C16-93CF566C6101,37E67FC4-4B9E-4C06-A522-A26A73BAC9B0
|
||||
INSERTED-ROW,7AA0D6AC-94F1-49B7-8FFE-A13A15144A84,F30E83BB-2FCA-40A1-A658-AE7ED22F294F
|
||||
INSERTED-ROW,6033AC61-19F0-4A4C-AD5E-BE54DE64DF6A,5A826EB9-A05A-41D4-A29C-BDEBE926E8DB
|
||||
INSERTED-ROW,AF61A942-23D0-469C-BB89-B7294BD1DB68,1F12D23C-A9A2-4863-A94D-C6278AD7835E
|
||||
|
||||
(15 rows affected)
|
||||
74
cms-admin-assets-root-folders-seed.md
Normal file
74
cms-admin-assets-root-folders-seed.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# cms-admin-assets-root-folders-seed
|
||||
|
||||
## Goal
|
||||
Для каждого `Sites.SiteId` в DB `MoreThenCms` где нет соответствующего root `Folders` row с `Discriminator='AssetsFolder'`, `LoweredPath='/'`, `OwnerId=<SiteId>` — добавить недостающий root row. Это unblock'нёт admin `/admin/assets/<siteId>/getList?path=` который сейчас crash'ит 500 NullReferenceException на пустых assets для 15+ sites (включая `emspb.ru`, `pilorama98.ru`, `labtools.pro`, `kupimknigi.spb.ru`, `sestech.ru`, etc.).
|
||||
|
||||
## Root cause
|
||||
`MoreThenCms.Admin.ViewModels.Builders.AssetsJsonViewModelBuilder.Build` (`AssetsJsonViewModelBuilder.cs:22`) делает `new JValue(model.ParentPath)` БЕЗ null-check на model. `_assetsFoldersService.GetFolderByPath(ctx, ownerId, '')` возвращает null когда root folder не существует. Это происходит для sites которые **никогда не открывали admin assets UI** (root создаётся lazy при first upload, видимо).
|
||||
|
||||
Frontend код (`AssetsAppFunc.cs:66-86`) делает proper null-check → HTTP 404. Только admin view-model builder упустил.
|
||||
|
||||
Двух-уровневое решение:
|
||||
- **Краткосрочно (этой task'и):** seed missing root rows в DB. Один INSERT per site. Risk: minimal (lookup existing row pattern; используем same shape).
|
||||
- **Долгосрочно (отдельный task):** patch `AssetsJsonViewModelBuilder.Build` → null-guard → empty response. Требует recompile DLL `MoreThenCms.Admin.dll` (нет полного build env, рискованно).
|
||||
|
||||
## Key files
|
||||
- `MoreThenCms\Assets\Services\AssetsFoldersService.cs:47-54` — `GetFolderByPath` query (returns null if not found).
|
||||
- `MoreThenCms.Web\ViewModels\Builders\AssetsJsonViewModelBuilder.cs:22` — точка падения.
|
||||
- `MoreThenCms.Web\Admin\Controllers\AssetsController.cs:44-54` — вызов GetList.
|
||||
- DB: `[MoreThenCms].[dbo].[Folders]` (polymorphic, Discriminator='AssetsFolder' для assets).
|
||||
|
||||
## Discovery (2026-05-19)
|
||||
- 15 sites без root AssetsFolder подтверждены через `SELECT s.SiteId, s.PrimaryDomain, ... FROM Sites s LEFT JOIN ...`. См. полный список в Decisions.
|
||||
- Sample existing root row: `FolderId=1591A38C-..., OwnerId=7EB313DD-F289-..., Path='/', LoweredPath='/', DateCreated=2017-03-13 07:10:15, CreatedById=E4CC416B-...`. Тот же shape надо воспроизвести для missing.
|
||||
- Затрагивает: emspb.ru (`96EBC481-...`), pilorama98.ru (`37E67FC4-...`), labtools.pro, kupimknigi.spb.ru, sestech.ru, aquamax.spb.ru, artmone.pro, priemka-kvartiry.ru, profund.spb.ru, ics-artmaterials.com, _voda-indigo.ru, plus 4 sites с NULL `PrimaryDomain`.
|
||||
|
||||
## План
|
||||
1. **Dry-run**: `SELECT COUNT(*) FROM Sites s WHERE NOT EXISTS (root for s.SiteId)` — должно быть = 15 (sanity check).
|
||||
2. **Seed**: INSERT root row per missing site. Один transaction, no rollback unless count mismatch.
|
||||
3. **Verify**: повторить original probe — root count should be 0 missing.
|
||||
4. **Test**: hit `https://emspb.snolla.com/admin/assets/96EBC481-.../getList?path=` (через docker exec без auth → 302→login без crash). Затем user-side browser test.
|
||||
|
||||
## SQL
|
||||
```sql
|
||||
DECLARE @CreatedById uniqueidentifier = (
|
||||
SELECT TOP 1 CreatedById FROM Folders
|
||||
WHERE LoweredPath='/' AND Discriminator='AssetsFolder'
|
||||
);
|
||||
INSERT INTO Folders (FolderId, OwnerId, Path, LoweredPath, DateCreated, UtcDateCreated, CreatedById, Discriminator)
|
||||
SELECT NEWID(), s.SiteId, '/', '/', SYSDATETIME(), SYSUTCDATETIME(), @CreatedById, 'AssetsFolder'
|
||||
FROM Sites s
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM Folders f
|
||||
WHERE f.OwnerId = s.SiteId
|
||||
AND f.LoweredPath = '/'
|
||||
AND f.Discriminator = 'AssetsFolder'
|
||||
);
|
||||
```
|
||||
|
||||
## Atomic revert
|
||||
Сохранить список inserted FolderId через `OUTPUT INSERTED.FolderId` в temp file. Если что:
|
||||
```sql
|
||||
DELETE FROM Folders WHERE FolderId IN (<list>);
|
||||
```
|
||||
|
||||
## Open questions
|
||||
- [ ] Аналогичная проблема для ImagesFolder/StylesheetsFolder/ScriptsFolder в admin Themes UI? Проверить.
|
||||
- [ ] DLL patch `AssetsJsonViewModelBuilder.Build` нужен в долгую — отдельная task. Сейчас обходим seed'ом.
|
||||
|
||||
## Decisions log
|
||||
- 2026-05-19: вынес из `cms-port-leak-fix` (там был open issue #8 на emspb). User подтвердил воспроизводимость на pilorama98 → не site-specific, общая data issue.
|
||||
- 2026-05-19: **DB seed применён** — 15 rows inserted (single transaction, idempotent NOT EXISTS). Inserted FolderId/OwnerId captured в `cms-admin-assets-root-folders-seed.inserted-rows.txt`. Server-side verified (probe вернул 302→login вместо 500). User browser-verified на pilorama98/emspb — admin assets открывается, empty list без ошибок.
|
||||
- 2026-05-19: **DLL recompile отложен** — `AssetsJsonViewModelBuilder.Build` нужен null-guard как defensive code, но требует build env (нет gitea/build/registry на recovery host'е). Ждёт [[vds-kzntsv-bootstrap]] для восстановления pipeline'а. На текущем seed-only fix'е admin assets работает для всех 15 sites.
|
||||
|
||||
## Completed steps
|
||||
- [x] Diagnostic: stack trace из Application event log → `AssetsJsonViewModelBuilder.cs:22` NullRef on `model.ParentPath`. Source code analysis показал отсутствие null-check (vs proper null-check во frontend `AssetsAppFunc.cs:66-86`).
|
||||
- [x] DB probe schema: `Folders` table polymorphic с Discriminator, columns FolderId/OwnerId/Path/LoweredPath/DateCreated/CreatedById обязательные.
|
||||
- [x] Dry-run: 15 sites без root AssetsFolder (включая emspb/pilorama98/labtools.pro/kupimknigi/sestech/etc), 4 sites с NULL PrimaryDomain тоже в списке.
|
||||
- [x] **SQL seed** через `docker exec mssql sqlcmd` — INSERT 15 rows с `OUTPUT INSERTED.FolderId, INSERTED.OwnerId INTO @Inserted`, output saved в `.tasks/cms-admin-assets-root-folders-seed.inserted-rows.txt`.
|
||||
- [x] Verify: missing-root count = 0. Probe `wget --header='Host: emspb.snolla.com'` на getList URL → 302 Found (auth redirect — normal), нет больше 500.
|
||||
- [x] User browser-verified pilorama98 admin assets открывается.
|
||||
- [x] Wiki ingest: новый concept `cms-admin-assets-root-folder-seed.md`, snapshot issue #8 → resolved, `cms-server-port-leak-fix` sibling-link, log.md + index.md обновлены.
|
||||
|
||||
## Notes
|
||||
- Связано: [[cms-server-port-leak-fix]] (предыдущая task'а закрыта; admin URLs теперь без `:8089`); [[recovery-architecture-snapshot]] (issue #8 — resolved); [[vds-kzntsv-bootstrap]] (build env для долгосрочного DLL fix'а).
|
||||
Reference in New Issue
Block a user