【要約】Django REST Frameworkで「アクセス許可された製品だけ」を参照できるようにする設計 [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
開発者が業務システムを構築する際、製品ごとに異なるアクセス権限を管理する複雑な要件に直面する。単一の所有者による管理ではなく、複数のユーザーに特定の製品への権限を割り当てる必要があるためである。
- ・管理者は全製品を操作できるが、一般ユーザーは許可された製品のみに制限したい。
- ・Viewごとにアクセス制御を書くと、実装漏れや重複が発生し、セキュリティリスクが高まる。
- ・製品がツリー構造を持つ場合、親への権限があっても子への権限がないケースの制御が困難である。
// Approach
設計者は、権限管理を「機能」と「対象」の2層に分離し、QuerySetを制御する共通関数を導入する手法を採用した。これにより、APIの増加に強い構造を構築する。
- ・
ProductAccess中間モデルを定義し、UserとProductを多対多で紐付ける。 - ・
accessible_products(user)関数を作成し、アクセス範囲の取得を一元管理する。 - ・SelectorやService層で、必ずこの関数を経由したQuerySetを使用するルールを徹底する。
- ・詳細取得時は
get_object_or_404を用い、権限がない場合は403ではなく404を返すことで情報を隠蔽する。
// Result
この設計を導入することで、開発チームはセキュリティの担保とコードの再利用性を両立できる。実装の標準化により、大規模な開発でも安全なアクセス制御が可能となる。
- ・APIが増えても、共通のQuerySet制御により、実装漏れによる脆弱性を防げる。
- ・ツリー構造においても、親子両方の権限をチェックすることで、情報の漏洩を確実に防げる。
- ・将来的な「閲覧のみ」「編集可能」といったロール拡張にも柔軟に対応できる。
Senior Engineer Insight
> 実戦的な設計である。特にPermissionとProductAccessを分離する思想は、複雑な権限要件を持つB2B SaaS等で極めて有効だ。Viewにロジックを分散させず、SelectorやServiceに集約する構成は、テスト容易性と保守性を劇的に高める。ただし、中間モデルのレコードが数百万規模に達する場合、
distinct()によるクエリの重さに注意が必要だ。大規模トラフィックを想定するなら、適切なインデックス設計やキャッシュ戦略を併せて検討すべきである。