Преглед изворни кода

Evolution #756: Sécuriser les urls playlist

Bastien Sevajol пре 11 година
родитељ
комит
a1f60d87a5

+ 18 - 2
src/Muzich/CoreBundle/Extension/MyTwigExtension.php Прегледај датотеку

@@ -5,16 +5,19 @@ namespace Muzich\CoreBundle\Extension;
5 5
 use Symfony\Bundle\FrameworkBundle\Translation\Translator;
6 6
 use Muzich\CoreBundle\Entity\Event;
7 7
 use Symfony\Component\Form\FormView;
8
+use Symfony\Component\DependencyInjection\Container;
8 9
 
9 10
 class MyTwigExtension extends \Twig_Extension {
10 11
 
11 12
   private $translator;
13
+  private $container;
12 14
   protected $params = array();
13 15
 
14
-  public function __construct(Translator $translator, $params)
16
+  public function __construct(Translator $translator, $params, Container $container)
15 17
   {
16 18
     $this->translator = $translator;
17 19
     $this->params = $params;
20
+    $this->container = $container;
18 21
   }
19 22
   
20 23
   public function getFilters()
@@ -33,7 +36,9 @@ class MyTwigExtension extends \Twig_Extension {
33 36
     return array(
34 37
       'date_or_relative_date'  => new \Twig_Function_Method($this, 'date_or_relative_date'),
35 38
       'event_const'            => new \Twig_Function_Method($this, 'event_const'),
36
-      'css_list_length_class'  => new \Twig_Function_Method($this, 'getCssLengthClassForList')
39
+      'css_list_length_class'  => new \Twig_Function_Method($this, 'getCssLengthClassForList'),
40
+      'token'                  => new \Twig_Function_Method($this, 'token'),
41
+      'path_token'             => new \Twig_Function_Method($this, 'path_token')
37 42
     );
38 43
   }
39 44
   
@@ -192,6 +197,17 @@ class MyTwigExtension extends \Twig_Extension {
192 197
     }
193 198
   }
194 199
   
200
+  public function token($intention = '')
201
+  {
202
+    return $this->container->get('form.csrf_provider')->generateCsrfToken($intention);
203
+  }
204
+  
205
+  public function path_token($route, $parameters = array(), $intention = '', $absolute = false)
206
+  {
207
+    $parameters = array_merge($parameters, array('token' => $this->token($intention)));
208
+    return $this->container->get('router')->generate($route, $parameters, $absolute);
209
+  }
210
+  
195 211
   public function form_has_errors(FormView $form)
196 212
   {
197 213
     $form_vars = $form->getVars();

+ 16 - 8
src/Muzich/CoreBundle/Tests/lib/Security/ContextTestCases.php Прегледај датотеку

@@ -266,7 +266,8 @@ class ContextTestCases
266 266
       $this->test->generateUrl('playlists_add_element', array(
267 267
         'playlist_id' => $playlist_id,
268 268
         'element_id'  => $element_id,
269
-        '_locale'     => 'fr'
269
+        '_locale'     => 'fr',
270
+        'token'       => $this->test->getToken()
270 271
       ))
271 272
     );
272 273
   }
@@ -293,7 +294,8 @@ class ContextTestCases
293 294
       'GET',
294 295
       $this->test->generateUrl('playlist_update_order', array(
295 296
         'playlist_id' => $playlist_id,
296
-        '_locale'     => 'fr'
297
+        '_locale'     => 'fr',
298
+        'token'       => $this->test->getToken()
297 299
       )),
298 300
       array(
299 301
         'elements' => $elements_ids
@@ -318,7 +320,8 @@ class ContextTestCases
318 320
       $this->test->generateUrl('playlist_remove_element', array(
319 321
         'playlist_id' => $playlist_id,
320 322
         'element_id'  => $element_id,
321
-        '_locale'     => 'fr'
323
+        '_locale'     => 'fr',
324
+        'token'       => $this->test->getToken()
322 325
       ))
323 326
     );
324 327
   }
