![](/img/trans.png)
[英]Delete and DeleteAll action override in yii2 ActiveController
[英]Yii2 - Override checkAccess in rest ActiveController
Product.supplierID = Supplier.supplierID
--------- ----------
|Product|---------|Supplier|
--------- ----------
|
| Supplier.supplierID = User.supplierID
|
---------
| User |
---------
使用上面的表結構,應用程序使用ActiveController
子類,並使用重寫的prepareDataProvider
來限制登錄的每個Product
的index
列表User
可以看到具有匹配的supplierID
值的那些。 在ProductController
的actions()
方法中有類似的東西。
$actions['index']['prepareDataProvider'] = function($action)
{
$query = Product::find();
if (Yii::$app->user->can('supplier') &&
Yii::$app->user->identity->supplierID) {
$query->andWhere(['supplierID' => Yii::$app->user->identity->supplierID]);
}
return new ActiveDataProvider(['query' => $query]);
};
這工作正常,但我希望使用checkAccess()
來限制單個Product
actionView()
。
目前,登錄User
可以通過更改URL中的productID
來訪問Product
,無論是否具有相應的supplierID
。
看起來我無法訪問Product
的特定實例,檢查supplierID
,直到actionView()
返回,這是我希望檢查發生的時間。
我可以覆蓋checkAccess()
來限制訪問並拋出適當的ForbiddenHttpException
嗎?
如何檢查模型是否存在:
protected function modelExist($id)
{
return Product::find()
->where([ 'productID' => $id ])
->andWhere(['supplierID' => Yii::$app->user->identity->supplierID ])
->exists();
}
如果productID
是您的產品主鍵,那么對/products/1
的請求將由yii \\ rest \\ UrlRule翻譯為/products?productID=1
。
在這種情況下,當productID
作為參數提供時,您可以使用beforeAction
快速檢查是否存在此類模型並執行操作或如果不執行則拋出錯誤:
// this array will hold actions to which you want to perform a check
public $checkAccessToActions = ['view','update','delete'];
public function beforeAction($action) {
if (!parent::beforeAction($action)) return false;
$params = Yii::$app->request->queryParams;
if (isset($params['productID']) {
foreach ($this->checkAccessToActions as $action) {
if ($this->action->id === $action) {
if ($this->modelExist($params['productID']) === false)
throw new NotFoundHttpException("Object not found");
}
}
}
return true;
}
由於問題是關於覆蓋休息ActiveController中的checkAccess方法,我認為留下一個例子會很有用。
在設計Yii2 REST的方式中,所有delete
, update
和view
操作都會在加載模型實例后調用checkAccess
方法:
// code snippet from yii\rest\ViewAction
$model = $this->findModel($id);
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id, $model);
}
對於create
和index
操作也是如此,除了它們不會將任何模型實例傳遞給它: call_user_func($this->checkAccess, $this->id)
。
因此,您嘗試做的事情( 當用戶試圖查看,更新或刪除他不是供應商的產品時拋出ForbiddenHttpException )也可以通過以下方式實現:
public function checkAccess($action, $model = null, $params = [])
{
if ($action === 'view' or $action === 'update' or $action === 'delete')
{
if ( Yii::$app->user->can('supplier') === false
or Yii::$app->user->identity->supplierID === null
or $model->supplierID !== \Yii::$app->user->identity->supplierID )
{
throw new \yii\web\ForbiddenHttpException('You can\'t '.$action.' this product.');
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.