Deleting Documents from Flutter if conditionals are met - firebase

I am trying to add a function so that whenever a button is pressed, it will take my variables and look through all documents in my database. Then when it finds a document that matches the variables, it will delete that item. However, I keep getting an error message that I need a ")" after the (doc). Is there a better way to run through all the items to delete them, or am I doing something wrong with the snapshots/forEach statements?
Object deleteUser() {
// Call the user's CollectionReference to add a new user
if(name!="" && type!="" && location!="") {
items.snapshots().forEach(
(doc) => if(doc.data['name']==deleteName && doc.data['type']==deleteType && doc.data['location']==deleteLocation => doc.delete();));
return items;
}else{
return "There was a null error";
}
}

Your forEach loop is what's throwing the error as it isn't valid dart. I cleaned it up, this should work for you.
Object deleteUser() {
// Call the user's CollectionReference to add a new user
if (name != "" && type != "" && location != "") {
for (var doc in items.snapshots()) {
if (doc.data['name'] == deleteName &&
doc.data['type'] == deleteType &&
doc.data['location'] == deleteLocation) {
doc.delete();
}
}
return items;
} else {
return "There was a null error";
}
}

Related

how to write Firestore security rules to also allow null value and undefined value in a single field?

I have a field in my Firestore document called lastApproval that should be a timestamp if it has a value.
this is my simplified rules
match /users/{userID} {
allow create: if isValidUserStructure(incomingData())
allow update: if isValidUserStructure(incomingData())
}
function incomingData() {
return request.resource.data;
}
function isValidUserStructure(user) {
return user.email is string
&& user.fullname is string
&& user.lastApproval is timestamp // error in here
}
as you can see, isValidUserStructure function will be used to check when creating and updating user document.
when creating user document, that lastApproval field will be null like this
const data = {
fullname: 'John Doe',
email: 'my#email.com',
lastApproval: null
};
await db.collection('users').doc('userIDHere').set(data);
but when updating document, I only want timestamp.
const data = {
lastApproval: new Date()
};
await db.collection('users').doc('userIDHere').update(data);
and also, I want to pass the security rules if lastApproval is not available, for example, if the user only want to update the fullname like this
const data = {
fullname: "My New Name"
};
await db.collection('users').doc('userIDHere').update(data);
so I want my security rules to accept timestamp, null and undefined value for lastApproval field
I have tried but error
please help :)
There isn't any type null as far as I know. You can find all available types in the documentation.
If you want to check if the value is null then try user.lastApproval == null instead. To check if the lastApproval property exists at first place, try this:
match /collection/{doc} {
allow write: if 'lastApproval' in request.resource.data && (..otherLogic)
}
So you can write your function as:
function isValidUserStructure(user) {
return user.email is string
&& user.fullname is string
&& (('lastApproval' in user && user.lastApproval is timestamp) || !('lastApproval' in user))
}

Flutter Firestore - NoSuchMethodError: The method '[]' was called on null

Okay. I've been using Flutter for a little more than a year now. I've been using this same code in almost every app, and it works. For some reason, it doesn't work in this new app that I'm building.
String testString(DocumentSnapshot doc, String val) {
try {
if (doc == null) {
return "error! DB not found!";
}
if (doc[val] == null) {
return "'" + val + "' doesn't exist in DB";
}
return doc[val];
} catch (e) {
return "Error: something went wrong";
}
}
I've also tried this:
String testUndString(DocumentSnapshot doc, String val) {
try {
return doc != null ? (doc[val] != null ? doc[val] : "undefined") : "undefined";
} catch (e) {
return "Error: something went wrong";
}
}
and this:
String testUndString(DocumentSnapshot doc, String val) {
try {
return doc.data != null ? (doc[val] != null ? doc[val] : "undefined") : "undefined";
} catch (e) {
return "Error: something went wrong";
}
}
After doing some searching, it looks like I've done this correctly, but it still returns the error:
NoSuchMethodError (NoSuchMethodError: The method '[]' was called on null.)
Try this code:
if (doc is !DocumentSnapshot) {
return "error! DB not found!";
}

correct way to fire out a fail result in page reponse event listener in codeceptJS

