2016-03-22 50 views
1

後跟this guide我無法獲得「更新自己的記錄」類型的功能工作。這是我的。Yii2 AccessControl和RBAC更新自己的記錄

管理員和作者角色。作者擁有imageUpdateOwn權限,該權限在兒童時擁有imageUpdate權限。 imageUpdateOwn權限已將isOwner規則分配給它。所有其他相關/相關的代碼如下。

數據庫

database

OwnerRule.php

Image模型具有created_by屬性,它是記錄的所有者。

public function execute($user, $item, $params) 
{ 
    return isset($params['model']) ? $params['model']->created_by == $user : false; 
} 

ImageController.php AccessControl的

public function behaviors() 
{ 
    return [ 
     'access' => [ 
      'class' => AccessControl::className(), 
      'rules' => [ 
       [ 
        'allow' => true, 
        'actions' => ['update'], 
        'roles' => ['imageUpdate'], 
       ], 
       [ 
        'allow' => true, 
        'actions' => ['delete'], 
        'roles' => ['imageDelete'], 
       ], 
       [ 
        'allow' => true, 
        'actions' => ['index', 'view', 'create'], 
        'roles' => ['@'], 
       ], 
       [ 
        'allow' => false, 
       ], 
      ], 
     ], 
    ]; 
} 

ImageController.php行動

public function actionUpdate($id) 
{ 
    $model = $this->findModel($id); 

    if (\Yii::$app->user->can('imageUpdate', ['model' => $model])) { 
     if ($model->load(Yii::$app->request->post()) && $model->save()) { 
      return $this->redirect(['view', 'id' => $model->id]); 
     } else { 
      return $this->render('update', [ 
       'model' => $model, 
      ]); 
     } 
    } else { 
     throw new HttpException(403, 'You do not have permission to update this record.'); 
    } 
} 

在我的測試,我登錄的作者和上傳圖像1000然後登錄作爲管理員和上傳的圖像1001.在登錄時執行以下快速測試因爲每個用戶都會得到預期的結果。

$image1000 = \app\models\Image::findOne(1000); // author uploaded 
$image1001 = \app\models\Image::findOne(1001); // admin uploaded 

echo \Yii::$app->user->can('imageUpdate', ['model' => $image1000]) . "<br>"; 
echo \Yii::$app->user->can('imageUpdate', ['model' => $image1001]); 

當以管理員身份登錄時,每個echo語句都會得到「true」。以作者身份登錄時,我只對圖像1000獲得「true」。這告訴我授權正在按照我所創建的isOwner規則返回正確的權限。

但是,當我嘗試去更新操作時,我甚至無法通過訪問控制。我沒有獲得我在動作中指定的403錯誤(這是我期望的),而是得到了「不允許執行此操作」的通用錯誤。這似乎是因爲我已將默認訪問設置爲拒絕。如果我將默認訪問權限設置爲允許,我可以完成操作並獲得預期的403錯誤消息。這告訴我行動不允許我通過。

我不知道,如果imageUpdateOwn作用應在訪問控制上市而擁有它的存在並不那麼具有後者改變的結果(大概是因爲imageUpdateimageUpdateOwn孩子,筆者也將有前)。

上述內容中缺少的內容完全阻止我在以作者身份登錄時訪問更新操作?

編輯1

或許是因爲該模型沒有在訪問控制正在檢查的時間加載,CREATED_BY用戶不能進行評估。如果是這樣,我很困惑,因爲作者有imageUpdate通過imageUpdateOwn它應該允許訪問繼續。除非在與imageUpdateOwn相關的規則通過時它們僅獲得imageUpdate。在這種情況下,作者將永遠不會「獲得」與imageUpdate角色相關的訪問權限,直到可以對模型進行評估。這意味着我必須允許所有經過身份驗證的用戶訪問update操作,並且只有在模型加載後才檢查操作本身的權限。

回答

1

從進一步的測試和更多的研究,這裏是我發現的(希望有人可以確認)。

管理員角色直接分配到imageUpdate,並且能夠更新任何圖像。作者直接被分配到imageUpdateOwn,其中imageUpdate作爲一個孩子。雖然imageUpdate是分配權限的子項,但如果父項的規則阻止給定父項,則不會給出該項權限。基本上,如果imageUpdateOwn評估爲false(意味着作者用戶不是給定圖像的所有者),那麼作者也不會被授予imageUpdate的子權限。

作者角色沒有超過任何記錄的訪問控制的原因是因爲在評估訪問控制時,模型不可用。如果模型不可用,附加到imageUpdateOwn的規則將被評估爲假(如果您沒有該記錄,則無法檢查其所有者),這意味着其子imageUpdate權限也不會被給出。

解決方法是讓所有授權用戶通過訪問控制,然後檢查在行動本身的具體權限,如下列:

public function behaviors() 
{ 
    return [ 
     'access' => [ 
      'class' => AccessControl::className(), 
      'rules' => [ 
       [ 
        'allow' => true, 
        'roles' => ['@'], 
       ], 
      ], 
     ], 
    ]; 
} 
... 
public function actionUpdate($id) 
{ 
    $model = $this->findModel($id); 

    if (\Yii::$app->user->can('imageUpdate', ['model' => $model])) { 
     // Save the record and redirect the user 
    } else { 
     throw new HttpException(403, 'You do not have permission to update this record.'); 
    } 
} 

這確保了非認證用戶不得在任何地方附近的動作,而認證用戶必須具有以下一項:

  1. imageUpdate權限(分配給管理員角色)。
  2. imageUpdateOwn權限(分配給作者角色)如果isOwner規則計算結果爲true(如果我們有模式,使車主可以檢查只能評價爲真),這將給imageUpdate許可。