私が答えているのが、最も乾燥した、ほぼ脱水状態の最善のアプローチであるかどうかはわかりませんが、私が考えることができる最も単純なことです.
Project モデルで、ユーザーに関連付けられたプロジェクト ID の配列を返す関数を作成します。
class Project extends AppModel {
public function getByUserId($userId) {
$projectsArray = array();
if ($userId != "valid")
//do all the checks, if it's not null, numeric, if the id exists, etc
$projects = $this->Project->find('all', array('conditions'=>
array('user_id'=>$userId)));
if (!empty($projects)) {
foreach($projects as $i => $project)
$projectsArray[] = $project['Project']['id'];
}
return $projectsArray;
}
}
コメントでa に言及しfind('first')
ていますが、最初のプロジェクトだけでなく、ユーザーに関連するすべてのプロジェクトが必要であると想定しています。そうでない場合は、その関数の単純な変更です。また、IDを取得しているだけですが、$id=>$name_project
配列が必要な場合があります。
さて、「アクションの実行のみが許可されている」とはどういう意味かわかりませんが、制限されているのは編集だけですか? または、プロジェクトがユーザーのものでない場合、リストまたはビューを制限し、ユーザーに表示しないようにする必要がありますか?
最初のケースでは、編集を制限し、変更しbeforeSave
ます。
public function beforeSave($options = array()) {
if(!$this->id && !isset($this->data[$this->alias][$this->primaryKey])) {
//INSERT
//not doing anything
} else {
//UPDATE
//check if project inside allowed projects array
$allowed = $this->getByUserId(CakeSession::read("Auth.User.id"));
if (!in_array($this->id, $allowed))
return false; //or throw error and catch it in the controller
}
return true;
}
コードはテストされていませんが、一般的には、レコードの更新の直前に「ユーザーの」プロジェクトではないプロジェクトの編集を防ぎます。新しいプロジェクトの挿入は誰にとっても無料だと思います。この投稿によると、このフィルターを除くすべての保存関数saveAll
は最初にこのフィルターを通過するため、saveAll
関数を上書きし、のような検証を追加する必要がありますbeforeSave
(そこの回答で説明されているように)。
そして 2 番目の部分では、ユーザーが自分のプロジェクトではなく他のプロジェクトがあることに気付かないように結果をフィルタリングしますbeforeFind
。ドキュメントは、ユーザーの役割に基づいて結果を制限することについて話しているので、私たちは正しい方向に進んでいると思います.
public function beforeFind($queryData) {
//force the condition
$allowed = $this->getByUserId(CakeSession::read("Auth.User.id"));
$queryData['conditions'][$this->alias.'.user_id'] = $allowed;
return $queryData;
}
$allowed
配列には id 値しかないため、句のように機能IN
しますが、その配列構造を変更する場合は、それに応じてこれらの関数を変更してください。
以上です。ここでは、より基本的なケース、編集、表示、削除について考えています...アップ、削除...beforeDelete
機能も変更して、他のプロパティを削除したい悪意のあるユーザーを回避します。ロジックは同じままです (プロジェクト ID が許可された配列にあるかどうかを確認し、そうでない場合は false を返すか、エラーをスローします)、その関数の例をここに追加しません。しかし、それは基本的なことです。何らかの理由で許可されたプロジェクトをコントローラーに入れたい場合は、getByUserId
関数を呼び出して、beforeFilter
そこでその ids 配列を処理します。セッションに保存することもできますが、プロジェクトを追加または削除するときにそのセッションを維持する必要があります。
すべてを表示および編集できるスーパー管理者が必要な場合getByUserId
は、ユーザーのロールをチェックする条件を に追加するだけで、それが管理者の場合はすべてのプロジェクトを返します。
また、心に留めておいてください: プロジェクトには多くの...サブプロジェクトがある可能性があります (想像力はあまりありません)。そのため、プロジェクトに関連するユーザーはサブプロジェクトを追加できますが、以前と同じ悪意のあるユーザーが、サブプロジェクトが持つ隠し project_id を変更して編集します。 . その場合、サブプロジェクトに検証を追加して、彼のものではないプロジェクトに関連するモデルに対するアクションを回避することをお勧めします。セキュリティ コンポーネントが適切に配置されていて、フォームから編集および削除アクションに到達できる場合、セキュリティ コンポーネントを適切に使用するとフォームの改ざんが回避されるため、これは些細なことです。ただし、「サブプロジェクト」インスタンスも検証する必要があるかどうかを検討してください。
Ayo Akinyemiが述べたように、これらすべてを動作として使用できます。私は個人的にそうしていませんが、要件を満たしています。ここで変更されたすべてのコールバックは、動作で変更したものです。ロジック、列名 (ハードコードされていない変数である必要がありますuser_id
) などをカプセル化する必要がありますが、他のケーキプロジェクトで再利用できます。StrongBelongBehavior
またはのようなものMoreDRYBehavior
。そして、あなたがそれをしたらそれを共有してください:)
Auth コンポーネントにあなたが望むことを行う方法があるかどうかはわかりませんが、それが最良の選択肢だと思います。誰かが私を啓発するまで (私はこの問題をあまり調査していません)、これが私が使用する解決策です。