我正在开发一个项目,在为版主设置权限时遇到困难。尽管添加了一个辅助函数来检查用户是否是主持人,但我的实现似乎没有按预期运行。我已经添加了控制台日志,似乎错误发生在 getModeratorSnippets 处。
这是我的代码的概述:
const onAddRemoveModerator = async (
user: User,
communityData: Community,
isModerator?: boolean
) => {
try {
setLoadingModeratorMap((prevLoadingMap) => ({
...prevLoadingMap,
[user.uid]: true, // Set loading state to true for the specific user
}));
if (!isModerator) {
// Change the condition here
// User is not a moderator, add them
const newSnippet: ModeratorSnippet = {
communityId: communityData.id,
isModerator: true,
userUid: user.uid,
};
const batch = writeBatch(firestore);
batch.set(
doc(
firestore,
`users/${user?.uid}/moderatorSnippets`,
communityData.id
),
newSnippet
);
await batch.commit();
setCommunityStateValue((prev) => ({
...prev,
moderatorSnippets: [...prev.moderatorSnippets, newSnippet],
}));
setIsModerator(true);
} else {
// User is already a moderator, remove them
const batch = writeBatch(firestore);
batch.delete(
doc(
firestore,
`users/${user?.uid}/moderatorSnippets/${communityData.id}`
)
);
await batch.commit();
setCommunityStateValue((prev) => ({
...prev,
moderatorSnippets: prev.moderatorSnippets.filter(
(snippet) =>
snippet.communityId !== communityData.id ||
snippet.userUid !== user.uid
),
}));
setIsModerator(false);
}
setLoadingModeratorMap((prevLoadingMap) => ({
...prevLoadingMap,
[user.uid]: false, // Set loading state to false for the specific user
}));
} catch (error) {
console.log("handleAddRemoveModerator error", error);
}
};
const fetchModeratorList = async () => {
setLoadMoreLoading(true);
const list: User[] = [];
try {
let querySnapshot;
if (searchQuery) {
const startAtKeyword = searchQuery.toUpperCase();
const endAtKeyword = searchQuery.toLowerCase() + "\uf8ff";
const queryRef = query(
collection(firestore, "users"),
orderBy("displayName"),
startAt(startAtKeyword),
endAt(endAtKeyword)
);
querySnapshot = await getDocs(queryRef);
} else {
querySnapshot = await getDocs(query(collection(firestore, "users")));
}
querySnapshot.forEach((doc) => {
list.push(doc.data() as User);
});
setModeratorList(list);
} catch (error: any) {
console.log("error", error);
}
setSearchLoading(false);
setLoadMoreLoading(false);
};
const getSnippets = async () => {
setLoading(true);
try {
const snippets = await getMySnippets(user?.uid!);
setCommunityStateValue((prev) => ({
...prev,
mySnippets: snippets as CommunitySnippet[],
initSnippetsFetched: true,
}));
setLoading(false);
} catch (error: any) {
console.log("Error getting user snippets", error);
setError(error.message);
}
setLoading(false);
};
const getModeratorSnippets = async () => {
setLoading(true);
try {
const snippets = await getAllModeratorSnippets();
setCommunityStateValue((prev) => ({
...prev,
moderatorSnippets: [...snippets], // Replace the existing snippets with the new ones
initSnippetsFetched: true,
}));
setLoading(false);
} catch (error: any) {
console.log("Error getting snippets", error);
setError(error.message);
setLoading(false);
}
};
const getAllModeratorSnippets = async () => {
const snippetsCollection = collectionGroup(firestore, "moderatorSnippets");
const snippetsDocs = await getDocs(snippetsCollection);
const snippets: ModeratorSnippet[] = [];
snippetsDocs.forEach((doc) => {
const snippet = doc.data() as ModeratorSnippet;
if (snippet.isModerator === true) {
snippets.push({ ...snippet });
}
});
return snippets;
};
这是我的规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Allow users to read, write, get, and update their own data
match /users/{userId}/{restOfPath=**} {
allow read, write: if request.auth != null;
// Allow moderators to read, write, update, and get
match /moderatorSnippets/{communityId} {
allow read, write: if isModerator(userId, communityId);
}
}
// Helper function to check if the user is a moderator
function isModerator(userId, communityId) {
return request.auth != null &&
exists(/databases/(database)/documents/users/$(userId)/moderatorSnippets/$(communityId));
}
}
我尝试实现一个辅助函数(isModerator),以在授予 moderatorSnippets 读写权限之前检查用户是否是版主。然而,它似乎并没有达到预期的效果。
您似乎错过了 Firebase 文档中的一个重要部分,其中解释了规则不是过滤器。这些规则本身不会过滤数据,而只是确保您的代码仅请求它有权访问的数据。
由于您的代码请求来自
moderatorSnippets
的所有文档,并且您已将规则设置为不允许这样做,因此规则引擎会拒绝该读取操作。
正确的设置是确保您的代码仅请求根据您的规则允许的文档。因此,您必须编写查询以符合规则。
我不确定这对于您当前的数据模型是否可行,因为查询只能对它返回的文档中存在的信息进行过滤/排序,并且您的规则似乎会检查另一个文档是否存在(
exists(/databases/(database)/documents/users/$(userId)/moderatorSnippets/$(communityId))
).
如果这确实是一个单独的文档,您将需要复制您正在查询的
moderatorSnippets
中的信息,以便您可以在那里进行过滤 - 然后通过您的规则保护 that。