Sending notification automatically firebase - reactjs

I have an application that sends data to the firebase realtime database. Now I'm creating a dashboard to manage this data. At the moment I need to receive a notification on the dashboard when the user sends some new data to the firebase. I need to receive a message with the data id he sent and submit a notification similar to a social network.
I'm using FCM, I've already configured and tried to implement the onCreate () function. But when the bank is upgrading, this function is not being performed.
I'm implementing the code in the dashboard
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.makeUppercase = functions.database
.ref("users")
.onCreate((snapshot, context) => {
const original = snapshot.val();
console.log(original);
});
I'm actually lost on how to do this, I read the documentation, but I didn't quite understand the correct steps to follow. Is there anything I should do before that? Or is this method of doing wrong?

Related

Bypassing Firestore Security Rules in jest tests

Currently working on a React/Typescript/Firebase Firestore project. When writing Jest-tests for some actions/functions that are called from the UI, I ran into the following problem:
In the test file I'm able to setup the firestore client using the v9 api and make it talk to emulator
const app = initializeApp(config.firebase);
const firestore = getFirestore(app);
connectFirestoreEmulator(firestore, "localhost", 8080);
In addition I also found out how to setup the admin client and make it talk to emulator
process.env.FIRESTORE_EMULATOR_HOST = "localhost:8080";
const serviceAccount = require("../../../my-key.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
...config.firebase
});
The test itself looks something like this:
describe("createCompanyAndRating action", () => {
test("call createCompanyAndRating and make sure it creates a proper rating entity", async () => {
// omitted: set testRatingFormState and other test data that are passed as args and
// pass in the firestore db client
const {
ratingId,
companyId,
} = await createCompanyAndRating({
ratingFormState: testRatingFormState,
visitorId: testVisitorId,
firestore,
});
// verify result by fetching the rating entity from the emulator db using the admin client
const ratingPath = `companies/${companyId}/ratings/${ratingId}`;
const ratingSnap = await admin.firestore().doc(ratingPath).withConverter(ratingConverter).get();
const rating: Rating | undefined = ratingSnap.data();
// omitted: verify result with some Jest expect-statetments...
});
})
My problem is now that the Firestore security rules apply and only authenticated users can write docs in the collections used in the createCompanyAndRating function, so the test already throws an error when calling that function.
In this scenario I'm not interested in testing the security rules per se.
Is there a way to bypass the security rules for the test?
If yes, how do I have to setup the firestore client?
Is there even the possibility to somehow impersonate a user in the test?
In addition, please note that I can't to pass the admin client into the createCompanyAndRating function as the admin client API is different from the v9 firebase API that I'm relying on in the createCompanyAndRating function implementation (tried and it didn't work and not only because some type errors in the way).
Maybe my whole approach is a little misguided and I should rather concentrate on testing the internals of the createCompanyAndRating function where I do a lot of factory stuff that could be tested without db interaction.
Anyway, any help/guidance is much appreciated.
Thanks for confirming that I was looking in the right place (i.e. #firebase/rules-unit-testing). Finally figured out what the problem was, missed an "await" in createCompanyAndRating, so the firestore admin instance wasn't getting the data (and I though it was a admin config issue...) Thanks!

Why 'onSnapshot' google firebase is so fast, instantly fired?

I build a simple react app to test google firebase. Anyone have any idea how the onSnapshot method works? I mean, it is so fast (like, instantly), even when I change network to slow 3G in devtools, it still fast. I noticed in XHR tab, when the app made request to firebase, request is still pending, but onSnapshot already fired and change the state in my react app. I thought it will wait until there's response from firebase, but that's not the case.
.firestore()
.collection("expense")
.onSnapshot((snapshot) => {
const newExpense = snapshot.docs.map((doc) => {
return {
id: doc.id,
...doc.data(),
};
});
//set state is fired, but request is still pending
this.setState({expense: newExpense});
});
Did firebase just store the app state somewhere, or just simply read the app state and then update the state (call onSnapshot) when making request? If that's the case then you can not handle network error (or you can but that would be weird), because the app state is already changed.
Did firebase update the app state when this function (function below is to add collection to firebase database) called? and didn't even wait until request is success?
firebase.firestore().collection("expense").add(value);
firebaser here
When you write to Firestore from your application, the Firestore client in that application immediately fires events for the local listeners to that data.
So after your call to firebase.firestore().collection("expense").add(value) the Firestore client does:
Send the new data off to the server.
Calls any local listeners to /expenses straight away.
It's the second step here that makes the local chances show up instantly, as it doesn't wait for the server to complete the write operation.
This leads to a possible problem: what happens if the server rejects the write operation (for example because it conflicts with the security rules of your database)? If that happens, a few more steps are taken:
The server checks the write against the security rules and rejects it.
The client then fires reconciliation events for the local state, so it calls your onSnapshot listener again with the document removed.
Because of these extra steps, it is possible to briefly see the new document appear and then be removed, if it violates the security rules of your app.
Most likely, offline storage is enabled.
I think I found it, thanks to Aprillion for mentioning this explanation
Firebase will cache the data you get, read from that and update the state based on that data while still making network request, that's why it is instantly

Can I fulfill purchases made through Stripe Checkout Client in React without a server?

I am using the Client integration of Stripe Checkout in my create-react-app React app.
Purchasing works fine, but it seems like I have no option to search for successful payments or receive relevant information after a payment.
(Stripe Checkout Fulfilment Options)
Stripe Checkout is implemented like this:
import React, { Component } from 'react';
const stripe = window.Stripe('INSERT_API_KEY');
class Checkout extends Component {
checkout() {
stripe.redirectToCheckout({
items: [
{plan: 'INSERT_PLAN_ID', quantity: 1}
],
successUrl: 'https://localhost:3000/checkout/success',
cancelUrl: 'https://localhost:3000/checkout/success'
}).then((result) => {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer
// using `result.error.message`.
console.log(result)
});
}
render() {
return (
<button onClick={this.checkout}>Pay</button>
)
}
}
The success/cancel urls don't help me a lot because I can't think of a security mechanism that would only give access to users who actually made a payment.
Do you have any ideas?
Of the options for fulfilling purchases, the most reliable path is to write a backend and use server code. That said, if you feel really strongly about avoiding writing server code, I’d recommend working with a third-party plugin like Zapier to handle successful purchases and sending those into a spreadsheet or another tool that you use to manage fulfillments.
Use Stripe+Zapier to trigger workflows based on common activities in Stripe like getting a new customers, receiving a new payment, and more. https://stripe.com/works-with/zapier
Polling from the client is not recommended for a number of reasons.

How to send sms messages from a React Native App programmatically ?

I want to be able to sent sms messages though my React Native app programatically in the background.
I know how to sent sms normally in the code, but the app keeps opening the default sms app, and that is not what i want.
The user should not push any buttons to sent the sms, because my goal is to notify a phonenumber every time the user is doing a particularly task in the app.
I have tried looking at Twilio, but they dont provide a api for React Native.
Does anybody know something about how I can do this ?
With the answer from kdenz, I followed a tutorial here: Seeting up a firebase function
This is my code for sending a request to Twilio, when the firebase database value 'visible' is changing.
import * as functions from 'firebase-functions';
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const twilio = require('twilio');
const accountSid = functions.config().twilio.sid;
const authToken = functions.config().twilio.token;
console.log(`Twilio account: ${accountSid}`);
const client = new twilio(accountSid, authToken);
const twilioNumber = 'xxx-xxx-xxx';
exports.textStatus = functions.database
.ref('/users/{userId}/data/visible')
.onUpdate(event => {
return admin.database()
.ref(`users/{userId}/data/`)
.once('value')
.then(snapshot => snapshot.val())
.then(user=> {
console.log(user[0]);
const longitude = user.longi;
const latitude = user.lati;
const phoneNumber = user.phone;
const textMessage = {
body: `See user position at Google: http://www.google.com/maps/place/${latitude},${longitude}`,
to: phoneNumber,
from: twilioNumber
}
return client.messages.create(textMessage);
})
.then(message => console.log(message.sid, 'success'))
.catch(err => console.log(err));
});
I think this is only possible with Android, as seen in this deprecated package https://www.npmjs.com/package/react-native-send-sms
For iOS, I don't think so, as seen in How to programmatically send a text message after the user has given permission?
To achieve what you want, you'll need a SMS service like Twilio. Then you can set up a server (Or a cloud function for minimal cost + easy maintainability) which receives API calls from your RN app, and sends the message to the desired recipient. You can then set up some security measures too, to prevent hackers from spamming the API.
Or if you don't care about security (Which I highly don't recommend), you can directly call Twilio send message API within your app, which is dangerous because hackers can easily extract your Twilio authorization token and use it to send messages for themselves.
On android, it is possible to send sms from user's number programmatically without user interaction.
But on IOS, the only way you can send an SMS without user interaction is to use an external provider such as Twilio; but the message will come from your server's number, not from the user.
I have already answered for same kind of question. Check this out
Is there anyway to send sms in background for both Android & IOS?

AngularFire realtime sync with additional data

I´m building kind of a social network where users may send requests to other users.
The controller which gets loaded if the user checks his messages page:
$scope.requestedProfileTrips = Requests.getRequests(user.id).then(function (requests) {
$scope.requestedProfileTrips = [];
for (var i = 0; i < requests.length; i++) {
// this function loads additional data depending on the request from firebase
// from another database
loadProfileTrips(requests[i]);
}
});
The service which gets the requests from firebase:
getRequests: function(userId){
// get requests
var sync = $firebase(ref.child("requests").child(userId));
var requestObject = sync.$asArray();
// add requests to object
return requestObject;
}
The request object includes a userId, a messageId and so on. In the then function of the controller I get the userId from another database. This should update in realtime.
If I do:
$scope.requestedProfileTrips = Requests.getRequests(user.id);
the updating in realtime works! But I only got the user id and the message id. Is it possible to get the data from the other database which stores the usernames etc. in realtime? So everytime a request is added from firebase, the content in the then function of getRequests is triggered?
Firebase is good in real time sync but other than that as far as I know there is no ready to use database offering the same.
You could however go for a hybrid approach like manually fetching the data from tradition SQL or NoSQL database when your firebase dataset/event get updates/fired. This way you could use both realtime sync of firebase and your traditional database.
Or if you require to integrate realtime sync with traditional databases, then would suggest you look at sockets. Preferably sockets.io would let you get started pretty fast.

Resources