From 994e6e17cb968dccc4aaf7503ca189ca453e8177 Mon Sep 17 00:00:00 2001 From: Hecht Date: Mon, 19 Oct 2020 23:34:54 +0200 Subject: [PATCH] played around with embedded entities --- config/orm/Hero.orm.yml | 3 ++ config/orm/Skillz.orm.yml | 18 +++++++ config/packages/security.yaml | 10 ++++ src/Controller/HeroController.php | 22 ++++++-- src/Controller/UserController.php | 22 ++++++-- src/DataFixtures/UserFixtures.php | 7 +-- src/Entity/Hero.php | 25 +++++++-- src/Entity/Skillz.php | 72 +++++++++++++++++++++++++ src/Entity/User.php | 12 ++--- src/Security/TokenAuthenticator.php | 8 ++- tests/Controller/RestTestBase.php | 6 ++- tests/Controller/UserControllerTest.php | 30 +++++++++++ 12 files changed, 207 insertions(+), 28 deletions(-) create mode 100644 config/orm/Skillz.orm.yml create mode 100644 src/Entity/Skillz.php diff --git a/config/orm/Hero.orm.yml b/config/orm/Hero.orm.yml index f2b6bab..db71bee 100644 --- a/config/orm/Hero.orm.yml +++ b/config/orm/Hero.orm.yml @@ -11,6 +11,9 @@ App\Entity\Hero: type: string length: 32 unique: true + embedded: + skills: + class: Skillz manyToOne: user: diff --git a/config/orm/Skillz.orm.yml b/config/orm/Skillz.orm.yml new file mode 100644 index 0000000..13f3e90 --- /dev/null +++ b/config/orm/Skillz.orm.yml @@ -0,0 +1,18 @@ +App\Entity\Skillz: + type: embeddable + fields: + constitution: # basically the HP + type: integer + nullable: false + ki: # former MP! Some moves will require Ki to be available + type: integer + nullable: false + strength: # damage dealer / block skill? + type: integer + nullable: false + agility: # evade / hit chance skill?? + type: integer + nullable: false + stamina: # if low => one is vulnerable for critical hits or slow attack speed / low damage + type: integer + nullable: false diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 0e4cf3d..abf61a8 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,4 +1,8 @@ security: + encoders: + App\Entity\User: + algorithm: argon2i + # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers providers: users_in_memory: { memory: null } @@ -6,6 +10,12 @@ security: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false + api: + pattern: ^/api/ + guard: + authenticators: + - App\Security\TokenAuthenticator + stateless: true main: anonymous: true lazy: true diff --git a/src/Controller/HeroController.php b/src/Controller/HeroController.php index 82fa49c..65293e6 100644 --- a/src/Controller/HeroController.php +++ b/src/Controller/HeroController.php @@ -6,10 +6,14 @@ use App\Repository\HeroRepository; use FOS\RestBundle\Controller\Annotations as Rest; use FOS\RestBundle\Controller\AbstractFOSRestController; use Symfony\Component\HttpFoundation\Response; +use App\Entity\Hero; +/** + * @Rest\Route("api/hero") + */ class HeroController extends AbstractFOSRestController { - protected $heroRepository; + protected HeroRepository $heroRepository; public function __construct(HeroRepository $heroRepository) { @@ -17,12 +21,20 @@ class HeroController extends AbstractFOSRestController } /** - * @Rest\Route("api/heroes") + * @Rest\Route("es") * @Rest\View() */ - public function cgetAction() + public function cgetAction() : array { - $heroes = $this->heroRepository->findAll(); - return $this->view($heroes, Response::HTTP_OK); + return $this->heroRepository->findAll(); + } + + /** + * @Rest\Route("/{id}")) + * @Rest\View() + */ + public function getAction(int $id) : ?Hero + { + return $this->heroRepository->find($id); } } diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index 7f32aeb..8f31b66 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -6,10 +6,14 @@ use App\Repository\UserRepository; use FOS\RestBundle\Controller\Annotations as Rest; use FOS\RestBundle\Controller\AbstractFOSRestController; use Symfony\Component\HttpFoundation\Response; +use App\Entity\User; +/** + * @Rest\Route("api/user") + */ class UserController extends AbstractFOSRestController { - protected $userRepository; + protected UserRepository $userRepository; public function __construct(UserRepository $userRepository) { @@ -17,13 +21,21 @@ class UserController extends AbstractFOSRestController } /** - * @Rest\Route("api/users") + * @Rest\Route("s") * @Rest\View() */ - public function cgetAction() + public function cgetAction() : array { - $users = $this->userRepository->findAll(); - return $this->view($users, Response::HTTP_OK); + return $this->userRepository->findAll(); + } + + /** + * @Rest\Route("/{id}")) + * @Rest\View() + */ + public function getAction(int $id) : ?User + { + return $this->userRepository->find($id); } } diff --git a/src/DataFixtures/UserFixtures.php b/src/DataFixtures/UserFixtures.php index c140326..9f60138 100644 --- a/src/DataFixtures/UserFixtures.php +++ b/src/DataFixtures/UserFixtures.php @@ -13,7 +13,7 @@ class UserFixtures extends Fixture public const DUDE_USER_REFERENCE = 'dummy-user'; - private $passwordEncoder; + private UserPasswordEncoderInterface $passwordEncoder; public function __construct(UserPasswordEncoderInterface $passwordEncoder) { @@ -25,13 +25,13 @@ class UserFixtures extends Fixture $userAdmin = new User(); $userAdmin->setUsername('admin'); $this->setPassword($userAdmin, '123456789'); - $userAdmin->setApiToken('ItsHammerTime!'); + $userAdmin->setApiToken(self::ADMIN_USER_REFERENCE); $manager->persist($userAdmin); $userDude = new User(); $userDude->setUsername('dude'); $this->setPassword($userDude, '1234'); - $userDude->setApiToken('ItsDuderzeit!'); + $userDude->setApiToken(self::DUDE_USER_REFERENCE); $manager->persist($userDude); $manager->flush(); @@ -44,4 +44,5 @@ class UserFixtures extends Fixture { $user->setPassword($this->passwordEncoder->encodePassword($user, $plainPassword)); } + } diff --git a/src/Entity/Hero.php b/src/Entity/Hero.php index 2ac1cce..1ff9ba2 100644 --- a/src/Entity/Hero.php +++ b/src/Entity/Hero.php @@ -4,12 +4,19 @@ namespace App\Entity; class Hero { - private $id; + private ?int $id; - private $name; + private ?string $name; - private $user; + private ?User $user; + + private Skillz $skills; + public function __construct() + { + $this->skills = new Skillz(); + } + public function getId(): ?int { return $this->id; @@ -38,4 +45,16 @@ class Hero return $this; } + + public function getSkills(): Skillz + { + return $this->skills; + } + + public function setSkills(Skillz $skills): self + { + $this->skills = $skills; + + return $this; + } } diff --git a/src/Entity/Skillz.php b/src/Entity/Skillz.php new file mode 100644 index 0000000..ed08b78 --- /dev/null +++ b/src/Entity/Skillz.php @@ -0,0 +1,72 @@ +strength; + } + + public function setStrength(int $strength): self + { + $this->strength = $strength; + + return $this; + } + + public function getAgility(): ?int + { + return $this->agility; + } + + public function setAgility(int $agility): self + { + $this->agility = $agility; + + return $this; + } + + public function getStamina(): ?int + { + return $this->stamina; + } + + public function setStamina(int $stamina): self + { + $this->stamina = $stamina; + + return $this; + } + + public function getConstitution(): ?int + { + return $this->constitution; + } + + public function setConstitution(int $constitution): self + { + $this->constitution = $constitution; + + return $this; + } + + public function getKi(): ?int + { + return $this->ki; + } + + public function setKi(int $ki): self + { + $this->ki = $ki; + + return $this; + } +} + diff --git a/src/Entity/User.php b/src/Entity/User.php index 08e220c..12ff661 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -8,17 +8,17 @@ use Symfony\Component\Security\Core\User\UserInterface; class User implements UserInterface { - private $id; + private ?int $id; - private $username; + private ?string $username; - private $password; + private ?string $password; - private $apiToken; + private ?string $apiToken; - private $roles = []; + private array $roles = []; - private $heroes; + private Collection $heroes; public function __construct() { diff --git a/src/Security/TokenAuthenticator.php b/src/Security/TokenAuthenticator.php index 18f86c6..b8124a8 100644 --- a/src/Security/TokenAuthenticator.php +++ b/src/Security/TokenAuthenticator.php @@ -14,10 +14,7 @@ use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; class TokenAuthenticator extends AbstractGuardAuthenticator { - /** - * @var UserRepository - */ - private $userRepository; + private UserRepository $userRepository; public function __construct(UserRepository $userRepository) { @@ -89,8 +86,9 @@ class TokenAuthenticator extends AbstractGuardAuthenticator { throw new UnauthorizedHttpException('', 'Authentication Required'); } + - public function supportsRememberMe() + public function supportsRememberMe() : bool { return false; } diff --git a/tests/Controller/RestTestBase.php b/tests/Controller/RestTestBase.php index a842b6d..64b8d14 100644 --- a/tests/Controller/RestTestBase.php +++ b/tests/Controller/RestTestBase.php @@ -23,7 +23,11 @@ class RestTestBase extends WebTestCase protected function reloadDoctrineFixtures() { - self::runCommand('doctrine:migration:migrate'); + // we need our fixtures to be stateless, so remove everything and recreate to get the same + // index values all along the tests + self::runCommand('doctrine:schema:drop --force -n'); + self::runCommand('doctrine:schema:create -n'); + self::runCommand('doctrine:migration:migrate -n'); self::runCommand('doctrine:fixtures:load --purge-with-truncate -n'); } diff --git a/tests/Controller/UserControllerTest.php b/tests/Controller/UserControllerTest.php index 7276fb4..37004dc 100644 --- a/tests/Controller/UserControllerTest.php +++ b/tests/Controller/UserControllerTest.php @@ -3,6 +3,8 @@ namespace App\Tests\Controller; use App\DataFixtures\UserFixtures; +use App\Entity\User; +use App\Entity\Hero; class UserControllerTest extends RestTestBase { @@ -28,4 +30,32 @@ class UserControllerTest extends RestTestBase $this->assertEquals(200, $response->getStatusCode(), 'Status code was ' . $response->getStatusCode() . ' but expected 200: ' . $response->getContent()); } + /** + * This test verifies that requesting + */ + public function testRetrieveUserWithID1() + { + $this->createRequestBuilder() + ->setMethod('GET') + ->setUri('/api/user/1') + ->setAcceptType('application/json') + ->addServerParameter('HTTP_X-AUTH-TOKEN', UserFixtures::ADMIN_USER_REFERENCE) + ->request(); + + $response = $this->client->getResponse(); + + $this->assertTrue( + $response->headers->contains('Content-Type', 'application/json'), + 'the "Content-Type" header is "' . $response->headers->get('Content-Type') . '"' // optional message shown on failure + ); + + $this->assertEquals(200, $response->getStatusCode(), 'Status code was ' . $response->getStatusCode() . ' but expected 200: ' . $response->getContent()); + } + + public function testUserDefaults() + { + $hero = new Hero(); + $this->assertEquals(0, $hero->getStrength()); + } + }