2013-06-10 30 views
5

Tôi đã sử dụng SonataUser với FOSUser để quản lý người dùng của mình và tạo trường tùy chỉnh company để đính kèm từng trường vào một công ty cụ thể.Sonata User - Security trên trường tùy chỉnh

Bây giờ tôi chỉ đơn giản là sẽ cần phải cung cấp cho người dùng khả năng để quản lý chỉ những người dùng thuộc cùng một công ty:

user1 company1 
user2 company1 
user3 company2 
user4 company2 

Ví dụ: user1 sẽ có thể liệt kê/chỉnh sửa chỉ user1 user2 &

Tôi có nên sử dụng ACL không?

Bạn có thể chỉ cho tôi đúng hướng hoặc hướng dẫn để tùy chỉnh SonataUser cho mục đích này không?

Trả lời

10

Có ACL là con đường để đi. tạo một CompanyVoter thực hiện VoterInterface và kiểm tra xem người dùng có ở cùng một công ty bên trong phương thức vote() của nó hay không.

mục nhập sổ nấu ăn "How to implement your own Voter to blacklist IP Addresses" cung cấp phần giới thiệu tốt.

thay đổi chiến lược của người quản lý quyết định quyền truy cập của bạn thành 'nhất trí'. Điều này có nghĩa là nếu chỉ có một cử tri từ chối quyền truy cập (ví dụ: CompanyVoter), quyền truy cập không được cấp cho người dùng cuối.

# app/config/security.yml 
security: 
    access_decision_manager: 
     strategy: unanimous 

Bây giờ tạo Cử Tri của bạn

// src/Acme/AcmeBundle/YourBundle/Security/Authorization/Voter/CompanyVoter.php 
namespace Acme\YourBundle\Security\Authorization\Voter; 

use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; 
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 

use Acme\YourUserBundleBundle\Entity\User; 
use Symfony\Component\Security\Core\User\UserInterface; 

class CompanyVoter implements VoterInterface 
{ 

    private $container; 

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

    public function supportsAttribute($attribute) 
    { 
     return in_array($attribute, array(
      'EDIT', 
      'ACTIVATE', 
      // ... 
     )); 
    } 

    public function supportsClass($class) 
    { 
     return in_array("FOS\UserBundle\Model\UserInterface", class_implements($class)); 
    } 

    public function vote(TokenInterface $token, $object, array $attributes) 
    { 
     if (!($this->supportsClass(get_class($object)))) { 
      return VoterInterface::ACCESS_ABSTAIN; 
     } 

     foreach ($attributes as $attribute) { 
      if (!$this->supportsAttribute($attribute)) { 
       return VoterInterface::ACCESS_ABSTAIN; 
      } 
     } 

     $user = $token->getUser(); 
     if (!($user instanceof UserInterface)) { 
      return VoterInterface::ACCESS_DENIED; 
     } 

     // check if the user has the same company 
     if ($user->getCompany() == $object->getCompany()) { 
      return VoterInterface::ACCESS_GRANTED; 
     } 

     return VoterInterface::ACCESS_DENIED; 
    } 

} 

Cuối cùng đăng ký cử tri như như một dịch vụ

# src/Acme/AcmeBundle/Resources/config/services.yml 
services: 
    security.access.company_voter: 
     class:  Acme\YourBundle\Security\Authorization\Voter\CompanyVoter 
     public:  false 
     tags: 
      - { name: security.voter } 

... bây giờ sử dụng nó trong mẫu cành lá của bạn

{% if is_granted('EDIT', user) %}<a href="#">Edit</a>{% endif %} 
{% if is_granted('ACTIVATE', user) %}<a href="#">activate</a>{% endif %} 

hoặc trong bộ điều khiển của bạn ...

public function editAction(UserInterface $user) 
{ 
    if ($this->get('security.context')->isGranted('EDIT',$user)) { 
     throw new \Symfony\ComponentSecurity\Core\Exception\AccessDeniedException(); 
    } 
} 

hoặc sử dụng JMSSecurityExtraBundle ...

/** 
* @SecureParam(name="user", permissions="EDIT") 
*/ 
public function editUser(UserInterface $user) 
{ 
    // ... 
} 
+0

tôi đã cố gắng theo cách này, nó hoạt động cho phiên bản (ngăn chặn phiên bản cho các công ty khác) nhưng danh sách này vẫn hiển thị tất cả những người sử dụng. Có vẻ như cử tri không được gọi để hiển thị dòng. –

+0

ý của bạn là gì khi hiển thị dòng? – nifr

+0

Vì tôi cần chỉ hiển thị một số người dùng trong lưới danh sách, nên không có dòng nào hiển thị cho họ (thay vì xuất hiện chỉ đọc) Lưu ý: Tôi đang nói về lưới SonataAdmin –

1

Như tôi đã không cần ACL ở đây, (chỉ cử tri) tôi đã sử dụng bộ xử lý vai trò an ninh của sonata.

Nhưng tôi đã gặp sự cố khi sử dụng vì thực thi mặc định isGranted() không chuyển đối tượng hiện tại cho cử tri.

Vì vậy, tôi đã phải mở rộng nó, kiểm tra độc thoại của tôi trong này github issue để biết thêm chi tiết.


Bằng cách này, PR của tôi đã được chấp nhận về vấn đề này

Các vấn đề liên quan