FCM send to specific user - google-cloud-firestore

I am using cloud Firestore.
When I use cloud messaging to send push notifications to an app, a message goes to all users (users registered with Authentication) who are registered in the app.
The app has a login function, so I hope only the logged-in user gets notified.
That is, how can I send notifications only to specific users?
I want to set the time and day of the week with cloud messaging and send it to a specific device.
Now I even marked the token on the logcat and tested it in cloud messaging as shown in the picture.
However, the test cannot set the time and day of the week.
Is it possible to do this in the Fire Store? Or do I have to set the time and day of the week in the code as shown in the link?
enter image description here
//FirebaseMessagingService
#Override
public void onNewToken(String token) {
Log.e("NEW_TOKEN", token);
}
//MainActivity
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
// Log and toast
//String msg = getString(R.string.msg_token_fmt, token);
Log.d("NEW_TOKEN", token);
Toast.makeText(MainActivity.this, token, Toast.LENGTH_SHORT).show();
}
});

I'll just write an answer just for better track.
As #Doug already mentioned, you could try using this code sample and try on your own.
Finally, is a good practice to show what you have tried and a code snippet to better understand your question.

Related

Cancel sent Web Push notifications

I'm sending push notifications to my website users when they (for example) receive a private message.
That notification goes to all browsers subscribed for that user. So could be desktop, mobile, work computer etc.
What I would like to do is close all the sent notifications once the user has a read a message.
So user logs in on mobile, reads the private message - at this point I want all the previously sent notifications for that PM to be closed/cancelled.
Is this possible?
Thanks in advance!
Matt
Yes this is possible, but not silently. For example, Chrome will replace the notification with a new one saying "This site has been updated in the background".
There are two separate APIs: the Push API which "gives web applications the ability to receive messages pushed to them from a server", and the Notification API which "is used to configure and display desktop notifications to the user".
The Notification API provides Notification.close(), which cancels the display of a notification.
You can use the Push API to trigger Notification.close(). Here's a sample which should go in your service worker:
self.addEventListener('push', async event => {
const data = event.data.json();
if (data.type === 'display_notification') {
self.registration.showNotification(data.title, data.options);
} else if (data.type === 'cancel_notification') {
const notifications = await self.registration.getNotifications({
tag: data.notificationTag
});
for (notification of notifications) {
notification.close();
}
} else {
console.warn("Unknown message type", event, data);
}
});
However! This design means that your cancel_notification message won't display a notification. This violates some browser policies, for example Chrome will display a new notification saying "This site has been updated in the background".

Actions on Google new SignIn() is cancelling before user can give input

We are creating an Action on Google using Dialogflow V2 API. We are using firebase cloud functions for our fulfillment and we are using an external rest api for our crud operations.
We have an undeployed action that I have tested in the simulator. The conversation flow is
The user is prompted to signin ie, new SignIn()
They are asked what they want to do and they respond
Their response is saved in our backend using their credentials
new SignIn() works in the simulator, but when I test on the Google Home Mini the SignIn() responds as if the user has rejected the propmpt to signin before they have time to respond
Is there some restriction regarding testing an Action that include Account Linking on the Google Home Mini?
The intent containing the new SignIn() is my Welcome intent, could that be causing the issue?
Here are the two intents handling SignIn(). Start Signin Intent is triggered by the Welcome Event
app.intent("Start Signin", (conv) => {
conv.ask(new SignIn());
});
app.intent("Get Signin", (conv, params, signin) => {
if (signin.status === "OK") {
const payload = conv.user.profile.payload;
conv.ask(`I got your account details, ${payload.name}. What do you want to do?`);
} else {
conv.ask(`I won't be able to save your data, please login`);
}
});

Identify users / generate token for Ionic.io Push

