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')