@@ -330,7 +333,8 @@ class ContextTestCases
330 333
       $this->test->generateUrl('playlists_add_element_and_copy', array(
331 334
         'playlist_id' => $playlist_id,
332 335
         'element_id'  => $element_id,
333
-        '_locale'     => 'fr'
336
+        '_locale'     => 'fr',
337
+        'token'       => $this->test->getToken()
334 338
       ))
335 339
     );
336 340
   }
@@ -385,7 +389,8 @@ class ContextTestCases
385 389
         $this->test->generateUrl('playlists_add_element_and_copy', array(
386 390
           'playlist_id' => 0,
387 391
           'element_id'  => 0,
388
-          '_locale'     => 'fr'
392
+          '_locale'     => 'fr',
393
+          'token'       => $this->test->getToken()
389 394
         ))
390 395
       ), 
391 396
       $success, 
@@ -410,7 +415,8 @@ class ContextTestCases
410 415
       'GET', 
411 416
       $this->test->generateUrl('playlist_delete', array(
412 417
           'playlist_id' => $playlist_id,
413
-          '_locale'     => 'fr'
418
+          '_locale'     => 'fr',
419
+          'token'       => $this->test->getToken()
414 420
         )), 
415 421
       array(), 
416 422
       array(), 
@@ -433,7 +439,8 @@ class ContextTestCases
433 439
   {
434 440
     $this->test->goToPage($this->test->generateUrl('playlist_unpick', array(
435 441
       'playlist_id' => $playlist_id,
436
-      '_locale'     => 'fr'
442
+      '_locale'     => 'fr',
443
+      'token'       => $this->test->getToken()
437 444
     )));
438 445
   }
439 446
   
@@ -453,7 +460,8 @@ class ContextTestCases
453 460
       'GET',
454 461
       $this->test->generateUrl('playlist_pick', array(
455 462
         'playlist_id' => $playlist_id,
456
-        '_locale'     => 'fr'
463
+        '_locale'     => 'fr',
464
+        'token'       => $this->test->getToken()
457 465
       ))
458 466
     );
459 467
   }

+ 8 - 0
src/Muzich/CoreBundle/lib/Controller.php Прегледај датотеку

@@ -685,4 +685,12 @@ class Controller extends BaseController
685 685
     return $this->createForm(new PlaylistForm(), $this->getPlaylistManager()->getNewPlaylist($this->getUserOrNullIfVisitor()));
686 686
   }
687 687
   
688
+  protected function tokenIsCorrect($intention = '')
689
+  {
690
+    if ($this->getRequest()->get('token') != $this->container->get('form.csrf_provider')->generateCsrfToken($intention))
691
+      return false;
692
+    
693
+    return true;
694
+  }
695
+  
688 696
 }

+ 6 - 0
src/Muzich/CoreBundle/lib/FunctionalTest.php Прегледај датотеку

@@ -551,6 +551,7 @@ class FunctionalTest extends WebTestCase
551 551
   public function jsonResponseIsSuccess($json_response)
552 552
   {
553 553
     $response = json_decode($json_response, true);
554
+    $this->assertFalse(is_null($response));
554 555
     $this->assertTrue(array_key_exists('status', $response));
555 556
     $this->assertEquals('success', $response['status']);
556 557
   }
@@ -568,4 +569,9 @@ class FunctionalTest extends WebTestCase
568 569
     $this->crawler = new Crawler($response['data']);
569 570
   }
570 571
   
572
+  public function getToken($intention = '')
573
+  {
574
+    return $this->getContainer()->get('form.csrf_provider')->generateCsrfToken($intention);
575
+  }
576
+  
571 577
 }

+ 7 - 7
src/Muzich/PlaylistBundle/Controller/EditController.php Прегледај датотеку

@@ -16,7 +16,7 @@ class EditController extends Controller
16 16
       return $this->jsonResponseError($uncondition);
17 17
     
18 18
     $playlist_manager = $this->getPlaylistManager();
19
-    if (!($playlist = $playlist_manager->findOwnedPlaylistWithId($playlist_id, $this->getUser())) || !$request->get('elements'))
19
+    if (!$this->tokenIsCorrect() || !($playlist = $playlist_manager->findOwnedPlaylistWithId($playlist_id, $this->getUser())) || !$request->get('elements'))
20 20
       return $this->jsonNotFoundResponse();
