社内でタイトルのような相談を受け、調査を行いました。PowerCMS Xで以下のようにロールを設定してAさん(ユーザーID: 3)に権限設定しているとします。
- 記事の全てのリスト
- 記事のリビジョン管理
- 記事の有効化(公開)
この状況で、管理者の記事(ID: 4308)だけをAさんに編集させたい、という特殊な要望です。これはcan_do
コールバックで操作すると実現できました。
config.jsonでentryモデルの場合にcan_doコールバックの処理が実行されるようにします。
{
"label": "CustomCanDo",
"id": "customcando",
"component": "CustomCanDo",
"description": "",
"version": "0.1",
"author": "",
"author_link": "",
"callbacks": {
"test_can_do": {
"entry": {
"can_do": {
"component": "CustomCanDo",
"priority": 10,
"method": "custom_can_do"
}
}
}
}
}
プラグインのPHPファイル(この例ではCustomCanDo.php)に以下のような記述をします。記事(ID: 4308)の時だけ$cb['can_do']
をtrue
にすると、記事の編集が可能となり、記事編集画面へのリンクも生きた状態になります。
<?php
require_once LIB_DIR . 'Prototype' . DS . 'class.PTPlugin.php';
class CustomCanDo extends PTPlugin {
function custom_can_do( &$cb, $app, $obj ) {
$user = $cb['user'];
$model = $cb['model'];
$object_id = $obj ? (int) $obj->id : (int) $app->param('id');
if ($model === 'entry' && (int) $user->id === 3) {
$target_object_id = 4308; // 記事IDを指定する
if ($object_id === $target_object_id) {
// 記事の編集
$cb['can_do'] = true;
} elseif (
in_array($cb['action'], ['list', 'edit', 'duplicate', 'revision'])
&& (
(int) $app->param('rev_object_id') === $target_object_id
|| (int) $obj->rev_object_id === $target_object_id
)
) {
// 記事編集ページでリビジョンの一覧表示
$cb['can_do'] = true;
} elseif ($cb['action'] === 'edit' && $app->param('edit_revision')) {
$rev_object_id = (int) $obj->rev_object_id;
if ($rev_object_id === $target_object_id) {
// リビジョンの編集
$cb['can_do'] = true;
}
}
}
}
}
この基本操作を踏まえてカスタマイズを実施すれば、特殊な権限の適用が可能になるかもしれません。(できると言い切れないのは、ワークフローとの併用は難しそうなど様々な条件が絡んでくるためです。)あらゆる場面でcan_do
メソッドによる権限チェックが走るので、そこでtrue
/ false
を変更すれば規定の操作可否判定を上書きできるのが本記事の要点です。
豆知識
例えば記事に担当(in_charge)カラムを作成しユーザーIDを数値で保存できるようにしておけば、プラグインのPHPファイルでは$obj->in_charge
で担当カラムの値が取得できます。よって、以下のような記述をすると現在のユーザーが担当カラムに指定されている時のみ編集可能にすることが可能なようです。
if ($model === 'entry') {
if ((int) $user->id === (int) $obj->in_charge) {
$cb['can_do'] = true;
}
}