10

オブジェクトごとのアクセス許可を管理するために、django-guardianを使用しています。

特定のユーザーに対して、1 つのオブジェクトに対するすべてのアクセス許可を与えます。

joe = User.objects.get(username="joe")

mytask = Task.objects.get(pk=1)

assign('add_task', joe, mytask)
assign('change_task', joe, mytask)
assign('delete_task', joe, mytask)

期待どおり、次のようになります。

In [57]: joe.has_perm("add_task", mytask)
Out[57]: True

In [58]: joe.has_perm("change_task", mytask)
Out[58]: True

In [59]: joe.has_perm("delete_task", mytask)
Out[59]: True

admin.py では、TaskAdmin をGuardedModelAdmin代わりに継承させます。admin.ModelAdmin

joe で自分のサイトに接続すると、admin で次のようになります。

You don't have permission to edit anything 

オブジェクト mytask を編集できないのでしょうか?

組み込みのモデルベースのアクセス許可システムを使用していくつかのアクセス許可を設定する必要がありますか?

何か不足していますか?

編集

user_can_access_owned_objects_only私の問題に対処するはずのオプションを追加しようとしましたが、まだ管理画面に何も表示されません...

class TaskAdmin(GuardedModelAdmin):

    user_can_access_owned_objects_only = True

    pass

admin.site.register(Task, TaskAdmin)

ありがとうございました

4

2 に答える 2

4

現在のユーザーが所有するインスタンスのみを表示するために、すべての権限を彼に与えます

add_task=Permission.objects.get(codename="add_task")
change_task=Permission.objects.get(codename="change_task")
delete_task=Permission.objects.get(codename="delete_task")

joe.user_permissions.add(add_task)
joe.user_permissions.add(change_task)
joe.user_permissions.add(delete_task)

次に、guardian.shortcuts.assign を使用していくつかのインスタンスにアクセス許可を設定し、管理者でクエリセットをフィルター処理します。

class TaskAdmin(admin.ModelAdmin):

    def queryset(self, request):
            if request.user.is_superuser:
                return super(TaskAdmin, self).queryset(request)
            return get_objects_for_user(user=request.user, perms=['add_task', 'change_task', 'delete_task'], klass=Task)

完璧にはほど遠いですが、他に解決策が見つかりません。

于 2012-06-07T16:41:55.910 に答える
4

Django Admin は、特にchangeパーミッションを扱う部分が少し粗いです。内部メソッドは、実際には不足している許可ModelAdmin.has_change_permission()のチェックをカバーしています。view

第 2 に、行レベルのパーミッションを管理するためのGuardedModelAdmin所有権チェック ( を介して) とフォームが提供されます。user_can_access_owned_objects_onlyDjango 管理者に他の行レベルのアクセス ポリシーは提供しません。

Django Admin の典型的な行レベルのパーミッション シーンについて、コードを提案したいと思います。ここでは、オプションの「表示」パーミッションを導入しました。

class ExtendedGuardedModelAdmin(GuardedModelAdmin):
    def queryset(self, request):
        qs = super(ExtendedGuardedModelAdmin, self).queryset(request)
        # Check global permission
        if super(ExtendedGuardedModelAdmin, self).has_change_permission(request) \
            or (not self.list_editable and self.has_view_permission(request)):
                return qs
        # No global, filter by row-level permissions. also use view permission if the changelist is not editable
        if self.list_editable:
            return get_objects_for_user(request.user, [self.opts.get_change_permission()], qs)
        else:
            return get_objects_for_user(request.user, [self.opts.get_change_permission(), self.get_view_permission(
)], qs, any_perm=True)

    def has_change_permission(self, request, obj=None):
        if super(ExtendedGuardedModelAdmin, self).has_change_permission(request, obj):
            return True
        if obj is None:
            # Here check global 'view' permission or if there is any changeable items
            return self.has_view_permission(request) or self.queryset(request).exists()
        else:
            # Row-level checking
            return request.user.has_perm(self.opts.get_change_permission(), obj)

    def get_view_permission(self):
        return 'view_%s' % self.opts.object_name.lower()

    def has_view_permission(self, request, obj=None):
        return request.user.has_perm(self.opts.app_label + '.' + self.get_view_permission(), obj)

    def has_delete_permission(self, request, obj=None):
        return super(ExtendedGuardedModelAdmin, self).has_delete_permission(request, obj) \
                or (obj is not None and request.user.has_perm(self.opts.get_delete_permission(), obj))

このようにして、より柔軟な権限チェックを実現できます。user-permissions はグローバルになり、user-obj-permissions は行レベル ベースになります。

  • joe.user_permissions.add(add_task)
    joe は新しいタスクを追加できます (行レベルの「追加」権限はありません)
  • joe.user_permissions.add(change_task)
    ジョーはすべてのタスクを変更できる
  • joe.user_permissions.add(delete_task)
    ジョーはすべてのタスクを削除できます
  • assign(Task._meta.get_change_permission(), joe, obj)
    joe は Task obj を変更できます。obj と他の変更可能なタスクを含む変更リストを参照してください。
  • assign(Task._meta.get_delete_permission(), joe, obj)
    joe は Task obj を削除できます
  • assign('view_task', joe, obj)
    [オプション] joe はタスク obj を表示できます (カスタマイズされた管理者ビュー ページでこの権限を確認することをお勧めします)
  • joe.user_permissions.add(Permission.objects.get(codename='view_task', ...))
    [オプション]変更リストがインライン編集可能でない限り、joe は変更リスト内のすべてのタスクを表示できます。これは、joe が変更許可なしで raw_id_fields からアイテムを取得できる場合に便利です。
  • ...

役に立たない場合は、「表示」権限を安全に無視できます。

現在、django.contrib.admin.util.get_deleted_objectsパーミッションのチェック中に obj を尊重しません。削除中に行レベルのパーミッションをチェックする必要がある場合は、行を にget_deleted_objects変更してパッチを適用します。相対チケットは13539 & 16862 ですif not user.has_perm(p):if not user.has_perm(p, obj):

于 2012-07-11T13:43:31.440 に答える