3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

djangoのpermissionについてまとめる

Posted at

Permissionとは

Permissionとはdjangoアプリケーションに実装されている概念であり、ユーザーの行動に制限をかけるために用いられる。

例えばdjangoアプリの管理者サイトへのログインはsuperuserでないとできないが、これはsuperuserにis_staffというpermissionが付与されていることによる(逆に言えばこの権限さえ与えてしまえばどのユーザーでも管理者サイトに入れるようになる)。

permissionは管理者サイトのような組み込みのシステムだけでなく、アプリケーション内に実装した機能の利用に制限をかける際にも使用可能。

アプリの独自機能に制限をかける場合にはMixinを用います。
そちらについては以下の記事をどうぞ。

Permissionの付与の仕組み

Permissionの付与の仕方には、ユーザーに直接付与する方法とあるグループを作ってそこに付与し、そのグループにユーザーを追加するという方法の2種類がある。

また、Permissionの実態はauth_permissionというテーブルのレコードであり、ユーザー及びグループにPermissionが付与されているのかどうかは、アプリ名_customuser_user_permissionsテーブルとauth_group_permissionsテーブルという二つの中間テーブルによって管理されている。

具体的なpermission操作のコードは以下の通り。

# "Can Change Item"というpermissionの付与・剥奪を行う場合。
permission = Permission.objects.get(name="Can change Item")

# ユーザーにpermissionを付与
user.user_permissions.add(permission)

# 以下の書き方でも可
user.user_permissions.set([permission])

# permissionの剥奪
user.user_permissions.remove(permission)

# permissionの全権剥奪
user.user_permission.clear()

# groupの場合は以下のように対応(add以外についてもuserと同様)
group.permissions.add(permission)

# ユーザーとグループの紐付けも同じようにして行う
user1.groups.add(group1)

# 以下でも同じ内容
group1.users.add(user1)

auth_permissionテーブルについて

スキーマ及びレコードについては以下の通り(レコードは一部を抜粋しています)。

sqlite> .schema auth_permission
CREATE TABLE IF NOT EXISTS "auth_permission" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "content_type_id" integer NOT NULL REFERENCES "django_content_type" ("id") DEFERRABLE INITIALLY DEFERRED, "codename" varchar(100) NOT NULL, "name" varchar(255) NOT NULL);
CREATE UNIQUE INDEX "auth_permission_content_type_id_codename_01ab375a_uniq" ON "auth_permission" ("content_type_id", "codename");
CREATE INDEX "auth_permission_content_type_id_2f476e4b" ON "auth_permission" ("content_type_id");
sqlite> select * from auth_permission;
1|1|add_logentry|Can add log entry
2|1|change_logentry|Can change log entry
3|1|delete_logentry|Can delete log entry
4|1|view_logentry|Can view log entry
5|2|add_permission|Can add permission
6|2|change_permission|Can change permission
7|2|delete_permission|Can delete permission
8|2|view_permission|Can view permission
# ...中略...
29|8|add_emailaddress|Can add email address
30|8|change_emailaddress|Can change email address
31|8|delete_emailaddress|Can delete email address
32|8|view_emailaddress|Can view email address
# ...中略...
49|13|add_subject|Can add subject
50|13|change_subject|Can change subject
51|13|delete_subject|Can delete subject
52|13|view_subject|Can view subject

permissionレコードのcondename(左から3番目のカラム)については操作名(add, changeなど)操作対象(emailやpermissionなど)を組み合わせたものになっている。

ほとんどは初回のマイグレーション時に作成されるほか、新たなモデルを定義した場合にはそれに合わせたpermissionも追加される(上記例の末尾にあるxxx_subjectpermissionはsubjectモデルの追加に伴って作成されたもの)。

なお、上記例のadd_subjectpermissionを例にとると、このpermissionがなければsubjectモデルのインスタンスを追加できないという意味ではない。

permissionを用いて特定の操作に対して制限をかけたい場合には、PermissionRequiredMixinを用いて必要なpermissionを指定する必要がある。

あくまでその際にわかりやすいように、djangoの側で組み込みのpermissionが用意されているという理解で問題ない。

PermissionRequiredMixinにおけるpermissionの指定方法

PermissionRequiredMixinにおいてpermission_requiredという属性値を用いて必要なpermissionを指定する場合には、対象permissionのcontent_typeのapp_label.対象permissionのcodenameという形式を用いる。
例えば上記のid=52のpermissionを指定したい場合には、app_labelはsubject, codenameはview_subjectなので以下のようになる。

Mixinを用いたpermissionの指定の例
class TestView(PermissionRequiredMixin, TemplateView):
  permission_required = ["subject.view_subject"]

というのが厳密な定義らしいですが、content_typeのapp_labelは基本的にそのモデルを定義しているアプリケーション名という認識で大丈夫そうです。

不安であれば、django_content_typeというテーブルから確認可能です。

sqlite> .schema django_content_type
CREATE TABLE IF NOT EXISTS "django_content_type" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "app_label" varchar(100) NOT NULL, "model" varchar(100) NOT NULL);
CREATE UNIQUE INDEX "django_content_type_app_label_model_76bd3d3b_uniq" ON "django_content_type" ("app_label", "model");
sqlite> select * from django_content_type
   ...> ;
1|admin|logentry
2|auth|permission
3|auth|group
4|contenttypes|contenttype
5|sessions|session
6|user|customuser
7|sites|site
8|account|emailaddress
9|account|emailconfirmation
10|socialaccount|socialaccount
11|socialaccount|socialapp
12|socialaccount|socialtoken
13|subject|subject

例えばcodename=view_subjectのpermissionはcontent_type_id(左から2番目のカラム)の値が13なのでdjango_content_typeテーブルのid=13のレコードを確認すると、app_label(左から2番目のカラム)subjectとなっています。

終わりに

Permissionについてはとりあえずはここまでにします。

必要があれば随時追加していきます。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?