소스 검색

fix post creation

master
Daniel 2 년 전
부모
커밋
69d3cc25dd
9개의 변경된 파일202개의 추가작업 그리고 91개의 파일을 삭제
  1. +2
    -0
      src/ApiResource/ContactApi.php
  2. +2
    -1
      src/ApiResource/PostingApi.php
  3. +1
    -1
      src/ApiResource/UserApi.php
  4. +2
    -1
      src/Entity/Contact.php
  5. +4
    -8
      src/Entity/Posting.php
  6. +17
    -3
      src/Mapper/ContactApiToEntityMapper.php
  7. +27
    -14
      src/Mapper/PostingApiToEntityMapper.php
  8. +81
    -0
      tests/Functional/PostingResourceTest.php
  9. +66
    -63
      tests/Functional/UserResourceTest.php

+ 2
- 0
src/ApiResource/ContactApi.php 파일 보기

@@ -78,7 +78,9 @@ class ContactApi
/**
* @var array<int, PostingApi>
*/
#[ApiProperty(writable: false)]
public array $postings = [];

#[ApiProperty(writable: false)]
public ?\DateTimeImmutable $createdAt = null;
}

+ 2
- 1
src/ApiResource/PostingApi.php 파일 보기

@@ -60,7 +60,8 @@ class PostingApi
#[NotBlank]
public ?string $message = null;

#[IsValidOwner]
//#[IsValidOwner]
#[ApiProperty(writable: false)]
public ?UserApi $owner = null;

#[ApiProperty(writable: false)]


+ 1
- 1
src/ApiResource/UserApi.php 파일 보기

@@ -29,7 +29,7 @@ use Symfony\Component\Validator\Constraints as Assert;
security: 'is_granted("ROLE_USER")'
),
new Post(
security: 'is_granted("PUBLIC_ACCESS")',
security: 'is_granted("ROLE_ADMIN")',
validationContext: ['groups' => ['Default', 'postValidation']],
),
new Patch(


+ 2
- 1
src/Entity/Contact.php 파일 보기

@@ -48,8 +48,9 @@ class Contact
#[ORM\OneToMany(mappedBy: 'contact', targetEntity: Posting::class, orphanRemoval: true)]
private Collection $postings;

public function __construct()
public function __construct(Partner $partner)
{
$this->partner = $partner;
$this->createdAt = new \DateTimeImmutable();
$this->postings = new ArrayCollection();
}


+ 4
- 8
src/Entity/Posting.php 파일 보기

@@ -39,8 +39,11 @@ class Posting
#[ORM\OneToMany(mappedBy: 'posting', targetEntity: Comment::class, orphanRemoval: true)]
private Collection $comments;

public function __construct()
public function __construct(User $owner, Partner $partner, Contact $contact = null)
{
$this->owner = $owner;
$this->partner = $partner;
$this->contact = $contact;
$this->createdAt = new \DateTimeImmutable();
$this->comments = new ArrayCollection();
}
@@ -72,13 +75,6 @@ class Posting
return $this->owner;
}

public function setOwner(?User $owner): static
{
$this->owner = $owner;

return $this;
}

