2015-04-01 17 views
7

Ứng dụng của tôi về mặt kỹ thuật có hai khu vực, khu vực toàn cầu (phản hồi, hồ sơ người dùng, cài đặt người dùng, v.v) và khu vực nhóm (danh bạ, dự án, hồ sơ nhóm, cài đặt nhóm, v.v.).Yii2 RBAC Nhiều bài tập cho mỗi người dùng Dựa trên nhóm

Tôi đang sử dụng RBAC DBManager cho khu vực toàn cầu và nó hoạt động tốt, nhưng tôi đang gặp sự cố khi triển khai cơ chế ủy quyền cho khu vực nhóm.

Lý do là nhóm có thể được chia sẻ giữa người dùng và người dùng có thể có nhiều bài tập trong bảng group_access (id, group_id, user_id, item_name) vì họ có thể là thành viên của nhiều nhóm và họ có thể có các cấp quyền khác nhau cho các nhóm đó.

Đây là thiết lập auth của tôi:

$auth = Yii::$app->authManager; 

    // group permissions 
    $manageGroupUsers = $auth->createPermission('manage_group_users'); 
    $manageGroupUsers->description = 'Manage Group Users'; 
    $auth->add($manageGroupUsers); 

    $manageGroupSettings = $auth->createPermission('manage_group_settings'); 
    $manageGroupSettings->description = 'Manage Group Settings'; 
    $auth->add($manageGroupSettings); 

    // app permissions 
    $manageAppUsers = $auth->createPermission('manage_app_users'); 
    $manageAppUsers->description = 'Manage App Users'; 
    $auth->add($manageAppUsers); 

    $manageAppGroups = $auth->createPermission('manage_app_groups'); 
    $manageAppGroups->description = 'Manage App Groups'; 
    $auth->add($manageAppGroups); 

    $manageAppSettings = $auth->createPermission('manage_app_settings'); 
    $manageAppSettings->description = 'Manage App Settings'; 
    $auth->add($manageAppSettings); 

    $manageAppFeedback = $auth->createPermission('manage_app_feedback'); 
    $manageAppFeedback->description = 'Manage App Feedback'; 
    $auth->add($manageAppFeedback); 

    // group roles 
    // -- create role 
    $groupUser = $auth->createRole('group_user'); 
    $groupUser->description = 'Group Users'; 
    $auth->add($groupUser); 

    // -- create role 
    $groupAdmin = $auth->createRole('group_admin'); 
    $groupAdmin->description = 'Group Administrators'; 
    $auth->add($groupAdmin); 
    // add permissions 
    $auth->addChild($groupAdmin, $manageGroupUsers); 
    $auth->addChild($groupAdmin, $manageGroupSettings); 
    // inherit permissions 
    $auth->addChild($groupAdmin, $groupUser); 

    // -- create role 
    $groupCreator = $auth->createRole('group_creator'); 
    $groupCreator->description = 'Group Creators'; 
    $auth->add($groupCreator); 
    // inherit permissions 
    $auth->addChild($groupCreator, $groupAdmin); 

    // app roles 
    // -- create role 
    $appUser = $auth->createRole('app_user'); 
    $appUser->description = 'App Users'; 
    $auth->add($appUser); 

    // -- create role 
    $appSupport = $auth->createRole('app_support'); 
    $appSupport->description = 'Support Users'; 
    $auth->add($appSupport); 
    // add permissions 
    $auth->addChild($appSupport, $manageAppFeedback); 

    // -- create role 
    $appAdmin = $auth->createRole('app_admin'); 
    $appAdmin->description = 'App Administrators'; 
    $auth->add($appAdmin); 
    // add permissions 
    $auth->addChild($appAdmin, $manageAppUsers); 
    $auth->addChild($appAdmin, $manageAppGroups); 
    $auth->addChild($appAdmin, $manageAppSettings); 
    // inherit permissions 
    $auth->addChild($appAdmin, $appUser); 
    $auth->addChild($appAdmin, $appSupport); 

    // -- create role 
    $appCreator = $auth->createRole('app_creator'); 
    $appCreator->description = 'App Creators'; 
    $auth->add($appCreator); 
    // inherit permissions 
    $auth->addChild($appCreator, $appAdmin); 

