Мое приложение хранит роль пользователя (подписчик, редактор или администратор) в виде карты «ролей» в своем пользовательском документе в коллекции пользователей Firestore. Ролевая карта выглядит так:
// Roles map for a subscriber
{
subscriber: true
}
// Roles map for a editor
{
editor: true
}
// Roles map for administrator
{
administrator: true
}
Я также могу по мере необходимости помещать несколько (или совершенно новые) ролевые поля в ролевую карту пользовательского документа.
Я хочу, чтобы пользователи могли обновлять свой профиль, не меняя карту ролей. Поэтому для правил безопасности я попытался убедиться в этом, проверив, что пользователь является владельцем, и что роли до и после одинаковы. Но я всегда получаю ошибку разрешения при попытке обновления. Вот правила:
match /users/{userUid} {
allow update: if
(
isOwner(userUid) &&
(
(request.resource.data.roles.administrator == resource.data.roles.administrator) &&
(request.resource.data.roles.editor == resource.data.roles.editor) &&
(request.resource.data.roles.subscriber == resource.data.roles.subscriber)
)
);
}
Первое isOwner(user)
условие выглядит следующим образом:
function isOwner(uid) {
return (isSignedIn() && (request.auth.uid == uid));
}
Я уверен, что эта часть работает, потому что когда я запускаю ее только с этим, она работает.
Я подозреваю, что моя проблема может заключаться в том, что в тех случаях, когда одно из полей ролей (например, подписчик) не существует до или после записи, оно не проходит проверку на равенство. Поэтому я также попытался добавить условие, разрешающее, если существующий объект не имеет этого поля, но он все еще не работает:
match /users/{userUid} {
allow update: if
(
isOwner(userUid) &&
(
(!request.resource.data.roles.administrator || request.resource.data.roles.administrator == resource.data.roles.administrator) &&
(!request.resource.data.roles.editor || request.resource.data.roles.editor == resource.data.roles.editor) &&
(!request.resource.data.roles.subscriber || request.resource.data.roles.subscriber == resource.data.roles.subscriber)
)
);
}
Заранее спасибо за любую помощь.
ОБНОВЛЕНИЕ 1
I нашел более простое решение с использованием writeFields
, которое работает, но writeFields устарело, так что это не долгосрочное решение:
allow update: if isOwner(userUid) && !('roles' in request.writeFields)
Опять-таки, writeFields устарел, поэтому его не следует использовать.
ОБНОВЛЕНИЕ 2
Это решение сработало для меня, заменив роль ролями, соответствующими моему случаю: https://stackoverflow.com/a/48214390/4407512