Bladeren bron

unit tests working

master
Daniel 2 jaren geleden
bovenliggende
commit
e9a55ab7f5
31 gewijzigde bestanden met toevoegingen van 713 en 370 verwijderingen
  1. +263
    -263
      composer.lock
  2. +2
    -2
      src/ApiResource/CommentApi.php
  3. +3
    -2
      src/ApiResource/ContactApi.php
  4. +2
    -1
      src/ApiResource/PartnerApi.php
  5. +13
    -3
      src/ApiResource/PostingApi.php
  6. +4
    -3
      src/ApiResource/UserApi.php
  7. +3
    -15
      src/Entity/Comment.php
  8. +7
    -7
      src/Entity/Contact.php
  9. +1
    -0
      src/Entity/MediaObject.php
  10. +5
    -0
      src/Entity/Posting.php
  11. +1
    -1
      src/EventListener/AuthenticationSuccessListener.php
  12. +1
    -1
      src/Factory/PostingFactory.php
  13. +16
    -10
      src/Mapper/CommentApiToEntityMapper.php
  14. +3
    -4
      src/Mapper/CommentEntityToApiMapper.php
  15. +1
    -3
      src/Mapper/ContactApiToEntityMapper.php
  16. +4
    -4
      src/Mapper/ContactEntityToApiMapper.php
  17. +1
    -12
      src/Mapper/PartnerApiToEntityMapper.php
  18. +1
    -1
      src/Mapper/PartnerEntityToApiMapper.php
  19. +2
    -2
      src/Mapper/PostingApiToEntityMapper.php
  20. +2
    -2
      src/Mapper/UserApiToEntityMapper.php
  21. +2
    -2
      src/Mapper/UserEntityToApiMapper.php
  22. +46
    -0
      src/Voter/CommentApiVoter.php
  23. +2
    -6
      src/Voter/PostingApiVoter.php
  24. +1
    -2
      src/Voter/UserApiVoter.php
  25. +78
    -0
      tests/Functional/CommentResourceTest.php
  26. +82
    -0
      tests/Functional/ContactResourceTest.php
  27. +66
    -0
      tests/Functional/MediaObjectResourceTest.php
  28. +79
    -0
      tests/Functional/PartnerResourceTest.php
  29. +11
    -12
      tests/Functional/PostingResourceTest.php
  30. +11
    -12
      tests/Functional/UserResourceTest.php
  31. BIN
      tests/fixtures/1176.png

+ 263
- 263
composer.lock
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 2
- 2
src/ApiResource/CommentApi.php Bestand weergeven

@@ -54,13 +54,13 @@ class CommentApi
#[NotBlank] #[NotBlank]
public ?string $message = null; public ?string $message = null;


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


#[ApiProperty(writable: false)] #[ApiProperty(writable: false)]
public ?string $ownerName = null; public ?string $ownerName = null;


public ?PostingApi $posting = null;
public ?PostingApi $post = null;


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


+ 3
- 2
src/ApiResource/ContactApi.php Bestand weergeven

@@ -35,7 +35,7 @@ use Symfony\Component\Validator\Constraints\NotBlank;
security: 'is_granted("ROLE_USER")', security: 'is_granted("ROLE_USER")',
), ),
new Patch( new Patch(
security: 'is_granted("EDIT", object)',
security: 'is_granted("ROLE_USER")',
), ),
new Delete( new Delete(
security: 'is_granted("ROLE_ADMIN")', security: 'is_granted("ROLE_ADMIN")',
@@ -59,6 +59,7 @@ class ContactApi
#[NotBlank] #[NotBlank]
public ?string $lastName = null; public ?string $lastName = null;


#[NotBlank]
public ?PartnerApi $partner = null; public ?PartnerApi $partner = null;


public ?\DateTimeInterface $birthday = null; public ?\DateTimeInterface $birthday = null;
@@ -79,7 +80,7 @@ class ContactApi
* @var array<int, PostingApi> * @var array<int, PostingApi>
*/ */
#[ApiProperty(writable: false)] #[ApiProperty(writable: false)]
public array $postings = [];
public array $posts = [];


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

+ 2
- 1
src/ApiResource/PartnerApi.php Bestand weergeven

@@ -37,7 +37,7 @@ use Symfony\Component\Validator\Constraints\NotBlank;
security: 'is_granted("ROLE_USER")', security: 'is_granted("ROLE_USER")',
), ),
new Patch( new Patch(
security: 'is_granted("EDIT", object)',
security: 'is_granted("ROLE_USER")',
), ),
new Delete( new Delete(
security: 'is_granted("ROLE_ADMIN")', security: 'is_granted("ROLE_ADMIN")',
@@ -84,5 +84,6 @@ class PartnerApi
/** /**
* @var array<int, ContactApi> * @var array<int, ContactApi>
*/ */
#[ApiProperty(writable: false)]
public array $contacts = []; public array $contacts = [];
} }

