2015-08-13 5 views
1

У меня две разные роли в моем проекте: ROLE_USER и ROLE_ADMIN.
Я хочу получить список всех пользователей через REST API's url '/users', но некоторые поля (например, email) могут видеть только те лица, которые прошли аутентификацию с помощью ROLE_ADMIN.
Итак, у меня вообще 2 вопроса:Как реализовать API REST на основе ролей

1) на каком уровне абстракции (в MVC шаблон) я должен решить, какая информация может быть возвращена на основе ROLE
2) Какой лучший способ реализации такой REST API на основе ролей в Symfony?


Благодаря

ответ

2

Если вы используете JMSSerializer, вы можете использовать группы, чтобы решить, что можно увидеть или нет. Затем в вашем контроллере или где бы то ни было, вы можете установить группу на основе роли.

Например, при отображении (в YAML) ..

Fully\Qualified\Class\Name: 
    exclusion_policy: ALL 
    properties: 
     id: 
      groups: [user] 
     userAndAdmin: 
      groups: [user] 
     adminOnly: 
      groups: [admin] 

И тогда в вашем контроллере вы бы установить группу как ...

public function getUsersAction(Request $request) 
{ 
    $users = $this->getRepository()->findAll(); 
    $serializer = $this->get('jms_serializer.serializer'); 

    $json = $serializer->serialize(
     $users, 
     'json', 
     SerializationContext::create()->setGroups($this->generateGroups()) 
    ); 

    return new Response($json); 

    // If you are using FOSRestBundle, which I would recommend, then you would just need to do... 
    $view = $this 
     ->view($this->getRepository()->findAll();) 
     ->setExclusionGroups($this->generateGroups()) 
    ; 

    return $this->handleView($view); 
} 

private function generateGroups() 
{ 
    $securityContext = $this->get('security.context'); 
    $groups = array(); 

    if ($securityContext->isGranted('ROLE_USER')) { 
     $groups[] = 'user'; 
    } 

    if ($securityContext->isGranted('ROLE_ADMIN')) { 
     $groups[] = 'admin'; 
    } 

    return $groups; 
} 

Хотя весь "generateGroups" и настройка групп будет лучше размещена в обработчике представлений клиента или генераторе ответов.

Предполагая, что ваша иерархия имеет ROLE_ADMIN в качестве родителя ROLE_USER, вы получите следующие результаты.

ROLE_USER

{ 
    "users": [ 
     { 
      "id": 1, 
      "userAndAdmin": "val" 
     } 
    ] 
} 

ROLE_ADMIN

{ 
    "users": [ 
     { 
      "id": 1, 
      "userAndAdmin": "val", 
      "adminOnly": "val" 
     } 
    ] 
} 
+0

Это здорово! Более того, я могу использовать его с аннотациями, и это будет просто, как несколько строк кода. Огромное спасибо! –

0

Поскольку API зависит от пользователя, сделавшего запрос, каждый запрос будет нести информацию о текущем пользователе. Обычно все задачи, связанные с авторизацией, обрабатываются в контроллере. Итак, ответ на ваш первый вопрос заключается в том, что вы должны обрабатывать роли в контроллере и на основе ролей, вы должны отфильтровывать поля из данных, возвращаемых из репозитория. Например,

//users is the array of user objects returned by your repository 

data = []; 

if ($this->get('security.context')->isGranted('ROLE_ADMIN')) { 
    foreach($users as $user){ 
    // Add ROLE_ADMIN specific data 
     data[][] = array(
      'name' => $user->getName(), 
      'email' => $user->getEmail(), 
     ); 
    }  
} 


if ($this->get('security.context')->isGranted('ROLE_USER')) { 
    foreach($users as $user){ 
    // Add ROLE_USER specific data 
    data[][] = array(
     'name' => $user->getName(), 
     'address' => $user->getAddress(), 
       ); 
    } 

    } 

Затем JSON кодирует массив данных и возвращает его как ответ Чтобы уменьшить количество запросов, вы можете добавить метод __toArray в свой класс User.

+0

Спасибо за ваш ответ. Но мне кажется, что это неудобно делать это. Код в контроллере будет большим и вряд ли доступен. –

Смежные вопросы