public function getHeadline(): ?string
{
return $this->headline;


+ 17
- 3
src/Mapper/ContactApiToEntityMapper.php 파일 보기

@@ -4,6 +4,8 @@ namespace App\Mapper;

use App\ApiResource\ContactApi;
use App\Entity\Contact;
use App\Entity\Partner;
use App\Repository\ContactRepository;
use App\Repository\PartnerRepository;
use Symfony\Bundle\SecurityBundle\Security;
use Symfonycasts\MicroMapper\AsMapper;
@@ -14,7 +16,7 @@ use Symfonycasts\MicroMapper\MicroMapperInterface;
class ContactApiToEntityMapper implements MapperInterface
{
public function __construct(
private PartnerRepository $repository,
private ContactRepository $repository,
private Security $security,
private MicroMapperInterface $microMapper,
)
@@ -27,9 +29,21 @@ class ContactApiToEntityMapper implements MapperInterface
$dto = $from;
assert($dto instanceof ContactApi);

$entity = $dto->id ? $this->repository->find($dto->id) : new Contact();
if ($dto->id) {
$entity = $this->repository->find($dto->id);
} else {
if ($dto->partner === null) {
throw new \Exception('Partner missing');
}
$partner = $this->microMapper->map($dto->partner, Partner::class, [
MicroMapperInterface::MAX_DEPTH => 0,
]);
$entity = new Contact($partner);
}


if (!$entity) {
throw new \Exception('Partner not found');
throw new \Exception('Contact not found');
}

return $entity;


+ 27
- 14
src/Mapper/PostingApiToEntityMapper.php 파일 보기

@@ -2,12 +2,12 @@

namespace App\Mapper;

use App\ApiResource\DragonTreasureApi;
use App\ApiResource\ContactApi;
use App\ApiResource\PostingApi;
use App\Entity\DragonTreasure;
use App\Entity\Contact;
use App\Entity\Partner;
use App\Entity\User;
use App\Entity\Posting;
use App\Repository\DragonTreasureRepository;
use App\Repository\PostingRepository;
use Symfony\Bundle\SecurityBundle\Security;
use Symfonycasts\MicroMapper\AsMapper;
@@ -31,7 +31,29 @@ class PostingApiToEntityMapper implements MapperInterface
$dto = $from;
assert($dto instanceof PostingApi);

$entity = $dto->id ? $this->repository->find($dto->id) : new Posting();
if ($dto->id) {
$entity = $this->repository->find($dto->id);
} else {
$user = $this->security->getUser();
assert($user instanceof User);
if ($dto->partner === null) {
throw new \Exception('Partner missing');
}
$partner = $this->microMapper->map($dto->partner, Partner::class, [
MicroMapperInterface::MAX_DEPTH => 0,
]);
$contact = null;
if ($dto->contact) {
assert($dto->contact instanceof ContactApi);
$contact = $this->microMapper->map($dto->contact, Contact::class, [
MicroMapperInterface::MAX_DEPTH => 0,
]);
}
assert($partner instanceof Partner);
assert($contact === null || $contact instanceof Contact);
$entity = new Posting($user, $partner, $contact);
}

if (!$entity) {
throw new \Exception('Posting not found');
}
@@ -46,16 +68,7 @@ class PostingApiToEntityMapper implements MapperInterface
$entity = $to;
assert($entity instanceof Posting);

if ($dto->owner) {
$entity->setOwner($this->microMapper->map($dto->owner, User::class, [
MicroMapperInterface::MAX_DEPTH => 0,
]));
} else {
$entity->setOwner($this->security->getUser());
}

$entity->setPartner($dto->partner);
$entity->setContact($dto->contact);
$entity->setHeadline($dto->headline);
$entity->setMessage($dto->message);

return $entity;


+ 81
- 0
tests/Functional/PostingResourceTest.php 파일 보기

@@ -0,0 +1,81 @@
<?php
/**
* @author Daniel Knudsen <d.knudsen@spawntree.de>
* @date 12.12.23
*/


namespace App\Tests\Functional;

use App\Factory\ContactFactory;
use App\Factory\MediaObjectLogoFactory;
use App\Factory\MediaObjectProfileFactory;
use App\Factory\PartnerFactory;
use App\Factory\PostingFactory;
use App\Factory\UserFactory;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Browser\Test\HasBrowser;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;

class PostingResourceTest extends KernelTestCase
{
use HasBrowser;
use ResetDatabase;
use Factories;

public function testPostPosting(): void
{
UserFactory::createOne(
[
'email' => 'peter@test.de',
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
]
);

MediaObjectProfileFactory::createOne();
MediaObjectLogoFactory::createOne();
$partner = PartnerFactory::createOne();
$contact = ContactFactory::createOne();
PostingFactory::createOne();

$response = $this->browser()
->post('/auth', [
'json' => [
'email' => 'peter@test.de',
'password' => 'test',
]
])
->assertSuccessful()
->content();
$authResponseData = json_decode($response, true);
$token = $authResponseData['token'];

$this->browser()
->post('/api/posts' , [
'json' => [
'headline' => 'hello',
'message' => 'world',
'partner' => '/api/partners/' . $partner->getId(),
'contact' => '/api/contacts/' . $contact->getId(),
],
'headers' => [
'Authorization' => 'Bearer ' . $token,
]
])
->assertSuccessful()
;

$this->browser()
->get('/api/posts', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
],
])
->assertSuccessful()
->assertJsonMatches('"hydra:totalItems"', 2)
;
}
}

