How to simulate partial success in `GCM` device group notifications - google-cloud-messaging

When I send notification to Device Groups I get the following response
{
"success": 2,
"failure": 0
}
I wanted to simulate partial success (https://developers.google.com/cloud-messaging/notifications#http_response) so that I can test my retry logic. A response like below-
{
"success":1,
"failure":2,
"failed_registration_ids":[
"regId1",
"regId2"
]
}
How should I do that?

In order to have a "partial success" response, you need to have not_registered_ids and/or invalid_registration_ids. A "not registered id" is a registration id that was valid. According to GCM documentation: "An existing registration token may cease to be valid in a number of scenarios...". You can try the following to have a partial successful push:
Client app unregisters with GCM.
Client app is automatically unregistered, which can happen if the user uninstalls the application.
Client app is updated but the new version is not configured to receive messages.
A partial successful push may also have to_be_retried_ids so that the user can retry these specific registration ids as they failed because the server returned with InternalServerError or Unavailable.

Related

Can we monitor for a particular text like (Name=abc) in API response and get notified in Postman?

API Testing:
Currently, I am using Postman to test API response
I want to monitor a particular text in API response and get notified for example-
{
"productname": "PARLE",
"customer": "ABC",
}
If I get a customer name in the API response as ABC I want to get notified through mail or slack or anything.
Is this possible? if Yes please share me the inputs.
you can run periodic tests with a software like Overseer, and receive notifications using a Notify17 notification template (see the sample recipe).
You could use a test rule like:
http://myurl.com/path must run http with not-content '"customer": "ABC"'
To have an easy start with Overseer, you can check out the Kubernetes deployment example.
You can achieve your use case using Postman Monitors to send an email or send a slack message by following these steps:
Configure your monitor to run with an environment. (Reference: https://learning.getpostman.com/docs/postman/monitors/intro_monitors/)
In the test script of your Collection's Request, fetch the response using pm.response.json() (Based on the response structure you mentioned)
Use the following code snippet to determine whether the response contains what you need:
if (pm.response.json().customer === 'ABC') {
// no op
}
else {
postman.setNextRequest(null);
}
Here, if the condition is not met, then the next request that will be executed is null, which means that the collection execution will stop here. However, if the condition is met, this will not be set and the next request will be executed.
You can use various Public APIs to achieve tasks like send an email or send a slack message:
Gmail API | Slack API
Create a request below the current request titled 'Send notification'. Use the documentation provided to set the request up.
When your monitor runs, if the condition is not met, then postman.setNextRequest will be set to null and the 'Send notification' request will not run. However, if the condition is indeed true, then the request will run and you will receive a notification on the respective channel.

Device Subscription Expired - Fix

I am using PushSharp library to send Push Notification to my Xamarin.Android App. Each time while launching the app, I am checking GCM registration and if registration expires, I am sending the device token to server. Sometimes I am getting
Device Subscription Expired Exception
in log. Due to this exception my device is not receiving notification and sometimes it is getting resolved automatically and I am started receiving notification. I am not sure what is happening. How to fix this issue?
I could handle DeviceSubscriptionExcpetion as below:
gcmBroker.OnNotificationFailed += (notification, aggregateEx) =>
{
if (ex is DeviceSubscriptonExpiredException)
{
var subExc = ex as DeviceSubscriptonExpiredException;
}
}
I could delete the expired token from DB, but my confusion is actually device token is not expired. Device is valid but sometimes unable to receive notification due to this exception.
According to this thread it happens only when we have multiple registration for the same device. But I am storing device token against unique device ID. I am getting device id as below:
try
{
var telephonyManager = (TelephonyManager)Forms.Context.GetSystemService(Android.Content.Context.TelephonyService);
if (telephonyManager != null)
{
deviceId = telephonyManager.DeviceId;
if (string.IsNullOrEmpty(deviceId))
{
deviceId = Android.OS.Build.Serial;
}
}
}
Even though its said that device id is unique, but its changing most of the time. Other way I am guessing to fix this exception is by getting some ID that is always unique in Android device.
Please give some suggestion to fix this issue.
Check NewSubscriptionId property of DeviceSubscriptonExpiredException exception if it is empty then you need request the new registrationId on your phone (start an intent with "com.google.android.c2dm.intent.REGISTER").
In some rare cases try reinstall application.

PushSharp "Notification send timed out" issue

I am trying to use PushSharp to send notification to my mobile devices using Google Gcm.
I downloaded the sample application from github depending upon that I have written my sample code. below is my sample code.
var googleKey = CustomConfigurationManager.GetValueFromSection("appSettings", "GoogleServerAccessKey");
AndroidPushBroker.RegisterGcmService(new PushSharp.Android.GcmPushChannelSettings(googleKey));
GcmNotification androidNotifcation = new GcmNotification().WithDryRun()
.WithJson("{\"alert\":\"Hello World!\",\"badge\":7,\"sound\":\"sound.caf\"}");
AndroidPushBroker.QueueNotification(androidNotifcation);
The issue is though I have used WithDryRun() and upon hooking up request it shows json data with "dry_run": true, but still I receive Notification failed error with reason : "Notification send timed out".
Anybody can tell me what am I missing ?
try to run it without WithDryRun(), and see do you get anything in events like NotificationSent, ChannelException, NotificationFailed or ServiceException.

Extra authentication criteria

I'm trying to implement an extra authentication layer with the purpose of authenticating the user only if he has a certain status.
If the status is different, I want to show a custom login error (Your account has been suspended) and not authenticate the user at all, similar to what happens if the credentials are wrong, but with a different error message.
So far I've tried two options:
I've added a check within a listener that checks for an "InteractiveLoginEvent". Here I can check the user status and set a flash error message but I don't see what's the proper way to redirect back to the login page, since this event has no response method, other than using a header() call which I definitely want to avoid.
I implemented a custom voter, set the "access_decision_manager" startegy to "unanimous" and returned "ACCESS_DENIED" if the status is not allowing the user to authenticate. So far so good, the user cannot access the resources but I see he still gets authenticated. And I definitely don't want that.
I'm not for sure if I'm missing something or if I'm going in the wrong direction.
Since symfony 2 makes a clear difference between authentication and authorization seems that option 2) is related to authorization, so option 1) is more suitable.
So among the "InteractiveLoginEvent" listener I just added the proper check for the user status and by throwing the following exception I managed to implement my functionality as needed:
throw new AuthenticationException('suspend error message');
So the listener looks something like this:
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
if ($this->securityContext->isGranted('ROLE_CUSTOMROLE')) {
$user = $this->securityContext->getToken()->getUser();
// ... check for the user status here
throw new AuthenticationException('Your account has been suspended!');
}
}

Fusion table api migration

I am using fusion table APIs to insert/update data in my table. Last week I migrated my API to new version v1 as referred in this sample. But now, when I run the code, the following error displayed.
400 Bad Request
{
"error" : "unauthorized_client"
}
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "unauthorized_client"
}
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:303)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:323)
at com.google.api.client.auth.oauth2.Credential.executeRefreshToken(Credential.java:607)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:526)
at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:287)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:836)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:412)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:345)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:463)
at com.prasanna.survey.pushapis.FusionPush.insertData(FusionPush.java:198)
at com.prasanna.survey.pushapis.FusionPush.main(FusionPush.java:96)
Java Result: 1
How to debug this error?
This error typically occurs if you change the client_id of an application.
The reason is, you already have an access token for the Fusion API that's based on the old client_id. When you request a refresh token (as you can see is happening in the stack trace) with the new client_id, you get that very unhelpful error message.
The easiest way to handle this is to clear the existing credential from the system so it has to receive a clean access token. You can do this programatically with the Google API Java Client, or you can just remove the file from your system. On my Ubuntu machine, it is located at ~/.credentials/<api-name>.json.