0

I am new to symfony. I want to be able to cofigure administrator role name to my application. I need to do something like: (in controller)

if($this->getUser()->isAdmin()) {
   //..
}

In User Entity I could define isAdmin as:

function isAdmin()
{
   $this->hasRole('ROLE_ADMIN');
}

but that way, ROLE_ADMIN can't be configured. Note that I don't want to pass 'a role name' as param (or default param) to isAdmin function. I want it like i can pass object to User Entity:

public function __construct(AuthConfiguration $config)
{
   $this->config = $config;
}

public function isAdmin()
{
   return $this->hasRole($this->config->getAdminRoleName());
}

But how can I pass object to user entity since user creation is handled by the repository ?

egig
  • 4,370
  • 5
  • 29
  • 50
  • Sounds like unnecessary complexity. You are already coupled to an interface with explicitly defines the term admin, because you want to be able to dynamically change the name of the admin role? I've personally never seen a need to do something like this. – John Cartwright May 13 '15 at 16:11

2 Answers2

0

You can set up custom Doctrine DBAL ENUM Type for roles using this bundle: https://github.com/fre5h/DoctrineEnumBundle

<?php

namespace AppBundle\DBAL\Types;

use Fresh\Bundle\DoctrineEnumBundle\DBAL\Types\AbstractEnumType;

class RoleType extends AbstractEnumType
{
    const ROLE_USER          = 'ROLE_USER';
    const ROLE_ADMIN         = 'ROLE_ADMIN';
    const ROLE_SUPER_ADMIN   = 'ROLE_SUPER_ADMIN';
    const ROLE_PROJECT_OWNER = 'ROLE_PROJECT_OWNER';

    /**
     * @var array Readable choices
     * @static
     */
    protected static $choices = [
        self::ROLE_USER          => 'role.user',
        self::ROLE_ADMIN         => 'role.administrator',
        self::ROLE_SUPER_ADMIN   => 'role.super_administrator',
        self::ROLE_PROJECT_OWNER => 'role.project_owner',
    ];
}

Register new type in config.yml:

doctrine:
    dbal:
        mapping_types:
            enum: string
        types:
            RoleType: AppBundle\DBAL\Types\RoleType

Configure your user's role field as ENUM RoleType type:

use Fresh\Bundle\DoctrineEnumBundle\Validator\Constraints as DoctrineAssert;

...

/**
 * @DoctrineAssert\Enum(entity="AppBundle\DBAL\Types\RoleType")
 * @ORM\Column(name="role", type="RoleType")
 */
protected $role = RoleType::ROLE_USER;

And use it in your entity or repository or anywhere else this way:

use AppBundle\DBAL\Types\RoleType;

...

public function isAdmin()
{
   $this->hasRole(RoleType::ROLE_ADMIN);
}
Mikhail Prosalov
  • 4,155
  • 4
  • 29
  • 41
0

The constructor is only called when you create a new instance of the object with the keyword new. Doctrine does not call the constructor even when it hydrates entities.

You could potentially create your own entity hydrator and call the entity's constructor however I haven't tried this solution. It may not be as maintainable.

I want to provide an alternative which I prefer (you may not).

On all my projects, the architecture is as follow: Controller <-> Service <-> Repository <-> Entity.

The advantage of this architecture is the use of dependency injection with services.

In your services.yml

services:
    my.user:
        class: Acme\HelloBundle\Service\MyUserService
        arguments:
            # First argument
            # You could also define another service that returns
            # a list of roles.
            0:
                admin: ROLE_ADMIN
                user: ROLE_USER

In your service:

namespace Acme\HelloBundle\Service;

use Symfony\Component\Security\Core\User\UserInterface;

class MyUserService {

    protected $roles = array();

    public function __constructor($roles)
    {
        $this->roles = $roles;
    }

    public function isAdmin(UserInterface $user = null)
    {
        if ($user === null) {
            // return current logged-in user
        }

        return $user->hasRole($this->roles['admin']);
    }
}

In your controller:

// Pass a user
$this->get('my.user')->isAdmin($this->getUser());

// Use current logged-in user
$this->get('my.user')->isAdmin();

It's away from the solution you are looking for but in my opinion it seems more inline with what Symfony2 provides.

Another advantage is that you can extend the definition of an admin. For example in my project, my user service has a isAdmin() method that has extra logic.

Community
  • 1
  • 1
Thomas Potaire
  • 6,166
  • 36
  • 39