bảng group_access tôi có schema tương tự như bảng auth_assignment, ngoại trừ rằng nó có một cột GROUP_ID, và cột user_id là không độc đáo.

Người dùng sẽ chỉ có một nhiệm vụ liên quan đến khu vực toàn cầu, nhưng có thể có nhiều xác nhận khác nhau về khu vực nhóm vì họ có thể có tư cách quản trị viên trên nhóm a, nhưng chỉ có quyền riêng tư của người dùng trên nhóm b.

My DB được thiết lập như:

  1. Người dùng (status_id, tên người dùng, auth_key, password_hash, email, vv)

  2. Groups (status_id, tên, mô tả, vv)

  3. Group_Access (group_id, user_id, item_name) Mỗi ​​người dùng nhận được một nhiệm vụ cho mỗi nhóm họ có quyền truy cập.

    sample_group_access_records [ [ 'id' => 1, 'user_id' => 35, 'GROUP_ID' => 17, 'ITEM_NAME' => 'group_admin' ], [ 'id' => 2, 'user_id' => 35, 'GROUP_ID' => 356, 'ITEM_NAME' => 'GROUP_USER' ], [ 'id' => 3, 'user_id' => 35, 'group_id' => 211, 'item_name' => 'group_creator' ], ];

Chức năng checkAccess có thể đủ điều kiện userID, và tôi thậm chí có thể sử dụng "có thể" phiên bản ngắn hơn mà hoạt động tuyệt vời cho người dùng đăng nhập, nhưng tôi cần phải kiểm tra quyền truy cập dựa trên một lựa chọn sử dụng như dưới đây:

Option::getOption('user', 'active_group_id') 

Đây là chức năng tùy chỉnh để kéo id nhóm đang hoạt động từ bảng tùy chọn của người dùng. Nếu người dùng chuyển đổi nhóm, điều này sẽ được thay đổi. Mô hình tùy chọn của tôi có ba loại 'ứng dụng', 'người dùng', 'nhóm'. Nó sẽ là tốt đẹp nếu tôi có thể tìm ra một chức năng hoạt động giống như checkAccess bản địa nhưng được gọi là checkGroupAccess và tự động lấy active_group_id và kéo các nhiệm vụ người dùng từ bảng group_access và thực hiện kiểm tra quyền.

Tôi hy vọng điều này có ý nghĩa.

Cảm ơn bạn đã dành thời gian.

Mike

** UPDATED **

Vì vậy, tôi có một giải pháp, mà sử dụng tùy chỉnh chức năng checkAccess để kiểm tra các điều khoản thích hợp vào nhóm hoặc các khu vực trên toàn cầu.

Tôi có hai bảng (user_access, group_access) có lược đồ tương tự với bảng {{auth_assignment}} mặc định, trong đó tôi hiện không sử dụng. Tôi đang sử dụng các bảng {{auth_item}}, {{auth_item_child}} và {{auth_rule}}.

Tôi có hai mô hình, một cho mỗi bảng truy cập GroupAccess => group_access và UserAccess => user_access.

Tôi cũng có một mô hình cho các chức năng truy cập và đã ánh xạ nó vào cấu hình thành phần.

Đây là mô hình truy cập của tôi:

<?php 

namespace app\models; 

use Yii; 