+ 13
- 3
src/ApiResource/PostingApi.php Bestand weergeven

@@ -20,8 +20,9 @@ use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Post;
use App\Validator\IsValidOwner;
use Symfony\Component\PropertyInfo\Type; use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotBlank;


#[ApiResource( #[ApiResource(
@@ -34,9 +35,11 @@ use Symfony\Component\Validator\Constraints\NotBlank;
security: 'is_granted("ROLE_USER")', security: 'is_granted("ROLE_USER")',
), ),
new Post( new Post(
denormalizationContext: ['groups' => 'posting_create'],
security: 'is_granted("ROLE_USER")', security: 'is_granted("ROLE_USER")',
), ),
new Patch( new Patch(
denormalizationContext: ['groups' => 'posting_patch'],
security: 'is_granted("EDIT", object)', security: 'is_granted("EDIT", object)',
), ),
new Delete( new Delete(
@@ -55,28 +58,35 @@ class PostingApi
public ?int $id = null; public ?int $id = null;


#[NotBlank] #[NotBlank]
#[Groups(['posting_create', 'posting_patch'])]
public ?string $headline = null; public ?string $headline = null;


#[NotBlank] #[NotBlank]
#[Groups(['posting_create', 'posting_patch'])]
public ?string $message = null; public ?string $message = null;


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


#[ApiProperty(writable: false)] #[ApiProperty(writable: false)]
public ?string $ownerName = null; public ?string $ownerName = null;


#[ApiProperty(writable: true)]
#[Groups(['posting_create'])]
#[Assert\NotBlank(groups: ['posting_create'])]
public ?PartnerApi $partner = null; public ?PartnerApi $partner = null;


#[ApiProperty(writable: true)]
#[Groups(['posting_create'])]
public ?ContactApi $contact = null; public ?ContactApi $contact = null;


/** /**
* @var array<int, CommentApi> * @var array<int, CommentApi>
*/ */
#[ApiProperty( #[ApiProperty(
writable: false,
readableLink: true, readableLink: true,
writableLink: true,
writableLink: false,
fetchEager: true, fetchEager: true,
builtinTypes: [ builtinTypes: [
new Type( new Type(


+ 4
- 3
src/ApiResource/UserApi.php Bestand weergeven

@@ -30,10 +30,10 @@ use Symfony\Component\Validator\Constraints as Assert;
), ),
new Post( new Post(
security: 'is_granted("ROLE_ADMIN")', security: 'is_granted("ROLE_ADMIN")',
validationContext: ['groups' => ['Default', 'postValidation']],
validationContext: ['groups' => ['Default', 'postValidation']]
), ),
new Patch( new Patch(
security: 'is_granted("ROLE_USER")'
security: 'is_granted("is_granted("EDIT", object)")'
), ),
], ],
security: 'is_granted("ROLE_USER")', security: 'is_granted("ROLE_USER")',
@@ -74,7 +74,8 @@ class UserApi
/** /**
* @var array<int, PostingApi> * @var array<int, PostingApi>
*/ */
public array $postings = [];
#[ApiProperty(writable: false)]
public array $posts = [];


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


+ 3
- 15
src/Entity/Comment.php Bestand weergeven

@@ -28,8 +28,10 @@ class Comment
#[ORM\Column] #[ORM\Column]
private ?\DateTimeImmutable $createdAt = null; private ?\DateTimeImmutable $createdAt = null;


public function __construct()
public function __construct(User $owner, Posting $posting)
{ {
$this->owner = $owner;
$this->posting = $posting;
$this->createdAt = new \DateTimeImmutable(); $this->createdAt = new \DateTimeImmutable();
} }


@@ -62,25 +64,11 @@ class Comment
return $this->owner; return $this->owner;
} }


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

