diff --git a/.circleci/config.yml b/.circleci/config.yml
index 74a10e308..fb202186f 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -10,6 +10,7 @@ jobs:
MYSQL_DATABASE: upont
MYSQL_USER: upont
MYSQL_PASSWORD: upont
+ - image: redis:5-alpine
working_directory: ~/upont
steps:
- run: sudo apt update && sudo apt install -y libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libpng-dev zlib1g-dev
diff --git a/.env.dist b/.env.dist
index 4ba976b33..1cb5a5208 100644
--- a/.env.dist
+++ b/.env.dist
@@ -43,3 +43,8 @@ APP_SECRET=c97499ba41de9fe24ad8d2ab083a7e66
#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
#TRUSTED_HOSTS=localhost,example.com
###< symfony/framework-bundle ###
+
+###> snc/redis-bundle ###
+# passwords that contain special characters (@, %, :, +) must be urlencoded
+REDIS_URL=redis://localhost
+###< snc/redis-bundle ###
diff --git a/back/composer.json b/back/composer.json
index 7376d3946..f38067d47 100644
--- a/back/composer.json
+++ b/back/composer.json
@@ -37,7 +37,10 @@
"nesbot/carbon": "^2.11",
"sensio/framework-extra-bundle": "^5.2",
"sensiolabs/security-checker": "^5.0",
+ "noxlogic/ratelimit-bundle": "^1.14",
+ "predis/predis": "^1.1",
"sentry/sentry-symfony": "~2.0",
+ "snc/redis-bundle": "^2.1",
"stof/doctrine-extensions-bundle": "~1.1",
"symfony/asset": "^4.2",
"symfony/console": "^4.2",
diff --git a/back/composer.lock b/back/composer.lock
index b2077379c..2cae4ab49 100644
--- a/back/composer.lock
+++ b/back/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "b14fe2251fda993d4216c13ec25ac352",
+ "content-hash": "2c3606ae85d0b20c57c0aa88717627e4",
"packages": [
{
"name": "behat/transliterator",
@@ -2686,6 +2686,63 @@
],
"time": "2019-03-29T12:23:12+00:00"
},
+ {
+ "name": "noxlogic/ratelimit-bundle",
+ "version": "1.14.0",
+ "target-dir": "Noxlogic/RateLimitBundle",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jaytaph/RateLimitBundle.git",
+ "reference": "6bd1126cafe69635fec02f374e46f413544469d5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jaytaph/RateLimitBundle/zipball/6bd1126cafe69635fec02f374e46f413544469d5",
+ "reference": "6bd1126cafe69635fec02f374e46f413544469d5",
+ "shasum": ""
+ },
+ "require": {
+ "sensio/framework-extra-bundle": "^2.3|^3.0|^4.0|^5.0",
+ "symfony/framework-bundle": "^2.3|^3.0|^4.0"
+ },
+ "require-dev": {
+ "doctrine/cache": "^1.5",
+ "friendsofsymfony/oauth-server-bundle": "^1.5",
+ "phpunit/phpunit": "^4.8|^5.0",
+ "predis/predis": "^0.8|^1.1",
+ "psr/cache": "^1.0",
+ "psr/simple-cache": "^1.0"
+ },
+ "suggest": {
+ "doctrine/doctrine-cache-bundle": "Use Doctrine Cache as a storage engine.",
+ "friendsofsymfony/oauth-server-bundle": "Throttle using OAuth access tokens.",
+ "leaseweb/memcache-bundle": "Use Memcache as a storage engine.",
+ "snc/redis-bundle": "Use Redis as a storage engine."
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-0": {
+ "Noxlogic\\RateLimitBundle": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Joshua Thijssen",
+ "email": "jthijssen@noxlogic.nl"
+ }
+ ],
+ "description": "This bundle provides functionality to limit calls to actions based on rate limits",
+ "keywords": [
+ "api",
+ "rest",
+ "x-rate-limit"
+ ],
+ "time": "2019-02-19T08:49:10+00:00"
+ },
{
"name": "ocramius/package-versions",
"version": "1.4.0",
@@ -3100,6 +3157,56 @@
],
"time": "2015-07-25T16:39:46+00:00"
},
+ {
+ "name": "predis/predis",
+ "version": "v1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nrk/predis.git",
+ "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1",
+ "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8"
+ },
+ "suggest": {
+ "ext-curl": "Allows access to Webdis when paired with phpiredis",
+ "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Predis\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Daniele Alessandri",
+ "email": "suppakilla@gmail.com",
+ "homepage": "http://clorophilla.net"
+ }
+ ],
+ "description": "Flexible and feature-complete Redis client for PHP and HHVM",
+ "homepage": "http://github.com/nrk/predis",
+ "keywords": [
+ "nosql",
+ "predis",
+ "redis"
+ ],
+ "time": "2016-06-16T16:22:20+00:00"
+ },
{
"name": "psr/cache",
"version": "1.0.1",
@@ -3540,6 +3647,72 @@
],
"time": "2019-01-28T09:23:48+00:00"
},
+ {
+ "name": "snc/redis-bundle",
+ "version": "2.1.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/snc/SncRedisBundle.git",
+ "reference": "af3ac967b0351ff880f646486bff87247abb5286"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/snc/SncRedisBundle/zipball/af3ac967b0351ff880f646486bff87247abb5286",
+ "reference": "af3ac967b0351ff880f646486bff87247abb5286",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/framework-bundle": "^2.7 || ^3.0 || ^4.0",
+ "symfony/yaml": "^2.7 || ^3.0 || ^4.0"
+ },
+ "require-dev": {
+ "doctrine/cache": "1.*",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
+ "predis/predis": "^1.0",
+ "symfony/console": "^2.7 || ^3.0 || ^4.0",
+ "symfony/phpunit-bridge": "^2.7 || ^3.0 || ^4.0"
+ },
+ "suggest": {
+ "monolog/monolog": "If you want to use the monolog redis handler.",
+ "predis/predis": "If you want to use predis.",
+ "symfony/console": "If you want to use commands to interact with the redis database",
+ "symfony/proxy-manager-bridge": "If you want to lazy-load some services"
+ },
+ "type": "symfony-bundle",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Snc\\RedisBundle\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Henrik Westphal",
+ "email": "henrik.westphal@gmail.com"
+ },
+ {
+ "name": "Community contributors",
+ "homepage": "https://github.com/snc/SncRedisBundle/contributors"
+ }
+ ],
+ "description": "A Redis bundle for Symfony",
+ "homepage": "https://github.com/snc/SncRedisBundle",
+ "keywords": [
+ "nosql",
+ "redis",
+ "symfony"
+ ],
+ "time": "2019-02-20T07:03:43+00:00"
+ },
{
"name": "stof/doctrine-extensions-bundle",
"version": "v1.3.0",
diff --git a/back/config/bundles.php b/back/config/bundles.php
index 3b9d6f1c7..b95a28848 100644
--- a/back/config/bundles.php
+++ b/back/config/bundles.php
@@ -20,4 +20,6 @@
Sentry\SentryBundle\SentryBundle::class => ['prod' => true],
Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true],
Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
+ Noxlogic\RateLimitBundle\NoxlogicRateLimitBundle::class => ['all' => true],
+ Snc\RedisBundle\SncRedisBundle::class => ['all' => true],
];
diff --git a/back/config/packages/noxlogic_rate_limit.yaml b/back/config/packages/noxlogic_rate_limit.yaml
new file mode 100644
index 000000000..4a5087810
--- /dev/null
+++ b/back/config/packages/noxlogic_rate_limit.yaml
@@ -0,0 +1,4 @@
+noxlogic_rate_limit:
+ storage_engine: redis
+ display_headers: false
+ rate_response_message: null
diff --git a/back/config/packages/snc_redis.yaml b/back/config/packages/snc_redis.yaml
new file mode 100644
index 000000000..1ad969779
--- /dev/null
+++ b/back/config/packages/snc_redis.yaml
@@ -0,0 +1,6 @@
+snc_redis:
+ clients:
+ default:
+ type: predis
+ alias: default
+ dsn: "%env(REDIS_URL)%"
diff --git a/back/config/services.yaml b/back/config/services.yaml
index d069af3de..1f405fbd1 100644
--- a/back/config/services.yaml
+++ b/back/config/services.yaml
@@ -283,4 +283,6 @@ services:
tags:
- { name: form.type, alias: user }
- BOMO\IcalBundle\Provider\IcsProvider: '@bomo_ical.ics_provider'
+ App\Listener\RateLimitGenerateKeyListener:
+ tags:
+ - { name: kernel.event_listener, event: ratelimit.generate.key, method: onGenerateKey }
diff --git a/back/phpunit.xml.circle b/back/phpunit.xml.circle
index 26825ee6a..5b6d89296 100644
--- a/back/phpunit.xml.circle
+++ b/back/phpunit.xml.circle
@@ -24,6 +24,11 @@
+
+
+
+
+
diff --git a/back/phpunit.xml.dist b/back/phpunit.xml.dist
index 8cf0fbbca..687648e2e 100644
--- a/back/phpunit.xml.dist
+++ b/back/phpunit.xml.dist
@@ -23,6 +23,11 @@
+
+
+
+
+
diff --git a/back/src/Controller/CoreController.php b/back/src/Controller/CoreController.php
index 8f766cd3e..95ac5a39c 100644
--- a/back/src/Controller/CoreController.php
+++ b/back/src/Controller/CoreController.php
@@ -99,6 +99,18 @@ public function dirtyAction()
* @Operation(
* tags={"Général"},
* summary="Se loger et recevoir un JSON Web Token",
+ * @SWG\Parameter(
+ * name="username",
+ * in="formData",
+ * required=true,
+ * type="string"
+ * ),
+ * @SWG\Parameter(
+ * name="password",
+ * in="formData",
+ * required=true,
+ * type="string"
+ * ),
* @SWG\Response(
* response="200",
* description="Requête traitée avec succès"
@@ -106,10 +118,6 @@ public function dirtyAction()
* @SWG\Response(
* response="401",
* description="Mauvaise combinaison username/password ou champ nom rempli"
- * ),
- * @SWG\Response(
- * response="502",
- * description="Erreur Proxy : l'utilisateur se connecte pour la première fois, mais le proxy DSI n'est pas configuré"
* )
* )
*
diff --git a/back/src/Controller/Publications/EventsController.php b/back/src/Controller/Publications/EventsController.php
index 8eaabcb23..7a4619e64 100644
--- a/back/src/Controller/Publications/EventsController.php
+++ b/back/src/Controller/Publications/EventsController.php
@@ -12,6 +12,7 @@
use App\Service\NotifyService;
use Carbon\Carbon;
use Nelmio\ApiDocBundle\Annotation\Operation;
+use Noxlogic\RateLimitBundle\Annotation\RateLimit;
use Swagger\Annotations as SWG;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
@@ -374,6 +375,12 @@ public function deleteEventAction($slug)
* @Operation(
* tags={"Publications"},
* summary="Shotgunne un événement",
+ * @SWG\Parameter(
+ * name="motivation",
+ * in="formData",
+ * required=true,
+ * type="string",
+ * ),
* @SWG\Response(
* response="201",
* description="Requête traitée avec succès avec création d’un document"
@@ -392,6 +399,7 @@ public function deleteEventAction($slug)
* )
* )
*
+ * @RateLimit(limit=3, period=10)
* @Route("/events/{slug}/shotgun", methods={"POST"})
*/
public function postEventUserAction(Request $request, $slug)
@@ -412,7 +420,7 @@ public function postEventUserAction(Request $request, $slug)
if (count($userEvent) != 0)
throw new BadRequestHttpException('Tu es déjà inscrit !');
- //S'il est l'heure, on accepte le shotgun
+ // S'il est l'heure, on accepte le shotgun
if (Carbon::now() >= $event->getShotgunDate()) {
$userEvent = new EventUser();
$userEvent->setEvent($event);
diff --git a/back/src/Listener/RateLimitGenerateKeyListener.php b/back/src/Listener/RateLimitGenerateKeyListener.php
new file mode 100644
index 000000000..15addadfe
--- /dev/null
+++ b/back/src/Listener/RateLimitGenerateKeyListener.php
@@ -0,0 +1,29 @@
+tokenStorage = $tokenStorage;
+ }
+
+ /**
+ * @param GenerateKeyEvent $event
+ */
+ public function onGenerateKey(GenerateKeyEvent $event)
+ {
+ $token = $this->tokenStorage->getToken();
+
+ $event->addToKey($token->getUsername());
+ }
+}
diff --git a/back/symfony.lock b/back/symfony.lock
index 93ed02a36..608f7361c 100644
--- a/back/symfony.lock
+++ b/back/symfony.lock
@@ -170,6 +170,9 @@
"nesbot/carbon": {
"version": "1.24.2"
},
+ "noxlogic/ratelimit-bundle": {
+ "version": "1.14.0"
+ },
"ocramius/proxy-manager": {
"version": "2.1.1"
},
@@ -191,6 +194,9 @@
"phpoption/phpoption": {
"version": "1.5.0"
},
+ "predis/predis": {
+ "version": "v1.1.1"
+ },
"psr/cache": {
"version": "1.0.1"
},
@@ -236,6 +242,15 @@
"ref": "fa1a2dfc020798cd7076b5419596e72dca07047a"
}
},
+ "snc/redis-bundle": {
+ "version": "2.0",
+ "recipe": {
+ "repo": "github.com/symfony/recipes-contrib",
+ "branch": "master",
+ "version": "2.0",
+ "ref": "e9c58bfc414cfb7f06e8e5ae9f589868498f5d6a"
+ }
+ },
"stof/doctrine-extensions-bundle": {
"version": "1.2",
"recipe": {
diff --git a/docker-compose.yml b/docker-compose.yml
index 5c86a6904..964806147 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -35,6 +35,10 @@ services:
- 127.0.0.1:10102:80
restart: always
+ redis:
+ image: redis:5-alpine
+ restart: always
+
upont-back:
image: quay.io/kiclubinfo/upont-back:${TAG:-latest}
volumes:
@@ -43,8 +47,10 @@ services:
- upont-uploads:/app/public/uploads:rw
depends_on:
- db
+ - redis
environment:
- DATABASE_HOST=db
+ - REDIS_URL=redis://redis
env_file:
- .env
restart: always