Giter Club home page Giter Club logo

loopback-component-push's Introduction

LoopBack Push Notification Component

โš ๏ธ LoopBack 3 is in Maintenance LTS mode, only critical bugs and critical security fixes will be provided. (See Module Long Term Support Policy below.)

We urge all LoopBack 3 users to migrate their applications to LoopBack 4 as soon as possible. Refer to our Migration Guide for more information on how to upgrade.

Overview

StrongLoop Labs projects provide early access to advanced or experimental functionality. In general, these projects may lack usability, completeness, documentation, and robustness, and may be outdated. However, StrongLoop supports these projects: Paying customers can open issues using the StrongLoop customer support system (Zendesk), and community users can report bugs on GitHub.

This module provides a set of LoopBack models to enable mobile device push notifications.

Please see the full documentation: Push notifications.

The loopback-component-push module supersedes loopback-push-notification. Please update your package.json accordingly.

Architecture

push-notification.png

Key Components

  • Device model and APIs to manage devices with applications and users
  • Application model to provide push settings for device types such as ios and android
  • Notification model to capture notification messages and persist scheduled notifications
  • Optional Job to take scheduled notification requests
  • Push connector that interact with device registration records and push providers such as APNS, GCM, and MPNS
  • Push model to provide high level APIs for device-independent push notifications

Samples

Node.js server

This module includes an example LoopBack server application.

To run it, use these commands:

$ cd example/server
$ npm install
$ bower install
$ node app

Open your browser to http://127.0.0.1:3010.

By default, the application uses an in-memory store for the application/installation data. To change to a MongoDB instance, set the MONGODB environment variable to the MongoDB URL. For example,

MONGODB=mongodb://localhost/demo node app

iOS client

The iOS example app uses the LoopBack iOS SDK to enable and handle push notifications.

Android client

The Android example app uses the LoopBack Android SDK to enable and handle push notifications.

References

Module Long Term Support Policy

This module adopts the Module Long Term Support (LTS) policy, with the following End Of Life (EOL) dates:

Version Status Published EOL
3.x Maintenance LTS Dec 2016 Dec 2020

Learn more about our LTS plan in docs.

loopback-component-push's People

Contributors

0candy avatar agnes512 avatar andrejsinigoj avatar ariskemper avatar bajtos avatar candytangnb avatar cgole avatar clarkbw avatar dahinir avatar deniselee avatar dhmlau avatar gunjpan avatar hideya avatar iliraga avatar jannyhou avatar jeveloper avatar jmah avatar nabdelgadir avatar raymondfeng avatar rmg avatar sam-github avatar seriousben avatar siddhipai avatar simonhoibm avatar superkhau avatar timosaikkonen avatar virkt25 avatar yunchancho avatar zbarbuto avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

loopback-component-push's Issues

Avoid duplicate deviceToken and installation records

what's the best practice to avoid multiple Installation records for the same deviceToken?
Trying to add a 'before save' observer but almost feels like there must be a different and easier way.

How do you guys handle that?

Server-2.0 doesn't work, throws timeout error

I get the error below upon pulling this repo and setting up the server-2.0:

/home/skyserpent/sandbox/loopback-component-push/example/server-2.0/server/push-demo.js:64 throw err; ^ Error: Timeout in connecting after 5000 ms

It seems to be calling out this function in push-demo.js:

updateOrCreateApp(function (err, appModel) { if (err) { throw err; } console.log('Application id: %j', appModel.id); });

What could be causing this? I didn't change anything everything is kept stock except that I installed the Node modules and added my GCM key.

Loopback 2.0 + Push?

Should this be working with the latest version of Loopback?

The biggest concern for me is that the documentation, all around, is extremely old or not working at all. Even some of the links are broken (both on the Strongloop website, as well as in other places, such as on the README.md of this repository).

I'm trying to follow along the push notification tutorials, and get a general idea of how to properly set up Loopback 2.0 to act as an iOS-only mBaaS.

This is essentially the only link I've found, but it seems to use Loopback < 2.0.0, so nothing's working: http://docs.strongloop.com/display/LB/Push+notifications#Pushnotifications-SetupyourLoopBackapplicationtosendpushnotifications

As far as I can tell, loopback-component-push can't be initialized with "require('loopback-component-push')(app, { dataSource: db });" anymore, so what's the correct (or easiest) way to do this?

Push Notification issue - iOS

Hi,

I have a problem with sending push notification from my application error. Please someone let me know how to fix this since I am trying to fix this issue for a month now.

