Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

The Server & New IsGranted

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $8.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Time to try our app! First, in .env, change the database name to symfony3_tutorial, or whatever the database name was called when you first setup the project. Now when we run doctrine:migrations:status... yes! We have a full database!

Installing the Server

Let's start the built-in web server:

./bin/console server:run

Surprise!

There are no commands defined in the "server" namespace.

Remember: with Flex, you opt in to features. Run:

composer require server

When it finishes, run:

./bin/console server:run

Interesting - it started on localhost:8001. Ah, that's because the old server is still running and hogging port 8000! And woh! It's super broken: we've removed a ton of files it was using. Hit Ctrl+C to stop the server. Ah! It's so broken it doesn't want to stop! It's taking over! Close that terminal!

Start the server again:

./bin/console server:run

It still starts on port 8001, but that's fine! Go back to your browser and load http://localhost:8001. Ha! It works! Check it out: Symfony 4.0.1.

Surf around to see if everything works: go to /genus. Looks great! Now /admin/genus. Ah! Looks terrible!

To use the @Security tag, you need to use the Security component and the ExpressionLanguage component.

The New @IsGranted

Hmm. Let's do some digging! Open src/AppBundle/Controller/Admin/GenusAdminController.php. Yep! Here is the @Security annotation from FrameworkExtraBundle. The string we're passing to it is an expression, so we need to install the ExpressionLanguage.

But wait! I have a better idea. Google for SensioFrameworkExtraBundle and find its GitHub page. Click on releases: the latest is 5.1.3. What version do we have? Open composer.json: woh! We're using version 3! Ancient!

Let's update this to ^5.0.

82 lines composer.json
{
... lines 2 - 16
"require": {
... lines 18 - 23
"sensio/framework-extra-bundle": "^5.0",
... lines 25 - 42
},
... lines 44 - 80
}

Then, run:

composer update sensio/framework-extra-bundle

to update just this library. Like with any major upgrade, look for a CHANGELOG to make sure there aren't any insane changes that will break your app.

So... why are we upgrading? So glad you asked: because the new version has a feature I really like! As soon as Composer finishes, go back to GenusAdminController. Instead of using @Security, use @IsGranted.

... lines 1 - 12
/**
* @IsGranted("ROLE_MANAGE_GENUS")
... line 15
*/
class GenusAdminController extends Controller
... lines 18 - 97

This is similar, but simpler. For the value, you only need to say: ROLE_MANAGE_GENUS.

Try it - refresh! Yes! We're sent to the login page - that's good! Sign in with password iliketurtles.

At this point... we're done! Unless... you want to move all of your classes from AppBundle directly into src/. I do! And it's much easier than you might think.

Leave a comment!

6
Login or Register to join the conversation
MattWelander Avatar
MattWelander Avatar MattWelander | posted 1 month ago

I'm unfamiliar with the @IsGranted stuff.

In my TWIG code I sometimes use
{% if is_granted('ROLE_SUPER_ADMIN') %}
to hide menu options etc from non-admins.

In my controllers I often use
if ( $this->get('security.authorization_checker')->isGranted('ROLE_EXTRAOPENING_ADMIN') )

And I also have access config in security.yaml
access_control:
- { path: /price, role: ROLE_EXTRAOPENING_ADMIN }
- { path: /extraopening/, role: ROLE_EXTRAOPENING_USER }

Is this sufficient or am I missing something when I'm not using the @IsGranted directive for certain classes (or functions, I suppose the @IsGranted could go before a specific function such as ::editAction as well?)

Reply

Hey Mattias,

It should be OK, if you prefer annotations (or PHP 8 attributes) - you can use IsGranted annotation/attribute above your controller's action. Or you can call that isGranted method explicitly in the method as you did. There is no difference, but the 1st option would make your controller cleaner (less code) while the 2nd option gives you a more control as you can write a PHP code and add more checks if needed.