class Access 
{ 

public function canUser($type, $permissionName, $params = []) 
{ 

    switch ($type) { 

     case 'group': 

     $userID = Yii::$app->user->identity->id; 
     $groupID = Yii::$app->options->getOption('user', 'active_group_id'); 

     $queryAll = GroupAccess::find() 
     ->where('user_id = :user_id and group_id = :group_id', [':user_id' => $userID, ':group_id' => $groupID]) 
     ->asArray() 
     ->all(); 

     $assignments = []; 
     foreach ($queryAll as $queryItem) { 
      $assignments[$queryItem['item_name']] = [ 
      'userId' => $queryItem['user_id'], 
      'roleName' => $queryItem['item_name'], 
      'createdAt' => $queryItem['created_date'], 
      ]; 
     } 

     $result = self::checkAccess($userID, $permissionName, $assignments, $params); 

     return $result; 

     break; 

     case 'user': 

     $userID = Yii::$app->user->identity->id; 

     $queryAll = UserAccess::find() 
     ->where(['user_id' => $userID]) 
     ->asArray() 
     ->all(); 

     $assignments = []; 
     foreach ($queryAll as $queryItem) { 
      $assignments[$queryItem['item_name']] = [ 
      'userId' => $queryItem['user_id'], 
      'roleName' => $queryItem['item_name'], 
      'createdAt' => $queryItem['created_date'], 
      ]; 
     } 

     $result = self::checkAccess($userID, $permissionName, $assignments, $params); 

     return $result; 

     break; 

    } 

} 

public function checkAccess($userID, $permissionName, $assignments, $params = []) 
{ 

    $auth = Yii::$app->authManager; 

    $auth->loadFromCache(); 

    if ($auth->items !== null) { 
     return $auth->checkAccessFromCache($userID, $permissionName, $params, $assignments); 
    } else { 
     return $auth->checkAccessRecursive($userID, $permissionName, $params, $assignments); 
    } 
} 

public function assign($type, $role, $userID = null, $groupID = null) 
{ 

    switch ($type) { 

     case 'group': 

     // clear existing assigments 
     self::revoke('group', $userID, $groupID); 

     $groupAccess = new GroupAccess(); 
     $groupAccess->group_id = $groupID; 
     $groupAccess->user_id = $userID; 
     $groupAccess->item_name = $role; 
     $groupAccess->created_date = time(); 

     return $groupAccess->save(); 

     break; 

     case 'user': 

     // clear existing assignments 
     self::revoke('user', $userID); 

     $userAccess = new UserAccess(); 
     $userAccess->user_id = $userID; 
     $userAccess->item_name = $role; 
     $userAccess->created_date = time(); 

     return $userAccess->save(); 

     break; 

    } 

} 

public function revoke($type, $userID, $groupID = null) 
{ 

    switch ($type) { 

     case 'group': 

     GroupAccess::deleteAll('user_id = :user_id and group_id = :group_id', [':user_id' => $userID, ':group_id' => $groupID]); 

     break; 

     case 'user': 

     UserAccess::deleteAll('user_id = :user_id', [':user_id' => $userID]); 

     break; 

    } 

} 

} 

Và đây là một số mẫu sử dụng để truy cập vào các chức năng:

// get the user option 
echo Yii::$app->options->getOption('user', 'active_group_id'); 

// assign group role 
Yii::$app->access->assign('group', 'group_creator', 22, 18); 
// assign user role 
Yii::$app->access->assign('user', 'app_user', 22); 

// revoke group access 
Yii::$app->access->revoke('group', 22, 18); 
// revoke user access 
Yii::$app->access->revoke('user', 22); 

// test user permission 
var_dump(Yii::$app->access->canUser('user', 'manage_app_settings')); 
// test the group permission 
var_dump(Yii::$app->access->canUser('group', 'manage_group_settings')); 

Về cơ bản, tôi đã sao chép chức năng checkAccess từ DbManager và làm lại nó một ít để kiểm tra quyền truy cập của người dùng dựa trên nhóm.

Vấn đề duy nhất, là tôi phải thực hiện thay đổi đối với lớp DbManager nguồn thực tế để tạo các mục $ (thuộc tính), checkAccessFromCache (function) và checkAccessRecursive (function) tất cả công khai để chúng có thể được truy cập bên ngoài lớp. Hạn chế chính là updateability ...

Bất kỳ cách nào xung quanh vấn đề này?

Cảm ơn.

+0

Tôi đã đăng một giải pháp làm việc. –

Trả lời

2

Đây là giải pháp cuối cùng hoạt động.

Vì vậy, một ngày khác, hãy tái cấu trúc thêm.