21 21
     
22 22
     $playlist_manager->updatePlaylistElementsOrder($playlist, $request->get('elements'));
@@ -30,7 +30,7 @@ class EditController extends Controller
30 30
       return $this->jsonResponseError($uncondition);
31 31
     
32 32
     $playlist_manager = $this->getPlaylistManager();
33
-    if (!($playlist = $playlist_manager->findOwnedPlaylistWithId($playlist_id, $this->getUser())))
33
+    if (!$this->tokenIsCorrect() || !($playlist = $playlist_manager->findOwnedPlaylistWithId($playlist_id, $this->getUser())))
34 34
       return $this->jsonNotFoundResponse();
35 35
     
36 36
     $playlist_manager->removePlaylistElementWithId($playlist, $element_id);
@@ -44,7 +44,7 @@ class EditController extends Controller
44 44
       return $this->jsonResponseError($uncondition);
45 45
     
46 46
     $playlist_manager = $this->getPlaylistManager();
47
-    if (!($playlist = $playlist_manager->findOwnedPlaylistWithId($playlist_id, $this->getUser()))
47
+    if (!$this->tokenIsCorrect() || !($playlist = $playlist_manager->findOwnedPlaylistWithId($playlist_id, $this->getUser()))
48 48
         || !($element = $this->getElementWithId($element_id)))
49 49
       return $this->jsonNotFoundResponse();
50 50
     
@@ -83,7 +83,7 @@ class EditController extends Controller
83 83
     if (($uncondition = $this->userHaveNonConditionToMakeAction(SecurityContext::ACTION_PLAYLIST_COPY)) !== false)
84 84
       return $this->jsonResponseError($uncondition);
85 85
     
86
-    if (!($element = $this->getElementWithId($element_id)))
86
+    if (!$this->tokenIsCorrect() || !($element = $this->getElementWithId($element_id)))
87 87
       return $this->jsonNotFoundResponse();
88 88
     
89 89
     if (!($playlist = $this->getPlaylistManager()->findOneAccessiblePlaylistWithId($playlist_id, $this->getUser())))
@@ -102,7 +102,7 @@ class EditController extends Controller
102 102
     if (($uncondition = $this->userHaveNonConditionToMakeAction(SecurityContext::ACTION_PLAYLIST_DELETE)) !== false)
103 103
       throw $this->createNotFoundException();
104 104
     
105
-    if (!($playlist = $this->getPlaylistManager()->findOwnedPlaylistWithId($playlist_id, $this->getUser())))
105
+    if (!$this->tokenIsCorrect() || !($playlist = $this->getPlaylistManager()->findOwnedPlaylistWithId($playlist_id, $this->getUser())))
106 106
       throw $this->createNotFoundException();
107 107
     
108 108
     $this->getPlaylistManager()->deletePlaylist($playlist);
@@ -118,7 +118,7 @@ class EditController extends Controller
118 118
     
119 119
     $playlist_manager = $this->getPlaylistManager();
120 120
     
121
-    if (!($playlist = $playlist_manager->findPlaylistWithId($playlist_id, $this->getUser())))
121
+    if (!$this->tokenIsCorrect() || !($playlist = $playlist_manager->findPlaylistWithId($playlist_id, $this->getUser())))
122 122
       throw $this->createNotFoundException();
123 123
     
124 124
     $playlist_manager->removePickedPlaylistToUser($this->getUser(), $playlist);
@@ -132,7 +132,7 @@ class EditController extends Controller
132 132
     if (($uncondition = $this->userHaveNonConditionToMakeAction(SecurityContext::ACTION_PLAYLIST_PICK)) !== false)
133 133
       return $this->jsonResponseError($uncondition);
134 134
     
135
-    if (!($playlist = $this->getPlaylistManager()->findOneAccessiblePlaylistWithId($playlist_id)))
135
+    if (!$this->tokenIsCorrect() || !($playlist = $this->getPlaylistManager()->findOneAccessiblePlaylistWithId($playlist_id)))
136 136
       return $this->jsonNotFoundResponse();
137 137
     
138 138
     $this->getPlaylistManager()->addPickedPlaylistToUser($this->getUser(), $playlist);

+ 7 - 7
src/Muzich/PlaylistBundle/Resources/config/routing.yml Прегледај датотеку

@@ -7,15 +7,15 @@ playlist:
7 7
   defaults: { _controller: MuzichPlaylistBundle:Show:show }
8 8
 
9 9
 playlist_delete:
10
-  pattern: /playlist/delete/{playlist_id}
10
+  pattern: /playlist/delete/{playlist_id}/{token}
11 11
   defaults: { _controller: MuzichPlaylistBundle:Edit:delete }
12 12
 
13 13
 playlist_unpick:
14
-  pattern: /playlist/unpick/{playlist_id}
14
+  pattern: /playlist/unpick/{playlist_id}/{token}
15 15
   defaults: { _controller: MuzichPlaylistBundle:Edit:unpick }
16 16
 
17 17
 playlist_pick:
18
-  pattern: /playlist/pick/{playlist_id}
18
+  pattern: /playlist/pick/{playlist_id}/{token}
19 19
   defaults: { _controller: MuzichPlaylistBundle:Edit:pick }
20 20
 
21 21
 playlist_datas_for_autoplay:
@@ -23,11 +23,11 @@ playlist_datas_for_autoplay:
23 23
   defaults: { _controller: MuzichPlaylistBundle:Show:getAutoplayData, offset: null }
24 24
 
25 25
 playlist_update_order:
26
-  pattern: /ajax/playlist/order/update/{playlist_id}
26
+  pattern: /ajax/playlist/order/update/{playlist_id}/{token}
27 27
   defaults: { _controller: MuzichPlaylistBundle:Edit:updateOrder }
28 28
 
29 29
 playlist_remove_element:
30
-  pattern: /ajax/playlist/element/remove/{playlist_id}/{element_id}
30
+  pattern: /ajax/playlist/element/remove/{playlist_id}/{element_id}/{token}
31 31
   defaults: { _controller: MuzichPlaylistBundle:Edit:removeElement }
32 32
 
33 33
 playlists_add_element_prompt:
@@ -35,11 +35,11 @@ playlists_add_element_prompt:
35 35
   defaults: { _controller: MuzichPlaylistBundle:Show:getAddElementPrompt }
36 36
 
37 37
 playlists_add_element:
38
-  pattern: /ajax/playlist/element/add/{playlist_id}/{element_id}
38
+  pattern: /ajax/playlist/element/add/{playlist_id}/{element_id}/{token}
39 39
   defaults: { _controller: MuzichPlaylistBundle:Edit:addElement }
40 40
   
41 41
 playlists_add_element_and_copy:
42
-  pattern: /ajax/playlist/element/add-and-copy/{playlist_id}/{element_id}
42
+  pattern: /ajax/playlist/element/add-and-copy/{playlist_id}/{element_id}/{token}
43 43
   defaults: { _controller: MuzichPlaylistBundle:Edit:addElementAndCopy }
44 44
 
45 45
 playlist_add_element_and_create:

+ 2 - 2
src/Muzich/PlaylistBundle/Resources/views/Show/prompt.html.twig Прегледај датотеку

@@ -12,12 +12,12 @@
12 12
         <li class="playlist">
13 13
           <a class="add_element_to_playlist"
14 14
             {% if playlist.owned(app.user) %}
15
-              href="{{ path('playlists_add_element', {
15
+              href="{{ path_token('playlists_add_element', {
16 16
                 'playlist_id' : playlist.id,
17 17
                 'element_id'  : element_id
18 18
               }) }}"
