web-dev-qa-db-ja.com

階層型オブジェクトグラフでのアクセス制御の構造化

ユーザーがモデレートできるフォルダエンティティがあります。フォルダには他のフォルダを含めることができます。だから私はこのような構造を持っているかもしれません:

Folder 1
    Folder 2
        Folder 3
    Folder 4

このエンティティにモデレートを実装する方法を決定する必要があります。私は2つのオプションを考え出しました:

オプション1

ユーザーにフォルダー1へのモデレート特権が与えられたら、フォルダー1とユーザー1の間にモデレーター関係を定義します。他の関係はデータベースに追加されません。

ユーザーがフォルダー3をモデレートできるかどうかを判断するために、ユーザー1が親フォルダーのモデレーターであるかどうかを確認します。

これにより、関係が定義された後、フォルダー1の下での更新/移動されたエンティティ/追加の処理の複雑さの一部が軽減され、関係を元に戻すと、1つのエンティティのみを処理すればよいようになります。

オプション2

ユーザーにフォルダー1へのモデレート特権が与えられたら、ユーザー1とフォルダー1の間の新しい関係を定義しますおよびすべての子エンティティから最孫までリレーションシップが作成されたとき、それが削除された場合は、グラフを下に反復してリレーションシップを削除します。この関係が作成された後でフォルダ2の下に何かを追加する場合、すべてのモデレータを新しいエンティティにコピーするだけです。

しかし、ユーザーがモデレートしている最上位のフォルダーのみを表示する必要がある場合、オプション1ではなく、ユーザーがモデレートしない親フォルダーを持つすべてのフォルダーをクエリする必要があります。ユーザーがモデレートしています。

考え

Ithinkそれは、ユーザーが子アイテムをクエリするよりも、すべての親アイテムをクエリするかどうかを決定することになります...もしそうなら、オプション1が良いようです。確信はないけど。

どちらのアプローチが他よりも優れていますか?どうして?または、両方よりも優れた別のアプローチはありますか?必要に応じて、Entity Frameworkを使用しています。

6
SB2055

オプション1は、最も簡単でクリーンで最小限のソリューションです。フォルダーを移動するときのアクセス許可の更新に関連する作業が少なく、ユーザーのモデレートアクセス許可が実際に設定された場所を確認することに関連する作業が少ないことは正しいです。だから私はこのメソッドを実装しようとしています。特権管理者が最初に入力したものを超えて追加のレコードを追加し始める場合(オプション2に従って)、モデルにノイズを追加し始め、実際の情報を再びフィルタリングして戻す必要があります。

データベースにデータを保存している場合は、 ネストされたセットモデル を調べる必要があります。このモデルでは、「左」および「右」フィールドをフォルダーテーブルに追加し、それらのフィールドにフォルダーの左と右の値がすべての子孫フォルダーの左と右の値を包含するような値を指定します(上に図があります)これをうまく示しているウィキペディアのページ)。このモデルを使用すると、フォルダーのすべての子や孫など、フォルダーのすべての親を簡単に識別できます。これは、標準の親IDリンクだけでは非常に複雑なものです。

2
Pixa

私はこの要件でシステムを構築し、メモリー内オブジェクトグラフを使用してフォルダーを表し、データベースからデータを引き出す必要なく、それに対して権限チェックを実行しました。

http://martinfowler.com/bliki/MemoryImage.html

1
mcintyre321

SQLを使用する場合は、SQLクエリ構文の一種である「再帰CTE」も使用できます。これにより、再帰的な階層クエリを単一のクエリとして実行できます。詳細については、この回答を参照してください: https://stackoverflow.com/questions/23722056/recursive-queries-cte-to-find-an-archive-permission

0
mcintyre321

オプション2では、権限が親から継承されているかどうかを保存することができます。そうしないと、親を変更するときにユーザーの意図が失われる可能性があります。

より良いアプローチは、それを論理的に保つことです。祖先を再帰して特権を決定します。平均的な階層の深さによっては、いくつかのクエリを実行する必要がない場合があります。それを測定します。 SQLを使用している場合も、データベース層のストアドプロシージャで再帰できます。

これが十分に速くない場合にのみ、私は特権を具体化します。私は、信頼できる正規化されたデータベースではなく、クエリキャッシュレイヤーでそれを実行しようとしています。

0
Joppe