Giải pháp cuối cùng của tôi sử dụng chức năng checkAccess trong tệp nguồn DbManager/ManagerInterface, nhưng tôi đã thêm thông số $ assignments được chuyển. Vấn đề chính là tôi phải xây dựng danh sách bài tập của riêng tôi để kiểm tra. Đảm bảo bạn nhận xét các dòng có biến $ assignments được đặt.

Đây là mô hình truy cập mới của tôi:

<?php 

namespace app\models; 

use Yii; 

class Access 
{ 

public function canUser($type, $permissionName, $params = []) 
{ 

    $auth = Yii::$app->authManager; 

    switch ($type) { 

     case 'group': 

     $userID = Yii::$app->user->identity->id; 
     $groupID = Yii::$app->options->getOption('user', 'active_group_id'); 

     $queryAll = GroupAccess::find() 
     ->where('user_id = :user_id and group_id = :group_id', [':user_id' => $userID, ':group_id' => $groupID]) 
     ->asArray() 
     ->all(); 

     $assignments = []; 
     foreach ($queryAll as $queryItem) { 
      $assignments[$queryItem['item_name']] = [ 
      'userId' => $queryItem['user_id'], 
      'roleName' => $queryItem['item_name'], 
      'createdAt' => $queryItem['created_date'], 
      ]; 
     } 

     $result = $auth->checkAccess($userID, $permissionName, $assignments, $params); 

     return $result; 

     break; 

     case 'user': 

     $userID = Yii::$app->user->identity->id; 

     $queryAll = UserAccess::find() 
     ->where('user_id = :user_id', [':user_id' => $userID]) 
     ->asArray() 
     ->all(); 

     $assignments = []; 
     foreach ($queryAll as $queryItem) { 
      $assignments[$queryItem['item_name']] = [ 
      'userId' => $queryItem['user_id'], 
      'roleName' => $queryItem['item_name'], 
      'createdAt' => $queryItem['created_date'], 
      ]; 
     } 

     $result = $auth->checkAccess($userID, $permissionName, $assignments, $params); 

     return $result; 

     break; 

    } 

} 

public function assign($type, $role, $userID = null, $groupID = null) 
{ 

    switch ($type) { 

     case 'group': 

     // clear existing assigments 
     self::revoke('group', $userID, $groupID); 

     $groupAccess = new GroupAccess(); 
     $groupAccess->group_id = $groupID; 
     $groupAccess->user_id = $userID; 
     $groupAccess->item_name = $role; 
     $groupAccess->created_date = time(); 

     return $groupAccess->save(); 

     break; 

     case 'user': 

     // clear existing assignments 
     self::revoke('user', $userID); 

     $userAccess = new UserAccess(); 
     $userAccess->user_id = $userID; 
     $userAccess->item_name = $role; 
     $userAccess->created_date = time(); 

     return $userAccess->save(); 

     break; 

    } 

} 

public function revoke($type, $userID, $groupID = null) 
{ 

    switch ($type) { 

     case 'group': 

     GroupAccess::deleteAll('user_id = :user_id and group_id = :group_id', [':user_id' => $userID, ':group_id' => $groupID]); 

     break; 

     case 'user': 

     UserAccess::deleteAll('user_id = :user_id', [':user_id' => $userID]); 

     break; 

    } 

} 

} 

Và đây là chức năng checkAccess sửa đổi trong DbManager:

public function checkAccess($userId, $permissionName, $assignments, $params = []) 
{ 
    //$assignments = $this->getAssignments($userId); 
    $this->loadFromCache(); 
    if ($this->items !== null) { 
     return $this->checkAccessFromCache($userId, $permissionName, $params, $assignments); 
    } else { 
     return $this->checkAccessRecursive($userId, $permissionName, $params, $assignments); 
    } 
} 

Và đây là chức năng checkAccess sửa đổi trong ManagerInterface.php:

public function checkAccess($userId, $permissionName, $assignments, $params = []); 

Tôi không thay đổi $ items, checkAccessFromCache và checkAccessRecursiv các chức năng điện tử cho công chúng được bảo vệ.