I wrote a helper methods to add a network response listener over Puppeteer page instance. the code looks like this
let Helper = codecept_helper;
class CheckHelper extends Helper {
async listenRequest(listener)
{
const helper = this.helpers['Puppeteer'];
await helper.page.setRequestInterception(true);
helper.page.on("request",listener);
return helper._waitForAction();
}
async listenResponse(listener)
{
const helper = this.helpers['Puppeteer'];
helper.page.on("response",listener);
return helper._waitForAction();
}
}
module.exports = CheckHelper;
then in the test script
let self=this;
I.listenResponse((response)=>{
if(response.url().match(/github.*\.js/) && response.headers()['content-length']>1000) {
//codeceptjs.event.emit(codeceptjs.event.test.failed, self, 'js file is too big!');
//codeceptjs.recorder.throw('js file is too big!')
//codeceptjs.recorder.stop();
//throw new Error('js file is too big!')
}
})
I.amOnPage("https://www.github.com");
i first add response listener, then i goto "github", when some js file size is too big,i will throw out an error,in order too check content size is correctly.
however, even i throw error out (like the comments codes did), the main test flow just not stop, how do i do is the right way?
well,i found a solution later
i recorded all the page response into a custom object in the page instance.
later i wrote a help methods to check whole records.
//in helper.js
startRecordResponse() {
const helper = this.helpers['Puppeteer'];
helper.page.on("response", (res) => {
//record all response instance into savedResponse object inside page, we'll use it later
helper.page.savedResponse = helper.page.savedResponse || {};
helper.page.savedResponse[res.url()] = res;
});
return helper._waitForAction();
}
checkFileIsTooBig(filter, sizeLimit) {
const helper = this.helpers['Puppeteer'];
//use the data recorded in savedResponse object
Object.keys(helper.page.savedResponse).forEach((url) => {
var res = helper.page.savedResponse[url];
if (((filter instanceof RegExp && filter.test(url)) || (typeof filter == "string" && url.indexOf(filter) != -1)) && res.headers()['content-length'] > sizeLimit) {
throw new Error(`file ${url} is too big,${res.headers()['content-length']} > ${sizeLimit}`)
}
})
return helper._waitForAction();
}
then in test file
Before((I) => {
I.startRecordResponse();
I.amOnPage("https://www.github.com");
});
Scenario('github_test', (I) => {
//check a js file contain github is less than 100 bytes
I.checkFileIsTooBig(/github.*\.js/,100);
}
);

Security for angularfire

I am trying to get rid of an error which arises on posting a new entry to an angularfire array. The array holds reports, this array should be able to be written to, but not read from. The rules I have are as follows:
"reports":{
".write":"(auth != null)",
"$report_id":{
//".write":"(auth != null)",// << commented out part
".validate":"!data.exists() && newData.exists() && newData.hasChildren(['reason', 'reportedUser', 'reportingUser', 'time'])",
"reason":{
".validate":"newData.isString() && newData.val().length < 100"
},
"reportedUser":{
".validate":"newData.isString() && newData.val().length < 30"
},
"reportingUser":{
".validate":"auth.uid === newData.val()"
},
"time":{
".validate":"newData.val() <= now"
},
"$other":{
".validate":false
}
}
}
I am calling the write to this array from within a function, the contents of which is as follows:
var reportsArray = $firebaseArray(new Firebase(FBaseURL + "/reports/"));
reportsArray.$add(reportData)
.then(function(ref) {
console.log('user reported');
})
.catch(function(error) {
console.log("Error:", error);
});
Whichever write rule I comment out in rules (also un-commenting the other), the write is successful but the creation of the variable reportsArray presents an error as follows Error: permission_denied: Client doesn't have permission to access the desired data. What's best to do here, ignore the error or am I doing something wrong?

How do I do a parameter based publication in Meteor and remove old subscription document?

I want to implement a parameter based publication in Meteor but I am running into some problems.
Here is what I have.
As the user types the keyup event that subscribes to publication and passes the value of the input.
'keyup #customerSearch': function(event, template){
var keyword = template.find('#customerSearch').value;
if(keyword){
if(keyword.length >= 3){
Meteor.subscribe('sessioncustomers', keyword);
}
}
}
The publication uses this keyword to return the records.
Meteor.publish("sessioncustomers", function(keyword){
if(keyword ){
if(keyword.length >= 3){
query.name = new RegExp(regExpQuoted(keyword), 'i' );
Customers.find(query);
} else {
return null;
}
}else{
return null;
}
});
The problem.
It works and documents are received except when the client changes the keyword or rather as the keywords changes the publication publishes additional documents that match the keywords but the client collection never removes the old documents.
How do I get the old documents that no longer match out of the client collection?
I thought that because the parameters of the subscription had changed that the non-matching documents would be unsubscribed and only the new matching documents would be subscribed.
In your keyup callback you need to "unsubscribe" to the previous publication,
otherwise you'll keep the old documents.
var sessionCustomersHandler = false;
'keyup #customerSearch': function(event, template) {
var keyword = template.find('#customerSearch').value;
if (keyword && keyword.length >= 3)
var newSessionCustomersHandler = Meteor.subscribe('sessioncustomers', keyword);
if (sessionCustomersHandler)
sessionCustomersHandler.stop();
sessionCustomersHandler = newSessionCustomersHandler;
}
Moreover, don't forget to check(keyword, String) in your publish function, for security.
Meteor.publish("sessioncustomers", function(keyword){
check(keyword, String)
if (keyword.length >= 3)
return Customers.find({
name: new RegExp(regExpQuoted(keyword), 'i' )
});
});
Make a local unnamed client collection
this.SessionCustomers = new Meteor.Collection(null);
Call a server method to get the results you want. Make the callback clear (remove all) and then insert to that local collection.
return Meteor.call('sessioncustomers', query, function(err, data) {
if (err) {
return console.log(err.message);
} else {
SessionCustomers.remove({});
var item, _i, _len;
for (_i = 0, _len = data.length; _i < _len; _i++) {
item = array[_i];
SessionCustomers.insert(item);
}
}
});

Resources