Query Firestore documents with role based security via Flutter
I´ve a role based data model on Firestore according to googles suggestion here: https://firebase.google.com/docs/firestore/solutions/role-based-access
Security rules are set up correctly and work fine. But now I´ve the problem on how to query for the roles.
This is my data model (one sample document):
id: "1234-5678-91234",
roles:
userId_1:"owner",
userId_2:"editor
title: "This is a sample document"
And this is my Firestore Query in Flutter which gets all documents for a specific user by its ID if the user has assigned the role "owner" for the document:
return firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots().map((snapshot) {
return snapshot.documents.map((catalog) {
return SomeDocumentObject(...);
}).toList();
});
My problem now is, that I need some kind of "OR" clause - which does not exist as far as I know. The query above only retrieves documents for users with role "owner" but I need a query that also retrieves the document if the userId is associated with the role "editor".
I´ve tried "arrayContains:" which also doesn´t seem to work (cause it´s a map).
I´ve read about solutions with two independent queries which doesn´t sound like a good solution due to a lot of overhead.
Maybe someone of you have a hint for me? :)
Thanks & best,
Michael
add a comment |
I´ve a role based data model on Firestore according to googles suggestion here: https://firebase.google.com/docs/firestore/solutions/role-based-access
Security rules are set up correctly and work fine. But now I´ve the problem on how to query for the roles.
This is my data model (one sample document):
id: "1234-5678-91234",
roles:
userId_1:"owner",
userId_2:"editor
title: "This is a sample document"
And this is my Firestore Query in Flutter which gets all documents for a specific user by its ID if the user has assigned the role "owner" for the document:
return firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots().map((snapshot) {
return snapshot.documents.map((catalog) {
return SomeDocumentObject(...);
}).toList();
});
My problem now is, that I need some kind of "OR" clause - which does not exist as far as I know. The query above only retrieves documents for users with role "owner" but I need a query that also retrieves the document if the userId is associated with the role "editor".
I´ve tried "arrayContains:" which also doesn´t seem to work (cause it´s a map).
I´ve read about solutions with two independent queries which doesn´t sound like a good solution due to a lot of overhead.
Maybe someone of you have a hint for me? :)
Thanks & best,
Michael
add a comment |
I´ve a role based data model on Firestore according to googles suggestion here: https://firebase.google.com/docs/firestore/solutions/role-based-access
Security rules are set up correctly and work fine. But now I´ve the problem on how to query for the roles.
This is my data model (one sample document):
id: "1234-5678-91234",
roles:
userId_1:"owner",
userId_2:"editor
title: "This is a sample document"
And this is my Firestore Query in Flutter which gets all documents for a specific user by its ID if the user has assigned the role "owner" for the document:
return firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots().map((snapshot) {
return snapshot.documents.map((catalog) {
return SomeDocumentObject(...);
}).toList();
});
My problem now is, that I need some kind of "OR" clause - which does not exist as far as I know. The query above only retrieves documents for users with role "owner" but I need a query that also retrieves the document if the userId is associated with the role "editor".
I´ve tried "arrayContains:" which also doesn´t seem to work (cause it´s a map).
I´ve read about solutions with two independent queries which doesn´t sound like a good solution due to a lot of overhead.
Maybe someone of you have a hint for me? :)
Thanks & best,
Michael
I´ve a role based data model on Firestore according to googles suggestion here: https://firebase.google.com/docs/firestore/solutions/role-based-access
Security rules are set up correctly and work fine. But now I´ve the problem on how to query for the roles.
This is my data model (one sample document):
id: "1234-5678-91234",
roles:
userId_1:"owner",
userId_2:"editor
title: "This is a sample document"
And this is my Firestore Query in Flutter which gets all documents for a specific user by its ID if the user has assigned the role "owner" for the document:
return firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots().map((snapshot) {
return snapshot.documents.map((catalog) {
return SomeDocumentObject(...);
}).toList();
});
My problem now is, that I need some kind of "OR" clause - which does not exist as far as I know. The query above only retrieves documents for users with role "owner" but I need a query that also retrieves the document if the userId is associated with the role "editor".
I´ve tried "arrayContains:" which also doesn´t seem to work (cause it´s a map).
I´ve read about solutions with two independent queries which doesn´t sound like a good solution due to a lot of overhead.
Maybe someone of you have a hint for me? :)
Thanks & best,
Michael
edited Dec 31 '18 at 14:52
Michael
asked Dec 31 '18 at 14:46
MichaelMichael
699920
699920
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.
Thanks, that was what I expected - too sad :)
– Michael
Jan 1 at 12:57
add a comment |
This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:
@override
Stream<List<Catalog>> catalogs(User user) {
// Retrieve all catalogs where user is owner
Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots());
// Retrieve all catalogs where user is editor
Observable<QuerySnapshot> editorCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "editor")
.snapshots());
// Convert merged stream to list of catalogs
return Observable.combineLatest([ownerCatalogs, editorCatalogs],
(List<QuerySnapshot> snapshotList) {
List<Catalog> catalogs = ;
snapshotList.forEach((snapshot) {
snapshot.documents.forEach((DocumentSnapshot catalog) {
catalogs.add(Catalog(
id: catalog.documentID,
title: catalog.data['title'],
roles: catalog.data['roles'],
));
});
});
return catalogs;
}).asBroadcastStream();
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53988693%2fquery-firestore-documents-with-role-based-security-via-flutter%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.
Thanks, that was what I expected - too sad :)
– Michael
Jan 1 at 12:57
add a comment |
Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.
Thanks, that was what I expected - too sad :)
– Michael
Jan 1 at 12:57
add a comment |
Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.
Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.
answered Dec 31 '18 at 18:04
Doug StevensonDoug Stevenson
76.4k990111
76.4k990111
Thanks, that was what I expected - too sad :)
– Michael
Jan 1 at 12:57
add a comment |
Thanks, that was what I expected - too sad :)
– Michael
Jan 1 at 12:57
Thanks, that was what I expected - too sad :)
– Michael
Jan 1 at 12:57
Thanks, that was what I expected - too sad :)
– Michael
Jan 1 at 12:57
add a comment |
This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:
@override
Stream<List<Catalog>> catalogs(User user) {
// Retrieve all catalogs where user is owner
Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots());
// Retrieve all catalogs where user is editor
Observable<QuerySnapshot> editorCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "editor")
.snapshots());
// Convert merged stream to list of catalogs
return Observable.combineLatest([ownerCatalogs, editorCatalogs],
(List<QuerySnapshot> snapshotList) {
List<Catalog> catalogs = ;
snapshotList.forEach((snapshot) {
snapshot.documents.forEach((DocumentSnapshot catalog) {
catalogs.add(Catalog(
id: catalog.documentID,
title: catalog.data['title'],
roles: catalog.data['roles'],
));
});
});
return catalogs;
}).asBroadcastStream();
}
add a comment |
This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:
@override
Stream<List<Catalog>> catalogs(User user) {
// Retrieve all catalogs where user is owner
Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots());
// Retrieve all catalogs where user is editor
Observable<QuerySnapshot> editorCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "editor")
.snapshots());
// Convert merged stream to list of catalogs
return Observable.combineLatest([ownerCatalogs, editorCatalogs],
(List<QuerySnapshot> snapshotList) {
List<Catalog> catalogs = ;
snapshotList.forEach((snapshot) {
snapshot.documents.forEach((DocumentSnapshot catalog) {
catalogs.add(Catalog(
id: catalog.documentID,
title: catalog.data['title'],
roles: catalog.data['roles'],
));
});
});
return catalogs;
}).asBroadcastStream();
}
add a comment |
This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:
@override
Stream<List<Catalog>> catalogs(User user) {
// Retrieve all catalogs where user is owner
Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots());
// Retrieve all catalogs where user is editor
Observable<QuerySnapshot> editorCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "editor")
.snapshots());
// Convert merged stream to list of catalogs
return Observable.combineLatest([ownerCatalogs, editorCatalogs],
(List<QuerySnapshot> snapshotList) {
List<Catalog> catalogs = ;
snapshotList.forEach((snapshot) {
snapshot.documents.forEach((DocumentSnapshot catalog) {
catalogs.add(Catalog(
id: catalog.documentID,
title: catalog.data['title'],
roles: catalog.data['roles'],
));
});
});
return catalogs;
}).asBroadcastStream();
}
This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:
@override
Stream<List<Catalog>> catalogs(User user) {
// Retrieve all catalogs where user is owner
Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots());
// Retrieve all catalogs where user is editor
Observable<QuerySnapshot> editorCatalogs = Observable(firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "editor")
.snapshots());
// Convert merged stream to list of catalogs
return Observable.combineLatest([ownerCatalogs, editorCatalogs],
(List<QuerySnapshot> snapshotList) {
List<Catalog> catalogs = ;
snapshotList.forEach((snapshot) {
snapshot.documents.forEach((DocumentSnapshot catalog) {
catalogs.add(Catalog(
id: catalog.documentID,
title: catalog.data['title'],
roles: catalog.data['roles'],
));
});
});
return catalogs;
}).asBroadcastStream();
}
answered Jan 1 at 21:27
MichaelMichael
699920
699920
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53988693%2fquery-firestore-documents-with-role-based-security-via-flutter%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown