diff --git a/config/api_platform/resources.xml b/config/api_platform/resources.xml index 2885aa3..023144a 100644 --- a/config/api_platform/resources.xml +++ b/config/api_platform/resources.xml @@ -109,7 +109,7 @@ public - + @@ -129,8 +129,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 600e3a0..6a298ee 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -10,8 +10,6 @@ security: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false main: - #custom_authenticators: - # - App\Security\ApiKeyAuthenticator stateless: true access_token: diff --git a/migrations/Version20240219220159.php b/migrations/Version20240219220159.php deleted file mode 100644 index f3fa10f..0000000 --- a/migrations/Version20240219220159.php +++ /dev/null @@ -1,112 +0,0 @@ -addSql('CREATE TABLE "character" (id UUID NOT NULL, dojo_id UUID DEFAULT NULL, name VARCHAR(255) NOT NULL, strength INT NOT NULL, constitution INT NOT NULL, agility INT NOT NULL, chi INT NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE INDEX IDX_937AB03432F09E9C ON "character" (dojo_id)'); - $this->addSql('COMMENT ON COLUMN "character".id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN "character".dojo_id IS \'(DC2Type:ulid)\''); - $this->addSql('CREATE TABLE character_technique (character_id UUID NOT NULL, technique_id UUID NOT NULL, PRIMARY KEY(character_id, technique_id))'); - $this->addSql('CREATE INDEX IDX_506B3A7A1136BE75 ON character_technique (character_id)'); - $this->addSql('CREATE INDEX IDX_506B3A7A1F8ACB26 ON character_technique (technique_id)'); - $this->addSql('COMMENT ON COLUMN character_technique.character_id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN character_technique.technique_id IS \'(DC2Type:ulid)\''); - $this->addSql('CREATE TABLE city (id UUID NOT NULL, dungeon_id UUID NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_2D5B0234B606863 ON city (dungeon_id)'); - $this->addSql('COMMENT ON COLUMN city.id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN city.dungeon_id IS \'(DC2Type:ulid)\''); - $this->addSql('CREATE TABLE country (id UUID NOT NULL, capital_id UUID NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_5373C966FC2D9FF7 ON country (capital_id)'); - $this->addSql('COMMENT ON COLUMN country.id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN country.capital_id IS \'(DC2Type:ulid)\''); - $this->addSql('CREATE TABLE dojo (id UUID NOT NULL, village_id UUID DEFAULT NULL, owner_id UUID NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_9494CCB15E237E06 ON dojo (name)'); - $this->addSql('CREATE INDEX IDX_9494CCB15E0D5582 ON dojo (village_id)'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_9494CCB17E3C61F9 ON dojo (owner_id)'); - $this->addSql('COMMENT ON COLUMN dojo.id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN dojo.village_id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN dojo.owner_id IS \'(DC2Type:ulid)\''); - $this->addSql('CREATE TABLE dungeon (id UUID NOT NULL, city_id UUID NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_3FFA1F908BAC62AF ON dungeon (city_id)'); - $this->addSql('COMMENT ON COLUMN dungeon.id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN dungeon.city_id IS \'(DC2Type:ulid)\''); - $this->addSql('CREATE TABLE prefecture (id UUID NOT NULL, capital_id UUID NOT NULL, country_id UUID NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_ABE6511AFC2D9FF7 ON prefecture (capital_id)'); - $this->addSql('CREATE INDEX IDX_ABE6511AF92F3E70 ON prefecture (country_id)'); - $this->addSql('COMMENT ON COLUMN prefecture.id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN prefecture.capital_id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN prefecture.country_id IS \'(DC2Type:ulid)\''); - $this->addSql('CREATE TABLE technique (id UUID NOT NULL, prerequisite_id UUID DEFAULT NULL, costs INT NOT NULL, damage VARCHAR(255) NOT NULL, energy VARCHAR(255) NOT NULL, accuracy VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_D73B9841276AF86B ON technique (prerequisite_id)'); - $this->addSql('COMMENT ON COLUMN technique.id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN technique.prerequisite_id IS \'(DC2Type:ulid)\''); - $this->addSql('CREATE TABLE "user" (id UUID NOT NULL, dojo_id UUID DEFAULT NULL, auth_name VARCHAR(255) NOT NULL, properties JSON NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D64932F09E9C ON "user" (dojo_id)'); - $this->addSql('COMMENT ON COLUMN "user".id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN "user".dojo_id IS \'(DC2Type:ulid)\''); - $this->addSql('CREATE TABLE village (id UUID NOT NULL, prefecture_id UUID NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE INDEX IDX_4E6C7FAA9D39C865 ON village (prefecture_id)'); - $this->addSql('COMMENT ON COLUMN village.id IS \'(DC2Type:ulid)\''); - $this->addSql('COMMENT ON COLUMN village.prefecture_id IS \'(DC2Type:ulid)\''); - $this->addSql('ALTER TABLE "character" ADD CONSTRAINT FK_937AB03432F09E9C FOREIGN KEY (dojo_id) REFERENCES dojo (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE character_technique ADD CONSTRAINT FK_506B3A7A1136BE75 FOREIGN KEY (character_id) REFERENCES "character" (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE character_technique ADD CONSTRAINT FK_506B3A7A1F8ACB26 FOREIGN KEY (technique_id) REFERENCES technique (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE city ADD CONSTRAINT FK_2D5B0234B606863 FOREIGN KEY (dungeon_id) REFERENCES dungeon (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE country ADD CONSTRAINT FK_5373C966FC2D9FF7 FOREIGN KEY (capital_id) REFERENCES city (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE dojo ADD CONSTRAINT FK_9494CCB15E0D5582 FOREIGN KEY (village_id) REFERENCES village (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE dojo ADD CONSTRAINT FK_9494CCB17E3C61F9 FOREIGN KEY (owner_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE dungeon ADD CONSTRAINT FK_3FFA1F908BAC62AF FOREIGN KEY (city_id) REFERENCES city (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE prefecture ADD CONSTRAINT FK_ABE6511AFC2D9FF7 FOREIGN KEY (capital_id) REFERENCES city (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE prefecture ADD CONSTRAINT FK_ABE6511AF92F3E70 FOREIGN KEY (country_id) REFERENCES country (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE technique ADD CONSTRAINT FK_D73B9841276AF86B FOREIGN KEY (prerequisite_id) REFERENCES technique (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE "user" ADD CONSTRAINT FK_8D93D64932F09E9C FOREIGN KEY (dojo_id) REFERENCES dojo (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE village ADD CONSTRAINT FK_4E6C7FAA9D39C865 FOREIGN KEY (prefecture_id) REFERENCES prefecture (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('CREATE SCHEMA public'); - $this->addSql('ALTER TABLE "character" DROP CONSTRAINT FK_937AB03432F09E9C'); - $this->addSql('ALTER TABLE character_technique DROP CONSTRAINT FK_506B3A7A1136BE75'); - $this->addSql('ALTER TABLE character_technique DROP CONSTRAINT FK_506B3A7A1F8ACB26'); - $this->addSql('ALTER TABLE city DROP CONSTRAINT FK_2D5B0234B606863'); - $this->addSql('ALTER TABLE country DROP CONSTRAINT FK_5373C966FC2D9FF7'); - $this->addSql('ALTER TABLE dojo DROP CONSTRAINT FK_9494CCB15E0D5582'); - $this->addSql('ALTER TABLE dojo DROP CONSTRAINT FK_9494CCB17E3C61F9'); - $this->addSql('ALTER TABLE dungeon DROP CONSTRAINT FK_3FFA1F908BAC62AF'); - $this->addSql('ALTER TABLE prefecture DROP CONSTRAINT FK_ABE6511AFC2D9FF7'); - $this->addSql('ALTER TABLE prefecture DROP CONSTRAINT FK_ABE6511AF92F3E70'); - $this->addSql('ALTER TABLE technique DROP CONSTRAINT FK_D73B9841276AF86B'); - $this->addSql('ALTER TABLE "user" DROP CONSTRAINT FK_8D93D64932F09E9C'); - $this->addSql('ALTER TABLE village DROP CONSTRAINT FK_4E6C7FAA9D39C865'); - $this->addSql('DROP TABLE "character"'); - $this->addSql('DROP TABLE character_technique'); - $this->addSql('DROP TABLE city'); - $this->addSql('DROP TABLE country'); - $this->addSql('DROP TABLE dojo'); - $this->addSql('DROP TABLE dungeon'); - $this->addSql('DROP TABLE prefecture'); - $this->addSql('DROP TABLE technique'); - $this->addSql('DROP TABLE "user"'); - $this->addSql('DROP TABLE village'); - } -} diff --git a/src/Controller/GetTournamentFights.php b/src/Controller/GetTournamentFights.php new file mode 100644 index 0000000..9d3d0a5 --- /dev/null +++ b/src/Controller/GetTournamentFights.php @@ -0,0 +1,21 @@ +getRepository(Fight::class)->findBy([ + 'tournament' => $tournamentId + ], [ + 'startDate' => 'ASC' + ]); + } +} + diff --git a/src/Entity/Character.php b/src/Entity/Character.php index 41231bd..38443b4 100644 --- a/src/Entity/Character.php +++ b/src/Entity/Character.php @@ -25,7 +25,7 @@ class Character extends Thing #[ApiProperty(readableLink: false, writableLink: false)] public ?Dojo $dojo; - #[Column] + #[Column(length: 64)] #[Groups('public')] public string $name; diff --git a/src/Entity/Dojo.php b/src/Entity/Dojo.php index dd2ecd6..1323ff4 100644 --- a/src/Entity/Dojo.php +++ b/src/Entity/Dojo.php @@ -22,7 +22,7 @@ class Dojo extends Thing #[ApiProperty(writable: false)] #[OneToMany(targetEntity: Character::class, mappedBy: 'dojo')] #[JoinColumn(onDelete: 'cascade', nullable: false)] - public iterable $members; + public Collection $members; #[ApiProperty(writable: false)] #[ManyToOne()] @@ -62,6 +62,7 @@ class Dojo extends Thing } /** + * * @return Collection */ public function getMembers(): Collection @@ -71,7 +72,7 @@ class Dojo extends Thing public function addMember(Character $member): static { - if (!$this->members->contains($member)) { + if (! $this->members->contains($member)) { $this->members->add($member); $member->setDojo($this); } diff --git a/src/Entity/Fight.php b/src/Entity/Fight.php new file mode 100644 index 0000000..bf6d0c8 --- /dev/null +++ b/src/Entity/Fight.php @@ -0,0 +1,108 @@ +characters = new ArrayCollection(); + } + + /** + * + * @return Collection + */ + public function getCharacters(): Collection + { + return $this->characters; + } + + public function addCharacter(Character $character): static + { + if (! $this->characters->contains($character)) { + $this->characters->add($character); + } + + return $this; + } + + public function removeCharacter(Character $character): static + { + $this->characters->removeElement($character); + + return $this; + } + + public function getStartDate(): ?\DateTimeInterface + { + return $this->startDate; + } + + public function setStartDate(\DateTimeInterface $startDate): static + { + $this->startDate = $startDate; + + return $this; + } + + public function getEvents(): array + { + return $this->events; + } + + public function setEvents(array $events): static + { + $this->events = $events; + + return $this; + } + + public function getWinner(): ?Character + { + return $this->winner; + } + + public function setWinner(?Character $winner): static + { + $this->winner = $winner; + + return $this; + } + + public function getTournament(): ?Tournament + { + return $this->tournament; + } + + public function setTournament(?Tournament $tournament): static + { + $this->tournament = $tournament; + + return $this; + } +} diff --git a/src/Entity/Technique.php b/src/Entity/Technique.php index 340d6b5..528047c 100644 --- a/src/Entity/Technique.php +++ b/src/Entity/Technique.php @@ -1,15 +1,19 @@ name; + } + + public function setName(string $name): static + { + $this->name = $name; + + return $this; + } } diff --git a/src/Entity/Tournament.php b/src/Entity/Tournament.php new file mode 100644 index 0000000..c616d89 --- /dev/null +++ b/src/Entity/Tournament.php @@ -0,0 +1,111 @@ +characters = new ArrayCollection(); + $this->fights = new ArrayCollection(); + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): static + { + $this->name = $name; + + return $this; + } + + /** + * + * @return Collection + */ + public function getCharacters(): Collection + { + return $this->characters; + } + + public function addCharacter(Character $character): static + { + if (! $this->characters->contains($character)) { + $this->characters->add($character); + } + + return $this; + } + + public function removeCharacter(Character $character): static + { + $this->characters->removeElement($character); + + return $this; + } + + public function getStartDate(): ?\DateTimeInterface + { + return $this->startDate; + } + + public function setStartDate(\DateTimeInterface $startDate): static + { + $this->startDate = $startDate; + + return $this; + } + + /** + * + * @return Collection + */ + public function getFights(): Collection + { + return $this->fights; + } + + public function addFight(Fight $fight): static + { + if (! $this->fights->contains($fight)) { + $this->fights->add($fight); + $fight->setTournament($this); + } + + return $this; + } + + public function removeFight(Fight $fight): static + { + if ($this->fights->removeElement($fight)) { + // set the owning side to null (unless already changed) + if ($fight->getTournament() === $this) { + $fight->setTournament(null); + } + } + + return $this; + } +} diff --git a/src/Entity/TournamentRegistration.php b/src/Entity/TournamentRegistration.php new file mode 100644 index 0000000..4a7e731 --- /dev/null +++ b/src/Entity/TournamentRegistration.php @@ -0,0 +1,11 @@ +authName == 'dehecht' || $this->authName == '.radiskull') { + $array[] = 'ROLE_ADMIN'; + } + + return $array; } public function getAuthName(): ?string diff --git a/src/Factory/FightFactory.php b/src/Factory/FightFactory.php new file mode 100644 index 0000000..2030a2f --- /dev/null +++ b/src/Factory/FightFactory.php @@ -0,0 +1,71 @@ + + * + * @method Fight|Proxy create(array|callable $attributes = []) + * @method static Fight|Proxy createOne(array $attributes = []) + * @method static Fight|Proxy find(object|array|mixed $criteria) + * @method static Fight|Proxy findOrCreate(array $attributes) + * @method static Fight|Proxy first(string $sortedField = 'id') + * @method static Fight|Proxy last(string $sortedField = 'id') + * @method static Fight|Proxy random(array $attributes = []) + * @method static Fight|Proxy randomOrCreate(array $attributes = []) + * @method static FightRepository|RepositoryProxy repository() + * @method static Fight[]|Proxy[] all() + * @method static Fight[]|Proxy[] createMany(int $number, array|callable $attributes = []) + * @method static Fight[]|Proxy[] createSequence(iterable|callable $sequence) + * @method static Fight[]|Proxy[] findBy(array $attributes) + * @method static Fight[]|Proxy[] randomRange(int $min, int $max, array $attributes = []) + * @method static Fight[]|Proxy[] randomSet(int $number, array $attributes = []) + */ +final class FightFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'events' => [], + 'startDate' => self::faker()->dateTime(), + 'tournament' => TournamentFactory::new(), + 'winner' => CharacterFactory::new(), + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(Fight $fight): void {}) + ; + } + + protected static function getClass(): string + { + return Fight::class; + } +} diff --git a/src/Factory/TechniqueFactory.php b/src/Factory/TechniqueFactory.php index c07d1b8..5f6b23d 100644 --- a/src/Factory/TechniqueFactory.php +++ b/src/Factory/TechniqueFactory.php @@ -47,6 +47,7 @@ final class TechniqueFactory extends ModelFactory protected function getDefaults(): array { return [ + 'name' => self::faker()->ean13(), 'accuracy' => self::faker()->text(), 'costs' => self::faker()->numberBetween(1, 2), 'damage' => self::faker()->text(), diff --git a/src/Factory/TournamentFactory.php b/src/Factory/TournamentFactory.php new file mode 100644 index 0000000..681fb24 --- /dev/null +++ b/src/Factory/TournamentFactory.php @@ -0,0 +1,69 @@ + + * + * @method Tournament|Proxy create(array|callable $attributes = []) + * @method static Tournament|Proxy createOne(array $attributes = []) + * @method static Tournament|Proxy find(object|array|mixed $criteria) + * @method static Tournament|Proxy findOrCreate(array $attributes) + * @method static Tournament|Proxy first(string $sortedField = 'id') + * @method static Tournament|Proxy last(string $sortedField = 'id') + * @method static Tournament|Proxy random(array $attributes = []) + * @method static Tournament|Proxy randomOrCreate(array $attributes = []) + * @method static TournamentRepository|RepositoryProxy repository() + * @method static Tournament[]|Proxy[] all() + * @method static Tournament[]|Proxy[] createMany(int $number, array|callable $attributes = []) + * @method static Tournament[]|Proxy[] createSequence(iterable|callable $sequence) + * @method static Tournament[]|Proxy[] findBy(array $attributes) + * @method static Tournament[]|Proxy[] randomRange(int $min, int $max, array $attributes = []) + * @method static Tournament[]|Proxy[] randomSet(int $number, array $attributes = []) + */ +final class TournamentFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'name' => self::faker()->text(255), + 'startDate' => self::faker()->dateTime(), + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(Tournament $tournament): void {}) + ; + } + + protected static function getClass(): string + { + return Tournament::class; + } +} diff --git a/src/Factory/UserFactory.php b/src/Factory/UserFactory.php index c8e24aa..6d9e013 100644 --- a/src/Factory/UserFactory.php +++ b/src/Factory/UserFactory.php @@ -47,7 +47,7 @@ final class UserFactory extends ModelFactory protected function getDefaults(): array { return [ - 'authName' => self::faker()->text(), + 'authName' => self::faker()->userName(), 'properties' => [] ]; } diff --git a/src/Repository/FightRepository.php b/src/Repository/FightRepository.php new file mode 100644 index 0000000..8691133 --- /dev/null +++ b/src/Repository/FightRepository.php @@ -0,0 +1,48 @@ + + * + * @method Fight|null find($id, $lockMode = null, $lockVersion = null) + * @method Fight|null findOneBy(array $criteria, array $orderBy = null) + * @method Fight[] findAll() + * @method Fight[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class FightRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Fight::class); + } + +// /** +// * @return Fight[] Returns an array of Fight objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('f') +// ->andWhere('f.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('f.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?Fight +// { +// return $this->createQueryBuilder('f') +// ->andWhere('f.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/src/Repository/TournamentRepository.php b/src/Repository/TournamentRepository.php new file mode 100644 index 0000000..67b3f27 --- /dev/null +++ b/src/Repository/TournamentRepository.php @@ -0,0 +1,48 @@ + + * + * @method Tournament|null find($id, $lockMode = null, $lockVersion = null) + * @method Tournament|null findOneBy(array $criteria, array $orderBy = null) + * @method Tournament[] findAll() + * @method Tournament[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class TournamentRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Tournament::class); + } + +// /** +// * @return Tournament[] Returns an array of Tournament objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('t') +// ->andWhere('t.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('t.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?Tournament +// { +// return $this->createQueryBuilder('t') +// ->andWhere('t.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/src/Security/ApiKeyAuthenticator.php b/src/Security/ApiKeyAuthenticator.php deleted file mode 100644 index 8cf0e0a..0000000 --- a/src/Security/ApiKeyAuthenticator.php +++ /dev/null @@ -1,68 +0,0 @@ -headers->has('X-AUTH-TOKEN'); - } - - public function authenticate(Request $request): Passport - { - $apiToken = $request->headers->get('X-AUTH-TOKEN'); - if (null === $apiToken) { - return null; - } - - $userIdentifier = $apiToken; - - return new SelfValidatingPassport( - new UserBadge($userIdentifier, - function (string $userIdentifier): ?UserInterface { - return $this->userRepository->findOneBy([ - 'authName' => $userIdentifier - ]); - })); - } - - public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response - { - // on success, let the request continue - return null; - } - - public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response - { - $this->logger->critical("YYY"); - $message = strtr($exception->getMessageKey(), $exception->getMessageData()); - // or to translate this message - // $this->translator->trans($exception->getMessageKey(), $exception->getMessageData()) - - // This should translated by FOSRestBundle! - throw new AccessDeniedHttpException($message); - } -} \ No newline at end of file diff --git a/tests/AbstractTest.php b/tests/AbstractTest.php index f110a1f..bb5f96b 100644 --- a/tests/AbstractTest.php +++ b/tests/AbstractTest.php @@ -3,6 +3,8 @@ namespace App\Tests; use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; use ApiPlatform\Symfony\Bundle\Test\Client; +use App\Entity\Thing; +use Zenstruck\Foundry\Proxy; use Zenstruck\Foundry\Test\Factories; use Zenstruck\Foundry\Test\ResetDatabase; use DateTimeZone; @@ -28,7 +30,7 @@ abstract class AbstractTest extends ApiTestCase return sodium_bin2base64(sodium_crypto_sign($message, $sign_secret), SODIUM_BASE64_VARIANT_URLSAFE); } - protected static function createClientWithToken($authName = null): Client + protected static function createClientWithToken($authName = "FooMan"): Client { return static::createClient([], [ @@ -38,5 +40,13 @@ abstract class AbstractTest extends ApiTestCase ] ]); } + + protected function getIri(Thing|Proxy $thing) + { + if ($thing instanceof Proxy) { + return $this->getIriFromResource($thing->object()); + } + return $this->getIriFromResource($thing); + } } diff --git a/tests/CharacterTest.php b/tests/CharacterTest.php index c3fa502..77aab74 100644 --- a/tests/CharacterTest.php +++ b/tests/CharacterTest.php @@ -22,7 +22,7 @@ class CharacterTest extends AbstractTest CharacterFactory::createMany(10); $response = static::createClientWithToken($requestUser->authName)->request('GET', - '/api/dojo/' . $dojo->id . '/characters'); + $this->getIri($dojo) . '/characters'); $this->assertResponseStatusCodeSame(200); @@ -115,8 +115,7 @@ class CharacterTest extends AbstractTest 'agility' => 1, 'chi' => 1, 'techniques' => [ - '/api/techniques/' . $tech->getId() - ->toBase32() + $this->getIri($tech) ] ] ]); @@ -149,8 +148,7 @@ class CharacterTest extends AbstractTest 'agility' => 1, 'chi' => 1, 'techniques' => [ - '/api/techniques/' . $tech->getId() - ->toBase32() + $this->getIri($tech) ] ] ]); @@ -181,8 +179,7 @@ class CharacterTest extends AbstractTest 'agility' => 1, 'chi' => 1, 'techniques' => [ - '/api/techniques/' . $tech->getId() - ->toBase32() + $this->getIri($tech) ] ] ]); diff --git a/tests/DojoTest.php b/tests/DojoTest.php index 8d0520c..97ee37f 100644 --- a/tests/DojoTest.php +++ b/tests/DojoTest.php @@ -53,8 +53,7 @@ class DojoTest extends AbstractTest [ 'name' => 'BigFightDojo', 'members' => [], - 'owner' => '/api/users/' . $dojo->owner->getId() - ->toBase32(), + 'owner' => $this->getIri($dojo->getOwner()), 'id' => $dojo->getId() ->toBase32() ]); diff --git a/tests/TechniqueTest.php b/tests/TechniqueTest.php new file mode 100644 index 0000000..051ff32 --- /dev/null +++ b/tests/TechniqueTest.php @@ -0,0 +1,134 @@ + NULL + ]); + + $response = static::createClientWithToken()->request('GET', '/api/techniques'); + $this->assertEquals(10, count($response->toArray())); + } + + public function testListTechniquesWithPrerequisite(): void + { + $prerequisite = TechniqueFactory::createOne([ + 'prerequisite' => NULL + ]); + + TechniqueFactory::createMany(2, [ + 'prerequisite' => $prerequisite + ]); + + $response = static::createClientWithToken()->request('GET', '/api/techniques'); + $this->assertEquals(3, count($response->toArray())); + } + + public function testShowTechnique(): void + { + $technique = TechniqueFactory::createOne([ + 'prerequisite' => NULL + ]); + + $response = static::createClientWithToken()->request('GET', + '/api/techniques/' . $technique->getId() + ->toBase32()); + + $this->assertJsonEquals( + [ + 'id' => $technique->getId() + ->toBase32(), + 'name' => $technique->getName(), + 'costs' => $technique->getCosts(), + 'damage' => $technique->getDamage(), + 'energy' => $technique->getEnergy(), + 'accuracy' => $technique->getAccuracy() + ], $response->getContent()); + } + + public function testShowTechniqueWithPrerequisite(): void + { + $prerequisite = TechniqueFactory::createOne([ + 'prerequisite' => NULL + ]); + + $technique = TechniqueFactory::createOne([ + 'prerequisite' => $prerequisite + ]); + + $response = static::createClientWithToken()->request('GET', + '/api/techniques/' . $technique->getId() + ->toBase32()); + + $this->assertJsonEquals( + [ + 'id' => $technique->getId() + ->toBase32(), + 'name' => $technique->getName(), + 'costs' => $technique->getCosts(), + 'damage' => $technique->getDamage(), + 'energy' => $technique->getEnergy(), + 'accuracy' => $technique->getAccuracy(), + 'prerequisite' => '/api/techniques/' . $prerequisite->getId() + ->toBase32() + ], $response->getContent()); + } + + public function testCreateTechniqueAsAdmin(): void + { + $response = static::createClientWithToken("dehecht")->request('POST', '/api/techniques', + [ + 'json' => [ + 'name' => 'Drei-Schwert-Style', + 'costs' => 2, + 'damage' => '3 * strength', + 'energy' => '1.5 * constitution + 2 * strength', + 'accuracy' => '2 * agility' + ] + ]); + + $this->assertResponseStatusCodeSame(201); + + $this->assertArrayHasKey('id', $response->toArray()); + } + + public function testCreateTechniqueFailsAsUser(): void + { + static::createClientWithToken()->request('POST', '/api/techniques', + [ + 'json' => [ + 'name' => 'Drei-Schwert-Style', + 'costs' => 2, + 'damage' => '3 * strength', + 'energy' => '1.5 * constitution + 2 * strength', + 'accuracy' => '2 * agility' + ] + ]); + + $this->assertResponseStatusCodeSame(403); + } + + public function testFailToCreateTechniqueWithNonExistentPrerequisite(): void + { + $response = static::createClientWithToken("dehecht")->request('POST', '/api/techniques', + [ + 'json' => [ + 'name' => 'Drei-Schwert-Style', + 'costs' => 2, + 'damage' => '3 * strength', + 'energy' => '1.5 * constitution + 2 * strength', + 'accuracy' => '2 * agility', + 'prerequisite' => '/api/techniques/01ARZ3NDEKTSV4RRFFQ69G5FAV' + ] + ]); + + $this->assertTrue($response->getStatusCode() / 100 != 2); + } +} + diff --git a/tests/TournamentTest.php b/tests/TournamentTest.php new file mode 100644 index 0000000..54d0b72 --- /dev/null +++ b/tests/TournamentTest.php @@ -0,0 +1,71 @@ + UserFactory::createOne() + ]); + + $character = CharacterFactory::createOne([ + 'dojo' => $dojo + ]); + + $response = static::createClientWithToken($dojo->getOwner()->authName)->request('POST', + '/api/tournament_registrations', + [ + 'json' => [ + 'tournament' => $this->getIri($tournament), + 'character' => $this->getIri($character) + ] + ]); + + $this->assertResponseStatusCodeSame(201); + + $this->assertArrayHasKey('id', $response->toArray()); + } + + public function testRegisterCharacterNotPossibleTwice(): void + {} + + public function testRegisterCharacterOnPastTournament(): void + {} + + public function testShowRegisteredCharacters(): void + {} + + public function testListTournaments(): void + {} + + /** + * Status is ... + * meta data like when it is starting, name, "location", Winner (nullable), etc. + */ + public function testTournamentStatus(): void + {} + + // /api/tournament/{id}/fights + // readableLink: true -> participant ids and winner + public function testTournamentFights(): void + {} + + // /api/tournament/{id}/character/{id}/fights + public function testTournamentFightsForCharacter(): void + {} + + // /api/tournament/{id}/ranking + public function testTournamentRanking(): void + {} +} +