メタデータを使ってFirebase Storageのデータを特定のユーザ間でシェアする方法
ここのグループ非公開のファイル メタデータを使用する方法。
1対1で相手に画像を送信したい場合
送信者と受信者のAuth uidがクライアント側で分かる前提。
iOSの場合
let metadata = StorageMetadata() metadata.contentType = "image/jpeg" metadata.customMetadata = [ "sender": <送信者のuid>, "receiver": <受信者のuid> ] let storage = Storage.storage() let ref = storage.reference().child("share/photo.jpg") ref.putData(data, metadata: metadata)
Storageのルールはこんな感じ。
service firebase.storage { match /b/{bucket}/o { match /share { match /{allPaths=**} { allow write: if request.auth.uid != null && request.resource.metadata["sender"] == request.auth.uid allow read: if request.auth.uid != null && (resource.metadata["sender"] == request.auth.uid || resource.metadata["receiver"] == request.auth.uid) } } } }
Firestoreで管理しているグループ内で共有したい場合
Storageのオブジェクト作成時にCloud Functionsを実行してメタデータを付けてあげる。 例えば送信者の属するグループがFirestoreで管理されており、そのグループのメンバーのみで画像を共有したいとする。
iOSアプリ側のコード。
let metadata = StorageMetadata() metadata.contentType = "image/jpeg" metadata.customMetadata = [ "sender": <送信者のuid> ] let storage = Storage.storage() let ref = storage.reference().child("share/photo.jpg") ref.putData(data, metadata: metadata)
Cloud Functionsのコード。
import * as functions from 'firebase-functions'; import * as admin from 'firebase-admin'; admin.initializeApp(); export const storagePermission = functions.storage.bucket().object().onFinalize(async (object, context) => { // <必要に応じてパスのチェックなどをする> const sender = object.metadata && object.metadata['sender']; if (sender && object.name) { const uidsInGroup = ... // Firestoreから共有したいユーザのuid配列を取得 const file = admin.storage().bucket(object.bucket).file(object.name); await file.setMetadata({ metadata: { uids: uidsInGroup.join(',') } }) // カスタムメタデータをセットする際setMetadataの引数オブジェクトにmetadataのキーが必要。 } return }
Storageのルール。
service firebase.storage { match /b/{bucket}/o { match /share { match /{allPaths=**} { allow write: if request.auth.uid != null && request.resource.metadata["sender"] == request.auth.uid && resource.metadata["uids"] == null allow read: if request.auth.uid != null && resource.metadata["uids"] != null && request.auth.uid in resource.metadata["uids"].split(",") } } } }
メタデータにひたすら <uid>: "true"
をセットする方法もありそうだが散らかりそう。
追記
このルールだと他のユーザが上げたデータ上書きできちゃうからStorageのパスは考えた方がいいかも。