19 19
             {% else %}
20
-              href="{{ path('playlists_add_element_and_copy', {
20
+              href="{{ path_token('playlists_add_element_and_copy', {
21 21
                 'playlist_id' : playlist.id,
22 22
                 'element_id'  : element_id
23 23
               }) }}"

+ 4 - 4
src/Muzich/PlaylistBundle/Resources/views/Show/show.html.twig Прегледај датотеку

@@ -14,11 +14,11 @@
14 14
     {% if app.user %}
15 15
       {% if not playlist.owned(app.user) and viewed_user.id != app.user.id %}
16 16
         {% if not app.user.havePlaylistPicked(playlist) %}
17
-          <a class="playlist_pick" href="{{ path('playlist_pick', { 'playlist_id' : playlist.id }) }}" >
17
+          <a class="playlist_pick" href="{{ path_token('playlist_pick', { 'playlist_id' : playlist.id }) }}" >
18 18
             P
19 19
           </a>
20 20
         {% else %}
21
-          <a class="playlist_unpick" href="{{ path('playlist_unpick', { 'playlist_id' : playlist.id }) }}" >
21
+          <a class="playlist_unpick" href="{{ path_token('playlist_unpick', { 'playlist_id' : playlist.id }) }}" >
22 22
             uP
23 23
           </a>
