2018.12.6
団体用集金システムを作りたい!#15【ゲートとポリシー】
ぱぱっと作るだけなら簡単なのですが、便利な機能は勉強して使えるようにしておきましょう、ということで今回は
ゲートとポリシーに手を出していきたいなって思います。
まぁこれは何かっていうと、アクセス制御の話ですね。権限のないユーザーにアクセスを許可しませんってやつですね。
試行錯誤の末、やっと言いたいことがわかってきたので実装に移してみたいと思います。
今回実装するのは、
自分が所属する団体以外のページに対してのアクセスを拒否というのを、なるべくロジックに組み込まない形で実装したいというオーダーです。
理想はルーティングで行うことなんですが、ユーザーインスタンス以外を受け取る手段がなさそうなので、コントローラーにて
ポリシーという形で実装するのがよいのかな、という結論に達しました。
URLパラメータを受け取れればゲートで処理できそうなんですけど、無理そうなので・・・・・・。めちゃくちゃな手段を講じればできると思うんですけど、可読性が落ちるしバグりそうなのでやめときます。
いや、共通のクロージャをもたせて、遷移先をifで人力でどうこうする、っていう手段を思いついたんですけど、まぁ現実的ではないというか。
と、いう話を書いたところで
なぜかゲートが動いたのでやっぱりその話をしたいと思います笑
Route::middleware(['auth'])->group(function () {
Route::name('org.')->group(function () {
Route::prefix('org')->group(function () {
Route::get('/create', 'OrgController@createForm')->name('createForm');
Route::post('/createExe', 'OrgController@createExe')->name('createExe');
Route::middleware("can:org-view,org")->group(function () {
Route::get('/{org}/index', 'OrgController@index')->name('index')->where('org', '[0-9]+');
});
});
});
});
まずルーティングですが、こんな無茶苦茶な構造になってます(笑)ネスト深すぎますがどうしたらいいのかわかりません笑
重要なのは最後の
middlewareの部分ですね。
ここで、
can:org-viewという条件を指定してて、さらに
orgという変数を渡してる?チックです。
ぶっちゃけこの辺よくわかんないです
ちなみに、基本的にはこのカンマの後は文字列として渡されてるっぽいんですけど、その後の処理によってこの文字列が解析されてるんですかね。とりあえずこれで動いてるのでこれはこれで良しとします。
で、次にコントローラーですね。
public function index(Org $org){
return view("org.index",["org"=>$org]);
}
ここでOrgインスタンスを受け取っていますが、この変数名のorgを、先程ミドルウェアの引数(?)として指定したorgと一致させるのが肝のようですね。
ちなみに、こうやってコントローラーメソッドにいきなりインスタンスを代入してくれる機能、さっき初めて知ったんですけどめちゃんこ便利ですね・・・・・・。
さきほどのルーティングのorgの部分にIDが入るんですが、そこからいい感じに取ってきてくれるみたいです。かしこすぎる・・・・・・。
では、つぎにミドルウェアの実体ですね。
namespace App\Policies;
use App\User;
use App\Org;
use Illuminate\Auth\Access\HandlesAuthorization;
class OrgPolicy
{
use HandlesAuthorization;
public function before($user, $ability){
if ($user->isSuperAdmin()) {
return true;
}
return null;
}
public function view(User $user, Org $org)
{
return $user->is_belonging($org);
}
}
まあざっとこんな感じですかね。ポリシーの根幹部分はartisanが生成してくれます。
今回はviewというのを定義してみました。閲覧専用ですね。自分の所属しているグループ、もしくはメタ権限がある管理者・・・・・・つまり僕のことなんですが、特別な権限を持っていればbeforeメソッドにより特別に認可される、みたいな感じになってます。
こんな感じにアクセスを統御できるので、いくぶんかコードが書きやすくなったと思われます。
んじゃ、これを元にばばーっと作っちゃいましょうねえ。