Djangoで組織とユーザーの権限の管理をやってみる #devio2022

ひょんなことからDjangoでWebアプリケーション開発をすることになったのですが、組織とユーザーの管理をどうやるか情報があまりなく結構ハマったので、その試行錯誤の備忘録です。
2022.07.31

クラスメソッドオンラインイベントDevelopersIO 2022で「Djangoで組織とユーザーの権限の管理をやってみる」というテーマで話した内容をご紹介します。

動画

スライド

GitHub

https://github.com/seiichi1101/devio2022

概要

やりたいこと

  • ユーザーの登録ができる
  • 組織の登録ができる
  • ユーザーは複数の組織に所属することができる
  • ユーザーは所属外の組織情報にはアクセスできない
  • ユーザーは所属する組織毎に権限を与えられる
  • 権限は Admin、Editor、Viewer のいずれかとする
  • 権限に応じたアクセス制御が可能とする

ERD

セットアップ

GitHubのブランチを参考にしてください。

ユーザーと組織の権限管理について

「ユーザーと組織の権限管理」についてどういったアプローチがあるのか考察

モデル設計

Djangoでユーザーと組織の権限を権限管理するにはいくつかパターンが考えられます。

1. 組み込みのGroupとPermissionsを利用する方法

まず1つ目が組み込みで用意されているGroupPermissionsモデルをそのまま利用する方法です。Django Permissions

Djangoでは、django.contrib.authINSTALLED_APPS設定にリストされていると、定義された各Djangoモデルに対して、add, change, delete, viewという4つの デフォルトパーミッションを作成してくれます。

このPermissionsUserGroupに割り当てることができ、Djangoの権限管理に利用できます。

これをそのまま利用できそうに思えますが、今回のような組織の中に複数の権限グループ[Admin, Editor, Viewer]があり権限グループにユーザーを割り当てるということはデフォルトパーミッションでは実現できません。

仮にやる場合は、GroupもしくはPermissionsモデルを拡張する必要があります。

テーブル数が増えず複雑になりにくいですが、Djangoがそもそも期待している使い方と異なるため少し面倒です。

2. 3rd Partyのライブラリを利用する方法

2つ目が、3rd Partyのライブラリを利用する方法です。

django-organizationというライブラリを使えば、組織管理者の作成や組織への招待など色々な機能が提供されています。

一方で、必要以上の機能があることで混乱したり、今回のような複数の権限グループを作成したい場合にはいずれにせよカスタマイズが必要になります。

3. 自分で必要なモデルと機能を実装する方法

3つ目が、自分でモデルを作成する方法です。 具体的にはER図に記載しているOrganization, Group, Roleのモデルを自作する方法です。

必要な機能を自分で実装することで、必要以上に複雑にならず、モデルの拡張もしやすくなります。

懸念点としては、コード量やテーブル数が増えたり、組み込みモデルとの使い分けを明確にする必要があり、管理が手間が増えます。

1,2は冒頭に紹介した要件にフィットしなかったため、今回は3つ目の方法を使います。

ライブラリを使った権限管理

次に、Djangoで権限管理をするパターンをいくつか紹介します。 前述でも説明した通り、権限管理には既存のGroupPermissionsを利用する方法がありますが、今回は既存のモデルは利用しないため別の方法を考えます。

Djangoでは権限管理のため有名なライブラリがいくつか存在するため、今回はそちらのいずれかを利用したいと思います。

3-1. django-guardian

1つ目がdjango-guardianです。

こちらのライブラリでは、既存のPermissionsを拡張することでインスタンスレベルでのアクセス制御する提供しています。

Group毎に権限を与えることはできますが、[Admin、Editor、Viewer]みたいな汎用的な権限のまとまりを設定することはできず、都度Permissionsを付与する必要があるため、複数組織にまたがって同じような権限を設定する際には少し面倒です。

3-2. django-role-permissions

2つ目がdjango-role-permissionsです。

こちらも前述のdjango-organizationとおなじく、既存のPermissionsを拡張することでインスタンスレベルでのアクセス制御を提供しています。

が、同じく組織にまたがった汎用的な権限のまとまりを設定することは難しいです。

3-3. django-rules

3つ目が、django-rulesです。

前述の2つとの違いは、権限の管理にデータベースモデルを使用しない点です。

事前に定義したコードをベースにアクセスコントロールを設定できるため、カスタマイズしやすく、今回のような汎用的な権限のまとまりを設定することも可能です。

ただ、既存のPermissionsモデルを利用しないため、コード量は増えます。

今回は権限グループのまとまりをうまく表現出来そうなdjango-rulesを採用します。

ユーザーと組織の実装

GitHubのブランチを参考にしてください。

権限の実装

GitHubのブランチを参考にしてください。

まとめ

いかかでしょうか。

どなたかの役に立てば幸いです。

また、もし他にいい方法を知っている方いれば是非教えてほしいです。