nHibernate上に構築されたリポジトリレイヤーを呼び出すASP.NETMVCWebアプリがあるとします。コントローラはISecurityToken
、現在のユーザーのIDと権限をカプセル化するリポジトリを渡します。リポジトリは、クエリを実行するときに、ユーザーが表示できるはずの行のみを返すためにそれを使用します。
エンティティ(チケット)を、チケットが割り当てられているユーザーだけでなく、特定のユーザーグループのみが閉じることができるようにしたい。言い換えると、架空のCanCloseTicket()
方法には2つの入力が必要です。
- チケット自体(またはその現在の所有者ID)
- 現在のユーザーの
ISecurityToken
この仮説的な方法はどこにあるべきですか?私はいくつかの可能性を見ることができますが、それぞれに欠点があります。
- コントローラ内:コントローラは必要なすべてにアクセスできますが、これによりセキュリティをバイパスできるようになります。(「おっと、falseに設定する前にこのアクションでCanCloseTicket()を呼び出すのを忘れまし
ticket.IsOpen
た!」これは悪臭がします。 - リポジトリ内:リポジトリも両方の部分にアクセスできますが、
Ticket.IsClosed
上記と同じことが起こらないようにするには、セッターをプライベートにする必要もあります。リポジトリはモデルとはまったく異なるアセンブリに存在するため、内部セッターを使用しても機能しません。代わりに、セッターを公開したままにして、プロパティの現在の値を元の値と比較し、特権のないユーザーがそれを閉じるとエラーを返すことができますが、これも少し臭いがします。repo.CloseTicket()
(「おっと、このアクションメソッドでの戻り値を確認するのを忘れました!」) - チケットの内容:
Ticket.Close(ISecurityToken token)
エンティティに独自のセキュリティロジックを追加して責任を持たせることは、SRPの違反のように感じます。
ここではリポジトリが最良のオプションだと思いますが、最悪のオプションのように感じます。他に何かありますか?