From b5731a28d9dd7a31ad5fce36663456e2c4f664d2 Mon Sep 17 00:00:00 2001 From: Shyim Date: Thu, 26 Apr 2018 00:02:22 +0200 Subject: [PATCH] Added error message callback, make stream name and user_id unique --- .../ReCast/Endpoints/EditEndpoint.vue | 15 +++++++- .../components/ReCast/Streams/EditStream.vue | 15 +++++++- src/Controller/Events.php | 1 - src/Controller/Streams.php | 37 ++++++++++++++++-- src/Entity/Streams.php | 10 ++++- src/Migrations/Version20180425210736.php | 38 +++++++++++++++++++ src/Migrations/Version20180425213959.php | 30 +++++++++++++++ src/Repository/StreamsRepository.php | 4 -- 8 files changed, 138 insertions(+), 12 deletions(-) create mode 100644 src/Migrations/Version20180425210736.php create mode 100644 src/Migrations/Version20180425213959.php diff --git a/public/theme/src/components/ReCast/Endpoints/EditEndpoint.vue b/public/theme/src/components/ReCast/Endpoints/EditEndpoint.vue index 04a4a19..6a95fdc 100644 --- a/public/theme/src/components/ReCast/Endpoints/EditEndpoint.vue +++ b/public/theme/src/components/ReCast/Endpoints/EditEndpoint.vue @@ -80,7 +80,20 @@ save: function () { this.axios.post('/streams/' + this.$route.params.streamId + '/endpoints/update', this.endpoint).then(() => { this.$router.push('/ucp/streams/' + this.$route.params.streamId + '/'); - }) + }).catch(error => { + const notification = { + template: `${error.response.data.message}` + }; + + this.$notify( + { + component: notification, + icon: 'fa fa-exclamation-triangle', + horizontalAlign: 'right', + verticalAlign: 'top', + type: 'danger' + }); + }); } }, computed: { diff --git a/public/theme/src/components/ReCast/Streams/EditStream.vue b/public/theme/src/components/ReCast/Streams/EditStream.vue index 2ba791d..4be2d63 100644 --- a/public/theme/src/components/ReCast/Streams/EditStream.vue +++ b/public/theme/src/components/ReCast/Streams/EditStream.vue @@ -83,7 +83,20 @@ save: function () { this.axios.post('/streams/update', this.stream).then(() => { this.$router.push('/ucp/streams/'); - }) + }).catch(error => { + const notification = { + template: `${error.response.data.message}` + }; + + this.$notify( + { + component: notification, + icon: 'fa fa-exclamation-triangle', + horizontalAlign: 'right', + verticalAlign: 'top', + type: 'danger' + }); + }); }, deleteEndpoint: function (endpoint) { this.endpoints.splice(this.endpoints.indexOf(endpoint), 1); diff --git a/src/Controller/Events.php b/src/Controller/Events.php index 994ebe4..45c7221 100644 --- a/src/Controller/Events.php +++ b/src/Controller/Events.php @@ -4,7 +4,6 @@ namespace App\Controller; use App\Entity\Streams; use App\Repository\StreamsRepository; -use Doctrine\Common\Util\Debug; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; diff --git a/src/Controller/Streams.php b/src/Controller/Streams.php index d32b575..89b5142 100644 --- a/src/Controller/Streams.php +++ b/src/Controller/Streams.php @@ -3,13 +3,12 @@ namespace App\Controller; -use App\Component\Forms\Endpoint as EndpointForm; -use App\Component\Forms\Streams as StreamsForm; use App\Component\ServiceManager; use App\Entity\Endpoint; use App\Entity\User; use App\Repository\EndpointRepository; use App\Repository\StreamsRepository; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\JsonResponse; @@ -96,14 +95,22 @@ class Streams extends Controller return new Response('Access denied', 401); } + if (empty($requestBody['name']) || !$this->isValidString($requestBody['name'])) { + return new JsonResponse(['message' => 'Name is empty or contains illegal strings'], 500); + } + $stream->setUser($this->getUser()); $stream->setName($requestBody['name']); $stream->setActive($requestBody['active']); $manager = $this->get('doctrine.orm.entity_manager'); - $manager->persist($stream); - $manager->flush(); + try { + $manager->persist($stream); + $manager->flush(); + } catch (UniqueConstraintViolationException $e) { + return new JsonResponse(['message' => sprintf('"%s" is already taken', $stream->getName())], 500); + } return new JsonResponse($stream); } @@ -205,6 +212,18 @@ class Streams extends Controller return new JsonResponse([]); } + if (empty($requestBody['name'])) { + return new JsonResponse(['message' => 'Name is empty'], 500); + } + + if (empty($requestBody['server']) || !$this->isValidString($requestBody['server'])) { + return new JsonResponse(['message' => 'Server is empty or contains illegal strings'], 500); + } + + if (!empty($requestBody['streamKey']) && !$this->isValidString($requestBody['streamKey'])) { + return new JsonResponse(['message' => 'Stream-Key contains illegal strings'], 500); + } + $endpoint = !empty($requestBody['id']) ? $this->endpointRepository->find($requestBody['id']) : new Endpoint(); $endpoint->setName($requestBody['name']); @@ -243,4 +262,14 @@ class Streams extends Controller return new JsonResponse(); } + + /** + * @param null|string $string + * @return false|int + * @author Soner Sayakci + */ + private function isValidString(?string $string) + { + return preg_match('/^[a-z|A-Z|a-z|A-Z|0-9|.|\-|_|]+$/', $string); + } } \ No newline at end of file diff --git a/src/Entity/Streams.php b/src/Entity/Streams.php index a3597e7..11347de 100644 --- a/src/Entity/Streams.php +++ b/src/Entity/Streams.php @@ -5,9 +5,17 @@ namespace App\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Event\LifecycleEventArgs; use Doctrine\ORM\Mapping as ORM; +use Doctrine\ORM\Mapping\UniqueConstraint; + /** * @ORM\Entity(repositoryClass="App\Repository\StreamsRepository") + * @ORM\Table(name="streams", + * uniqueConstraints={ + * @UniqueConstraint(name="stream_name", + * columns={"name", "user_id"}) + * } + * ) * @ORM\HasLifecycleCallbacks() */ class Streams implements \JsonSerializable @@ -21,7 +29,7 @@ class Streams implements \JsonSerializable private $id; /** - * @ORM\Column(type="string", length=255, nullable=false) + * @ORM\Column(type="string", length=50, nullable=false) * @var string */ private $name; diff --git a/src/Migrations/Version20180425210736.php b/src/Migrations/Version20180425210736.php new file mode 100644 index 0000000..b7e6965 --- /dev/null +++ b/src/Migrations/Version20180425210736.php @@ -0,0 +1,38 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE streams (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, name VARCHAR(255) NOT NULL, active TINYINT(1) NOT NULL, live TINYINT(1) DEFAULT \'0\' NOT NULL, stream_key VARCHAR(255) NOT NULL, INDEX IDX_FFF7AFAA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB'); + $this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(100) NOT NULL, password VARCHAR(255) NOT NULL, email VARCHAR(100) NOT NULL, role VARCHAR(255) DEFAULT \'user\' NOT NULL, created_at DATETIME NOT NULL, UNIQUE INDEX UNIQ_8D93D649F85E0677 (username), UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB'); + $this->addSql('CREATE TABLE endpoint (id INT AUTO_INCREMENT NOT NULL, stream_id INT DEFAULT NULL, active TINYINT(1) DEFAULT \'1\' NOT NULL, name VARCHAR(255) NOT NULL, type VARCHAR(255) NOT NULL, server VARCHAR(255) NOT NULL, streamKey VARCHAR(255) NOT NULL, INDEX IDX_C4420F7BD0ED463E (stream_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB'); + $this->addSql('CREATE TABLE queue (id INT AUTO_INCREMENT NOT NULL, task VARCHAR(100) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB'); + $this->addSql('ALTER TABLE streams ADD CONSTRAINT FK_FFF7AFAA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)'); + $this->addSql('ALTER TABLE endpoint ADD CONSTRAINT FK_C4420F7BD0ED463E FOREIGN KEY (stream_id) REFERENCES streams (id)'); + } + + public function down(Schema $schema) + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE endpoint DROP FOREIGN KEY FK_C4420F7BD0ED463E'); + $this->addSql('ALTER TABLE streams DROP FOREIGN KEY FK_FFF7AFAA76ED395'); + $this->addSql('DROP TABLE streams'); + $this->addSql('DROP TABLE user'); + $this->addSql('DROP TABLE endpoint'); + $this->addSql('DROP TABLE queue'); + } +} diff --git a/src/Migrations/Version20180425213959.php b/src/Migrations/Version20180425213959.php new file mode 100644 index 0000000..8aef530 --- /dev/null +++ b/src/Migrations/Version20180425213959.php @@ -0,0 +1,30 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE streams CHANGE name name VARCHAR(50) NOT NULL'); + $this->addSql('CREATE UNIQUE INDEX stream_name ON streams (name, user_id)'); + } + + public function down(Schema $schema) + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP INDEX stream_name ON streams'); + $this->addSql('ALTER TABLE streams CHANGE name name VARCHAR(255) NOT NULL COLLATE utf8mb4_unicode_ci'); + } +} diff --git a/src/Repository/StreamsRepository.php b/src/Repository/StreamsRepository.php index 28ccc1f..e11c492 100644 --- a/src/Repository/StreamsRepository.php +++ b/src/Repository/StreamsRepository.php @@ -7,7 +7,6 @@ use App\Entity\User; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\Query; use Symfony\Bridge\Doctrine\RegistryInterface; -use Symfony\Bundle\MakerBundle\Str; /** * @method Streams|null find($id, $lockMode = null, $lockVersion = null) @@ -67,12 +66,9 @@ class StreamsRepository extends ServiceEntityRepository public function getStreamByNameAndUsername(string $streamName, string $userName, string $streamKey): ?Streams { $qb = $this->createQueryBuilder('streams') - ->addSelect('endpoints') ->addSelect('user') - ->leftJoin('streams.endpoints', 'endpoints') ->innerJoin('streams.user', 'user') ->andWhere('streams.active = true') - ->andWhere('endpoints.active = true') ->andWhere('streams.name = :streamName') ->andWhere('user.username = :userName') ->andWhere('streams.streamKey = :streamKey')