I have an inherited Ionic framework app that is using Ionic.io
The app authorises against our API, and is given an API token to use in future requests.
I'm trying to work on push notifications - I've set up ionic push, and can trigger push notifications out to all users with no problems.
I'd like the ability to target specific users / devices to send notifications, and I understand that to do this, I have to register the device to generate a token.
Within my $ionicPlatform.ready function, I have:
$ionicPush.register().then(function(t) {
return $ionicPush.saveToken(t);
}).then(function(t) {
console.log('Token saved:', t.token);
});
This however does not seem to be returning a token, and calling
console.log($ionicPush);
Shows that the token is not set.
Any ideas here? What am I missing?
So after digging though some documentation, I found that the issue was linked with the ionic user.
In the main run function, I fire off a
if ($ionicAuth.isAuthenticated()) {
If this fails, I try a login of a user, and a register of the user if appropriate. (user is already logged in using a custom auth token against our api)
Before I attempt to register the token, I then have to reload the user in order to have the app save off and push back up to ionic.io.
$ionicUser.load().then(function() {
$ionicPush.register().then(function(t) {
console.log('Token sent:', t.token);
return $ionicPush.saveToken(t);
}).then(function(t) {
console.log('Token saved:', t.token);
});
});

Swift2 Firebase: Is the email check done on the backend server? [duplicate]

Question says it all. In Firebase, how do I confirm email when a user creates an account, or, for that matter, do password reset via email.
I could ask more broadly: is there any way to send emails out from Firebase? E.g. notifications, etc. This isn't the kind of thing you would usually do client-side.
Update
Note that this was never a very secure way of handling email verification, and since Firebase now supports email verification, it should probably be used instead.
Original answer
I solved the email verification using the password reset feature.
On account creation I give the user a temporary (randomly generated) password. I then trigger a password reset which will send an email to the user with a link. The link will allow the user to set a new password.
To generate a random password you can use code similar to this:
function () {
var possibleChars = ['abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!?_-'];
var password = '';
for(var i = 0; i < 16; i += 1) {
password += possibleChars[Math.floor(Math.random() * possibleChars.length)];
}
return password;
}
Note that this is happening on the client, so a malicious user could tamper with your logic.
This would need to be done outside of firebase. I store users at /users/ and keep a status on them (PENDING, ACTIVE, DELETED). I have a small service that monitors users of a PENDING status and sends out a confirmation email. Which has a link to a webservice I've created to update the user status to ACTIVE.
[Engineer at Firebase - Update 2014-01-27]
Firebase Simple Login now supports password resets for email / password authentication.
Each of the Simple Login client libraries has been given a new method for generating password reset emails for the specified email address - sendPasswordResetEmail() on the Web and Android, and sendPasswordResetForEmail() on iOS.
This e-mail will contain a temporary token that the user may use to log into their account and update their credentials. This token will expire after 24 hours or when the user changes their password, whichever occurs first.
Also note that Firebase Simple Login enables full configuration of the email template as well as the sending address (including whitelabel email from your domain for paid accounts).
To get access to this feature, you'll need to update your client library to a version of v1.2.0 or greater. To grab the latest version, check out https://www.firebase.com/docs/downloads.html.
Also, check out https://www.firebase.com/docs/security/simple-login-email-password.html for the latest Firebase Simple Login - Web Client docs.
As at 2016 July, you might not have to use the reset link etc. Just use the sendEmailVerification() and applyActionCode functions:
In short, below is basically how you'll approach this, in AngularJS:
// thecontroller.js
$scope.sendVerifyEmail = function() {
console.log('Email sent, whaaaaam!');
currentAuth.sendEmailVerification();
}
// where currentAuth came from something like this:
// routerconfig
....
templateUrl: 'bla.html',
resolve: {
currentAuth:['Auth', function(Auth) {
return Auth.$requireSignIn() // this throws an AUTH_REQUIRED broadcast
}]
}
...
// intercept the broadcast like so if you want:
....
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
if (error === "AUTH_REQUIRED") {
$state.go('login', { toWhere: toState });
}
});
....
// So user receives the email. How do you process the `oobCode` that returns?
// You may do something like this:
// catch the url with its mode and oobCode
.state('emailVerify', {
url: '/verify-email?mode&oobCode',
templateUrl: 'auth/verify-email.html',
controller: 'emailVerifyController',
resolve: {
currentAuth:['Auth', function(Auth) {
return Auth.$requireSignIn()
}]
}
})
// Then digest like so where each term is what they sound like:
.controller('emailVerifyController', ['$scope', '$stateParams', 'currentAuth', 'DatabaseRef',
function($scope, $stateParams, currentAuth, DatabaseRef) {
console.log(currentAuth);
$scope.doVerify = function() {
firebase.auth()
.applyActionCode($stateParams.oobCode)
.then(function(data) {
// change emailVerified for logged in User
console.log('Verification happened');
})
.catch(function(error) {
$scope.error = error.message;
console.log(error.message, error.reason)
})
};
}
])
And ooh, with the above approach, I do not think there's any need keeping the verification of your user's email in your user data area. The applyActionCode changes the emailVerified to true from false.
Email verification is important when users sign in with the local account. However, for many social authentications, the incoming emailVerified will be true already.
Explained more in the article Email Verification with Firebase 3.0 SDK
What I did to work around this was use Zapier which has a built in API for firebase. It checks a location for added child elements. Then it takes the mail address and a verification url from the data of new nodes and sends them forwards. The url points back to my angular app, which sets the user email as verified.
As I host my app files in firebase, I don't need have to take care of any servers or processes doing polling in the background.
There is a delay, but as I don't block users before verifying mails it's ok. Zapier has a free tier and since I don't have much traffic it's a decent workaround for time being.
The new Firebase SDK v3 appears to support email address verification, see here (put your own project id in the link) but it doesn't appear to be documented yet.
I have asked the question on SO here
See #SamQuayle's answer there with this link to the official docs.
As noted by various others Firebase does now support account related emails but even better, as of 10 days ago or so it also supports sending any kind of email via Firebase Functions. Lots of details in the docs and example code here.
I used following code to check the email verification after creating new account.
let firAuth = FIRAuth.auth()
firAuth?.addAuthStateDidChangeListener { auth, user in
if let loggedUser = user {
if loggedUser.emailVerified == false {
loggedUser.sendEmailVerificationWithCompletion({ (error) in
print("error:\(error)")
})
}
else {
print(loggedUser.email)
}
} else {
// No user is signed in.
print("No user is signed in.")
}
}
I used MandrillApp. You can create an API key that only allows sending of a template. This way even thought your key is exposed it can't really be abused unless someone wants to fire off tonnes of welcome emails for you.
That was a hack to get myself off the ground. I'm now enabling CORS from a EC2 that uses the token to verify that the user exists before extending them a welcome via SES.

