web-dev-qa-db-ja.com

Djangoロールベースのビュー?

他の人がこれをどのように設計するかについてのいくつかのインプットを探しています。クラス(Djangoグループ)ベースのビューを提供します。

たとえば、ユーザーのグループは、ユーザーがアクセスできるビュー/テンプレートを決定します。ユーザーのリンクバーが何で構成されるかを決定するために、関数を表示するためのパスをテーブルに格納することを考えています。フィルタ仕様を保存して、これらのテンプレートを埋める行を決定することもできます。

良い例は病院の看護ユニットです。 1つのユニットの看護師は、病院全体の患者を診察する必要はありません。彼らは彼らの患者に会う必要があるだけです。同じユニットの医師は、それらの患者も診察する必要がありますが、はるかに優れた機能にアクセスできる必要があります。

これはサードパーティのアプリケーションを介して行われましたか?そして、この問題にどのようにアプローチしますか?

ありがとう、ピート

30
slypete

Djangoにはすでにグループと権限システムがあり、これで十分な場合があります。

http://docs.djangoproject.com/en/dev/topics/auth/

通常、コードでは、ユーザーに権限があるかどうかを確認します。ユーザーには、自分自身の権限と、自分が属するグループの権限があります。これは、管理コンソールから非常に簡単に管理できます。

あなたが見る必要がある2つの部分があります。

  1. ページをリクエストしているユーザーにそうする権限があることを確認してください。
  2. ユーザーが権限を持っている場合にのみ、ユーザーへのリンクを表示します。

1.の場合、デコレータの権限を次のように確認できます。

from Django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def some_view(request):

2.の場合、現在ログインしているユーザーの権限は、テンプレート変数{{perms}}に保存されます。このコードは、上記と同じ権限をチェックします。

{% if perms.polls.can_vote %}
    <a href="/vote">vote</a>
{% endif %}

リンクのリストを生成するには、user.get_all_permissions()を反復処理し、dictからリンク(またはリンクを生成する関数)をフェッチします。

def more_elaborate_list_of_links_for_a_perm(user):
    return ["/link1", ...]

_LINKS = {
    'polls.can_vote' : lambda u: ["/user/specific/link/" + u.id],
    'polls.can_close': lambda u: ['/static/link/1', 'static/link/2'],
    'polls.can_open' : more_elaborate_list_of_links_for_a_perm
}

def gen_links(user):
    # get_all_permissions also gets permissions for users groups
    perms = user.get_all_permissions()
    return sum((_LINKS[p](user) for p in perms if p in _LINKS), [])

おそらく他にも多くのアプローチがあります。

43
mbarkhau

Djangoのロールベースのアクセス許可に関する新しい非常に興味深いプロジェクトがあります: http://bitbucket.org/nabucosound/Django-rbac

5
jujule

同様の問題がありました。 Djangoのグループはこれに本当に適しているわけではありませんが、靴べらを入れることはできます。

私たちがそれをした方法は次のとおりでした:

すべてのアクセス制御オブジェクトには、グループテーブルとのManyToMany関係があります。各グループは、特定のタイプの許可(「患者の基本を表示できる」、「患者の連絡先情報を編集できる」など)を定義するために使用されました。ユーザーは、許可が必要なグループに追加されます(この病院の患者のみを表示する例では、「valley-view-hospital」グループを作成できます)。

次に、レコードのリストをユーザーに表示するときに、2つのグループの結合に基づいてフィルタリングします。特定のオブジェクトを表示するには、ユーザーは関連するすべてのグループ権限を持っている必要があります。

システムで必要な場合は、個別のManyToManyの負の権限、または個別の読み取り/書き込み権限を保持できます。ルックアップフィルターがアクセス許可の実際のサブセットを取得する結果となるメタグループのセット(医師、看護師)を定義することもできます。

リンクバーの問題に関する限り、同じシステムを使用してプログラムでそれらを生成できます。ユーザーが表示または編集できるオブジェクトのクラスに基づいてフィルターをかけ、get_absolute_url()タイプの関数を使用します(おそらくオブジェクトの各クラスのインデックスへのリンクを返すのはget_index_url())です。

これはすべてかなり複雑なので、おそらくこれらのことに対してある程度のキャッシュを実行したいと思うでしょうが、最適化する前にそれを機能させてください。それは可能であり、コードでは言葉よりも醜いものではありません。

4
Paul McMillan

私は少し前に同様の問題を抱えていました。私たちのソリューションはうまくいきましたが、あなたの状況には単純すぎるかもしれません。誰もが示唆しているように、Djangoパーミッションシステムを使用して、モデルとのユーザーインタラクションを制御しました。ただし、ユーザーをグループ化するだけでなく、GenericForeignKeyを使用してオブジェクトをグループ化しました。

