Tags
FirestoreData Model PatternData ModelPersonal Dataアクセス制御
Last Updated
Sep 9, 2024 5:37 AM
Created
Sep 3, 2024 12:30 AM
「ユーザの情報をセキュアに管理する」という要件を持つシステムは無数に存在するものと思います。 たとえば以下のような要件です。
- 「ユーザーはシステムへのメールアドレスを登録して、メールで通知を受け取る事ができる」ただし、「メールアドレスはユーザー本人と管理者以外からは閲覧できない」
本記事では、Personal Dataへのセキュアなアクセス制御を実現するためのData Model Patternについて、NoSQL DatabaseであるFirestoreにおける実装方法を例に解説していきます。
Data Model
- 「誰にReadを許可するのか?」という観点から、Personal Dataを3つのコレクションに分けて格納する
# user_accounts Readを許可しない
- 'ゲンスルー' :documentId ※1
- customer_score :Double
- …
# users ユーザ本人にのみ、Readを許可 ※2
- 'ゲンスルー' :documentId ※1
- private_email :String
- phone_number :String
- age: Double
- organization_roles: Map ※3
- name :String
- role :Array
- admin :String ※4
- editor :String
- …
- name :String
- roles: Array
- viewer :String
- …
- …
# user_profiles 本人以外からのReadを許可
- 'ゲンスルー' :documentId ※1
- public_email :String
- bio :String
- avater_url :String
- …
- …
- ※1 usersのdocumentIdとuser_account、organization_roles、、user_profilesのidは一致させる
- ※2 Firebase Authenticationを用いて認証連携した場合、usersに自動的にドキュメントが作成される
- ※3 organization_rolesの扱い方については、以下も参照のこと
- ※4 Document Reference型はIndexが使えないため、String型としている
Security Rule
- Writeの許可については、SecurityRuleでスキーマチェックを行うことでフィールド単位でアクセス制御を行う
// rules.json
match /user_accounts/{id} {
allow read, write: if false;
}
match /users/{id} {
allow read: if id == request.auth.uid;
allow update: if id == request.auth.uid && !request.data.age; // ageの更新は許可しない
}
match /users/organization_roles/{id} {
allow read: if id == request.auth.uid;
}
match /user_profiles/{id} {
allow read: if request.auth != null;
allow update: if id == request.auth.uid;
}
Reference
(5.1 ドキュメント設計の原則)