2015-03-11 4 views
2

Я в настоящее время использую FOSRESTBundle с JMSSerialize, чтобы сделать RESTFull API (конечно).Динамические группы сериализации на FOS REST bundle

Мой проект - экстрасеть для клиентов и администраторов.

Таким образом, я должен отключить какое-либо поле от просмотра клиентом, только видимое для администраторов.

Я начал из этой конфигурации сериализатора для объекта:

AppBundle\Entity\IncidentComment: 
    exclusion_policy: ALL 
    properties: 
     id: 
      expose: true 
      groups: [list, details] 
     author: 
      expose: true 
      groups: [list, details] 
     addedAt: 
      expose: true 
      groups: [list, details] 
     content: 
      expose: true 
      groups: [details] 
     customerVisible: 
      expose: true 
      groups: [list_admin, details_admin] 

Как вы можете видеть, customerVisible группы имеют _admin суффикс. Это поле должно отображаться только для администраторов.

Я хочу динамически добавлять группы с суффиксом _admin для установки групп на представлениях, если у пользователя есть, например, роль ROLE_ADMIN или другое условие, не записывая его на каждое действие каждого контроллера останова.

Я думал о создании custom view handler с аргументом контекста безопасности для добавления группы, но я не знаю, является ли это правильным способом.

Как вы думаете, это хороший способ? Есть ли у вас какие-либо предложения по этому поводу?

Кстати, если у какого-то разработчика была такая же проблема, я буду рад здесь, как он это решил! :)

Спасибо.

+0

Привет Soullivaneuh, я в настоящее время сталкивается с точно такой же проблемой. Было бы замечательно, если бы был способ добавить группу к сериализатору во время выполнения в контроллере. –

ответ

3

Я просто понял, легкий способ добавить SerializerGroups во время выполнения:

private function determineRolebasedSerializerGroup($role, $groupToAdd, Request $request) { 
    if (!$this->get('security.context')->isGranted($role)) 
     return; 

    $groups = $request->attributes->get('_view')->getSerializerGroups(); 
    $groups[] = $groupToAdd; 
    $x = $request->attributes->get('_view')->setSerializerGroups($groups); 
} 

Я добавил этот метод, чтобы мой контроллер. Теперь я в состоянии назвать это таким образом:

/** 
* @REST\View(serializerGroups={"company"}) 
*/ 
public function getCompanyAction(Company $company, Request $request) { 
    $this->determineRolebasedSerializerGroup('ROLE_ADMIN', 'company-admin', $request); 

    return $company; 
} 

который добавляет группу «компания-администратор» в группу сериализатора, если текущий пользователь имеет роль «ROLE_ADMIN». Это очень хорошо для меня.

+0

Хорошая идея! Но проблема такая же, нам всегда приходится называть ее на каждом контроллере. Любой способ добавить его к слушателю, например? И какой слушатель? – Soullivaneuh

+0

attributes-> get ('_ view) return null – julestruong

1

Если вы хотите сделать это с помощью слушателя, вы можете создать свой собственный ViewResponseListener и подписаться на него на мероприятие kernel.view. Ваш слушатель должен быть запущен после прослушивания FOSRest, поэтому вам необходимо установить приоритет 101.

app.event.listener.extended_view_response: 
    class: AppBundle\EventListener\ExtendedViewResponseListener 
    arguments: ["@security.authorization_checker"] 
    tags: 
     - { name: kernel.event_listener, event: kernel.view, method: onKernelView, priority: 101 } 

ExtendedViewResponseListener.php

public function onKernelView(GetResponseForControllerResultEvent $event) 
{ 
    if (null !== $viewAttribute = $event->getRequest()->attributes->get('_template')) { 
     $groups = []; 

     foreach(User::getPossibleRoles() as $role) { 
      if ($this->authorizationChecker->isGranted($role)) { 
       $groups[] = strtolower(str_replace('ROLE_', '', $role)); // ROLE_USER => user group 
      } 
     } 

     $viewAttribute->setSerializerGroups($groups); 
    } 

} 

И, пожалуйста, не забудьте включить _template атрибут в контроллере, я имею в виду @\FOS\RestBundle\Controller\Annotations\View() в аннотации контроллера. Если вы хотите выяснить, как это работает - PLS проверить ViewResponseListener.php в FosRestBundle.

Второй способ сделать это - ваш заказ сериализатору tokenstorageaware_serializer