feat(blog): add city_id query parameter to blog detail endpoint for domain scoping

This commit is contained in:
hamed
2026-07-24 10:01:30 +03:30
parent e766407bd1
commit c729bb13e0
3 changed files with 85 additions and 4 deletions
+25 -2
View File
@@ -115,6 +115,13 @@ class BlogController extends BaseController
description: 'Blog slug or UUID',
schema: new OA\Schema(type: 'string')
),
new OA\Parameter(
name: 'city_id',
in: 'query',
required: false,
description: 'Domain scope of the caller. A post that belongs to another city is 404 here, exactly as it is absent from GET /api/v1/blogs?city_id=…. Nationwide posts (city IS NULL) are always returned. Omit on the main domain to read any post.',
schema: new OA\Schema(type: 'integer')
),
],
responses: [
new OA\Response(
@@ -133,20 +140,36 @@ class BlogController extends BaseController
]
)
),
new OA\Response(response: 404, description: 'Blog post not found or not published'),
new OA\Response(response: 404, description: 'Blog post not found, not published, or owned by another city'),
]
)]
#[Route('/api/v1/blog/{slug}', methods: ['GET'])]
public function detail(string $slug): JsonResponse
public function detail(string $slug, Request $request): JsonResponse
{
$blog = $this->blogRepo->findBySlug($slug) ?? $this->blogRepo->findByUuid($slug);
if ($blog === null || $blog->getStatus() !== Blog::STATUS_PUBLISHED) {
return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'مقاله یافت نشد', 404);
}
// یک پستِ شهریافته فقط روی دامنهٔ خودش وجود دارد. بدون این شرط، پستی که از
// لیستِ دامنه حذف شده بود همچنان با URL مستقیم روی هر دامنه‌ای ۲۰۰ می‌گرفت و
// همان محتوا روی چند دامنه تکرار می‌شد. پست سراسری (city IS NULL) استثناست.
$cityId = $request->query->get('city_id');
if ($cityId !== null && $cityId !== '' && !$this->isVisibleOnCity($blog, (int) $cityId)) {
return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'مقاله یافت نشد', 404);
}
return $this->success(['data' => $blog->toArray()]);
}
/** آینهٔ BlogRepository::applyCityFilter — پست همان شهر یا پست سراسری. */
private function isVisibleOnCity(Blog $blog, int $cityId): bool
{
$owner = $blog->getCity();
return $owner === null || $owner->getId() === $cityId;
}
// ── Admin CRUD ────────────────────────────────────────────────────────────
#[OA\Get(