Birçok ortak çalışma uygulaması, kullanıcıların farklı verileri okumasına ve yazmasına olanak tanır. izin verir. Örneğin, bir doküman düzenleme uygulamasında kullanıcılar, çalışırken dokümanlarını okumasına ve yazmasına izin vermek engelleme.
Çözüm: Rol Tabanlı Erişim Denetimi
Cloud Firestore'un veri modelinin yanı sıra özel rol tabanlı erişimi uygulamak için güvenlik kurallarını emin olun.
Kullanıcıların, ortak çalışmaya dayalı bir yazma uygulaması oluşturduğunuzu varsayalım. "hikayeler" oluşturabilir ve "yorumlar" :
- Her hikayenin bir sahibi vardır ve "yazarlar", "yorumcular" ve "okuyucular" ile paylaşılabilir.
- Okuyucular yalnızca hikayeleri ve yorumları görebilir. Hiçbir şeyi düzenleyemezler.
- Yorumcular, okuyucuların tüm erişimine sahiptir ve haberlere yorum ekleyebilirler.
- Yazarlar, yorumcuların tüm erişimine sahiptir ve hikaye içeriklerini de düzenleyebilir.
- Sahipler, hikayenin herhangi bir bölümünü düzenleyebilir ve diğer kullanıcıların erişimini kontrol edebilir.
Veri Yapısı
Uygulamanızda, her dokümanın temsil ettiği bir stories
koleksiyonu olduğunu varsayalım
anlatabilmişimdir. Her hikayede, her belgenin mevcut olduğu comments
alt koleksiyon da vardır.
o hikayeyle ilgili bir yorumdur.
Erişim rollerini takip etmek için bir roles
alanı ekleyin. Bu alan
rollere kullanıcı kimlikleri:
/Hikayeler/{storyid}
{
title: "A Great Story",
content: "Once upon a time ...",
roles: {
alice: "owner",
bob: "reader",
david: "writer",
jane: "commenter"
// ...
}
}
Yorumlarda, yazarın kullanıcı kimliği ve bazı içerikler olmak üzere yalnızca iki alan bulunur:
/Hikayeler/{storyid}/yorumlar/{commentid}
{
user: "alice",
content: "I think this is a great story!"
}
Kurallar
Artık kullanıcılarınızın her bir rol için bunları ayrı olarak
Güvenlik Kuralları'nı inceleyin. Bu kurallar, uygulamanın
Firebase Auth'u kullanarak request.auth.uid
değişkeni kullanıcının kimliğidir.
1. Adım: Hikayeler için boş kurallar içeren temel kural dosyasıyla başlayın ve yorumlar:
service cloud.firestore {
match /databases/{database}/documents {
match /stories/{story} {
// TODO: Story rules go here...
match /comments/{comment} {
// TODO: Comment rules go here...
}
}
}
}
2. Adım: Sahiplere aşağıdakilerin üzerinde tam kontrol sağlayan basit bir write
kuralı ekleyin:
hikayeler. Tanımlanan işlevler, kullanıcı rollerinin belirlenmesine yardımcı olur ve yeni
dokümanların geçerli olduğu durumlar:
service cloud.firestore {
match /databases/{database}/documents {
match /stories/{story} {
function isSignedIn() {
return request.auth != null;
}
function getRole(rsc) {
// Read from the "roles" map in the resource (rsc).
return rsc.data.roles[request.auth.uid];
}
function isOneOfRoles(rsc, array) {
// Determine if the user is one of an array of roles
return isSignedIn() && (getRole(rsc) in array);
}
function isValidNewStory() {
// Valid if story does not exist and the new story has the correct owner.
return resource == null && isOneOfRoles(request.resource, ['owner']);
}
// Owners can read, write, and delete stories
allow write: if isValidNewStory() || isOneOfRoles(resource, ['owner']);
match /comments/{comment} {
// ...
}
}
}
}
3. Adım: Her pozisyondaki kullanıcının hikayeleri okumasına ve yorum. Önceki adımda tanımlanan işlevleri kullandığınızda, kuralları korursunuz. kısa ve özlü olmalıdır:
service cloud.firestore {
match /databases/{database}/documents {
match /stories/{story} {
function isSignedIn() {
return request.auth != null;
}
function getRole(rsc) {
return rsc.data.roles[request.auth.uid];
}
function isOneOfRoles(rsc, array) {
return isSignedIn() && (getRole(rsc) in array);
}
function isValidNewStory() {
return resource == null
&& request.resource.data.roles[request.auth.uid] == 'owner';
}
allow write: if isValidNewStory() || isOneOfRoles(resource, ['owner']);
// Any role can read stories.
allow read: if isOneOfRoles(resource, ['owner', 'writer', 'commenter', 'reader']);
match /comments/{comment} {
// Any role can read comments.
allow read: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
['owner', 'writer', 'commenter', 'reader']);
}
}
}
}
4. adım: Hikaye yazarları, yorumcuları ve sahiplerinin yorum yayınlamasına izin verin.
Bu kuralın, yorumun owner
değerinin
kullanıcının birbirlerinin yorumlarına yazmasını önleyen, istekte bulunan kullanıcı:
service cloud.firestore {
match /databases/{database}/documents {
match /stories/{story} {
function isSignedIn() {
return request.auth != null;
}
function getRole(rsc) {
return rsc.data.roles[request.auth.uid];
}
function isOneOfRoles(rsc, array) {
return isSignedIn() && (getRole(rsc) in array);
}
function isValidNewStory() {
return resource == null
&& request.resource.data.roles[request.auth.uid] == 'owner';
}
allow write: if isValidNewStory() || isOneOfRoles(resource, ['owner'])
allow read: if isOneOfRoles(resource, ['owner', 'writer', 'commenter', 'reader']);
match /comments/{comment} {
allow read: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
['owner', 'writer', 'commenter', 'reader']);
// Owners, writers, and commenters can create comments. The
// user id in the comment document must match the requesting
// user's id.
//
// Note: we have to use get() here to retrieve the story
// document so that we can check the user's role.
allow create: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
['owner', 'writer', 'commenter'])
&& request.resource.data.user == request.auth.uid;
}
}
}
}
5. Adım: Yazarlara hikaye içeriğini düzenleme izni verin ancak hikayeyi düzenleme izni vermeyin
dokümanın diğer özelliklerini değiştirebilirsiniz. Bu işlem,
write
haberleri create
, update
ve
Yazarlar yalnızca haberleri güncelleyebileceği için delete
:
service cloud.firestore {
match /databases/{database}/documents {
match /stories/{story} {
function isSignedIn() {
return request.auth != null;
}
function getRole(rsc) {
return rsc.data.roles[request.auth.uid];
}
function isOneOfRoles(rsc, array) {
return isSignedIn() && (getRole(rsc) in array);
}
function isValidNewStory() {
return request.resource.data.roles[request.auth.uid] == 'owner';
}
function onlyContentChanged() {
// Ensure that title and roles are unchanged and that no new
// fields are added to the document.
return request.resource.data.title == resource.data.title
&& request.resource.data.roles == resource.data.roles
&& request.resource.data.keys() == resource.data.keys();
}
// Split writing into creation, deletion, and updating. Only an
// owner can create or delete a story but a writer can update
// story content.
allow create: if isValidNewStory();
allow delete: if isOneOfRoles(resource, ['owner']);
allow update: if isOneOfRoles(resource, ['owner'])
|| (isOneOfRoles(resource, ['writer']) && onlyContentChanged());
allow read: if isOneOfRoles(resource, ['owner', 'writer', 'commenter', 'reader']);
match /comments/{comment} {
allow read: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
['owner', 'writer', 'commenter', 'reader']);
allow create: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
['owner', 'writer', 'commenter'])
&& request.resource.data.user == request.auth.uid;
}
}
}
}
Sınırlamalar
Yukarıda gösterilen çözüm, Güvenlik Kuralları'nı kullanarak kullanıcı verilerinin güvenliğini sağlamayı gösterir. ancak aşağıdaki sınırlamalara da dikkat etmelisiniz:
- Ayrıntı düzeyi: Yukarıdaki örnekte birden fazla rol (yazar ve sahip) aynı dokümana farklı sınırlamalarla yazma erişimine sahip olmalıdır. Daha karmaşık belgelerle bunu yönetmek zor olabilir ve tek bir dokümanı birden çok dokümana bölmek daha iyi olabilir tek bir role ait.
- Büyük Gruplar: Çok büyük veya karmaşık gruplarla paylaşımda bulunmanız gerekiyorsa Rollerin kendi koleksiyonlarında depolandığı bir sistem yalnızca hedef belgedeki bir alan olarak kullanılabilir.