feat: add BlogBodySanitizer for HTML sanitization on article save

- Implemented BlogBodySanitizer to clean HTML content before saving articles, ensuring security against XSS attacks.
- Added tests for BlogBodySanitizer to verify that unsafe tags and attributes are stripped from the content.
- Introduced ApiLeastPrivilegeTest to ensure that unauthorized users cannot access sensitive API routes, maintaining strict access control.
This commit is contained in:
hamed
2026-08-07 21:13:38 +03:30
parent a4a24c51af
commit 6876135a53
114 changed files with 2067 additions and 269 deletions
+7 -3
View File
@@ -40,7 +40,10 @@ late shifts the rest of their course rather than getting the next session too ea
## GET `/api/v1/service-item/{uuid}/treatment-protocol`
**Permission:** `IS_AUTHENTICATED_FULLY`, محدود به محیط جاری — سرویس محیط دیگر `404` می‌گیرد.
**Permission:** `IS_AUTHENTICATED_FULLY` + `services.view`, محدود به محیط جاری — سرویس محیط دیگر
`404` می‌گیرد. پروتکل خاصیتِ سرویس است، پس همان مجوزِ `services` را می‌گیرد، نه مجوز `treatment`
که برای پروندهٔ درمان است. گیتِ مجوز **پیش از** واکشی سرویس اجرا می‌شود، پس منشیِ بدون
`services.view` روی uuid ناموجود هم `403` می‌گیرد نه `404`.
`data: null` یعنی سوییچ خاموش است، نه اینکه چیزی پیدا نشد.
@@ -93,7 +96,7 @@ Everything is validated **before** anything is written: an invalid step at the e
not wipe the valid steps already stored. Steps and staff are then cleared and rewritten inside one
transaction.
**Permission:** `IS_AUTHENTICATED_FULLY`, محدود به محیط جاری.
**Permission:** `IS_AUTHENTICATED_FULLY` + `services.update`, محدود به محیط جاری.
### Request Body (`application/json`)
| Field | Type | Required | توضیح |
@@ -189,7 +192,8 @@ A no-show does not burn the session: its status becomes `no_show`, its appointme
Turn the switch off — the protocol, its steps and its staff list are removed and the service is
single-session again. Idempotent: deleting a service that has no protocol still answers `200`.
**Permission:** `IS_AUTHENTICATED_FULLY`, محدود به محیط جاری.
**Permission:** `IS_AUTHENTICATED_FULLY` + `services.update`, محدود به محیط جاری. عمداً `update`
است نه `delete`: سرویس حذف نمی‌شود، فقط سوییچِ «طول درمان» روی همان سرویس خاموش می‌شود.
### Response `200`
```json