From 7c592472227b246235a923496dcbefc289fd3d23 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Fri, 18 Oct 2013 11:56:29 +0200 Subject: [PATCH 01/25] Tries to clearify redirecting article --- cookbook/routing/redirect_in_config.rst | 179 ++++++++++++++++++++---- 1 file changed, 151 insertions(+), 28 deletions(-) diff --git a/cookbook/routing/redirect_in_config.rst b/cookbook/routing/redirect_in_config.rst index 4d6b7004e6e..cb37de745c9 100644 --- a/cookbook/routing/redirect_in_config.rst +++ b/cookbook/routing/redirect_in_config.rst @@ -1,40 +1,163 @@ .. index:: - single: Routing; Configure redirect to another route without a custom controller + single: Routing; Redirect using Framework:RedirectController -How to configure a redirect to another route without a custom controller -======================================================================== +How to Configure a Redirect Without a Custom Controller +======================================================= -This guide explains how to configure a redirect from one route to another -without using a custom controller. +Sometimes, a URL needs to redirect to another URL. You can do that by creating +a new controller action which only task is to redirect, but using the +:class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController` of +the FrameworkBundle, it's a lot easier. -Assume that there is no useful default controller for the ``/`` path of -your application and you want to redirect these requests to ``/app``. +You can redirect to a specific path (e.g. ``/about``) or to a specific route +using it's name (e.g. ``homepage``). -Your configuration will look like this: +Redirecting Using a Path +------------------------ -.. code-block:: yaml +Assume there is no default controller for the ``/`` path of your application +and you want to redirect these requests to ``/app``. You will need to use the +:method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirect` +action to redirect to this new url: - AppBundle: - resource: "@App/Controller/" - type: annotation - prefix: /app +.. configuration-block:: - root: - path: / - defaults: - _controller: FrameworkBundle:Redirect:urlRedirect - path: /app - permanent: true + .. code-block:: yaml -In this example, you configure a route for the ``/`` path and let :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController` -handle it. This controller comes standard with Symfony and offers two actions -for redirecting request: + # app/config/routing.yml -* ``urlRedirect`` redirects to another *path*. You must provide the ``path`` - parameter containing the path of the resource you want to redirect to. + # loading the App controllers + AppBundle: + resource: "@AcmeAppBundle/Controller/" + type: annotation + prefix: /app -* ``redirect`` (not shown here) redirects to another *route*. You must provide the ``route`` - parameter with the *name* of the route you want to redirect to. + # redirecting the root + root: + path: / + defaults: + _controller: FrameworkBundle:Redirect:urlRedirect + path: /app + permanent: true -The ``permanent`` switch tells both methods to issue a 301 HTTP status code -instead of the default ``302`` status code. + .. code-block:: xml + + + + + + + + + + + FrameworkBundle:Redirect:urlRedirect + /app + true + + + + .. code-block:: php + + // app/config/routing.php + use Symfony\Component\Routing\RouteCollection; + use Symfony\Component\Routing\Route; + + $collection = new RouteCollection(); + + // loading the App controllers + $acmeApp = $loader->import( + "@AcmeAppBundle/Controller/", + "annotation" + ); + $acmeApp->setPrefix('/app'); + + $collection->addCollection($acmeApp); + + // redirecting the root + $collection->add('root', new Route('/', array( + '_controller' => 'FrameworkBundle:Redirect:urlRedirect', + 'path' => '/app', + 'permanent' => true, + ))); + + return $collection; + +In this example, you configured a route for the ``/`` path and let the +``RedirectController`` handle it to redirect it to ``/app``. The ``permanent`` +switch tells the action to issue a ``301`` HTTP status code instead of the +default ``302`` HTTP status code. + +Redirecting Using a Route +------------------------- + +Assume you are migrating your website from WordPress to Symfony, you want to +redirect ``/wp-admin`` to the route ``sonata_admin_dashboard``. You don't know +the path, only the route name. This can be achieved using the +:method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::redirect` +action: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/routing.yml + + # ... + + # redirecting the admin home + root: + path: /wp-admin + defaults: + _controller: FrameworkBundle:Redirect:redirect + route: sonata_admin_dashboard + permanent: true + + .. code-block:: xml + + + + + + + + + + FrameworkBundle:Redirect:redirect + sonata_admin_dashboard + true + + + + .. code-block:: php + + // app/config/routing.php + use Symfony\Component\Routing\RouteCollection; + use Symfony\Component\Routing\Route; + + $collection = new RouteCollection(); + // ... + + // redirecting the root + $collection->add('root', new Route('/wp-admin', array( + '_controller' => 'FrameworkBundle:Redirect:redirect', + 'route' => 'sonata_admin_dashboard', + 'permanent' => true, + ))); + + return $collection; + +.. caution:: + + Because you are redirecting to a route instead of a path, the required + option is called ``route`` in the ``redirect`` action, instead of ``path`` + in the ``urlRedirect`` action. From 5753411bf2dd192cad2555207ff3ab70c71b8874 Mon Sep 17 00:00:00 2001 From: Massimiliano Arione Date: Fri, 1 Nov 2013 20:57:39 +0100 Subject: [PATCH 02/25] Update references to current branch E.g. changed "2.2" to "2.3" and so on --- contributing/documentation/overview.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contributing/documentation/overview.rst b/contributing/documentation/overview.rst index 60f93d72178..c47b9162060 100644 --- a/contributing/documentation/overview.rst +++ b/contributing/documentation/overview.rst @@ -13,7 +13,7 @@ Before contributing, you need to become familiar with the :doc:`markup language ` used by the documentation. The Symfony2 documentation is hosted on GitHub: - +2 .. code-block:: text https://github.com/symfony/symfony-docs @@ -29,17 +29,17 @@ Consistent with Symfony's source code, the documentation repository is split int multiple branches, corresponding to the different versions of Symfony itself. The ``master`` branch holds the documentation for the development branch of the code. -Unless you're documenting a feature that was introduced *after* Symfony 2.2 -(e.g. in Symfony 2.3), your changes should always be based on the 2.2 branch. -To do this checkout the 2.2 branch before the next step: +Unless you're documenting a feature that was introduced *after* Symfony 2.3 +(e.g. in Symfony 2.4), your changes should always be based on the 2.3 branch. +To do this checkout the 2.3 branch before the next step: .. code-block:: bash - $ git checkout 2.2 + $ git checkout 2.3 .. tip:: - Your base branch (e.g. 2.2) will become the "Applies to" in the :ref:`doc-contributing-pr-format` + Your base branch (e.g. 2.3) will become the "Applies to" in the :ref:`doc-contributing-pr-format` that you'll use later. Next, create a dedicated branch for your changes (for organization): @@ -57,8 +57,8 @@ Creating a Pull Request Following the example, the pull request will default to be between your ``improving_foo_and_bar`` branch and the ``symfony-docs`` ``master`` branch. -If you have made your changes based on the 2.2 branch then you need to change -the base branch to be 2.2 on the preview page by clicking the ``edit`` button +If you have made your changes based on the 2.3 branch then you need to change +the base branch to be 2.3 on the preview page by clicking the ``edit`` button on the top left: .. image:: /images/docs-pull-request-change-base.png @@ -66,8 +66,8 @@ on the top left: .. note:: - All changes made to a branch (e.g. 2.2) will be merged up to each "newer" - branch (e.g. 2.3, master, etc) for the next release on a weekly basis. + All changes made to a branch (e.g. 2.3) will be merged up to each "newer" + branch (e.g. 2.4, master, etc) for the next release on a weekly basis. GitHub covers the topic of `pull requests`_ in detail. From ef5c36859d8b5999e3363ef045a2a2bcf3b7e903 Mon Sep 17 00:00:00 2001 From: Massimiliano Arione Date: Sat, 2 Nov 2013 18:53:22 +0100 Subject: [PATCH 03/25] Update overview.rst --- contributing/documentation/overview.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributing/documentation/overview.rst b/contributing/documentation/overview.rst index c47b9162060..f264887670b 100644 --- a/contributing/documentation/overview.rst +++ b/contributing/documentation/overview.rst @@ -13,7 +13,7 @@ Before contributing, you need to become familiar with the :doc:`markup language ` used by the documentation. The Symfony2 documentation is hosted on GitHub: -2 + .. code-block:: text https://github.com/symfony/symfony-docs From a5c4a4fe159f75fd17fee42eacaec77b1b4d7e35 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 13 Sep 2013 11:00:44 +0200 Subject: [PATCH 04/25] use handleRequest() instead of bind() --- components/form/introduction.rst | 70 ++++++++++++-------------------- 1 file changed, 27 insertions(+), 43 deletions(-) diff --git a/components/form/introduction.rst b/components/form/introduction.rst index 90c93ce4dc0..a7f86a86e09 100644 --- a/components/form/introduction.rst +++ b/components/form/introduction.rst @@ -66,13 +66,13 @@ factory. Request Handling ~~~~~~~~~~~~~~~~ -To process form data, you'll need to grab information off of the request (typically -``$_POST`` data) and pass the array of submitted data to -:method:`Symfony\\Component\\Form\\Form::bind`. The Form component optionally -integrates with Symfony's :doc:`HttpFoundation ` -component to make this even easier. +.. versionadded:: 2.3 + The ``handleRequest()`` method was added in Symfony 2.3. -To integrate the HttpFoundation component, add the +To process form data, you'll need to call the :method:`Symfony\\Component\\Form\\Form::handleRequest` +method. + +To optionally integrate the HttpFoundation component, add the :class:`Symfony\\Component\\Form\\Extension\\HttpFoundation\\HttpFoundationExtension` to your form factory:: @@ -84,8 +84,7 @@ to your form factory:: ->getFormFactory(); Now, when you process a form, you can pass the :class:`Symfony\\Component\\HttpFoundation\\Request` -object to :method:`Symfony\\Component\\Form\\Form::bind` instead of the raw -array of submitted values. +object to :method:`Symfony\\Component\\Form\\Form::handleRequest`. .. note:: @@ -480,7 +479,7 @@ to do that in the ":ref:`form-rendering-template`" section. Handling Form Submissions ~~~~~~~~~~~~~~~~~~~~~~~~~ -To handle form submissions, use the :method:`Symfony\\Component\\Form\\Form::bind` +To handle form submissions, use the :method:`Symfony\\Component\\Form\\Form::handleRequest` method: .. configuration-block:: @@ -497,19 +496,17 @@ method: $request = Request::createFromGlobals(); - if ($request->isMethod('POST')) { - $form->bind($request); + $form->handleRequest($request); - if ($form->isValid()) { - $data = $form->getData(); + if ($form->isValid()) { + $data = $form->getData(); - // ... perform some action, such as saving the data to the database + // ... perform some action, such as saving the data to the database - $response = new RedirectResponse('/task/success'); - $response->prepare($request); + $response = new RedirectResponse('/task/success'); + $response->prepare($request); - return $response->send(); - } + return $response->send(); } // ... @@ -525,17 +522,14 @@ method: ->add('dueDate', 'date') ->getForm(); - // only process the form if the request is a POST request - if ($request->isMethod('POST')) { - $form->bind($request); + $form->handleRequest($request); - if ($form->isValid()) { - $data = $form->getData(); + if ($form->isValid()) { + $data = $form->getData(); - // ... perform some action, such as saving the data to the database + // ... perform some action, such as saving the data to the database - return $this->redirect($this->generateUrl('task_success')); - } + return $this->redirect($this->generateUrl('task_success')); } // ... @@ -546,25 +540,15 @@ This defines a common form "workflow", which contains 3 different possibilities: 1) On the initial GET request (i.e. when the user "surfs" to your page), build your form and render it; -If the request is a POST, process the submitted data (via ``bind``). Then: +If the request is a POST, process the submitted data (via ``handleRequest()``). +Then: -2) if the form is invalid, re-render the form (which will now contain errors) -3) if the form is valid, perform some action and redirect; - -.. note:: - - If you're not using HttpFoundation, just pass the POST'ed data directly - to ``bind``:: - - if (isset($_POST[$form->getName()])) { - $form->bind($_POST[$form->getName()]); - - // ... - } +2) if the form is invalid, re-render the form (which will now contain errors); +3) if the form is valid, perform some action and redirect. - If you're uploading files, you'll need to do a little bit more work by - merging the ``$_POST`` array with the ``$_FILES`` array before passing - it into ``bind``. +Luckily, you don't need to decide whether or not a form has been submitted. +Just pass the current request to the ``handleRequest()`` method. Then, the Form +component will do all the necessary work for you. .. _component-form-intro-validation: From 0bcc16bf9b8f67c349b12a17d88d5fa8251f51d0 Mon Sep 17 00:00:00 2001 From: Bill Israel Date: Tue, 3 Dec 2013 08:17:05 -0600 Subject: [PATCH 05/25] Add gender-neutrality to documentation standards Modeled after changes made to the Django project: https://github.com/django/django/commit/c0a2daad78c66def2ce6592977b78dab6475dd53 --- contributing/documentation/standards.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/contributing/documentation/standards.rst b/contributing/documentation/standards.rst index e623f1d0f3d..935a99674f7 100644 --- a/contributing/documentation/standards.rst +++ b/contributing/documentation/standards.rst @@ -125,6 +125,14 @@ Language Standards * Do not use `Serial (Oxford) Commas`_; * You should use a form of *you* instead of *we* (i.e. avoid the first person point of view: use the second instead). +* When referencing a hypothetical person, such as "a user with a session cookie", gender-neutral + pronouns (they/their/them) should be used. For example, instead of: + + * he or she, use they + * him or her, use them + * his or her, use their + * his or hers, use theirs + * himself or herself, use themselves .. _`the Sphinx documentation`: http://sphinx-doc.org/rest.html#source-code .. _`Twig Coding Standards`: http://twig.sensiolabs.org/doc/coding_standards.html From 8d3a4754b0ba337822d66237e8260a0f8987053e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Egyed?= <1ed@mailbox.hu> Date: Wed, 4 Dec 2013 21:04:53 +0100 Subject: [PATCH 06/25] fixed setfacl invocation --- book/installation.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/installation.rst b/book/installation.rst index 9ea45d139b0..009cdad8a12 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -252,8 +252,8 @@ If there are any issues, correct them now before moving on. .. code-block:: bash $ APACHEUSER=`ps aux | grep -E '[a]pache|[h]ttpd' | grep -v root | head -1 | cut -d\ -f1` - $ sudo setfacl -R -m u:$APACHEUSER:rwX -m u:`whoami`:rwX app/cache app/logs - $ sudo setfacl -dR -m u:$APACHEUSER:rwX -m u:`whoami`:rwX app/cache app/logs + $ sudo setfacl -R -m u:"$APACHEUSER":rwX -m u:`whoami`:rwX app/cache app/logs + $ sudo setfacl -dR -m u:"$APACHEUSER":rwX -m u:`whoami`:rwX app/cache app/logs **3. Without using ACL** From 9e909fcc490f850cf08b05668ab1e5b7f565de64 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 8 Dec 2013 13:09:48 +0100 Subject: [PATCH 07/25] Removing unused reference --- reference/dic_tags.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/reference/dic_tags.rst b/reference/dic_tags.rst index b5da3ea5cd1..05d600afaa7 100644 --- a/reference/dic_tags.rst +++ b/reference/dic_tags.rst @@ -1220,6 +1220,5 @@ For an example, see the ``EntityInitializer`` class inside the Doctrine Bridge. .. _`Twig's documentation`: http://twig.sensiolabs.org/doc/advanced.html#creating-an-extension .. _`Twig official extension repository`: https://github.com/fabpot/Twig-extensions -.. _`KernelEvents`: https://github.com/symfony/symfony/blob/2.2/src/Symfony/Component/HttpKernel/KernelEvents.php .. _`SwiftMailer's Plugin Documentation`: http://swiftmailer.org/docs/plugins.html .. _`Twig Loader`: http://twig.sensiolabs.org/doc/api.html#loaders From 7bf21c277f1d1487d7395a79b191b92fb0662b0b Mon Sep 17 00:00:00 2001 From: Dorthe Luebbert Date: Sat, 7 Dec 2013 14:48:21 +0100 Subject: [PATCH 08/25] changed create-project example with the current version of composer you can use wildcards like "2.3.*" :-) --- quick_tour/the_big_picture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index 1ab6cea7eea..0d56e6cf381 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -66,7 +66,7 @@ have a ``Symfony/`` directory that looks like this: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition Symfony 2.3.0 + $ php composer.phar create-project symfony/framework-standard-edition Symfony 2.3.* .. _`quick-tour-big-picture-built-in-server`: From 621296819d699c08cf7327506040a0b6d517a7ea Mon Sep 17 00:00:00 2001 From: Dorthe Luebbert Date: Sun, 8 Dec 2013 09:20:24 +0100 Subject: [PATCH 09/25] changed version in create project example to 2.4.* and remove the hint above as it is not longer necessary due to the new wildcard feature in composer --- quick_tour/the_big_picture.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index 0d56e6cf381..2305a55990e 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -61,12 +61,11 @@ have a ``Symfony/`` directory that looks like this: .. note:: If you are familiar with `Composer`_, you can download Composer and then - run the following command instead of downloading the archive (replacing - ``2.3.0`` with the latest Symfony release like ``2.3.1``): + run the following command instead of downloading the archive: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition Symfony 2.3.* + $ php composer.phar create-project symfony/framework-standard-edition Symfony 2.4.* .. _`quick-tour-big-picture-built-in-server`: From 8f3ee1913d26ab82318572e62cfccfaac4457a2b Mon Sep 17 00:00:00 2001 From: Fran Moreno Date: Thu, 5 Dec 2013 00:16:58 +0100 Subject: [PATCH 10/25] [Cookbook][Form - direct submit] Fixed broken links to API --- cookbook/form/direct_submit.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cookbook/form/direct_submit.rst b/cookbook/form/direct_submit.rst index f48fe216fff..dc4143b118f 100644 --- a/cookbook/form/direct_submit.rst +++ b/cookbook/form/direct_submit.rst @@ -27,7 +27,7 @@ submissions:: return $this->redirect($this->generateUrl('task_success')); } - + return $this->render('AcmeTaskBundle:Default:new.html.twig', array( 'form' => $form->createView(), )); @@ -45,9 +45,9 @@ Calling Form::submit() manually In some cases, you want better control over when exactly your form is submitted and what data is passed to it. Instead of using the -:method:`Symfony\Component\Form\FormInterface::handleRequest` +:method:`Symfony\\Component\\Form\\FormInterface::handleRequest` method, pass the submitted data directly to -:method:`Symfony\Component\Form\FormInterface::submit`:: +:method:`Symfony\\Component\\Form\\FormInterface::submit`:: use Symfony\Component\HttpFoundation\Request; // ... @@ -76,8 +76,8 @@ method, pass the submitted data directly to .. tip:: Forms consisting of nested fields expect an array in - :method:`Symfony\Component\Form\FormInterface::submit`. You can also submit - individual fields by calling :method:`Symfony\Component\Form\FormInterface::submit` + :method:`Symfony\\Component\\Form\\FormInterface::submit`. You can also submit + individual fields by calling :method:`Symfony\\Component\\Form\\FormInterface::submit` directly on the field:: $form->get('firstName')->submit('Fabien'); @@ -90,7 +90,7 @@ Passing a Request to Form::submit() (deprecated) .. versionadded:: 2.3 Before Symfony 2.3, the ``submit`` method was known as ``bind``. -Before Symfony 2.3, the :method:`Symfony\Component\Form\FormInterface::submit` +Before Symfony 2.3, the :method:`Symfony\\Component\\Form\\FormInterface::submit` method accepted a :class:`Symfony\\Component\\HttpFoundation\\Request` object as a convenient shortcut to the previous example:: @@ -118,7 +118,7 @@ a convenient shortcut to the previous example:: )); } -Passing the :class:`Symfony\\Component\HttpFoundation\\Request` directly to +Passing the :class:`Symfony\\Component\\HttpFoundation\\Request` directly to :method:`Symfony\\Component\\Form\\FormInterface::submit` still works, but is deprecated and will be removed in Symfony 3.0. You should use the method -:method:`Symfony\Component\Form\FormInterface::handleRequest` instead. +:method:`Symfony\\Component\\Form\\FormInterface::handleRequest` instead. From 700747d9bce25b5fa9ac699546c33ae95ab28108 Mon Sep 17 00:00:00 2001 From: Zbigniew Czapran Date: Wed, 11 Dec 2013 17:10:39 +0100 Subject: [PATCH 11/25] [Book][Validation] validate method in Validator returns ContraintViolationList object not an array --- book/validation.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/book/validation.rst b/book/validation.rst index a6ec3bebe0c..45c1027385f 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -113,8 +113,9 @@ Next, to actually validate an ``Author`` object, use the ``validate`` method on the ``validator`` service (class :class:`Symfony\\Component\\Validator\\Validator`). The job of the ``validator`` is easy: to read the constraints (i.e. rules) of a class and verify whether or not the data on the object satisfies those -constraints. If validation fails, an array of errors is returned. Take this -simple example from inside a controller:: +constraints. If validation fails, a non-empty list +(class :class:`Symfony\\Component\\Validator\\ConstraintViolationList`) of errors +is returned. Take this simple example from inside a controller:: // ... use Symfony\Component\HttpFoundation\Response; From 1b0e32b92926d21f64baab04bde0f551414bf63f Mon Sep 17 00:00:00 2001 From: Zbigniew Czapran Date: Wed, 11 Dec 2013 17:32:17 +0100 Subject: [PATCH 12/25] applies WouterJ suggestion --- book/validation.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/book/validation.rst b/book/validation.rst index 45c1027385f..8809fa60be8 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -113,9 +113,9 @@ Next, to actually validate an ``Author`` object, use the ``validate`` method on the ``validator`` service (class :class:`Symfony\\Component\\Validator\\Validator`). The job of the ``validator`` is easy: to read the constraints (i.e. rules) of a class and verify whether or not the data on the object satisfies those -constraints. If validation fails, a non-empty list -(class :class:`Symfony\\Component\\Validator\\ConstraintViolationList`) of errors -is returned. Take this simple example from inside a controller:: +constraints. If validation fails, a non-empty list of errors +(class :class:`Symfony\\Component\\Validator\\ConstraintViolationList`) is +returned. Take this simple example from inside a controller: // ... use Symfony\Component\HttpFoundation\Response; From 37deaa779402d85bc7df4b3d1a50a9949b7e88e0 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 19 Aug 2013 19:32:06 +0200 Subject: [PATCH 13/25] document the new authentication customization options --- cookbook/map.rst.inc | 1 + cookbook/security/custom_authenticator.rst | 208 +++++++++++++++++++++ cookbook/security/index.rst | 1 + 3 files changed, 210 insertions(+) create mode 100644 cookbook/security/custom_authenticator.rst diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index b901380cfa5..686620c99f7 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -135,6 +135,7 @@ * :doc:`/cookbook/security/form_login` * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` + * :doc:`/cookbook/security/custom_authenticator` * :doc:`/cookbook/security/custom_authentication_provider` * :doc:`/cookbook/security/target_path` diff --git a/cookbook/security/custom_authenticator.rst b/cookbook/security/custom_authenticator.rst new file mode 100644 index 00000000000..817952489e8 --- /dev/null +++ b/cookbook/security/custom_authenticator.rst @@ -0,0 +1,208 @@ +.. index:: + single: Security; Custom Authenticator + +How to create a custom Authenticator +==================================== + +Introduction +------------ + +Imagine you want to allow access to your website only between 2pm and 4pm (for +the UTC timezone). Before Symfony 2.4, you had to create a custom token, factory, +listener and provider. + +The Authenticator +----------------- + +Thanks to new simplified authentication customization options in Symfony 2.4, +you don't need to create a whole bunch of new classes, but use the +:class:`Symfony\\Component\\Security\\Core\\Authentication\\SimpleFormAuthenticatorInterface` +interface instead:: + + // src/Acme/HelloBundle/Security/TimeAuthenticator.php + namespace Acme\HelloBundle\Security; + + use Symfony\Component\HttpFoundation\Request; + use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface; + use Symfony\Component\Security\Core\Authentication\TokenInterface; + use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; + use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; + use Symfony\Component\Security\Core\Exception\AuthenticationException; + use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; + use Symfony\Component\Security\Core\User\UserProviderInterface; + + class TimeAuthenticator implements SimpleFormAuthenticatorInterface + { + private $encoderFactory; + + public function __construct(EncoderFactoryInterface $encoderFactory) + { + $this->encoderFactory = $encoderFactory; + } + + public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) + { + try { + $user = $userProvider->loadUserByUsername($token->getUsername()); + } catch (UsernameNotFoundException $e) { + throw new AuthenticationException('Invalid username or password'); + } + + $encoder = $this->encoderFactory->getEncoder($user); + $passwordValid = $encoder->isPasswordValid( + $user->getPassword(), + $token->getCredentials(), + $user->getSalt() + ); + + if ($passwordValid) { + $currentHour = date('G'); + if ($currentHour < 14 || $currentHour > 16) { + throw new AuthenticationException( + 'You can only log in between 2 and 4!', + 100 + ); + } + + return new UsernamePasswordToken( + $user->getUsername(), + $user->getPassword(), + $providerKey, + $user->getRoles() + ); + } + + throw new AuthenticationException('Invalid username or password'); + } + + public function supportsToken(TokenInterface $token, $providerKey) + { + return $token instanceof UsernamePasswordToken + && $token->getProviderKey() === $providerKey; + } + + public function createToken(Request $request, $username, $password, $providerKey) + { + return new UsernamePasswordToken($username, $password, $providerKey); + } + } + +.. versionadded:: 2.4 + The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. + +How it works +------------ + +There are a lot of things going on: + +* ``createToken()`` creates a Token that will be used to authenticate the user; +* ``authenticateToken()`` checks that the Token is allowed to log in by first + getting the User via the user provider and then, by checking the password + and the current time (a Token with roles is authenticated); +* ``supportsToken()`` is just a way to allow several authentication mechanisms to + be used for the same firewall (that way, you can for instance first try to + authenticate the user via a certificate or an API key and fall back to a + form login); +* An encoder is needed to check the user password's validity; this is a + service provided by default:: + + $encoder = $this->encoderFactory->getEncoder($user); + $passwordValid = $encoder->isPasswordValid( + $user->getPassword(), + $token->getCredentials(), + $user->getSalt() + ); + +Configuration +------------- + +Now, configure your ``TimeAuthenticator`` as a service: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + time_authenticator: + class: Acme\HelloBundle\Security\TimeAuthenticator + arguments: [@security.encoder_factory] + + .. code-block:: xml + + + + + + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + use Symfony\Component\DependencyInjection\Reference; + + $container->setDefinition('time_authenticator', new Definition( + 'Acme\HelloBundle\Security\TimeAuthenticator', + array(new Reference('security.encoder_factory')) + )); + +Then, activate it in your ``firewalls`` section using the ``simple-form`` key +like this: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + + firewalls: + secured_area: + pattern: ^/admin + provider: authenticator + simple-form: + provider: ... + authenticator: time_authenticator + check_path: login_check + login_path: login + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/admin', + 'provider' => 'authenticator', + 'simple-form' => array( + 'provider' => ..., + 'authenticator' => 'time_authenticator', + 'check_path' => 'login_check', + 'login_path' => 'login', + ), + ), + ), + )); diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index a8edbdc4317..c61b279ff3c 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -13,5 +13,6 @@ Security form_login securing_services custom_provider + custom_authenticator custom_authentication_provider target_path From 1bd187fe17c599682da7b0547ed43ab7ddbc196a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 19 Aug 2013 20:10:58 +0200 Subject: [PATCH 14/25] fixes thanks to @WouterJ --- cookbook/security/custom_authenticator.rst | 40 +++++++++++++--------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/cookbook/security/custom_authenticator.rst b/cookbook/security/custom_authenticator.rst index 817952489e8..de17f80d7d9 100644 --- a/cookbook/security/custom_authenticator.rst +++ b/cookbook/security/custom_authenticator.rst @@ -1,12 +1,9 @@ .. index:: single: Security; Custom Authenticator -How to create a custom Authenticator +How to create a Custom Authenticator ==================================== -Introduction ------------- - Imagine you want to allow access to your website only between 2pm and 4pm (for the UTC timezone). Before Symfony 2.4, you had to create a custom token, factory, listener and provider. @@ -14,8 +11,8 @@ listener and provider. The Authenticator ----------------- -Thanks to new simplified authentication customization options in Symfony 2.4, -you don't need to create a whole bunch of new classes, but use the +But now, thanks to new simplified authentication customization options in +Symfony 2.4, you don't need to create a whole bunch of new classes, but use the :class:`Symfony\\Component\\Security\\Core\\Authentication\\SimpleFormAuthenticatorInterface` interface instead:: @@ -90,7 +87,7 @@ interface instead:: .. versionadded:: 2.4 The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. -How it works +How it Works ------------ There are a lot of things going on: @@ -131,18 +128,26 @@ Now, configure your ``TimeAuthenticator`` as a service: .. code-block:: xml - - - - - + + + + + + + + .. code-block:: php // app/config/config.php use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; + + // ... $container->setDefinition('time_authenticator', new Definition( 'Acme\HelloBundle\Security\TimeAuthenticator', @@ -180,11 +185,12 @@ like this: xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - + + check-path="login_check" + login-path="login" /> From 8ddb26b36960ee35cf654ab61ae263eabbb76409 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 13 Sep 2013 14:09:41 +0200 Subject: [PATCH 15/25] clarify the authenticator type --- cookbook/map.rst.inc | 2 +- ....rst => custom_password_authenticator.rst} | 33 ++++++++++++------- cookbook/security/index.rst | 2 +- 3 files changed, 24 insertions(+), 13 deletions(-) rename cookbook/security/{custom_authenticator.rst => custom_password_authenticator.rst} (94%) diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 686620c99f7..e876acec3d3 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -135,7 +135,7 @@ * :doc:`/cookbook/security/form_login` * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` - * :doc:`/cookbook/security/custom_authenticator` + * :doc:`/cookbook/security/custom_password_authenticator` * :doc:`/cookbook/security/custom_authentication_provider` * :doc:`/cookbook/security/target_path` diff --git a/cookbook/security/custom_authenticator.rst b/cookbook/security/custom_password_authenticator.rst similarity index 94% rename from cookbook/security/custom_authenticator.rst rename to cookbook/security/custom_password_authenticator.rst index de17f80d7d9..2560bd52223 100644 --- a/cookbook/security/custom_authenticator.rst +++ b/cookbook/security/custom_password_authenticator.rst @@ -1,15 +1,18 @@ .. index:: - single: Security; Custom Authenticator + single: Security; Custom Password Authenticator -How to create a Custom Authenticator -==================================== +How to create a Custom Password Authenticator +============================================= Imagine you want to allow access to your website only between 2pm and 4pm (for the UTC timezone). Before Symfony 2.4, you had to create a custom token, factory, listener and provider. -The Authenticator ------------------ +The Password Authenticator +-------------------------- + +.. versionadded:: 2.4 + The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. But now, thanks to new simplified authentication customization options in Symfony 2.4, you don't need to create a whole bunch of new classes, but use the @@ -84,9 +87,6 @@ interface instead:: } } -.. versionadded:: 2.4 - The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. - How it Works ------------ @@ -121,6 +121,8 @@ Now, configure your ``TimeAuthenticator`` as a service: # app/config/config.yml services: + # ... + time_authenticator: class: Acme\HelloBundle\Security\TimeAuthenticator arguments: [@security.encoder_factory] @@ -134,9 +136,12 @@ Now, configure your ``TimeAuthenticator`` as a service: xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + - + class="Acme\HelloBundle\Security\TimeAuthenticator" + > + @@ -185,12 +190,15 @@ like this: xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + + login-path="login" + /> @@ -198,6 +206,9 @@ like this: .. code-block:: php // app/config/security.php + + // .. + $container->loadFromExtension('security', array( 'firewalls' => array( 'secured_area' => array( diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index c61b279ff3c..6de91f12a88 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -13,6 +13,6 @@ Security form_login securing_services custom_provider - custom_authenticator + custom_password_authenticator custom_authentication_provider target_path From afdb708ded8d4ae88a3a00fbf464279bb0cb5c58 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 13 Sep 2013 17:37:15 +0200 Subject: [PATCH 16/25] add example on how to use the new SimplePreAuthenticatorInterface --- cookbook/map.rst.inc | 1 + cookbook/security/api_key_authentication.rst | 208 +++++++++++++++++++ cookbook/security/index.rst | 1 + 3 files changed, 210 insertions(+) create mode 100644 cookbook/security/api_key_authentication.rst diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index e876acec3d3..37d9c9dcf0a 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -136,6 +136,7 @@ * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` * :doc:`/cookbook/security/custom_password_authenticator` + * :doc:`/cookbook/security/api_key_authentication` * :doc:`/cookbook/security/custom_authentication_provider` * :doc:`/cookbook/security/target_path` diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst new file mode 100644 index 00000000000..48aa3f0aa20 --- /dev/null +++ b/cookbook/security/api_key_authentication.rst @@ -0,0 +1,208 @@ +.. index:: + single: Security; Custom Request Authenticator + +How to Authenticate Users with API Keys +======================================= + +Nowadays, it's quite usual to authenticate the user via an API key (when developing +a web service for instance). The API key is provided for every request and is +passed as a query string parameter or via a HTTP header. + +The API Key Authenticator +------------------------- + +.. versionadded:: 2.4 + The ``SimplePreAuthenticatorInterface`` interface was added in Symfony 2.4. + +Authenticating a user based on the Request information should be done via a +pre-authentication mechanism. The :class:`Symfony\\Component\\Security\\Core\\Authentication\\SimplePreAuthenticatorInterface` +interface allows to implement such a scheme really easily:: + + // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php + namespace Acme\HelloBundle\Security; + + use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface; + use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + use Symfony\Component\Security\Core\Exception\AuthenticationException; + use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; + use Symfony\Component\HttpFoundation\Request; + use Symfony\Component\Security\Core\User\User; + use Symfony\Component\Security\Core\User\UserProviderInterface; + use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; + use Symfony\Component\Security\Core\Exception\BadCredentialsException; + + class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface + { + protected $userProvider; + + public function __construct(ApiKeyUserProviderInterface $userProvider) + { + $this->userProvider = $userProvider; + } + + public function createToken(Request $request, $providerKey) + { + if (!$request->query->has('apikey')) { + throw new BadCredentialsException('No API key found'); + } + + return new PreAuthenticatedToken( + 'anon.', + $request->query->get('apikey'), + $providerKey + ); + } + + public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) + { + $apikey = $token->getCredentials(); + if (!$this->userProvider->getUsernameForApiKey($apikey)) { + throw new AuthenticationException( + sprintf('API Key "%s" does not exist.', $apikey) + ); + } + + $user = new User( + $this->userProvider->getUsernameForApiKey($apikey), + $apikey, + array('ROLE_USER') + ); + + return new PreAuthenticatedToken( + $user, + $apikey, + $providerKey, + $user->getRoles() + ); + } + + public function supportsToken(TokenInterface $token, $providerKey) + { + return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey; + } + } + +``$userProvider`` can be any user provider implementing an interface similar to +this:: + + // src/Acme/HelloBundle/Security/ApiKeyUserProviderInterface.php + namespace Acme\HelloBundle\Security; + + use Symfony\Component\Security\Core\User\UserProviderInterface; + + interface ApiKeyUserProviderInterface extends UserProviderInterface + { + public function getUsernameForApiKey($apikey); + } + +.. note:: + + Read the dedicated article to learn + :doc:`how to create a custom user provider `. + +To access a resource protected by such an authenticator, you need to add an apikey +parameter to the query string, like in ``http://example.com/admin/foo?apikey=37b51d194a7513e45b56f6524f2d51f2``. + +Configuration +------------- + +Configure your ``ApiKeyAuthenticator`` as a service: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + # ... + + apikey_authenticator: + class: Acme\HelloBundle\Security\ApiKeyAuthenticator + arguments: [@your_api_key_user_provider] + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + use Symfony\Component\DependencyInjection\Reference; + + // ... + + $container->setDefinition('apikey_authenticator', new Definition( + 'Acme\HelloBundle\Security\ApiKeyAuthenticator', + array(new Reference('your_api_key_user_provider')) + )); + +Then, activate it in your firewalls section using the ``simple-preauth`` key +like this: + +.. configuration-block:: + + .. code-block:: yaml + + security: + firewalls: + secured_area: + pattern: ^/admin + simple-preauth: + provider: ... + authenticator: apikey_authenticator + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // .. + + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/admin', + 'provider' => 'authenticator', + 'simple-preauth' => array( + 'provider' => ..., + 'authenticator' => 'apikey_authenticator', + ), + ), + ), + )); diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index 6de91f12a88..d0856f144cf 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -14,5 +14,6 @@ Security securing_services custom_provider custom_password_authenticator + api_key_authentication custom_authentication_provider target_path From 1beb526f45e7febfd88809e438ab61c4f5a6250b Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 17 Dec 2013 11:25:19 -0600 Subject: [PATCH 17/25] [#2969][#2974] Small tweaks to handleRequest in Form component Added some additional details about what's going on behind the scenes --- components/form/introduction.rst | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/components/form/introduction.rst b/components/form/introduction.rst index 8e455e89dbd..53df8636db3 100644 --- a/components/form/introduction.rst +++ b/components/form/introduction.rst @@ -70,11 +70,19 @@ Request Handling The ``handleRequest()`` method was added in Symfony 2.3. To process form data, you'll need to call the :method:`Symfony\\Component\\Form\\Form::handleRequest` -method. +method:: -To optionally integrate the HttpFoundation component, add the -:class:`Symfony\\Component\\Form\\Extension\\HttpFoundation\\HttpFoundationExtension` -to your form factory:: + $form->handleRequest(); + +Behind the scenes, this uses a :class:`Symfony\\Component\\Form\\NativeRequestHandler` +object to read data off of the correct PHP superglobals (i.e. ``$_POST`` or +``$_GET``) based on the HTTP method configured on the form (POST is default). + +.. sidebar:: Integration with the HttpFoundation Component + + If you use the HttpFoundation component, then you should add the + :class:`Symfony\\Component\\Form\\Extension\\HttpFoundation\\HttpFoundationExtension` + to your form factory:: use Symfony\Component\Form\Forms; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; @@ -83,13 +91,15 @@ to your form factory:: ->addExtension(new HttpFoundationExtension()) ->getFormFactory(); -Now, when you process a form, you can pass the :class:`Symfony\\Component\\HttpFoundation\\Request` -object to :method:`Symfony\\Component\\Form\\Form::handleRequest`. + Now, when you process a form, you can pass the :class:`Symfony\\Component\\HttpFoundation\\Request` + object to :method:`Symfony\\Component\\Form\\Form::handleRequest`:: -.. note:: + $form->handleRequest($request); + + .. note:: - For more information about the HttpFoundation component or how to - install it, see :doc:`/components/http_foundation/introduction`. + For more information about the HttpFoundation component or how to + install it, see :doc:`/components/http_foundation/introduction`. CSRF Protection ~~~~~~~~~~~~~~~ From 37b13e15dd34c0854b3207a1a691b2cc6b530fb8 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 17 Dec 2013 11:39:34 -0600 Subject: [PATCH 18/25] [#3071] Minor tweaks to a nice facelift for this entry --- cookbook/routing/redirect_in_config.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cookbook/routing/redirect_in_config.rst b/cookbook/routing/redirect_in_config.rst index cb37de745c9..c9bdeca4147 100644 --- a/cookbook/routing/redirect_in_config.rst +++ b/cookbook/routing/redirect_in_config.rst @@ -1,16 +1,16 @@ .. index:: single: Routing; Redirect using Framework:RedirectController -How to Configure a Redirect Without a Custom Controller +How to Configure a Redirect without a Custom Controller ======================================================= Sometimes, a URL needs to redirect to another URL. You can do that by creating -a new controller action which only task is to redirect, but using the +a new controller action whose only task is to redirect, but using the :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController` of -the FrameworkBundle, it's a lot easier. +the FrameworkBundle is even easier. You can redirect to a specific path (e.g. ``/about``) or to a specific route -using it's name (e.g. ``homepage``). +using its name (e.g. ``homepage``). Redirecting Using a Path ------------------------ @@ -26,7 +26,7 @@ action to redirect to this new url: # app/config/routing.yml - # loading the App controllers + # load some routes - one should ultimately have the path "/app" AppBundle: resource: "@AcmeAppBundle/Controller/" type: annotation @@ -49,7 +49,7 @@ action to redirect to this new url: xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> - + import( "@AcmeAppBundle/Controller/", "annotation" @@ -90,9 +90,9 @@ action to redirect to this new url: return $collection; In this example, you configured a route for the ``/`` path and let the -``RedirectController`` handle it to redirect it to ``/app``. The ``permanent`` -switch tells the action to issue a ``301`` HTTP status code instead of the -default ``302`` HTTP status code. +``RedirectController`` redirect it to ``/app``. The ``permanent`` switch +tells the action to issue a ``301`` HTTP status code instead of the default +``302`` HTTP status code. Redirecting Using a Route ------------------------- From 827014eea11d20931683d98968ce6bd659e44555 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Fri, 13 Sep 2013 21:42:44 +0100 Subject: [PATCH 19/25] Documented xml namespace autodiscovery. --- components/dom_crawler.rst | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 61f28d37e95..65cdd93eb38 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -95,6 +95,52 @@ To remove a node the anonymous function must return false. All filter methods return a new :class:`Symfony\\Component\\DomCrawler\\Crawler` instance with filtered content. +Both :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath` and +:method:`Symfony\\Component\\DomCrawler\\Crawler::filter` methods work with +XML namespaces, which are automatically registered. + +.. versionadded:: 2.4 + Auto discovery of namespaces was introduced in Symfony 2.4. + +Consider an XML below: + + + + tag:youtube.com,2008:video:kgZRZmEc9j4 + + + + Chordates - CrashCourse Biology #24 + widescreen + + + +It can be filtered with ``DomCrawler`` without a need to register namespace +aliases both with :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath`:: + + $crawler = $crawler->filterXPath('//default:entry/media:group//yt:aspectRatio'); + +and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: + + use Symfony\Component\CssSelector\CssSelector; + + CssSelector::disableHtmlExtension(); + $crawler = $crawler->filter('default|entry media|group yt|aspectRatio'); + +.. note:: + + The default namespace is registered with a name "default". + +.. caution:: + + To query an XML with a CSS selector, the HTML extension needs to be disabled with + :method:`Symfony\\Component\\CssSelector\\CssSelector::disableHtmlExtension` + to avoid converting the selector to lowercase. + + Node Traversing ~~~~~~~~~~~~~~~ From 47bc7dc258189b55dd74f9618b14ab0d348ce7f2 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Wed, 18 Sep 2013 13:22:31 +0100 Subject: [PATCH 20/25] Documented changing of default namespace prefix. --- components/dom_crawler.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 65cdd93eb38..17d4a8fc2b2 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -132,7 +132,9 @@ and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: .. note:: - The default namespace is registered with a name "default". + The default namespace is registered with a prefix "default". It can be + changed with the + :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix`. .. caution:: From 68fa18e8fc53924e32fe77f28e02950ce28088cd Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Sun, 22 Sep 2013 23:41:41 +0100 Subject: [PATCH 21/25] Documented explicit namespace registration. --- components/dom_crawler.rst | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 17d4a8fc2b2..0062a4bbd7c 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -97,10 +97,12 @@ To remove a node the anonymous function must return false. Both :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath` and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter` methods work with -XML namespaces, which are automatically registered. +XML namespaces, which can be either automatically discovered or registered +explicitly. .. versionadded:: 2.4 - Auto discovery of namespaces was introduced in Symfony 2.4. + Auto discovery and explicit registration of namespaces was introduced + in Symfony 2.4. Consider an XML below: @@ -136,13 +138,18 @@ and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: changed with the :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix`. +Namespaces can be explicitly registered with the +:method:`Symfony\\Component\\DomCrawler\\Crawler::registerNamespace`:: + + $crawler->registerNamespace('m', 'http://search.yahoo.com/mrss/'); + $crawler = $crawler->filterXPath('//m:group//yt:aspectRatio'); + .. caution:: To query an XML with a CSS selector, the HTML extension needs to be disabled with :method:`Symfony\\Component\\CssSelector\\CssSelector::disableHtmlExtension` to avoid converting the selector to lowercase. - Node Traversing ~~~~~~~~~~~~~~~ From baec6deae76d311a0f41d2dde232c1bf5f8a4c72 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 16 Dec 2013 22:25:11 +0000 Subject: [PATCH 22/25] Added a note about removing the default namespace. --- components/dom_crawler.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 0062a4bbd7c..af4cc3f93d0 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -138,6 +138,9 @@ and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: changed with the :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix`. + The default namespace is removed when loading the content if it's the only + namespace in the document. It's done to simplify the xpath queries. + Namespaces can be explicitly registered with the :method:`Symfony\\Component\\DomCrawler\\Crawler::registerNamespace`:: From daf5d3c8776531cd7f60fe4078ab84eff16852e1 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 17 Dec 2013 11:29:48 -0600 Subject: [PATCH 23/25] [#2979] Minor tweaks --- components/dom_crawler.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index af4cc3f93d0..568f0202417 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -95,7 +95,7 @@ To remove a node the anonymous function must return false. All filter methods return a new :class:`Symfony\\Component\\DomCrawler\\Crawler` instance with filtered content. -Both :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath` and +Both the :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath` and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter` methods work with XML namespaces, which can be either automatically discovered or registered explicitly. @@ -104,7 +104,7 @@ explicitly. Auto discovery and explicit registration of namespaces was introduced in Symfony 2.4. -Consider an XML below: +Consider the XML below: -It can be filtered with ``DomCrawler`` without a need to register namespace +This can be filtered with the ``Crawler`` without needing to register namespace aliases both with :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath`:: $crawler = $crawler->filterXPath('//default:entry/media:group//yt:aspectRatio'); @@ -136,21 +136,22 @@ and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: The default namespace is registered with a prefix "default". It can be changed with the - :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix`. + :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix` + method. The default namespace is removed when loading the content if it's the only namespace in the document. It's done to simplify the xpath queries. Namespaces can be explicitly registered with the -:method:`Symfony\\Component\\DomCrawler\\Crawler::registerNamespace`:: +:method:`Symfony\\Component\\DomCrawler\\Crawler::registerNamespace` method:: $crawler->registerNamespace('m', 'http://search.yahoo.com/mrss/'); $crawler = $crawler->filterXPath('//m:group//yt:aspectRatio'); .. caution:: - To query an XML with a CSS selector, the HTML extension needs to be disabled with - :method:`Symfony\\Component\\CssSelector\\CssSelector::disableHtmlExtension` + To query XML with a CSS selector, the HTML extension needs to be disabled with + :method:`CssSelector::disableHtmlExtension ` to avoid converting the selector to lowercase. Node Traversing From 14c538217b32d47833e02281c85c4c0d48fe5b8a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 15 Sep 2013 15:17:31 +0200 Subject: [PATCH 24/25] document how to restrict a firewall to a specific host --- cookbook/map.rst.inc | 1 + cookbook/security/host_restriction.rst | 62 ++++++++++++++++++++++++++ cookbook/security/index.rst | 1 + 3 files changed, 64 insertions(+) create mode 100644 cookbook/security/host_restriction.rst diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 37d9c9dcf0a..92c7bdc8957 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -132,6 +132,7 @@ * :doc:`/cookbook/security/acl` * :doc:`/cookbook/security/acl_advanced` * :doc:`/cookbook/security/force_https` + * :doc:`/cookbook/security/host_restriction` * :doc:`/cookbook/security/form_login` * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` diff --git a/cookbook/security/host_restriction.rst b/cookbook/security/host_restriction.rst new file mode 100644 index 00000000000..fcb2960651b --- /dev/null +++ b/cookbook/security/host_restriction.rst @@ -0,0 +1,62 @@ +.. index:: + single: Security; Restrict Security Firewalls to a Host + +How to restrict Firewalls to a Specific Host +============================================ + +.. versionadded:: 2.4 + Support for restricting security firewalls to a specific host was added in + Symfony 2.4. + +When using the Security component, you can create firewalls that match certain +url patterns and thereby restrict access to all urls matching these patterns. +Additionally, you can restrict a firewall to a host using the ``host`` key: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + + # ... + + security: + firewalls: + secured_area: + pattern: ^/ + host: admin\.example\.com + http_basic: true + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // ... + + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/', + 'host' => 'admin.example.com', + 'http_basic' => true, + ), + ), + )); diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index d0856f144cf..e9cad89cb50 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -10,6 +10,7 @@ Security acl acl_advanced force_https + host_restriction form_login securing_services custom_provider From 0a9241d1756aba87382b6b325a06481824fe5461 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 17 Dec 2013 11:35:03 -0600 Subject: [PATCH 25/25] [#2953][#2986] Tweaks to firewall hostname Biggest change is to clarify that matching a firewall has no guarantee (is unrelated) to whether or not access is restricted. Also, fixed up some of the regex. --- cookbook/security/host_restriction.rst | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/cookbook/security/host_restriction.rst b/cookbook/security/host_restriction.rst index fcb2960651b..9ac7a294a8e 100644 --- a/cookbook/security/host_restriction.rst +++ b/cookbook/security/host_restriction.rst @@ -1,7 +1,7 @@ .. index:: single: Security; Restrict Security Firewalls to a Host -How to restrict Firewalls to a Specific Host +How to Restrict Firewalls to a Specific Host ============================================ .. versionadded:: 2.4 @@ -9,8 +9,9 @@ How to restrict Firewalls to a Specific Host Symfony 2.4. When using the Security component, you can create firewalls that match certain -url patterns and thereby restrict access to all urls matching these patterns. -Additionally, you can restrict a firewall to a host using the ``host`` key: +URL patterns and therefore are activated for all pages whose URL matches +that pattern. Additionally, you can restrict the initialization of a firewall +to a host using the ``host`` key: .. configuration-block:: @@ -24,7 +25,7 @@ Additionally, you can restrict a firewall to a host using the ``host`` key: firewalls: secured_area: pattern: ^/ - host: admin\.example\.com + host: ^admin\.example\.com$ http_basic: true .. code-block:: xml @@ -39,7 +40,7 @@ Additionally, you can restrict a firewall to a host using the ``host`` key: - + @@ -55,8 +56,15 @@ Additionally, you can restrict a firewall to a host using the ``host`` key: 'firewalls' => array( 'secured_area' => array( 'pattern' => '^/', - 'host' => 'admin.example.com', + 'host' => '^admin\.example\.com$', 'http_basic' => true, ), ), )); + +The ``host`` (like the ``path``) is a regular expression. In this example, +the firewall will only be activated if the host is equal exactly (due to +the ``^`` and ``$`` regex characters) to the hostname ``admin.example.com``. +If the hostname does not match this pattern, the firewall will not be activated +and subsequent firewalls will have the opportunity to be matched for this +request.