events.js:72
throw er; // Unhandled 'error' event
^
TypeError: Cannot set property 'socket' of null
at Object.exports._extend (util.js:573:21)
at normalizeConnectArgs (tls.js:1324:20)
at Object.exports.connect (tls.js:1331:14)
at apnSocketLegacy (/Users/Buddhika/Development/cloud/google/myapp//node_modules/loopback-component-push/node_modules/apn/lib/socket.js:40:19)
at Connection.initialize.spread.fail.terminated (/Users/Buddhika/Development/cloud/google/myapp/node_modules/loopback-component-push/node_modules/apn/lib/connection.js:175:17)
at /Users/Buddhika/Development/cloud/google/myapp/node_modules/loopback-component-push/node_modules/apn/node_modules/q/q.js:1225:26
at _fulfilled (/Users/Buddhika/Development/cloud/google/myapp/node_modules/loopback-component-push/node_modules/apn/node_modules/q/q.js:830:54)
a

Please find my configuration below. Even if I use sample certificates, keys in the example2.0 in the module, the server will crash.

dependencies:

"assert": "^1.3.0",
"compression": "^1.0.3",
"easyimage": "^1.2.2",
"errorhandler": "^1.1.1",
"imageMagick": "^0.1.2",
"loopback": "^2.15.0",
"loopback-boot": "^2.6.5",
"loopback-component-storage": "^1.3.0",
"loopback-connector-mongodb": "^1.8.0",
"loopback-datasource-juggler": "^2.26.4",
"loopback-component-push": "^1.4.4",
"mkdirp": "^0.5.0",
"mongodb": "^1.4.31",
"quickthumb": "0.0.11",
"serve-favicon": "^2.0.1",
"cron": "^1.0.9"

Push settings

var myApp = {
id: 'xxxxxxx',
userId: 'xxxxxx',
name: config.getApplicationName(),

        description: ' xxxx Notification',
        pushSettings: {
            apns: {
                certData: //my apns cert
                keyData: //my apns key,
                pushOptions: {
                    // Extra options can go here for APN
                },
                feedbackOptions: {
                    batchFeedback: true,
                    interval: 300
                }
            },
            gcm: {
                serverApiKey: //my gcm Key, this works perfectly
            }
        }
    };

I can not find a place to attach files here hence I will post my cert and the key.

Key

Bag Attributes
localKeyID: FB 63 93 D8 54 23 F9 88 7B 35 56 91 CC 87 F7 67 C5 8A 9B 56 
Key Attributes: 
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAs3pckX9tucncRtiX0BDT9YumJGhMSW7Xn/yGPxU9zD96dS4q
gApATYOrWfpDWZ8wYnqjIOJ9vYAZPG3Qvbco5hE6fdVVKMNK9C8AcxyXXczomOG1
0YhOwIXTCt1lVcVYcxZeOGOcrlh5sd6RYl8zOMaTcI7aVBxTQuKjy3IUVAp/qnbO
4kpAT6rvXikw6RQqdlH24efqLesk97SyF6RgxPdU9GjD0Pyj/zOL3vjKjtB8oTuF
f8PnA4MpwTNwSIHAKKG3Bj/Q6wVFx30JRRd6n8HXWs3YyWe7TzCekZK+IvaEW+xD
nq0e+12Dup8aKG5CV0sHRDbWYqUzNIWVkBaM+wIDAQABAoIBABzzxDMEZ2LtGUek
cPjzff3CRU7iNEw0QTxhtBZBCvMD2nFEvT5iaPUYJHAjWvH+KAP63I3Ve4syOt/w
pxezkDls1g6ud0pYFqNFYcEv/4r2Hx9qabYfUvTjoaPDCzHG3/nQxeo6x2+ofhkf
WjyQNucVwXsK0FV5LEVB4kJTaMwVj/2hh5gcRLcT/Q+50QN6c4xWXTDYHFPx54up
YgzJyzK4+6kE+0prbJ4tX2bsuSG07/R6ABFc2PmvVnmXJ9UwYde9blNmAGTz69/K
ArIQRkgaYr+6KMLqX4K3MNHLJ8LF/2diwpARWfacRUdNGY/Kq0Zj0pTw/aw+dLig
y4v6+2ECgYEA7GdQKEVQjaEZR62654Ce/+8TCGatGhWZOioe3ozxr3VMDtnF42Wg
6Pik/27x4y8EDeI7wuqX3kY5UNL0qXv67qmEOoFsjZvdDAPxAZJnl4h4eNNeS8J4
XCNByGWQGeR2EGeP5bEU0SK01TqHUMfHwO3TrZZ4jV0TGT1ML76PIo0CgYEAwlsJ
2pZLnwkE0ViCamfjtN+JFstNF0kVS5/xH57yCgWp9Pvqi5W3k6ltMM0bJWcDT9BK
IpYFhjVKOx+zdTwajX+FLEyKuFdJI0ynkyyPuKhE8QbIvyyiaA5sFl2zLdXBAW7V
+bTvI1NsPnGzObaPL1iibedil70d2LRatpSjz6cCgYBimTx/b1mHmLd4g+c+gxDN
4iLoEBsGlBeSgNrbK6Hp8lxEnWPB0jNot7vppZZRkNx6Be+y/jFVTai+Ix5USheA
z0cNN8nUzjtFtachZrS6KPtGObJMmtGkbDgVovaVNgpgETGdNVxfVcBiZsTlVk3k
E82DywyAuV8r2bsa9rmwSQKBgCrCwuk/1gV4g4HXumHU16mM4OmN8zkjUDciSnfN
ja0cz+bhohnx58DqLubkyYsyHe1qg1UWssJzaRCXCfHKNoFZRCCZ+o9STPoiPGBK
FpjnFLv+5R4CoPzJ54gIN4rnE57QFu3onBCmoxMeCvOwsdIV6y7JEM0Xw8BQ9gBj
taLTAoGBAKSuPFNG4F9ZKCLa+ElNxvL4V+xLm4pxjVf2fJ9HA8Ity2/9DAGj6r3N
seWrcCH7HUiXkV447PsmDO47oHPJcr9ygf0NlAEF8jjoWEGFBSP9OpEBRg8XS6yv
HxskBsdPgpaLlMzohhtS5sfySHUhgkO64bBpHqWwKxw7gLGFmUGI
-----END RSA PRIVATE KEY-----

Cert

Bag Attributes
localKeyID: FB 63 93 D8 54 23 F9 88 7B 35 56 91 CC 87 F7 67 C5 8A 9B 56 
subject=/UID=com.fishrank.app/CN=Apple Development IOS Push Services: com.fishrank.app/OU=C2JEACD3CH/C=US
issuer=/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority
-----BEGIN CERTIFICATE-----
MIIFhTCCBG2gAwIBAgIIcJJfOCsLiB0wDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNV
BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
HhcNMTUwNTIyMDMwNDI2WhcNMTYwNTIxMDMwNDI2WjCBhDEgMB4GCgmSJomT8ixk
AQEMEGNvbS5maXNocmFuay5hcHAxPjA8BgNVBAMMNUFwcGxlIERldmVsb3BtZW50
IElPUyBQdXNoIFNlcnZpY2VzOiBjb20uZmlzaHJhbmsuYXBwMRMwEQYDVQQLDApD
MkpFQUNEM0NIMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBALN6XJF/bbnJ3EbYl9AQ0/WLpiRoTElu15/8hj8VPcw/enUuKoAKQE2D
q1n6Q1mfMGJ6oyDifb2AGTxt0L23KOYROn3VVSjDSvQvAHMcl13M6JjhtdGITsCF
0wrdZVXFWHMWXjhjnK5YebHekWJfMzjGk3CO2lQcU0Lio8tyFFQKf6p2zuJKQE+q
714pMOkUKnZR9uHn6i3rJPe0shekYMT3VPRow9D8o/8zi974yo7QfKE7hX/D5wOD
KcEzcEiBwCihtwY/0OsFRcd9CUUXep/B11rN2Mlnu08wnpGSviL2hFvsQ56tHvtd
g7qfGihuQldLB0Q21mKlMzSFlZAWjPsCAwEAAaOCAeUwggHhMB0GA1UdDgQWBBTj
H8OBR8xuNVY13ksdC6r+xFehrDAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFIgnFwmp
thhgi+zruvZHWcVSVKO3MIIBDwYDVR0gBIIBBjCCAQIwgf8GCSqGSIb3Y2QFATCB
8TCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRl
IGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBw
bGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNl
cnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0
ZW1lbnRzLjApBggrBgEFBQcCARYdaHR0cDovL3d3dy5hcHBsZS5jb20vYXBwbGVj
YS8wTQYDVR0fBEYwRDBCoECgPoY8aHR0cDovL2RldmVsb3Blci5hcHBsZS5jb20v
Y2VydGlmaWNhdGlvbmF1dGhvcml0eS93d2RyY2EuY3JsMAsGA1UdDwQEAwIHgDAT
BgNVHSUEDDAKBggrBgEFBQcDAjAQBgoqhkiG92NkBgMBBAIFADANBgkqhkiG9w0B
AQUFAAOCAQEAkTXcifA298nhBZD23DxKo++K9rICl5Jn/txL9Cg2gwSToPH7zzUf
3eu+52s681g7EyqXLIGawzbgTGiwe8cLQbrIyBChO73+ydlbKVCIEb8/Y8RxMx0y
/sfxPPEHBAnJDqOu2trYI3jPVyOy4uyAJCHRKq15T1xvbpPqqK3UCrUWauVTXolG
APnKJjkg6N9Fnonmr4q42+Y/aYqjbSM08b31oNEauZX1gOTtX9CkpX/UQZXRCwMZ
HZ+qB/+aw1aniVTez9dDw8GVTc0AmokA/jzo2h2IECSWxtsxvEgjZSDClGEBbGSr
774b0xYWXF9Pj/SJuGnpTjNTYg0iZVB50w==
-----END CERTIFICATE-----

Thanks
Buddhika

loopback-component-push is not installed

Hey all,

I'm getting an issue with the example apps (server & server-2.0)

I do npm install and all looks good
Then when I slc run I get an error:

WARNING: LoopBack connector "loopback-component-push" is not installed as any of the following modules:

 ./connectors/loopback-component-push
loopback-connector-loopback-component-push
loopback-component-push

To fix, run:

    npm install loopback-component-push


events.js:72
        throw er; // Unhandled 'error' event

Not sure what's going on /:

Thanks!


PS: Originally got this issue on my production application, then tried it on the example apps and got the issues as well...

Validation error on Notification model

The Push model reports a validation error on the Notification object when using the API. Error does not occur when you create a Notification using the 'new Notification(...)' constructor.

APNS Push error

I'm trying to push notifications to my iOS app and I get the following error when the server tries to send the notification. Could someone please point me to the cause?

pushing notification to "5546bdf06c21b74d6eb4ee0f"
events.js:85

events.js:85
      throw er; // Unhandled 'error' event
            ^
Error: socket hang up
    at TLSSocket.onHangUp (_tls_wrap.js:961:21)
    at TLSSocket.g (events.js:199:16)
    at TLSSocket.emit (events.js:129:20)
    at _stream_readable.js:908:16
    at /Users/ajay/projects/igazab-backend/node_modules/loopback/node_modules/continuation-local-storage/node_modules/async-listener/glue.js:188:31
    at process._tickDomainCallback (node.js:381:11)
    at process.<anonymous> (/Users/ajay/projects/igazab-backend/node_modules/loopback/node_modules/continuation-local-storage/node_modules/async-listener/index.js:18:15)

Loopback-component-push version : 1.5.1
Node version : v0.12.2
slc version : v3.1.1

It seems that notifyByQuery method with 'inq' operator didn't work

I tried to send a notification to devices with specified userId.
But It seems that notifyByQuery method with 'inq' operator didn't work.
I don't know what it wrong with filter string.

For checking 'notifyByQuery', I modified filter in push-manager.js as below.

PushManager.prototype.notifyByQuery = function(installationQuery, notification, cb) {
  assert.ok(cb, 'callback should be defined');
  var self = this;
  var list = [];

  list.push('553dbde51da38a1a0bfc2f8c');
  list.push('553dc6bb8bf8f63a0e99039a');

 //var filter = { where: installationQuery};

// Query success
var filter = { where: { userId: '553dbde51da38a1a0bfc2f8c'}};

// Empty result
var filter = { where: {userId: {inq: list} } };
var filter = { where : { userId: {inq: [ '553dbde51da38a1a0bfc2f8c','553dc6bb8bf8f63a0e99039a' ]}}};

Keeping deviceToken of the installation up to date

This is a question about what would be the right way to handle deviceToken expiration and refresh.
Here are two use cases and the ways I assume they are being handled:

  1. client submits a new token which is different from the previous one, it will be saved as a separate installation, and will be used to send push notifications; the previous one will be removed eventually as it becomes gone device (based on enabled feedback service support);
  2. client submits a token using POST (create), which is the same as the previous one. Second installation will be created, which has the same deviceToken. For the sake of API simplicity it may not make any sense to handle this on client side. Then, on the backend side it requires some simple logic based on search for installation with the same deviceToken and probably just updating modified timestamp, however, it will change the POST (create) logic from create to createOrUpdate, which is still different from PUT, as it would not operate with the installation ID.

Could you please validate my assumptions and let me know what would be the good way to handle use case 2.

GCM push notifcations not sending full data dictionary

I've set up to push notifications to Android devices after having already set them up for iOS.
However, when the notifications come down to the Android app, the data dictionary is missing most of the values

{object=2562, type=NewQuestionAlert, contentAvailable=true, collapse_key=do_not_collapse}

when the notification object is

var note = new loopbackPush.Notification({
  expirationInterval: 3600,
  contentAvailable: true,
  badge: badge,
  alert: message,
  type: type,
  object: object
});

I determined the root of the problem seems to be in the gcm.js file's _createMessage function when copying data from the notification object to the message object.

Object.keys(notification).forEach(function (key) {

This is only iterating through three keys at the base level of the object, where as all the key/value pairs et when creating the notification are stored deeper in __data.

Object.keys(notification.__data).forEach(function (key) {

seems to be the quickest way to get it to iterate through the correct keys and put them in the message object, meaning it comes down correctly

{deviceToken=adevicetoken, object=2562, type=NewQuestionAlert, alert=This is some text, badge=15, deviceType=android, expirationInterval=3600, created=2015-12-22T05:08:35.569Z, contentAvailable=true, collapse_key=do_not_collapse}

But I'm not sure if this is the best solution to the problem.

Simplify the plugin API

I an offline discussion with @ritch, he said the new way of writing loopback plugins is to make them regular node modules exporting a bunch of functions. Instead of making it a module exporting super function accepting app & options and returning back the exported functions.

We should update LBPN to follow the new style, ideally before the first release. Along the way, we should IMO get rid of the push-connector and export directly push-manager methods, probably dissolving the PushManager into a set of exported functions.

// old style
var PushModel = require('loopback-push-notification')(
  app, { dataSource: db });

// new style
var push = require('loopback-push-notification');

// this is optional, loopback should auto-attach
// the model to the default data source
push.Notification.attachTo(customDb);

push.on('error', /* handle errors */);

push.notifyById(id, msg, cb);

@raymondfeng What's your opinion? Is there any catch we should be aware of?

Recommended ACLs for Installation Model

I have a question regarding the correct usage of the installation model. The clients must be able to read and modify none but "their own" installation (the one it has the deviceToken of (?)). I cannot use the $owner role here because there is no relation to User.

Any thoughts?

Push notifications testing strategy

I wonder if you have any suggestions how to implement testing strategy of push notifications implemented using LoopBack's push component. Use case:

  • System sends a push notification with a number to a User. The problem is to make sure that the proper number is sent.

Since the message is sent to a remote service, the first option would be putting man-in-the-middle and validating expectations based on what was caught. That's what can be done with nock and HTTP, but not for APNs and sockets. Mitm.js can handle this on a necessary lower level. However, for testing purposes, we don't want to establish real connection to APNs for a valid app. And that basically means that since a connection will not be established, nothing will ever be sent and caught by Mitm as a result.
I tried to approach this from another angle by verifying that Notification instance is created, assuming that if it is in database, the framework took care of sending the message properly. However, as per http://docs.strongloop.com/display/LB/Push+notifications regular Notifications are not saved to database (unless they are scheduled):

Notification model to capture notification messages and persist scheduled notifications.

Could you please suggest any ways how to test this in isolation without real APNs communication?

GCM device not registered error

When a gcm device is no longer registered, I am getting the error:

"TypeError: Object 'deviceToken' has no method 'map'
at /loopback-connector-mongodb/lib/mongodb.js:422:32"

Looking at the code of "lib/providers/gcm.js", on line 35:
self.emit('devicesGone', deviceToken);

It probably should be:

self.emit('devicesGone', registrationIds);

Because the emitted data for 'devicesGone' should be an array and not a string.

Error Connecting to APNS doesn't show

Hey,

Followed the documentation provided here:
http://docs.strongloop.com/display/DOC/Creating+push+notifications#Creatingpushnotifications-Configuretheapplicationwithpushsettings

When configuring the loopback server with APNS there is nothing in the documentation that explains you need to specify a port in the push options. If no port is specified then it is null, causing a connection error (connecting to APNS).

No error shows in PushModel methods fn callbacks (e.g. notifyByQuery) or by listening for push connector errors, the two methods of catching errors described here:
http://docs.strongloop.com/display/DOC/Creating+push+notifications#Creatingpushnotifications-Errorhandling

Made it very had to debug, since the absence of server errors made everything server-side appear to be working.

Installation and Notification models are not found

I used npm to install loopback-component-push but when I try to use Installation as a base model I get the following.

/home/user/app/node_modules/loopback/lib/registry.js:273
  throw new Error('Model not found: ' + modelName);
        ^
Error: Model not found: Installation
    at Function.registry.getModel (/home/user/app/node_modules/loopback/lib/registry.js:273:9)
    at Function.registry.createModel (/home/user/app/node_modules/loopback/lib/registry.js:103:22)
    at /home/user/app/node_modules/loopback-boot/lib/executor.js:187:28
    at Array.forEach (native)
    at defineModels (/home/user/app/node_modules/loopback-boot/lib/executor.js:171:23)
    at setupModels (/home/user/app/node_modules/loopback-boot/lib/executor.js:160:3)
    at execute (/home/user/app/node_modules/loopback-boot/lib/executor.js:33:3)
    at bootLoopBackApp (/home/user/app/node_modules/loopback-boot/index.js:129:3)
    at Object.<anonymous> (/home/user/app/server/server.js:10:1)
    at Module._compile (module.js:456:26)

I checked and double checked everything in the example/server-2.0 to make sure I was doing everything the same so I am not sure why the model is not showing up. I tried the example as a sanity check and it has no problem finding the models.

server/models/installation.json

{
   "name": "installation",
   "base": "Installation"
}

server/model-config.json

{
  "_meta": {
    "sources": [
      "loopback/common/models",
      "loopback/server/models",
      "../common/models",
      "./models"
    ]   
  },

...

  "installation": {
    "dataSource": "db",
    "public": true
  },
  "app": {
    "dataSource": "db",
    "public": true
  }
}

server/server.js

var loopback = require('loopback');
var boot = require('loopback-boot');
//var path = require('path');
var app = module.exports = loopback();


//app.use(loopback.static(path.resolve(__dirname, '../client/www/')));
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname);

...

package.json

{
  "name": "app",
  "version": "1.0.0",
  "main": "server/server.js",
  "scripts": {
    "pretest": "jshint .",
    "test": "mocha"
  },  
  "dependencies": {
    "async": "^0.9.0",
    "bower": "^1.3.12",
    "compression": "^1.0.3",
    "errorhandler": "^1.1.1",
    "loopback": "^2.8.0",
    "loopback-boot": "^2.4.0",
    "loopback-component-push": "~1.3.0",
    "loopback-component-storage": "^1.3.0",
    "loopback-connector-mongodb": "^1.6.0",
    "loopback-datasource-juggler": "^2.7.0",
    "serve-favicon": "^2.0.1"
  },  
  "optionalDependencies": {
    "loopback-explorer": "^1.1.0"
  },  
  "devDependencies": {
    "jshint": "^2.5.6",
    "mocha": "^2.1.0",
    "supertest": "^0.15.0"
  },  
  "repository": {
    "type": "", 
    "url": ""
  },  
  "description": "Testing push"
}

Component Realiability

Hi Guys,

I have found three issues with the Push Component that stops it from currently being reliable in a production environment.

When you are sending high-volume Push Notifications to Apple, especially in their development sandbox, sometimes Apple will reject a perfectly good Notification because it will detect a device token error. However, if you have the "retryLimit" set to a positive value, the APN module will retry to send a failed notification.

The problem with this comes in four places:

  1. After a umber of failed notifications, Apple will abruptly kill the socket. This is normal behaviour but it causes an uncaught exception inside of "loopback->contination-local-storage->glue.js" https://github.com/othiym23/async-listener/blob/master/glue.js#L188 This will cause the Node process to die, and you will never get the retry on your Push Notification. When I wrap it with `try { ... } catch(e) {console.log(e);}' I get the expected behaviour.
  2. There seems to be something wrong with how we are emitting transmissionError messages. Here https://github.com/strongloop/loopback-component-push/blob/master/lib/providers/apns.js#L69-L72 It seems like we are trying to emit the transmissionError message, but we are mangling it. This error is important because it is the one that lets you know exactly which message has been rejected by Apple.
  3. If the code above worked just fine, I assume there would be a matching block here: https://github.com/strongloop/loopback-component-push/blob/master/lib/push-manager.js#L129-L131 to catch the transmissionError and to send it up the chain.
  4. However even it is was, I never seem to get these messages from the PushManager. I expected to be able to something like:
var PushModel = app.models.Push;

PushModel.on('error', function (err) {
console.log('PushNotification->error: %j', err);
});

PushModel.on('transmissionError', function (code, notification, recipient) {
console.log('PushNotification->transmissionError: %j', code, notification, recipient);
});

But neither the 'error' or 'transmissionError' events make it further up the chain.

What am I missing here?

No Content in notification on GCM

Hey all,

So running the example app (server-2.0) and sending a push notification works great on iOS but when sent to Android devices, the push has no content.

{
  "deviceType": "ios",
  "deviceToken": "__token__",
  "alert": "test message",
  "badge": 1,
  "sound": "ping.aiff",
  "expirationInterval": 3600
}

--> I see a push notification on my iPhone saying "test message"

{
  "deviceType": "android",
  "deviceToken": "__token__",
  "alert": "test message",
  "badge": 1,
  "sound": "ping.aiff",
  "expirationInterval": 3600
}

--> I see a push notification on my android device saying "" (no content)

Am I missing something with regards to content?

According to http://developer.android.com/google/gcm/server.html#params there is no specific data member for the message...


I did notice that in apns.js and gcm.js the iteration over the notification object members does not do anything:
gcm.js:

Object.keys(notification).forEach(function (key) {
    if (notification[key] != null) {
      message.addData(key, notification[key]);
    }
  });

--> message.data is undefined
apns.js

Object.keys(notification).forEach(function (key) {
    note.payload[key] = notification[key];
  });

--> note.payload is undefined

Configuring Application (push notification settings)

Provisioning a new Application for push notification is all but not easy in our present solution. The same is true for changing the configuration of an existing Application (e.g. add GCM config to an Application that used to have APNS only).

Before the change proposed in #15, the server removed all existing data and created a new Application, which got a new id assigned by MongoDB. Since iOS and Android mobile apps have the Application id hard-coded, they had to be rebuilt after each restart.

After #15, the Application is created only once, which solves the problem mentioned above. Because the sample server is using a database available to general public, I am intentionally not rewriting existing Applications. This makes it difficult to change the push settings once the Application was created.

I feel we are lacking a configuration tool here. It could be a CLI, or a simple built-in website similar to loopback-explorer.

Or maybe we should change the demo app, so that it does not use a shared database?

@raymondfeng @ritch @Schoonology your thoughts?

Correctly handle GCM response for multiple repositories

When the notification is sent to multiple devices, we returning the status/error code of the first token for all tokens. It is very likely that some of the tokens are valid (the notification was sent) and only subset of tokens is reject.

See #41.

Need add custom provider

I use other messaging provider instead of gcm. so I have to code like this:

var Provider = require('customprovider');

var PushManager = require('loopback-component-push/lib/push-manager');
PushManager.providers.android_lc = leancloudProvider;

It's ugly, any better way?

Notification model not working as in the examples. data parameter required

I've been testing push notifications for GCM following the examples at https://github.com/strongloop/loopback-component-push/tree/master/example/server-2.0. Although the notification was arriving to the mobile phone the message I got from the Bundle.extras was:

Bundle[{android.support.content.wakelockid=9, collapse_key=do_not_collapse, from=212428590570}]

So the actual message I'm sending is not arriving.I'm assuming that the alert parameter is supposed to be parsed from the mobile clients, so received in the push notification. Here the Notification object:

      var Notification = Test.app.models.notification;
      var note = new Notification({
        expirationInterval: 3600, // Expires 1 hour from now.
        //badge: 2,
        sound: 'ping.aiff',
        alert: message
      });

So I changed it for this and it worked

      var note = new Notification({
        expirationInterval: 3600, // Expires 1 hour from now.
        //badge: 2,
        sound: 'ping.aiff',
        alert: message,
        message : message
      });

Actually any other parameter added to the Notification object will arrive.
Is alert doing what is supposed to? Or should the documentation be updated to reflect that at least the "message" parameter is required. Probably in order to clarify the example at https://github.com/strongloop/loopback-component-push/tree/master/example/server-2.0 should add some other parameters so who reads it understand that additional data can be sent.

Regression 1.0 -> 1.2

When I attempted to upgrade loopback-android tests from v1.0 to v1.2, I am getting the following error:

TypeError: object is not a function
    at Object.<anonymous> (/Users/bajtos/src/loopback/android/test-server/index.js:12:17)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:902:3

Here is the relevant code:

var lbpn = require('loopback-push-notification');
var PushModel = lbpn(app, { dataSource: app.datasources.Memory });

The documentation describes the same API usage:

var loopback = require('loopback');
var app = loopback();
var db = require('./data-sources/db');
// Load & configure loopback-push-notification
var PushModel = require('loopback-push-notification')(app, { dataSource: db });

According to semver, major versions should preserve backwards compatibility, which seems to not be the case here.

/to @raymondfeng It seems the problem was introduced by your commit 4c2c785.

Using `alert` property in android pushes doesn't work

Caused by alert not being an enumerable property on Notification.

Workaround is:

 Object.defineProperty(notification, 'alert', {
  value: notification.alert,
  writable: true,
  enumerable: true,
  configurable: true
});

iOS sample app has inappropriate code to handle push registration

It doesn't seem appropriate to invoke [UIApplication registerUserNotificationSettings:] (or [UIApplication registerForRemoteNotificationTypes:] on iOS 7) in [UIApplicationDelegate application:didFinishLaunchingWithOptions:] of AppDelegate.m.

The code example found in Push notifications for iOS apps doesn't do it. Instead, reading the iOS SDK code, [UIApplication registerUserNotificationSettings:] is supposed to be invoked as a consequence of an invocation of [LBPushNotification application: didFinishLaunchingWithOptions:] (which is also done in [UIApplicationDelegate application:didFinishLaunchingWithOptions:]).

It looks that the code is put there to deal with a backward incompatible change regarding [UIApplication registerForRemoteNotificationTypes:] taken place in iOS 8. The issue should have been fixed inside of the SDK code, but the seemingly temporary patch is done in the demo code to make it work somehow on iOS 8.

I supposed the followings need to be taken place:
(1) Fix the [UIApplication registerForRemoteNotificationTypes:] issue in the iOS SDK (this issue has been filed as strongloop-community/loopback-sdk-ios#32 (comment))
(2) Revert the patch done in the iOS sample app (a part of PR #67)

RFC: a better name for Device entity

The current API we have in loopback-push-notification can be little bit confusing for LoopBack users - mobile developers.

For most mobile developers, a Device is the physical item and a Device Id is a unique identifier of this physical item.

In LoopBack, we are using Device to represent a concept of a single instance/installation of an app on a device. A Device Id is an identifier of a Device record in the datastore (database).

This confusion shows in the API. At the moment, we have PushManager.pushByRegistrationId(registrationId, notification) where registrationId is the id of our Device record. PushManager.pushByDeviceId(deviceId, notification) would be more appropriate, but it may give an impression that deviceId is the id of the physical phone.

What better name can we come up with? --> Installation.

ToDo list:

  • Rename Device model to Installation
  • iOS SDK: iRename LBDevice to LBInstallation
  • iOS SDK: fix LBDevice to use "installations" instead of "devices" as the REST-full name

RFC: How to support both development and production mode for push notifications

Push notification services such as APNS and GCM support both development and production mode. Each mode requires different settings, including:

  • hostname/port
  • certificates

For a LoopBack application, it needs to have a way to support both modes.

There are a few options:

  1. Allow the client application to have both dev/prod push settings in the Application model. Add an option to the Push connector config to set the mode. And it can be default to NODE_ENV === 'production'.
  2. Use external configuration management tool such as Chef or Puppet to swap the configuration when the application is moved from dev to prod.

Thanks,
Raymond

/push rest api gives me 500 error but the message gets through

Can someone give me an example of how to send a push notification with Strongloop using the REST API?

What endpoint do I use? POST /push or POST /notifications?

Docs do not tell me what the difference is and when to use which.

When I send a test push notification using /push REST API I'm getting a 500 error.

http://localhost:3010/api/push
Response Body
{
  "error": {
    "name": "Error",
    "status": 500,
    "message": "Cannot configure push notifications - unknown application id \"MyLoopBackApp\"",
    "details": {
      "appId": "MyLoopBackApp"
    },
    "stack": "Error: Cannot configure push notifications - unknown application id \"MyLoopBackApp\"\n   
  }
}

Ironically, the push message actually works. So I don't understand the error. I assure you that MyLoopBackApp is not my app id. It's loopback-component-push-app The only place this text is on my computer is in some device-registration-test.js files that are for testing this component.

When I send a push notification using the /notifications API, I get a 200 success but the message never comes to my phone.

The notificaiton I'm sending is:

{"deviceType":["android"],"deviceToken":["APA91bGIiIpDdrJ797BvCjNjXPuZ4qKr_L2MjPjASDFWerYUiNB9AhvnjEQhWIHxAfRMa5nn9vUdlgbyMmnERS3asCtyDHbpElazIN66D9djRGWWH08FTBMwMXniuvmiKIhskVIPRQw"],"badge" : 5, "sound": "ping.aiff", "alert": "Hello World", "messageFrom": "Errfan"}

Creating a submodel for Installation breaks find* methods

Find* methods refer to Installation.find* instead of this.find*, thus causing a "Error: Cannot call Installation.find(). The find method has not been setup. The PersistedModel has not been correctly attached to a DataSource!"

Pull request following shortly.

Server 2.0 Push Notification Error

Getting an error when pushing using the server 2.0 example. I've verified that my cert and key are valid. Any help?

pushing notification to "xxxxxxxxxxxxxxxxxxxxxxxx"
Push Notification error: TypeError: Cannot set property 'socket' of null
at Object.exports._extend (util.js:572:21)
at normalizeConnectArgs (tls.js:1316:20)
at Object.exports.connect (tls.js:1323:14)
at Connection. (/Users/jonathanrhone/WrkSrc/reela/loopback-component-push/example/server-2.0/node_modules/loopback-component-push/node_modules/apn/lib/connection.js:224:21)
at /Users/jonathanrhone/WrkSrc/reela/loopback-component-push/example/server-2.0/node_modules/loopback-component-push/node_modules/apn/node_modules/q/q.js:1142:26
at _fulfilled (/Users/jonathanrhone/WrkSrc/reela/loopback-component-push/example/server-2.0/node_modules/loopback-component-push/node_modules/apn/node_modules/q/q.js:787:54)
at self.promiseDispatch.done (/Users/jonathanrhone/WrkSrc/reela/loopback-component-push/example/server-2.0/node_modules/loopback-component-push/node_modules/apn/node_modules/q/q.js:816:30)
at Promise.promise.promiseDispatch (/Users/jonathanrhone/WrkSrc/reela/loopback-component-push/example/server-2.0/node_modules/loopback-component-push/node_modules/apn/node_modules/q/q.js:749:13)
at /Users/jonathanrhone/WrkSrc/reela/loopback-component-push/example/server-2.0/node_modules/loopback-component-push/node_modules/apn/node_modules/q/q.js:509:49
at flush (/Users/jonathanrhone/WrkSrc/reela/loopback-component-push/example/server-2.0/node_modules/loopback-component-push/node_modules/apn/node_modules/q/q.js:108:17)

Setting not to remove installations on devicesGone event

Maybe would be good to add main setting, which doesnt remove installations on devicesGone event, but it sets the date when application was deleted. It should set for example field that the device is gone and then notifications are not send to this installations.
Reason for this is further processing and knowing how many installations were deleted for specific app.

push notification to angularjs app

Hi, It is possible to use this module to send push notifications to web app based on angularjs.
I don't found any documentation how to use loopback to send push notifications to web apps.
I want for exemple when i add data from api explorer it send push notifications and in my client view i can listen loopback server. Please share any code or documentation about this topic.

Thanks

demo-server has no method 'findById' when pushing to Android emulator

When I tried to push notifications using demo-server/app.js to my Android emulator I got:

POST /notify/52e2e52d6cd08aa031b3ddc6 500 1ms
TypeError: Object function ModelConstructor(data, dataSource) {
if(!(this instanceof ModelConstructor)) {
return new ModelConstructor(data, dataSource);
}
if(ModelClass.settings.unresolved) {
throw new Error('Model ' + ModelClass.modelName + ' is not defined.');
}
ModelBaseClass.apply(this, arguments);
if(dataSource) {
hiddenProperty(this, '__dataSource', dataSource);
}
} has no method 'findById'
at PushManager.notifyById (/Users/qihanzhang/git/loopback-push-notification/example/demo-server/lib/push-manager.js:168:21)
at Function.f as notifyById
at /Users/qihanzhang/git/loopback-push-notification/example/demo-server/app.js:149:15
at callbacks (/Users/qihanzhang/git/loopback-push-notification/example/demo-server/node_modules/loopback/node_modules/express/lib/router/index.js:164:37)
at param (/Users/qihanzhang/git/loopback-push-notification/example/demo-server/node_modules/loopback/node_modules/express/lib/router/index.js:138:11)
at param (/Users/qihanzhang/git/loopback-push-notification/example/demo-server/node_modules/loopback/node_modules/express/lib/router/index.js:135:11)
at pass (/Users/qihanzhang/git/loopback-push-notification/example/demo-server/node_modules/loopback/node_modules/express/lib/router/index.js:145:5)
at Router._dispatch (/Users/qihanzhang/git/loopback-push-notification/example/demo-server/node_modules/loopback/node_modules/express/lib/router/index.js:173:5)
at Object.router (/Users/qihanzhang/git/loopback-push-notification/example/demo-server/node_modules/loopback/node_modules/express/lib/router/index.js:33:10)
at next (/Users/qihanzhang/git/loopback-push-notification/example/demo-server/node_modules/loopback/node_modules/express/node_modules/connect/lib/proto.js:193:15)

Loopback-component-push doesn't work well when automigrating application,notification,installation models.

When one add the line
require('./push')(app); to server.js and the user has configured the automigration of application,notifcation and installation models. The error pops up that the table is not available for model. This is happening because even before the model is created, the code inside push.js starts.

https://github.com/harshil93/loopback-component-push-bug-example

The above code is setup for mysql automigration and crashes.

Cannot POST /notify/1123 (custom route)

Hi,
I have imported the client package from server to server-2.0 (loopback-component-push) to manually push to a particular device form index.html. But when I execute the "notify/:id" customer route as written in push-demo.js it gives me the following error. I think in loopback 2.0 there is the new routing way. If so is there an example to follow? I have tried to put a routing in router/index.js file and included the router in server.js, it can find the route but it cannot find the notification/installation models from app.

Error: Cannot POST /notify/1123
    at raiseUrlNotFoundError (/Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/lib/middleware/urlNotFound.js:15:17)
    at Layer.handle [as handle_request] (/Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/node_modules/express/lib/router/layer.js:82:5)
    at trim_prefix (/Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/node_modules/express/lib/router/index.js:271:13)
    at /Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/node_modules/express/lib/router/index.js:238:9
    at Function.proto.process_params (/Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/node_modules/express/lib/router/index.js:313:12)
    at /Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/node_modules/express/lib/router/index.js:229:12
    at Function.match_layer (/Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/node_modules/express/lib/router/index.js:296:3)
    at next (/Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/node_modules/express/lib/router/index.js:190:10)
    at serveStatic (/Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/node_modules/express/node_modules/serve-static/index.js:59:14)
    at Layer.handle [as handle_request] (/Users/shahriarnewaz/AndroidStudioProjects/assignment/probe/probe-server/node_modules/loopback/node_modules/express/lib/router/layer.js:82:5)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.