【发布时间】:2020-03-19 05:22:50
【问题描述】:
考虑一个允许用户将照片存储在 Firebase 存储中的应用,这些照片的用户 ID 设置在自定义元数据“所有者”字段中。
以下 Firebase 存储安全规则确保只有他们可以看到他们的照片:
allow read: if resource.metadata.owner == request.auth.uid;
现在想象一下,如果用户愿意,该应用允许用户公开他们的照片,任何人都可以看到,甚至是未登录的用户 (request.auth == null)。这可以通过另一个自定义元数据字段和稍微不同的规则来完成:
allow read: if resource.metadata.owner == request.auth.uid || resource.metadata.public == "true";
这在理论上可行,但需要在用户每次打开/关闭公共/私人访问时更改所有照片的元数据。
为了实现这一点,可以使用以下云功能来更新给定“文件夹”下所有照片的元数据:
import * as functions from 'firebase-functions';
import * as storage from '@google-cloud/storage';
// 'data' contains 'path' of all photos to update and 'public' which will be set to "true" or "false"
export const updatePublicMetadataField = functions.https.onCall( async (data, context) => {
const s = new storage.Storage();
const bucket = s.bucket("bucket name")
const options = { prefix: data.path }
const md = { metadata: {public: data.public}}
const [files] = await bucket.getFiles(options)
for (const file of files) {
try {
await file.setMetadata(md)
} catch(error) {
return { r: 'Error: ' + error};
}
}
return { r: 'Files processed: ' + files.length};
});
这种方法的问题在于,如果用户有数百张照片,云函数将简单地超时,因为对 setMetadata 的调用并不快。
那么是否有另一种方法可以打开/关闭多个文件(都在同一个“文件夹”中)的公共访问?
我的一些想法目前似乎不受 Firebase 支持:
- 使用同一文件夹中的单个“安全文件”,其中包含所需的元数据,可以通过 get() 函数读取,类似于 Firestore 安全规则读取任意文档的方式。
- 从 Firebase 存储安全规则访问 Firestore,以允许从 Firestore 读取用户所需的“public”值。
- Firebase 存储“文件夹”上的元数据。
- 一个(快速)函数,用于更新“文件夹”中所有文件的元数据。例如。 bucket.setMetadata(前缀,元数据)
【问题讨论】:
标签: firebase google-cloud-firestore firebase-security