+ 66
- 63
tests/Functional/UserResourceTest.php 파일 보기

@@ -20,95 +20,98 @@ class UserResourceTest extends KernelTestCase
use ResetDatabase;
use Factories;

public function testPostToCreateUser(): void
public function testPostUser(): void
{
$this->browser()
->post('/api/users', [
UserFactory::createOne(
[
'email' => 'peter@test.de',
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
'roles' => ["ROLE_ADMIN"]
]
);
$response = $this->browser()
->post('/auth', [
'json' => [
'email' => 'draggin_in_the_morning@coffee.com',
'firstName' => 'Danny',
'lastName' => 'Boy',
'password' => 'password',
'email' => 'peter@test.de',
'password' => 'test',
]
])
->assertStatus(201)
->use(function (Json $json) {
$json->assertMissing('password');
$json->assertMissing('id');
$json->assertHas('token');
$json->assertHas('id');
$json->assertHas('email');
$json->assertHas('firstName');
$json->assertHas('lastName');
$json->assertHas('roles');
})
->post('/auth', [
->assertSuccessful()
->content();
$authResponseData = json_decode($response, true);
$token = $authResponseData['token'];

$this->browser()
->post('/api/users' , [
'json' => [
'email' => 'draggin_in_the_morning@coffee.com',
'password' => 'password',
'email' => 'norbert@test.de',
'firstName' => 'Norbert',
'lastName' => 'Test',
'password' => 'sehr geheim',
],
'headers' => [
'Authorization' => 'Bearer ' . $token,
]
])
->assertSuccessful()
;
}

public function testGetUsersWithoutAuthentication()
{
UserFactory::createMany(2);
$this->browser()
->get('/api/users')
->assertStatus(401)
;
}

public function testGetOneUserWithoutAuthentication()
{
UserFactory::createOne();
$this->browser()
->get('/api/users/1')
->assertStatus(401)
;
}

public function testPatchUserAsSameUser()
{
$user = UserFactory::createOne(
[
'firstName' => 'John',
'lastName' => 'Doe'
]
);

$this->browser()
->actingAs($user)
->patch('/api/users/' . $user->getId(), [
->post('/auth', [
'json' => [
'firstName' => 'Joe',
'lastName' => 'Black'
],
'headers' => ['Content-Type' => 'application/merge-patch+json']
'email' => 'norbert@test.de',
'password' => 'sehr geheim',
]
])
->assertStatus(200)
->get('/api/users/' . $user->getId())
->assertStatus(200)
->assertJsonMatches('firstName', 'Joe')
->assertJsonMatches('lastName', 'Black')
;
->assertSuccessful()
->assertJsonMatches('email', 'norbert@test.de');
}

public function testPatchUserInactiveAsSameUser()
public function testPostUserNoAdmin(): void
{
$user = UserFactory::createOne(
UserFactory::createOne(
[
'firstName' => 'John'
'email' => 'peter@test.de',
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
]
);
$response = $this->browser()
->post('/auth', [
'json' => [
'email' => 'peter@test.de',
'password' => 'test',
]
])
->assertSuccessful()
->content();
$authResponseData = json_decode($response, true);
$token = $authResponseData['token'];

$this->browser()
->actingAs($user)
->patch('/api/users/' . $user->getId(), [
->post('/api/users' , [
'json' => [
'firstName' => 'Joe'
'email' => 'norbert@test.de',
'firstName' => 'Norbert',
'lastName' => 'Test',
'password' => 'sehr geheim',
],
'headers' => ['Content-Type' => 'application/merge-patch+json']
'headers' => [
'Authorization' => 'Bearer ' . $token,
]
])
->assertStatus(200)
->get('/api/users/' . $user->getId())
->assertJsonMatches('firstName', 'A shiny thing')
->assertStatus(403);
;
}
}

불러오는 중...
취소
저장