How to make a wall post using windows phone 7 native app

I have created a native app on Windows Phone 7.
The user of the app will provide his login credentials to us when he registers as a new user. What i want to do is to give a handle of share on facebook in my app.
On clicking on the handle the selected image should be posted on to the user's wall and just display a message to the user that the image is posted successfully or not.
The problem is that facebook has not provided with a developent environment for Windows Phone 7 native apps.
I want some alternate solution to this.
thanks for the link. I had already visited the link earlier. I have implemented facebook integration in wp7. Its working properly and i am able to make wall posts.
Here's my code,
//Users clicks on Share on facebook button
private void btnFacebookPost_Click(object sender, RoutedEventArgs e)
{
//Check if access tokens are already set.
if (App.accessTokens == null)
{
GetAccessTokens();
}
else
{
//Use the access tokens to post on facebook
}
}
private void GetAccessTokens()
{
// Navigate user to facebooks login page
// if user has already authenticated your app you'll receive the access tokens directly
webBrowser.Source = new Uri("https://www.facebook.com/dialog/oauth?client_id='your app id'&redirect_uri=https://www.facebook.com/connect/login_success.html&response_type=token&scope='whatever extended permissions you require'");
}
//On The Navigated event of web browser check for access tokens
//Use the facebook c# sdk to get the access tokens from the url
void webBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
FacebookClient fbClient = new FacebookClient();
FacebookOAuthResult oauthResult;
if (fbClient.TryParseOAuthCallbackUrl(e.Uri, out oauthResult))
{
// The url is the result of OAuth 2.0 authentication
if (oauthResult.IsSuccess)
{
App.accessTokens = oauthResult.AccessToken;
}
else
{
var errorDescription = oauthResult.ErrorDescription;
var errorReason = oauthResult.ErrorReason;
}
}
else
{
// The url is NOT the result of OAuth 2.0 authentication.
}
}
Now use the access tokens with the facebook sdk for C#.net to make the wall posts or any other transactions as required.
The problem with this method is that the application user and the facebook's logged in user may be different thus making a transaction to different account.
Since the SSO for WP7 is not available this method should do the trick.