return $this;
}

public function getPosting(): ?Posting public function getPosting(): ?Posting
{ {
return $this->posting; return $this->posting;
} }


public function setPosting(?Posting $posting): static
{
$this->posting = $posting;

return $this;
}

public function getCreatedAt(): ?\DateTimeImmutable public function getCreatedAt(): ?\DateTimeImmutable
{ {
return $this->createdAt; return $this->createdAt;


+ 7
- 7
src/Entity/Contact.php Bestand weergeven

@@ -46,13 +46,13 @@ class Contact
private ?\DateTimeImmutable $createdAt = null; private ?\DateTimeImmutable $createdAt = null;


#[ORM\OneToMany(mappedBy: 'contact', targetEntity: Posting::class, orphanRemoval: true)] #[ORM\OneToMany(mappedBy: 'contact', targetEntity: Posting::class, orphanRemoval: true)]
private Collection $postings;
private Collection $posts;


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


public function getId(): ?int public function getId(): ?int
@@ -169,15 +169,15 @@ class Contact
/** /**
* @return Collection<int, Posting> * @return Collection<int, Posting>
*/ */
public function getPostings(): Collection
public function getPosts(): Collection
{ {
return $this->postings;
return $this->posts;
} }


public function addPosting(Posting $posting): static public function addPosting(Posting $posting): static
{ {
if (!$this->postings->contains($posting)) {
$this->postings->add($posting);
if (!$this->posts->contains($posting)) {
$this->posts->add($posting);
$posting->setContact($this); $posting->setContact($this);
} }


@@ -186,7 +186,7 @@ class Contact


public function removePosting(Posting $posting): static public function removePosting(Posting $posting): static
{ {
if ($this->postings->removeElement($posting)) {
if ($this->posts->removeElement($posting)) {
// set the owning side to null (unless already changed) // set the owning side to null (unless already changed)
if ($posting->getContact() === $this) { if ($posting->getContact() === $this) {
$posting->setContact(null); $posting->setContact(null);


+ 1
- 0
src/Entity/MediaObject.php Bestand weergeven

@@ -23,6 +23,7 @@ use Vich\UploaderBundle\Mapping\Annotation as Vich;
#[Vich\Uploadable] #[Vich\Uploadable]
#[ORM\Entity] #[ORM\Entity]
#[ApiResource( #[ApiResource(
shortName: 'Media',
types: ['https://schema.org/MediaObject'], types: ['https://schema.org/MediaObject'],
operations: [ operations: [
new Get(), new Get(),


+ 5
- 0
src/Entity/Posting.php Bestand weergeven

@@ -70,6 +70,11 @@ class Posting
return $this->createdAt; return $this->createdAt;
} }


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

public function getOwner(): ?User public function getOwner(): ?User
{ {
return $this->owner; return $this->owner;


+ 1
- 1
src/EventListener/AuthenticationSuccessListener.php Bestand weergeven

@@ -38,7 +38,7 @@ class AuthenticationSuccessListener
} }


$userApi = $this->microMapper->map($user, UserApi::class, [ $userApi = $this->microMapper->map($user, UserApi::class, [
MicroMapperInterface::MAX_DEPTH => 3,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);


$data['id'] = $this->iriConverter->getIriFromResource($userApi); $data['id'] = $this->iriConverter->getIriFromResource($userApi);


+ 1
- 1
src/Factory/PostingFactory.php Bestand weergeven

@@ -46,7 +46,7 @@ final class PostingFactory extends ModelFactory
*/ */
protected function getDefaults(): array protected function getDefaults(): array
{ {
$randomBoolean = (bool)random_int(0, 1);
$randomBoolean = ContactFactory::count() > 0 && (bool)random_int(0, 1);
return [ return [
'headline' => self::faker()->words(random_int(1, 5), true), 'headline' => self::faker()->words(random_int(1, 5), true),
'message' => $randomBoolean ? self::faker()->sentence() : self::faker()->sentences(random_int(1, 3), true), 'message' => $randomBoolean ? self::faker()->sentence() : self::faker()->sentences(random_int(1, 3), true),


+ 16
- 10
src/Mapper/CommentApiToEntityMapper.php Bestand weergeven

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


use App\ApiResource\CommentApi; use App\ApiResource\CommentApi;
use App\Entity\Comment; use App\Entity\Comment;
use App\Entity\Posting;
use App\Entity\User; use App\Entity\User;
use App\Repository\CommentRepository; use App\Repository\CommentRepository;
use Symfony\Bundle\SecurityBundle\Security; use Symfony\Bundle\SecurityBundle\Security;
@@ -28,7 +29,21 @@ class CommentApiToEntityMapper implements MapperInterface
$dto = $from; $dto = $from;
assert($dto instanceof CommentApi); assert($dto instanceof CommentApi);


$entity = $dto->id ? $this->repository->find($dto->id) : new Comment();
if ($dto->id) {
$entity = $this->repository->find($dto->id);
} else {
$user = $this->security->getUser();
assert($user instanceof User);
if ($dto->post === null) {
throw new \Exception('Posting missing');
}
$posting = $this->microMapper->map($dto->post, Posting::class, [
MicroMapperInterface::MAX_DEPTH => 1,
]);
assert($posting instanceof Posting);
$entity = new Comment($user, $posting);
}

if (!$entity) { if (!$entity) {
throw new \Exception('Comment not found'); throw new \Exception('Comment not found');
} }
@@ -42,15 +57,6 @@ class CommentApiToEntityMapper implements MapperInterface
assert($dto instanceof CommentApi); assert($dto instanceof CommentApi);
$entity = $to; $entity = $to;
assert($entity instanceof Comment); assert($entity instanceof Comment);

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


return $entity; return $entity;


+ 3
- 4
src/Mapper/CommentEntityToApiMapper.php Bestand weergeven

@@ -15,8 +15,7 @@ use Symfonycasts\MicroMapper\MicroMapperInterface;
class CommentEntityToApiMapper implements MapperInterface class CommentEntityToApiMapper implements MapperInterface
{ {
public function __construct( public function __construct(
private MicroMapperInterface $microMapper,
private Security $security,
private MicroMapperInterface $microMapper
) )
{ {
} }
@@ -41,12 +40,12 @@ class CommentEntityToApiMapper implements MapperInterface


$dto->message = $entity->getMessage(); $dto->message = $entity->getMessage();
$dto->owner = $this->microMapper->map($entity->getOwner(), UserApi::class, [ $dto->owner = $this->microMapper->map($entity->getOwner(), UserApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);
$dto->ownerName = $entity->getOwner()?->getFirstName()." ".$entity->getOwner()?->getLastName(); $dto->ownerName = $entity->getOwner()?->getFirstName()." ".$entity->getOwner()?->getLastName();


$dto->posting = $this->microMapper->map($entity->getPosting(), PostingApi::class, [ $dto->posting = $this->microMapper->map($entity->getPosting(), PostingApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);


$dto->createdAt = $entity->getCreatedAt(); $dto->createdAt = $entity->getCreatedAt();


+ 1
- 3
src/Mapper/ContactApiToEntityMapper.php Bestand weergeven

@@ -17,7 +17,6 @@ class ContactApiToEntityMapper implements MapperInterface
{ {
public function __construct( public function __construct(
private ContactRepository $repository, private ContactRepository $repository,
private Security $security,
private MicroMapperInterface $microMapper, private MicroMapperInterface $microMapper,
) )
{ {
@@ -36,7 +35,7 @@ class ContactApiToEntityMapper implements MapperInterface
throw new \Exception('Partner missing'); throw new \Exception('Partner missing');
} }
$partner = $this->microMapper->map($dto->partner, Partner::class, [ $partner = $this->microMapper->map($dto->partner, Partner::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);
$entity = new Contact($partner); $entity = new Contact($partner);
} }
@@ -58,7 +57,6 @@ class ContactApiToEntityMapper implements MapperInterface


$entity->setFirstName($dto->firstName); $entity->setFirstName($dto->firstName);
$entity->setLastName($dto->lastName); $entity->setLastName($dto->lastName);
$entity->setPartner($dto->partner);
$entity->setBirthday($dto->birthday); $entity->setBirthday($dto->birthday);
$entity->setImage($dto->image); $entity->setImage($dto->image);
$entity->setPosition($dto->position); $entity->setPosition($dto->position);


+ 4
- 4
src/Mapper/ContactEntityToApiMapper.php Bestand weergeven

@@ -44,7 +44,7 @@ class ContactEntityToApiMapper implements MapperInterface
$dto->lastName = $entity->getLastName(); $dto->lastName = $entity->getLastName();
$dto->partner = $this->microMapper->map( $dto->partner = $this->microMapper->map(
$entity->getPartner(), PartnerApi::class, [ $entity->getPartner(), PartnerApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
] ]
); );
$dto->birthday = $entity->getBirthday(); $dto->birthday = $entity->getBirthday();
@@ -55,11 +55,11 @@ class ContactEntityToApiMapper implements MapperInterface
$dto->email = $entity->getEmail(); $dto->email = $entity->getEmail();
$dto->createdAt = $entity->getCreatedAt(); $dto->createdAt = $entity->getCreatedAt();


$dto->postings = array_map(function(Posting $posting) {
$dto->posts = array_map(function(Posting $posting) {
return $this->microMapper->map($posting, PostingApi::class, [ return $this->microMapper->map($posting, PostingApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);
}, $entity->getPostings()->getValues());
}, $entity->getPosts()->getValues());


return $dto; return $dto;
} }


+ 1
- 12
src/Mapper/PartnerApiToEntityMapper.php Bestand weergeven

@@ -19,10 +19,7 @@ use Symfonycasts\MicroMapper\MicroMapperInterface;
class PartnerApiToEntityMapper implements MapperInterface class PartnerApiToEntityMapper implements MapperInterface
{ {
public function __construct( public function __construct(
private PartnerRepository $repository,
private Security $security,
private MicroMapperInterface $microMapper,
private PropertyAccessorInterface $propertyAccessor,
private PartnerRepository $repository
) )
{ {


@@ -58,14 +55,6 @@ class PartnerApiToEntityMapper implements MapperInterface
$entity->setWebsite($dto->website); $entity->setWebsite($dto->website);
$entity->setLogo($dto->logo); $entity->setLogo($dto->logo);


$contactEntities = [];
foreach ($dto->contacts as $contactApi) {
$contactEntities[] = $this->microMapper->map($contactApi, Contact::class, [
MicroMapperInterface::MAX_DEPTH => 0,
]);
}
$this->propertyAccessor->setValue($entity, 'contacts', $contactEntities);

return $entity; return $entity;
} }
} }

+ 1
- 1
src/Mapper/PartnerEntityToApiMapper.php Bestand weergeven

@@ -52,7 +52,7 @@ class PartnerEntityToApiMapper implements MapperInterface
$dto->createdAt = $entity->getCreatedAt(); $dto->createdAt = $entity->getCreatedAt();
$dto->contacts = array_map(function(Contact $contact) { $dto->contacts = array_map(function(Contact $contact) {
return $this->microMapper->map($contact, ContactApi::class, [ return $this->microMapper->map($contact, ContactApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);
}, $entity->getContacts()->getValues()); }, $entity->getContacts()->getValues());
return $dto; return $dto;


+ 2
- 2
src/Mapper/PostingApiToEntityMapper.php Bestand weergeven

@@ -40,13 +40,13 @@ class PostingApiToEntityMapper implements MapperInterface
throw new \Exception('Partner missing'); throw new \Exception('Partner missing');
} }
$partner = $this->microMapper->map($dto->partner, Partner::class, [ $partner = $this->microMapper->map($dto->partner, Partner::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);
$contact = null; $contact = null;
if ($dto->contact) { if ($dto->contact) {
assert($dto->contact instanceof ContactApi); assert($dto->contact instanceof ContactApi);
$contact = $this->microMapper->map($dto->contact, Contact::class, [ $contact = $this->microMapper->map($dto->contact, Contact::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);
} }
assert($partner instanceof Partner); assert($partner instanceof Partner);


+ 2
- 2
src/Mapper/UserApiToEntityMapper.php Bestand weergeven

@@ -53,9 +53,9 @@ class UserApiToEntityMapper implements MapperInterface
} }


$userPostsEntities = new ArrayCollection(); $userPostsEntities = new ArrayCollection();
foreach ($dto->postings as $userPostApi) {
foreach ($dto->posts as $userPostApi) {
$userPostsEntities[] = $this->microMapper->map($userPostApi, Posting::class, [ $userPostsEntities[] = $this->microMapper->map($userPostApi, Posting::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);
} }
$this->propertyAccessor->setValue($entity, 'postings', $userPostsEntities); $this->propertyAccessor->setValue($entity, 'postings', $userPostsEntities);


+ 2
- 2
src/Mapper/UserEntityToApiMapper.php Bestand weergeven

@@ -41,9 +41,9 @@ class UserEntityToApiMapper implements MapperInterface
$dto->firstName = $entity->getFirstName(); $dto->firstName = $entity->getFirstName();
$dto->lastName = $entity->getLastName(); $dto->lastName = $entity->getLastName();


$dto->postings = array_map(function(Posting $posting) {
$dto->posts = array_map(function(Posting $posting) {
return $this->microMapper->map($posting, PostingApi::class, [ return $this->microMapper->map($posting, PostingApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]); ]);
}, $entity->getPostings()->getValues()); }, $entity->getPostings()->getValues());




+ 46
- 0
src/Voter/CommentApiVoter.php Bestand weergeven

@@ -0,0 +1,46 @@
<?php

namespace App\Voter;

use App\ApiResource\CommentApi;
use App\ApiResource\PostingApi;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;

class CommentApiVoter extends Voter
{
public const EDIT = 'EDIT';

public function __construct()
{
}

protected function supports(string $attribute, mixed $subject): bool
{
return $attribute === self::EDIT && $subject instanceof CommentApi;
}

protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
// if the user is anonymous, do not grant access
if (!$user instanceof User) {
return false;
}

assert($subject instanceof CommentApi);

// ... (check conditions and return true to grant permission) ...
switch ($attribute) {
case self::EDIT:
if ($subject->owner?->id === $user->getId()) {
return true;
}
break;
}

return false;
}
}

+ 2
- 6
src/Voter/PostingApiVoter.php Bestand weergeven

@@ -12,13 +12,13 @@ class PostingApiVoter extends Voter
{ {
public const EDIT = 'EDIT'; public const EDIT = 'EDIT';


public function __construct(private Security $security)
public function __construct()
{ {
} }


protected function supports(string $attribute, mixed $subject): bool protected function supports(string $attribute, mixed $subject): bool
{ {
return in_array($attribute, [self::EDIT]) && $subject instanceof PostingApi;
return $attribute === self::EDIT && $subject instanceof PostingApi;
} }


protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
@@ -29,10 +29,6 @@ class PostingApiVoter extends Voter
return false; return false;
} }


if ($this->security->isGranted('ROLE_ADMIN')) {
return true;
}

assert($subject instanceof PostingApi); assert($subject instanceof PostingApi);


// ... (check conditions and return true to grant permission) ... // ... (check conditions and return true to grant permission) ...


+ 1
- 2
src/Voter/UserApiVoter.php Bestand weergeven

@@ -18,12 +18,11 @@ class UserApiVoter extends Voter


protected function supports(string $attribute, mixed $subject): bool protected function supports(string $attribute, mixed $subject): bool
{ {
return in_array($attribute, [self::EDIT]) && $subject instanceof UserApi;
return $attribute === self::EDIT && $subject instanceof UserApi;
} }


protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{ {
//dd($subject);
$user = $token->getUser(); $user = $token->getUser();
// if the user is anonymous, do not grant access // if the user is anonymous, do not grant access
if (!$user instanceof User) { if (!$user instanceof User) {


+ 78
- 0
tests/Functional/CommentResourceTest.php Bestand weergeven

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


namespace App\Tests\Functional;

use App\Enum\PartnerType;
use App\Factory\CommentFactory;
use App\Factory\MediaObjectLogoFactory;
use App\Factory\MediaObjectProfileFactory;
use App\Factory\PartnerFactory;
use App\Factory\PostingFactory;
use App\Factory\UserFactory;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Browser\Test\HasBrowser;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;

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

private JWTTokenManagerInterface $JWTManager;

protected function setUp(): void
{
parent::setUp();
$this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager');
}

public function testPostComment(): void
{
$user = UserFactory::createOne(
[
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
'email' => 'peter@test.de',
]
);
MediaObjectLogoFactory::createOne();
PartnerFactory::createOne();
$posting = PostingFactory::createOne();
CommentFactory::createOne();

$token = $this->JWTManager->create($user->object());

$this->browser()
->post('/api/comments' , [
'json' => [
'message' => 'my comment',
'post' => '/api/posts/' . $posting->getId(),
],
'headers' => [
'Authorization' => 'Bearer ' . $token,
]
])
->assertSuccessful()
;

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

+ 82
- 0
tests/Functional/ContactResourceTest.php Bestand weergeven

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


namespace App\Tests\Functional;

use App\Enum\PartnerType;
use App\Factory\MediaObjectLogoFactory;
use App\Factory\MediaObjectProfileFactory;
use App\Factory\PartnerFactory;
use App\Factory\UserFactory;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Browser\Test\HasBrowser;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;

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

private JWTTokenManagerInterface $JWTManager;

protected function setUp(): void
{
parent::setUp();
$this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager');
}

public function testPostContact(): void
{
MediaObjectLogoFactory::createOne();
$partner = PartnerFactory::createOne();
$user = UserFactory::createOne(
[
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
'email' => 'peter@test.de',
]
);

$mediaObject = MediaObjectProfileFactory::createOne();

$token = $this->JWTManager->create($user->object());

$this->browser()
->post('/api/contacts' , [
'json' => [
'firstName' => 'Peter',
'lastName' => 'Test',
'partner' => '/api/partners/' . $partner->getId(),
'birthday' => '1984-02-10',
'image' => '/api/medias/' . $mediaObject->getId(),
'position' => 'CEO',
'phone' => '123456789',
'email' => 'peter@test2.de',
],
'headers' => [
'Authorization' => 'Bearer ' . $token,
]
])
->assertSuccessful()
;

$this->browser()
->get('/api/contacts', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
],
])
->assertSuccessful()
->assertJsonMatches('"hydra:totalItems"', 1)
->assertJsonMatches('"hydra:member"[0].position', 'CEO')
;
}
}

+ 66
- 0
tests/Functional/MediaObjectResourceTest.php Bestand weergeven

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


namespace App\Tests\Functional;

use App\Factory\UserFactory;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Zenstruck\Browser\Test\HasBrowser;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;

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

private JWTTokenManagerInterface $JWTManager;
private string $projectDir;

protected function setUp(): void
{
parent::setUp();
$this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager');
$this->projectDir = self::getContainer()->get('kernel')->getProjectDir();
}

public function testCreateAMediaObject(): void
{
$path = $this->projectDir . '/tests/fixtures/';
$srcFile = $path . '1176.png';
$dstFile = $path . '1176_upload.png';
copy($srcFile, $dstFile);

$file = new UploadedFile($dstFile, 'image.png');

$user = UserFactory::createOne(
[
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
'email' => 'peter@test.de',
]
);
$token = $this->JWTManager->create($user->object());

$this->browser()
->post('/api/medias', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'multipart/form-data'
],
'files' => [
'file' => $file,
],
])
->assertSuccessful()
;
}
}

+ 79
- 0
tests/Functional/PartnerResourceTest.php Bestand weergeven

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


namespace App\Tests\Functional;

use App\Enum\PartnerType;
use App\Factory\MediaObjectLogoFactory;
use App\Factory\UserFactory;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Browser\Test\HasBrowser;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;

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

private JWTTokenManagerInterface $JWTManager;

protected function setUp(): void
{
parent::setUp();
$this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager');
}

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

$mediaObject = MediaObjectLogoFactory::createOne();
$token = $this->JWTManager->create($user->object());

$this->browser()
->post('/api/partners' , [
'json' => [
'name' => 'test customer',
'type' => PartnerType::Customer,
'street' => 'test street',
'streetNo' => '11',
'zip' => '22335',
'city' => 'test city',
'country' => 'test country',
'website' => 'wwe.test.de',
'logo' => '/api/medias/' . $mediaObject->getId(),
],
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/ld+json'
]
])
->assertSuccessful()
;

$this->browser()
->get('/api/partners', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
],
])
->assertSuccessful()
->assertJsonMatches('"hydra:totalItems"', 1)
->assertJsonMatches('"hydra:member"[0].name', 'test customer')
;
}
}

+ 11
- 12
tests/Functional/PostingResourceTest.php Bestand weergeven

@@ -13,6 +13,7 @@ use App\Factory\MediaObjectProfileFactory;
use App\Factory\PartnerFactory; use App\Factory\PartnerFactory;
use App\Factory\PostingFactory; use App\Factory\PostingFactory;
use App\Factory\UserFactory; use App\Factory\UserFactory;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Browser\Test\HasBrowser; use Zenstruck\Browser\Test\HasBrowser;
use Zenstruck\Foundry\Test\Factories; use Zenstruck\Foundry\Test\Factories;
@@ -24,9 +25,17 @@ class PostingResourceTest extends KernelTestCase
use ResetDatabase; use ResetDatabase;
use Factories; use Factories;


private JWTTokenManagerInterface $JWTManager;

protected function setUp(): void
{
parent::setUp();
$this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager');
}

public function testPostPosting(): void public function testPostPosting(): void
{ {
UserFactory::createOne(
$user = UserFactory::createOne(
[ [
'email' => 'peter@test.de', 'email' => 'peter@test.de',
'firstName' => 'Peter', 'firstName' => 'Peter',
@@ -41,17 +50,7 @@ class PostingResourceTest extends KernelTestCase
$contact = ContactFactory::createOne(); $contact = ContactFactory::createOne();
PostingFactory::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'];
$token = $this->JWTManager->create($user->object());


$this->browser() $this->browser()
->post('/api/posts' , [ ->post('/api/posts' , [


+ 11
- 12
tests/Functional/UserResourceTest.php Bestand weergeven

@@ -8,6 +8,7 @@
namespace App\Tests\Functional; namespace App\Tests\Functional;


use App\Factory\UserFactory; use App\Factory\UserFactory;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Browser\Json; use Zenstruck\Browser\Json;
use Zenstruck\Browser\Test\HasBrowser; use Zenstruck\Browser\Test\HasBrowser;
@@ -20,6 +21,14 @@ class UserResourceTest extends KernelTestCase
use ResetDatabase; use ResetDatabase;
use Factories; use Factories;


private JWTTokenManagerInterface $JWTManager;

protected function setUp(): void
{
parent::setUp();
$this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager');
}

public function testPostUser(): void public function testPostUser(): void
{ {
UserFactory::createOne( UserFactory::createOne(
@@ -79,7 +88,7 @@ class UserResourceTest extends KernelTestCase


public function testPostUserNoAdmin(): void public function testPostUserNoAdmin(): void
{ {
UserFactory::createOne(
$user = UserFactory::createOne(
[ [
'email' => 'peter@test.de', 'email' => 'peter@test.de',
'firstName' => 'Peter', 'firstName' => 'Peter',
@@ -87,18 +96,8 @@ class UserResourceTest extends KernelTestCase
'password' => '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'];


$token = $this->JWTManager->create($user->object());
$this->browser() $this->browser()
->post('/api/users' , [ ->post('/api/users' , [
'json' => [ 'json' => [


BIN
tests/fixtures/1176.png Bestand weergeven

Voor Na
Breedte: 256  |  Hoogte: 256  |  Grootte: 3.9 KiB

Laden…
Annuleren
Opslaan