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
+51
View File
@@ -108,6 +108,57 @@ class BlogCityScopeTest extends ApiTestCase
$this->assertNull($natDetail['city']);
}
/**
* The detail endpoint must scope exactly like the list: a post owned by
* another city does not exist on this domain. Without this, a post filtered
* out of /api/v1/blogs?city_id=… was still served with a direct URL, so the
* same article appeared on every city domain.
*/
public function testDetailIsNotFoundOnAnotherCityDomain(): void
{
$yasuj = $this->makeCity('یاسوج');
$tabriz = $this->makeCity('تبریز');
$post = $this->makePost('یاسوجی ' . bin2hex(random_bytes(3)), $yasuj);
$this->em->flush();
$this->client->request('GET', '/api/v1/blog/' . $post->getSlug() . '?city_id=' . $tabriz->getId());
$this->assertSame(404, $this->responseCode(), 'another city\'s post must not be readable');
}
public function testDetailIsFoundOnItsOwnCityDomain(): void
{
$yasuj = $this->makeCity('یاسوج');
$post = $this->makePost('یاسوجی ' . bin2hex(random_bytes(3)), $yasuj);
$this->em->flush();
$this->client->request('GET', '/api/v1/blog/' . $post->getUuid() . '?city_id=' . $yasuj->getId());
$this->assertSame(200, $this->responseCode());
}
public function testNationwideDetailIsReadableFromEveryCityDomain(): void
{
$tabriz = $this->makeCity('تبریز');
$post = $this->makePost('سراسری ' . bin2hex(random_bytes(3)), null);
$this->em->flush();
$this->client->request('GET', '/api/v1/blog/' . $post->getSlug() . '?city_id=' . $tabriz->getId());
$this->assertSame(200, $this->responseCode(), 'nationwide posts stay visible on city domains');
}
public function testDetailWithoutCityIdStaysUnscoped(): void
{
$yasuj = $this->makeCity('یاسوج');
$post = $this->makePost('یاسوجی ' . bin2hex(random_bytes(3)), $yasuj);
$this->em->flush();
// The main domain (and any API consumer) omits city_id and sees everything.
$this->client->request('GET', '/api/v1/blog/' . $post->getSlug());
$this->assertSame(200, $this->responseCode());
$this->client->request('GET', '/api/v1/blog/' . $post->getSlug() . '?city_id=');
$this->assertSame(200, $this->responseCode(), 'an empty city_id must not scope the request');
}
public function testAdminCanCreatePostWithAndWithoutCity(): void
{
$admin = $this->createUser(['ROLE_ADMIN']);