Well, isGranted() PHP function will just return you either true or false, i.e. you should throw an AccessDeniedException manually to actually deny the access. Btw, it depends on what class your controller extends, but if you extends Symfony base controller - you could shorten that method call to just "$this->isGranted(...)" instead of doing it via "security.authorization_checker" service. And btw, there's another method call createAccessDeniedException() that helps to create the actual exception for you, i.e. you can do something like:


if ($this->isGranted(...)) {
throw $this->createAccessDeniedException(...);
}

But of course, it would be great to check that your code works and you see that access denied exception in your browser :)

Cheers!

Reply
MattWelander Avatar
MattWelander Avatar MattWelander | victor | posted 1 month ago

The Controller class is created like this


namespace AppBundle\Controller\ExtraOpening;

use AppBundle\Entity\ACRGroup as ACRGroup;
use AppBundle\Entity\ExtraOpening\DebitPeriod;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Service\globalHelper;

/**
* Debitperiod controller.
*
*/
class DebitPeriodController extends Controller {
...

Is the Base controller you mentioned different from the Symfony\Bundle\FrameworkBundle\Controller\Controller I'm using?

In this particular case I did this with the logic, but I see what you're saying.

if ( $this->get('security.authorization_checker')->isGranted('ROLE_EXTRAOPENING_ADMIN') ) {
//If user is extraopening admin, list debit periods for all units...
$units = $em->getRepository('AppBundle:ACRGroup')->findAll();
} else {
//...otherwise list only units that user has permission to work with
$units = $user->getACRGroups();

Reply

Hey Mattias,

Ah, yes, I was mention the Symfony\Bundle\FrameworkBundle\Controller\AbstractController - this one should have that isGranted() method. Otherwise, using a special service for this is fine, it's up to you!

Cheers!

Reply
GDIBass Avatar
GDIBass Avatar GDIBass | posted 4 years ago

Will IsGranted work with 2 different roles?

I.E.

* @IsGranted('ROLE_THIS_ACCESS')
* @IsGranted('ROLE_SUPER_USER')

will allow any user with either role to access?

Reply

Hey Matt,

Yes, it should work according to the docs:

> Each IsGranted() must grant access for the user to have access to the controller.

See https://symfony.com/doc/mas... . Or you can use @Security for more flexibility.

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "doctrine/doctrine-bundle": "^1.6", // 1.8.1
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.2
        "doctrine/doctrine-migrations-bundle": "^1.1", // v1.3.1
        "doctrine/orm": "^2.5", // v2.7.2
        "fzaninotto/faker": "^1.7", // v1.7.1
        "knplabs/knp-markdown-bundle": "^1.4", // 1.6.0
        "sensio/framework-extra-bundle": "^5.0", // v5.1.3
        "stof/doctrine-extensions-bundle": "dev-master", // dev-master
        "symfony/asset": "^4.0", // v4.0.1
        "symfony/console": "^4.0", // v4.0.1
        "symfony/flex": "^1.0", // v1.9.10
        "symfony/form": "^4.0", // v4.0.1
        "symfony/framework-bundle": "^4.0", // v4.0.1
        "symfony/lts": "^4@dev", // dev-master
        "symfony/maker-bundle": "^1.0", // v1.0.2
        "symfony/monolog-bundle": "^3.1", // v3.1.2
        "symfony/polyfill-apcu": "^1.0", // v1.6.0
        "symfony/profiler-pack": "^1.0", // v1.0.3
        "symfony/security-bundle": "^4.0", // v4.0.1
        "symfony/security-csrf": "^4.0",
        "symfony/swiftmailer-bundle": "^3.1", // v3.1.6
        "symfony/translation": "^4.0", // v4.0.1
        "symfony/twig-bundle": "^4.0", // v4.0.1
        "symfony/validator": "^4.0", // v4.0.1
        "symfony/web-server-bundle": "^4.0", // v4.0.1
        "symfony/yaml": "^4.0" // v4.0.1
    },
    "require-dev": {
        "symfony/dotenv": "^4.0", // v4.0.1
        "symfony/phpunit-bridge": "^4.0", // v4.0.1
        "doctrine/doctrine-fixtures-bundle": "^3.0" // 3.0.2
    }
}