24 24
         {% endif %}
@@ -32,7 +32,7 @@
32 32
     } %}
33 33
     
34 34
     {% if playlist.elements|length %}
35
-      <form action="{{ path('playlist_update_order', { 'playlist_id' : playlist.id }) }}" method="post">
35
+      <form action="{{ path_token('playlist_update_order', { 'playlist_id' : playlist.id }) }}" method="post">
36 36
         <ul class="playlist_elements">
37 37
           {% for element in playlist.elements %}
38 38
             <li class="playlist_element">
@@ -43,7 +43,7 @@
43 43
               <a class="open_element" href="{{ path('element_get_one', { 'element_id' : element.id }) }}" data-id="{{ element.id }}">
44 44
                 {{ element.name }}
45 45
               </a>
46
-              <a class="remove_element" href="{{ path('playlist_remove_element', { 'playlist_id' : playlist.id, 'element_id' : element.id }) }}">
46
+              <a class="remove_element" href="{{ path_token('playlist_remove_element', { 'playlist_id' : playlist.id, 'element_id' : element.id }) }}">
47 47
                 X
48 48
               </a>
49 49
             </li>

+ 4 - 4
src/Muzich/PlaylistBundle/Resources/views/Show/user.html.twig Прегледај датотеку

@@ -21,11 +21,11 @@
21 21
         {% if app.user %}
22 22
           {% if viewed_user.id == app.user.id %}
23 23
             {% if playlist.owned(app.user) %}
24
-              <a class="playlist_delete" href="{{ path('playlist_delete', { 'playlist_id' : playlist.id }) }}" >
24
+              <a class="playlist_delete" href="{{ path_token('playlist_delete', { 'playlist_id' : playlist.id }) }}" >
25 25
                 X
26 26
               </a>
27 27
             {% else %}
28
-              <a class="playlist_unpick" href="{{ path('playlist_unpick', { 'playlist_id' : playlist.id }) }}" >
28
+              <a class="playlist_unpick" href="{{ path_token('playlist_unpick', { 'playlist_id' : playlist.id }) }}" >
29 29
                 X
30 30
               </a>
31 31
             {% endif %}
@@ -35,11 +35,11 @@
35 35
         {% if app.user %}
36 36
           {% if not playlist.owned(app.user) and viewed_user.id != app.user.id %}
37 37
             {% if not app.user.havePlaylistPicked(playlist) %}
38
-              <a class="playlist_pick" href="{{ path('playlist_pick', { 'playlist_id' : playlist.id }) }}" >
38
+              <a class="playlist_pick" href="{{ path_token('playlist_pick', { 'playlist_id' : playlist.id }) }}" >
39 39
                 P
40 40
               </a>
41 41
             {% else %}
42
-              <a class="playlist_unpick" href="{{ path('playlist_unpick', { 'playlist_id' : playlist.id }) }}" >
42
+              <a class="playlist_unpick" href="{{ path_token('playlist_unpick', { 'playlist_id' : playlist.id }) }}" >
43 43
                 uP
44 44
               </a>
45 45
             {% endif %}