feat: create SanitizeBlogBodiesCommand to clean existing blog bodies according to current HTML sanitization policies
test: add AppointmentTreatmentSessionLinkTest to ensure appointment booking functionality works correctly with treatment session links
- 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.
- Fix tag filtering to correctly match Persian tags by adjusting JSON encoding in the applyTagFilter method.
- Add new endpoint GET /api/v1/blogs/tags to retrieve distinct tag names and their counts for published posts, respecting city scope.
- Update API documentation to reflect changes in tag filtering and the new tags endpoint.
- Create BlogTagFilterTest to ensure correct functionality of tag filtering and facets, including edge cases for Persian tags and city filtering.
- Implemented `adminDetail()` method in `BlogController` to retrieve blog posts of any status for admin editing.
- Introduced `BlogCacheInvalidator` service to handle cache invalidation after blog create/update/delete actions.
- Updated existing methods in `BlogController` and `RepresentationBlogController` to call cache invalidation on blog modifications.
- Enhanced `BlogFormPage` and `RepresentationBlogFormPage` to utilize the new admin endpoint for fetching blog data.
- Added tests for `BlogCacheInvalidator` to ensure proper functionality and error handling.
- Updated documentation to reflect new API endpoint and cache invalidation behavior.
- Introduced new SEO fields (meta_title, meta_description, primary_keyword, secondary_keywords, faq, internal_links, external_links, reading_time, canonical_url, og_image) to the Blog entity.
- Added scheduling capability with a scheduled_at field to manage automatic publishing of blog posts.
- Implemented representative ownership through a foreign key representation_id in the Blog entity, allowing representatives to manage their own posts.
- Updated BlogController and RepresentationBlogController to handle new fields and ensure proper data handling for SEO and scheduling.
- Created BlogWriter service to encapsulate the logic for applying SEO and scheduling fields to blog entities.
- Added PublishScheduledBlogsMessage and its handler to manage the publishing of scheduled blogs.
- Implemented ScheduledBlogPublisher service to publish drafts whose scheduled_at has arrived, respecting review status.
- Created migration to update the database schema with new fields and constraints.
- Added tests to ensure the correct functionality of new features, including SEO fields, representative scope, and scheduled publishing.
- Added new fields to the Blog entity: sources, review_status, reviewer, reviewed_at, review_note, and topic_slug.
- Created API endpoints for reviewing blog posts: GET /api/v1/admin/blog/review-queue and POST /api/v1/admin/blog/{uuid}/review.
- Updated BlogController to handle review logic, including approval and rejection of posts.
- Introduced BlogReviewPage component for admin interface to manage blog reviews.
- Added migration to update the database schema for new fields.
- Implemented tests for review queue functionality and review decision handling.
- Introduced a new nullable city_id column in the blogs table to allow scoping of blog posts to specific cities.
- Updated Blog entity to include a ManyToOne relationship with the City entity.
- Enhanced BlogController to handle city_id in the request, allowing filtering of posts by city.
- Modified BlogRepository to support querying published posts based on city_id.
- Added tests to ensure correct behavior for city-scoped and nationwide posts, including creation and updating of posts with city associations.