Và đây là mô hình UserAccess tôi:

<?php 

namespace app\models; 

use Yii; 
use yii\db\ActiveRecord; 

/** 
* This is the model class for table "app_user_access". 
* 
* @property integer $id 
* @property integer $user_id 
* @property string $item_name 
* @property integer $created_date 
* 
* @property AppAuthItem $itemName 
* @property AppUsers $user 
*/ 
class UserAccess extends ActiveRecord 
{ 
/** 
* @inheritdoc 
*/ 
public static function tableName() 
{ 
    return 'app_user_access'; 
} 

/** 
* @inheritdoc 
*/ 
public function rules() 
{ 
    return [ 
     [['user_id', 'item_name', 'created_date'], 'required'], 
     [['user_id', 'created_date'], 'integer'], 
     [['item_name'], 'string', 'max' => 64] 
    ]; 
} 

/** 
* @inheritdoc 
*/ 
public function attributeLabels() 
{ 
    return [ 
     'id' => 'ID', 
     'user_id' => 'User ID', 
     'item_name' => 'Item Name', 
     'created_date' => 'Created Date', 
    ]; 
} 

/** 
* @return \yii\db\ActiveQuery 
*/ 
public function getItemName() 
{ 
    return $this->hasOne(AppAuthItem::className(), ['name' => 'item_name']); 
} 

/** 
* @return \yii\db\ActiveQuery 
*/ 
public function getUser() 
{ 
    return $this->hasOne(AppUsers::className(), ['id' => 'user_id']); 
} 
} 

Và đây là các Model GroupAccess:

<?php 

namespace app\models; 

use Yii; 
use yii\db\ActiveRecord; 

/** 
* This is the model class for table "app_group_access". 
* 
* @property integer $id 
* @property integer $group_id 
* @property integer $user_id 
* @property string $item_name 
* @property integer $created_date 
* 
* @property AppUsers $user 
* @property AppAuthItem $itemName 
* @property AppGroups $group 
*/ 
class GroupAccess extends ActiveRecord 
{ 
/** 
* @inheritdoc 
*/ 
public static function tableName() 
{ 
    return 'app_group_access'; 
} 

/** 
* @inheritdoc 
*/ 
public function rules() 
{ 
    return [ 
     [['group_id', 'user_id', 'item_name', 'created_date'], 'required'], 
     [['group_id', 'user_id', 'created_date'], 'integer'], 
     [['item_name'], 'string', 'max' => 64] 
    ]; 
} 

/** 
* @inheritdoc 
*/ 
public function attributeLabels() 
{ 
    return [ 
     'id' => 'ID', 
     'group_id' => 'Group ID', 
     'user_id' => 'User ID', 
     'item_name' => 'Item Name', 
     'created_date' => 'Created Date', 
    ]; 
} 

/** 
* @return \yii\db\ActiveQuery 
*/ 
public function getUser() 
{ 
    return $this->hasOne(AppUsers::className(), ['id' => 'user_id']); 
} 

/** 
* @return \yii\db\ActiveQuery 
*/ 
public function getItemName() 
{ 
    return $this->hasOne(AppAuthItem::className(), ['name' => 'item_name']); 
} 

/** 
* @return \yii\db\ActiveQuery 
*/ 
public function getGroup() 
{ 
    return $this->hasOne(AppGroups::className(), ['id' => 'group_id']); 
} 
} 

Và một lần nữa, một số mẫu hữu ích:

// assign group role 
Yii::$app->access->assign('group', 'group_creator', 24, 20); 
// assign user role 
Yii::$app->access->assign('user', 'app_user', 24); 

// revoke group 
Yii::$app->access->revoke('group', 22, 18); 
// revoke user 
Yii::$app->access->revoke('user', 22); 

// test user permission 
var_dump(Yii::$app->access->canUser('user', 'manage_app_settings')); 
// test the group permission 
var_dump(Yii::$app->access->canUser('group', 'manage_group_settings')); 
Các vấn đề liên quan