階層を開発できるように、それ自体にリンクするモデルを構築しました。

class Group( models.Model ):
    name = models.CharField( ... )
    parent = models.ForeignKey( 'self', blank=True, null=True)
    content_type = models.ForeignKey( ContentType )
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey( 'content_type', 'object_id' )
    ...

それを機能させるために、Djangoユーザーモデルのユーザープロファイルとして機能するモデルも作成しました。含まれているのは、上記のグループモデルにリンクされたManyToManyFieldだけでした。これにより、ユーザーはにアクセスできるようになりました。必要に応じて0個以上のグループ。( ドキュメント

class UserProfile( models.Model ):
    user = models.ForeignKey( User, unique=True )
    groups = models.ManyToManyField( Group )
    ...

これにより、両方の長所が得られ、Djangoの許可システムにすべてを詰め込もうとすることができなくなりました。私はこの基本的な設定を使用して、スポーツコンテンツへのユーザーのアクセスを制御しています(一部のユーザーはリーグ全体にアクセスでき、一部のユーザーは1つまたは2つの会議にのみアクセスでき、一部のユーザーは個々のチームにしかアクセスできません)。この状況ではうまく機能します。それはおそらくあなたのニーズに合うように十分に一般化されているかもしれません。

2
Thomas

実際のオブジェクトごとのACLが必要ない場合は、Djangoアクセス許可システムを使用できます。使用可能なすべてのアクセス許可のリストを取得するには:

from Django.contrib.auth.models import Permission
perms = Permission.objects.all()

他の認証および承認ソース用のAPI があるため、このアクセス許可テーブルに固執する必要はありません。

このDjangoシステムをハックして、この承認モデル(RBAC)の観点からニーズに合わせるか、ACLのようなソリューションを考え出すことができます。

1

Djangoユーザーロールを使用できます

https://github.com/dabapps/Django-user-roles

1
ecabuk

ピノノワールワインの専門家向けのサイトで、さまざまな基準に基づいてオブジェクトごとのアクセスを作成しました。インバウンドリンクに注目のワイナリーのドメイン名と一致するリファラーフィールドがある場合、ユーザーはそのワイナリーに関連するすべての記事、テイスティングノートなどに展開される「ワイナリートークン」を取得しました。テイスティングイベントでのプレゼントには「名前付きトークン」を使用し、サイトの特定の部分にアクセスできるようにしました。これを使用して、検索エンジンスパイダーに特定の種類のアクセス許可を付与し、それらの検索エンジンからのリンクがスパイダーと同じアクセス許可を持っていることを確認します(つまり、クローキングゲームはありません)。

短いバージョンでは、クラス(トークンを保持するTokenBucketsと呼びます)を作成でき、各オブジェクト(詳細ページ、リストページなど)は、特定のレベルのアクセスが許可されているかどうかをユーザーのTokenBucketに尋ねることができます。

基本的に、それは奇妙な種類のACLシステムです。メカニズムを作成することはそれほど難しくありませんでした。すべての魔法は、どの状況でどのトークンがバケットに入るのかを決定することにあります。

1
Peter Rowell

この質問は2009年10月に行われ、問題は2012年7月にまだ存在します-)。

良いロールベースアプリを検索し、 Django-permission 最良の結果として。

私が必要とした3つの重要な機能は、Roles、viewDecorators、およびテンプレートタグ;どうやらDjango-permissionsそれらすべてがあります。それを読んでください docs その使用法について。

唯一の欠点は、開発中であることです。

1
Soask

同様の問題に対して、ロールベースシステムを使用しました。基本的に、ユーザーにはさまざまな役割を引き受ける権限があります。

表示機能が装飾されました:

def needs_capability(capability,redirect_to="/cms/"):
   def view_func_wrapper(view_func):
       def wrapped_view_func(request,*args,**kwargs):
           if not request.role._can(capability):
              return HttpResponseRedirect(redirect_to)
           return view_func(request,*args,**kwargs)
       return wrapped_view_func
   return view_func_wrapper

残りの魔法は、コンテキストプロセッサ内で設定されたrequest.role属性内にあります。認証されたユーザーは、洗浄されていない大衆のためにDummyRoleの役割を取得しました。

テンプレート内では、情報へのアクセスがさらに制限されていました。

 {% if not request.role.can.view_all_products %}
          Lots of products, yeah!
 {% endif %}

私の意見では最もクリーンな解決策ではありませんが、期待どおりに機能しました。

0
phoku