Merge remote-tracking branch 'ParsePlatform/master' into user-roles
This commit is contained in:
234
spec/OneSignalPushAdapter.spec.js
Normal file
234
spec/OneSignalPushAdapter.spec.js
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
|
||||||
|
var OneSignalPushAdapter = require('../src/Adapters/Push/OneSignalPushAdapter');
|
||||||
|
|
||||||
|
describe('OneSignalPushAdapter', () => {
|
||||||
|
it('can be initialized', (done) => {
|
||||||
|
// Make mock config
|
||||||
|
var pushConfig = {
|
||||||
|
oneSignalAppId:"APP ID",
|
||||||
|
oneSignalApiKey:"API KEY"
|
||||||
|
};
|
||||||
|
|
||||||
|
var oneSignalPushAdapter = new OneSignalPushAdapter(pushConfig);
|
||||||
|
|
||||||
|
var senderMap = oneSignalPushAdapter.senderMap;
|
||||||
|
|
||||||
|
expect(senderMap.ios instanceof Function).toBe(true);
|
||||||
|
expect(senderMap.android instanceof Function).toBe(true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get valid push types', (done) => {
|
||||||
|
var oneSignalPushAdapter = new OneSignalPushAdapter();
|
||||||
|
|
||||||
|
expect(oneSignalPushAdapter.getValidPushTypes()).toEqual(['ios', 'android']);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can classify installation', (done) => {
|
||||||
|
// Mock installations
|
||||||
|
var validPushTypes = ['ios', 'android'];
|
||||||
|
var installations = [
|
||||||
|
{
|
||||||
|
deviceType: 'android',
|
||||||
|
deviceToken: 'androidToken'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deviceType: 'ios',
|
||||||
|
deviceToken: 'iosToken'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deviceType: 'win',
|
||||||
|
deviceToken: 'winToken'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deviceType: 'android',
|
||||||
|
deviceToken: undefined
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
var deviceMap = OneSignalPushAdapter.classifyInstallation(installations, validPushTypes);
|
||||||
|
expect(deviceMap['android']).toEqual([makeDevice('androidToken')]);
|
||||||
|
expect(deviceMap['ios']).toEqual([makeDevice('iosToken')]);
|
||||||
|
expect(deviceMap['win']).toBe(undefined);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('can send push notifications', (done) => {
|
||||||
|
var oneSignalPushAdapter = new OneSignalPushAdapter();
|
||||||
|
|
||||||
|
// Mock android ios senders
|
||||||
|
var androidSender = jasmine.createSpy('send')
|
||||||
|
var iosSender = jasmine.createSpy('send')
|
||||||
|
|
||||||
|
var senderMap = {
|
||||||
|
ios: iosSender,
|
||||||
|
android: androidSender
|
||||||
|
};
|
||||||
|
oneSignalPushAdapter.senderMap = senderMap;
|
||||||
|
|
||||||
|
// Mock installations
|
||||||
|
var installations = [
|
||||||
|
{
|
||||||
|
deviceType: 'android',
|
||||||
|
deviceToken: 'androidToken'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deviceType: 'ios',
|
||||||
|
deviceToken: 'iosToken'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deviceType: 'win',
|
||||||
|
deviceToken: 'winToken'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deviceType: 'android',
|
||||||
|
deviceToken: undefined
|
||||||
|
}
|
||||||
|
];
|
||||||
|
var data = {};
|
||||||
|
|
||||||
|
oneSignalPushAdapter.send(data, installations);
|
||||||
|
// Check android sender
|
||||||
|
expect(androidSender).toHaveBeenCalled();
|
||||||
|
var args = androidSender.calls.first().args;
|
||||||
|
expect(args[0]).toEqual(data);
|
||||||
|
expect(args[1]).toEqual([
|
||||||
|
makeDevice('androidToken')
|
||||||
|
]);
|
||||||
|
// Check ios sender
|
||||||
|
expect(iosSender).toHaveBeenCalled();
|
||||||
|
args = iosSender.calls.first().args;
|
||||||
|
expect(args[0]).toEqual(data);
|
||||||
|
expect(args[1]).toEqual([
|
||||||
|
makeDevice('iosToken')
|
||||||
|
]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can send iOS notifications", (done) => {
|
||||||
|
var oneSignalPushAdapter = new OneSignalPushAdapter();
|
||||||
|
var sendToOneSignal = jasmine.createSpy('sendToOneSignal');
|
||||||
|
oneSignalPushAdapter.sendToOneSignal = sendToOneSignal;
|
||||||
|
|
||||||
|
oneSignalPushAdapter.sendToAPNS({'data':{
|
||||||
|
'badge': 1,
|
||||||
|
'alert': "Example content",
|
||||||
|
'sound': "Example sound",
|
||||||
|
'content-available': 1,
|
||||||
|
'misc-data': 'Example Data'
|
||||||
|
}},[{'deviceToken':'iosToken1'},{'deviceToken':'iosToken2'}])
|
||||||
|
|
||||||
|
expect(sendToOneSignal).toHaveBeenCalled();
|
||||||
|
var args = sendToOneSignal.calls.first().args;
|
||||||
|
expect(args[0]).toEqual({
|
||||||
|
'ios_badgeType':'SetTo',
|
||||||
|
'ios_badgeCount':1,
|
||||||
|
'contents': { 'en':'Example content'},
|
||||||
|
'ios_sound': 'Example sound',
|
||||||
|
'content_available':true,
|
||||||
|
'data':{'misc-data':'Example Data'},
|
||||||
|
'include_ios_tokens':['iosToken1','iosToken2']
|
||||||
|
})
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can send Android notifications", (done) => {
|
||||||
|
var oneSignalPushAdapter = new OneSignalPushAdapter();
|
||||||
|
var sendToOneSignal = jasmine.createSpy('sendToOneSignal');
|
||||||
|
oneSignalPushAdapter.sendToOneSignal = sendToOneSignal;
|
||||||
|
|
||||||
|
oneSignalPushAdapter.sendToGCM({'data':{
|
||||||
|
'title': 'Example title',
|
||||||
|
'alert': 'Example content',
|
||||||
|
'misc-data': 'Example Data'
|
||||||
|
}},[{'deviceToken':'androidToken1'},{'deviceToken':'androidToken2'}])
|
||||||
|
|
||||||
|
expect(sendToOneSignal).toHaveBeenCalled();
|
||||||
|
var args = sendToOneSignal.calls.first().args;
|
||||||
|
expect(args[0]).toEqual({
|
||||||
|
'contents': { 'en':'Example content'},
|
||||||
|
'title': {'en':'Example title'},
|
||||||
|
'data':{'misc-data':'Example Data'},
|
||||||
|
'include_android_reg_ids': ['androidToken1','androidToken2']
|
||||||
|
})
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can post the correct data", (done) => {
|
||||||
|
var pushConfig = {
|
||||||
|
oneSignalAppId:"APP ID",
|
||||||
|
oneSignalApiKey:"API KEY"
|
||||||
|
};
|
||||||
|
var oneSignalPushAdapter = new OneSignalPushAdapter(pushConfig);
|
||||||
|
|
||||||
|
var write = jasmine.createSpy('write');
|
||||||
|
oneSignalPushAdapter.https = {
|
||||||
|
'request': function(a,b) {
|
||||||
|
return {
|
||||||
|
'end':function(){},
|
||||||
|
'on':function(a,b){},
|
||||||
|
'write':write
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var installations = [
|
||||||
|
{
|
||||||
|
deviceType: 'android',
|
||||||
|
deviceToken: 'androidToken'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deviceType: 'ios',
|
||||||
|
deviceToken: 'iosToken'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deviceType: 'win',
|
||||||
|
deviceToken: 'winToken'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deviceType: 'android',
|
||||||
|
deviceToken: undefined
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
oneSignalPushAdapter.send({'data':{
|
||||||
|
'title': 'Example title',
|
||||||
|
'alert': 'Example content',
|
||||||
|
'content-available':1,
|
||||||
|
'misc-data': 'Example Data'
|
||||||
|
}}, installations);
|
||||||
|
|
||||||
|
expect(write).toHaveBeenCalled();
|
||||||
|
|
||||||
|
// iOS
|
||||||
|
args = write.calls.first().args;
|
||||||
|
expect(args[0]).toEqual(JSON.stringify({
|
||||||
|
'contents': { 'en':'Example content'},
|
||||||
|
'content_available':true,
|
||||||
|
'data':{'title':'Example title','misc-data':'Example Data'},
|
||||||
|
'include_ios_tokens':['iosToken'],
|
||||||
|
'app_id':'APP ID'
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Android
|
||||||
|
args = write.calls.mostRecent().args;
|
||||||
|
expect(args[0]).toEqual(JSON.stringify({
|
||||||
|
'contents': { 'en':'Example content'},
|
||||||
|
'title': {'en':'Example title'},
|
||||||
|
'data':{"content-available":1,'misc-data':'Example Data'},
|
||||||
|
'include_android_reg_ids':['androidToken'],
|
||||||
|
'app_id':'APP ID'
|
||||||
|
}));
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
function makeDevice(deviceToken, appIdentifier) {
|
||||||
|
return {
|
||||||
|
deviceToken: deviceToken
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
@@ -129,6 +129,22 @@ describe('miscellaneous', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('query without limit get default 100 records', function(done) {
|
||||||
|
var objects = [];
|
||||||
|
for (var i = 0; i < 150; i++) {
|
||||||
|
objects.push(new TestObject({name: 'name' + i}));
|
||||||
|
}
|
||||||
|
Parse.Object.saveAll(objects).then(() => {
|
||||||
|
return new Parse.Query(TestObject).find();
|
||||||
|
}).then((results) => {
|
||||||
|
expect(results.length).toEqual(100);
|
||||||
|
done();
|
||||||
|
}, (error) => {
|
||||||
|
fail(error);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('basic saveAll', function(done) {
|
it('basic saveAll', function(done) {
|
||||||
var alpha = new TestObject({ letter: 'alpha' });
|
var alpha = new TestObject({ letter: 'alpha' });
|
||||||
var beta = new TestObject({ letter: 'beta' });
|
var beta = new TestObject({ letter: 'beta' });
|
||||||
@@ -572,6 +588,35 @@ describe('miscellaneous', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('test cloud function query parameters', (done) => {
|
||||||
|
Parse.Cloud.define('echoParams', (req, res) => {
|
||||||
|
res.success(req.params);
|
||||||
|
});
|
||||||
|
var headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Parse-Application-Id': 'test',
|
||||||
|
'X-Parse-Javascript-Key': 'test'
|
||||||
|
};
|
||||||
|
request.post({
|
||||||
|
headers: headers,
|
||||||
|
url: 'http://localhost:8378/1/functions/echoParams', //?option=1&other=2
|
||||||
|
qs: {
|
||||||
|
option: 1,
|
||||||
|
other: 2
|
||||||
|
},
|
||||||
|
body: '{"foo":"bar", "other": 1}'
|
||||||
|
}, (error, response, body) => {
|
||||||
|
expect(error).toBe(null);
|
||||||
|
var res = JSON.parse(body).result;
|
||||||
|
expect(res.option).toEqual('1');
|
||||||
|
// Make sure query string params override body params
|
||||||
|
expect(res.other).toEqual('2');
|
||||||
|
expect(res.foo).toEqual("bar");
|
||||||
|
delete Parse.Cloud.Functions['echoParams'];
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('test cloud function parameter validation success', (done) => {
|
it('test cloud function parameter validation success', (done) => {
|
||||||
// Register a function with validation
|
// Register a function with validation
|
||||||
Parse.Cloud.define('functionWithParameterValidation', (req, res) => {
|
Parse.Cloud.define('functionWithParameterValidation', (req, res) => {
|
||||||
|
|||||||
@@ -133,26 +133,6 @@ describe('Installations', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails for android with device token', (done) => {
|
|
||||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
|
||||||
var t = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
|
||||||
var device = 'android';
|
|
||||||
var input = {
|
|
||||||
'installationId': installId,
|
|
||||||
'deviceType': device,
|
|
||||||
'deviceToken': t,
|
|
||||||
'channels': ['foo', 'bar']
|
|
||||||
};
|
|
||||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
|
||||||
.then(() => {
|
|
||||||
fail('Should not have been able to create an Installation.');
|
|
||||||
done();
|
|
||||||
}).catch((error) => {
|
|
||||||
expect(error.code).toEqual(114);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('fails for android with missing type', (done) => {
|
it('fails for android with missing type', (done) => {
|
||||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||||
var input = {
|
var input = {
|
||||||
|
|||||||
@@ -1606,7 +1606,30 @@ describe('Parse.User testing', () => {
|
|||||||
}).then(function(newUser) {
|
}).then(function(newUser) {
|
||||||
fail('Session should have been invalidated');
|
fail('Session should have been invalidated');
|
||||||
done();
|
done();
|
||||||
}, function() {
|
}, function(err) {
|
||||||
|
expect(err.code).toBe(Parse.Error.INVALID_SESSION_TOKEN);
|
||||||
|
expect(err.message).toBe('invalid session token');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test parse user become', (done) => {
|
||||||
|
var sessionToken = null;
|
||||||
|
Parse.Promise.as().then(function() {
|
||||||
|
return Parse.User.signUp("flessard", "folo",{'foo':1});
|
||||||
|
}).then(function(newUser) {
|
||||||
|
equal(Parse.User.current(), newUser);
|
||||||
|
sessionToken = newUser.getSessionToken();
|
||||||
|
ok(sessionToken);
|
||||||
|
newUser.set('foo',2);
|
||||||
|
return newUser.save();
|
||||||
|
}).then(function() {
|
||||||
|
return Parse.User.become(sessionToken);
|
||||||
|
}).then(function(newUser) {
|
||||||
|
equal(newUser.get('foo'), 2);
|
||||||
|
done();
|
||||||
|
}, function(e) {
|
||||||
|
fail('The session should still be valid');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
230
src/Adapters/Push/OneSignalPushAdapter.js
Normal file
230
src/Adapters/Push/OneSignalPushAdapter.js
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
"use strict";
|
||||||
|
// ParsePushAdapter is the default implementation of
|
||||||
|
// PushAdapter, it uses GCM for android push and APNS
|
||||||
|
// for ios push.
|
||||||
|
|
||||||
|
const Parse = require('parse/node').Parse;
|
||||||
|
var deepcopy = require('deepcopy');
|
||||||
|
|
||||||
|
function OneSignalPushAdapter(pushConfig) {
|
||||||
|
this.https = require('https');
|
||||||
|
|
||||||
|
this.validPushTypes = ['ios', 'android'];
|
||||||
|
this.senderMap = {};
|
||||||
|
|
||||||
|
pushConfig = pushConfig || {};
|
||||||
|
this.OneSignalConfig = {};
|
||||||
|
this.OneSignalConfig['appId'] = pushConfig['oneSignalAppId'];
|
||||||
|
this.OneSignalConfig['apiKey'] = pushConfig['oneSignalApiKey'];
|
||||||
|
|
||||||
|
this.senderMap['ios'] = this.sendToAPNS.bind(this);
|
||||||
|
this.senderMap['android'] = this.sendToGCM.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an array of valid push types.
|
||||||
|
* @returns {Array} An array of valid push types
|
||||||
|
*/
|
||||||
|
OneSignalPushAdapter.prototype.getValidPushTypes = function() {
|
||||||
|
return this.validPushTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
OneSignalPushAdapter.prototype.send = function(data, installations) {
|
||||||
|
console.log("Sending notification to "+installations.length+" devices.")
|
||||||
|
let deviceMap = classifyInstallation(installations, this.validPushTypes);
|
||||||
|
|
||||||
|
let sendPromises = [];
|
||||||
|
for (let pushType in deviceMap) {
|
||||||
|
let sender = this.senderMap[pushType];
|
||||||
|
if (!sender) {
|
||||||
|
console.log('Can not find sender for push type %s, %j', pushType, data);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let devices = deviceMap[pushType];
|
||||||
|
|
||||||
|
if(devices.length > 0) {
|
||||||
|
sendPromises.push(sender(data, devices));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Parse.Promise.when(sendPromises);
|
||||||
|
}
|
||||||
|
|
||||||
|
OneSignalPushAdapter.prototype.sendToAPNS = function(data,tokens) {
|
||||||
|
|
||||||
|
data= deepcopy(data['data']);
|
||||||
|
|
||||||
|
var post = {};
|
||||||
|
if(data['badge']) {
|
||||||
|
if(data['badge'] == "Increment") {
|
||||||
|
post['ios_badgeType'] = 'Increase';
|
||||||
|
post['ios_badgeCount'] = 1;
|
||||||
|
} else {
|
||||||
|
post['ios_badgeType'] = 'SetTo';
|
||||||
|
post['ios_badgeCount'] = data['badge'];
|
||||||
|
}
|
||||||
|
delete data['badge'];
|
||||||
|
}
|
||||||
|
if(data['alert']) {
|
||||||
|
post['contents'] = {en: data['alert']};
|
||||||
|
delete data['alert'];
|
||||||
|
}
|
||||||
|
if(data['sound']) {
|
||||||
|
post['ios_sound'] = data['sound'];
|
||||||
|
delete data['sound'];
|
||||||
|
}
|
||||||
|
if(data['content-available'] == 1) {
|
||||||
|
post['content_available'] = true;
|
||||||
|
delete data['content-available'];
|
||||||
|
}
|
||||||
|
post['data'] = data;
|
||||||
|
|
||||||
|
let promise = new Parse.Promise();
|
||||||
|
|
||||||
|
var chunk = 2000 // OneSignal can process 2000 devices at a time
|
||||||
|
var tokenlength=tokens.length;
|
||||||
|
var offset = 0
|
||||||
|
// handle onesignal response. Start next batch if there's not an error.
|
||||||
|
let handleResponse = function(wasSuccessful) {
|
||||||
|
if (!wasSuccessful) {
|
||||||
|
return promise.reject("OneSignal Error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(offset >= tokenlength) {
|
||||||
|
promise.resolve()
|
||||||
|
} else {
|
||||||
|
this.sendNext();
|
||||||
|
}
|
||||||
|
}.bind(this)
|
||||||
|
|
||||||
|
this.sendNext = function() {
|
||||||
|
post['include_ios_tokens'] = [];
|
||||||
|
tokens.slice(offset,offset+chunk).forEach(function(i) {
|
||||||
|
post['include_ios_tokens'].push(i['deviceToken'])
|
||||||
|
})
|
||||||
|
offset+=chunk;
|
||||||
|
this.sendToOneSignal(post, handleResponse);
|
||||||
|
}.bind(this)
|
||||||
|
|
||||||
|
this.sendNext()
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
OneSignalPushAdapter.prototype.sendToGCM = function(data,tokens) {
|
||||||
|
data= deepcopy(data['data']);
|
||||||
|
|
||||||
|
var post = {};
|
||||||
|
|
||||||
|
if(data['alert']) {
|
||||||
|
post['contents'] = {en: data['alert']};
|
||||||
|
delete data['alert'];
|
||||||
|
}
|
||||||
|
if(data['title']) {
|
||||||
|
post['title'] = {en: data['title']};
|
||||||
|
delete data['title'];
|
||||||
|
}
|
||||||
|
if(data['uri']) {
|
||||||
|
post['url'] = data['uri'];
|
||||||
|
}
|
||||||
|
|
||||||
|
post['data'] = data;
|
||||||
|
|
||||||
|
let promise = new Parse.Promise();
|
||||||
|
|
||||||
|
var chunk = 2000 // OneSignal can process 2000 devices at a time
|
||||||
|
var tokenlength=tokens.length;
|
||||||
|
var offset = 0
|
||||||
|
// handle onesignal response. Start next batch if there's not an error.
|
||||||
|
let handleResponse = function(wasSuccessful) {
|
||||||
|
if (!wasSuccessful) {
|
||||||
|
return promise.reject("OneSIgnal Error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(offset >= tokenlength) {
|
||||||
|
promise.resolve()
|
||||||
|
} else {
|
||||||
|
this.sendNext();
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
this.sendNext = function() {
|
||||||
|
post['include_android_reg_ids'] = [];
|
||||||
|
tokens.slice(offset,offset+chunk).forEach(function(i) {
|
||||||
|
post['include_android_reg_ids'].push(i['deviceToken'])
|
||||||
|
})
|
||||||
|
offset+=chunk;
|
||||||
|
this.sendToOneSignal(post, handleResponse);
|
||||||
|
}.bind(this)
|
||||||
|
|
||||||
|
|
||||||
|
this.sendNext();
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OneSignalPushAdapter.prototype.sendToOneSignal = function(data, cb) {
|
||||||
|
let headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": "Basic "+this.OneSignalConfig['apiKey']
|
||||||
|
};
|
||||||
|
let options = {
|
||||||
|
host: "onesignal.com",
|
||||||
|
port: 443,
|
||||||
|
path: "/api/v1/notifications",
|
||||||
|
method: "POST",
|
||||||
|
headers: headers
|
||||||
|
};
|
||||||
|
data['app_id'] = this.OneSignalConfig['appId'];
|
||||||
|
|
||||||
|
let request = this.https.request(options, function(res) {
|
||||||
|
if(res.statusCode < 299) {
|
||||||
|
cb(true);
|
||||||
|
} else {
|
||||||
|
console.log('OneSignal Error');
|
||||||
|
res.on('data', function(chunk) {
|
||||||
|
console.log(chunk.toString())
|
||||||
|
});
|
||||||
|
cb(false)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request.on('error', function(e) {
|
||||||
|
console.log("Error connecting to OneSignal")
|
||||||
|
console.log(e);
|
||||||
|
cb(false);
|
||||||
|
});
|
||||||
|
request.write(JSON.stringify(data))
|
||||||
|
request.end();
|
||||||
|
}
|
||||||
|
/**g
|
||||||
|
* Classify the device token of installations based on its device type.
|
||||||
|
* @param {Object} installations An array of installations
|
||||||
|
* @param {Array} validPushTypes An array of valid push types(string)
|
||||||
|
* @returns {Object} A map whose key is device type and value is an array of device
|
||||||
|
*/
|
||||||
|
function classifyInstallation(installations, validPushTypes) {
|
||||||
|
// Init deviceTokenMap, create a empty array for each valid pushType
|
||||||
|
let deviceMap = {};
|
||||||
|
for (let validPushType of validPushTypes) {
|
||||||
|
deviceMap[validPushType] = [];
|
||||||
|
}
|
||||||
|
for (let installation of installations) {
|
||||||
|
// No deviceToken, ignore
|
||||||
|
if (!installation.deviceToken) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let pushType = installation.deviceType;
|
||||||
|
if (deviceMap[pushType]) {
|
||||||
|
deviceMap[pushType].push({
|
||||||
|
deviceToken: installation.deviceToken
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('Unknown push type from installation %j', installation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deviceMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
|
||||||
|
OneSignalPushAdapter.classifyInstallation = classifyInstallation;
|
||||||
|
}
|
||||||
|
module.exports = OneSignalPushAdapter;
|
||||||
@@ -330,7 +330,7 @@ RestWrite.prototype.transformUser = function() {
|
|||||||
if (!this.data.password) {
|
if (!this.data.password) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.query) {
|
if (this.query && !this.auth.isMaster ) {
|
||||||
this.storage['clearSessions'] = true;
|
this.storage['clearSessions'] = true;
|
||||||
}
|
}
|
||||||
return passwordCrypto.hash(this.data.password).then((hashedPassword) => {
|
return passwordCrypto.hash(this.data.password).then((hashedPassword) => {
|
||||||
@@ -509,11 +509,6 @@ RestWrite.prototype.handleInstallation = function() {
|
|||||||
this.data.installationId = this.data.installationId.toLowerCase();
|
this.data.installationId = this.data.installationId.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.data.deviceToken && this.data.deviceType == 'android') {
|
|
||||||
throw new Parse.Error(114,
|
|
||||||
'deviceToken may not be set for deviceType android');
|
|
||||||
}
|
|
||||||
|
|
||||||
var promise = Promise.resolve();
|
var promise = Promise.resolve();
|
||||||
|
|
||||||
if (this.query && this.query.objectId) {
|
if (this.query && this.query.objectId) {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ export class ClassesRouter {
|
|||||||
}
|
}
|
||||||
if (body.limit) {
|
if (body.limit) {
|
||||||
options.limit = Number(body.limit);
|
options.limit = Number(body.limit);
|
||||||
|
} else {
|
||||||
|
options.limit = Number(100);
|
||||||
}
|
}
|
||||||
if (body.order) {
|
if (body.order) {
|
||||||
options.order = String(body.order);
|
options.order = String(body.order);
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
|
|
||||||
handleMe(req) {
|
handleMe(req) {
|
||||||
if (!req.info || !req.info.sessionToken) {
|
if (!req.info || !req.info.sessionToken) {
|
||||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND,
|
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid session token');
|
||||||
'Object not found.');
|
|
||||||
}
|
}
|
||||||
return rest.find(req.config, Auth.master(req.config), '_Session',
|
return rest.find(req.config, Auth.master(req.config), '_Session',
|
||||||
{ _session_token: req.info.sessionToken },
|
{ _session_token: req.info.sessionToken },
|
||||||
@@ -51,8 +50,7 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
if (!response.results ||
|
if (!response.results ||
|
||||||
response.results.length == 0 ||
|
response.results.length == 0 ||
|
||||||
!response.results[0].user) {
|
!response.results[0].user) {
|
||||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND,
|
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid session token');
|
||||||
'Object not found.');
|
|
||||||
} else {
|
} else {
|
||||||
let user = response.results[0].user;
|
let user = response.results[0].user;
|
||||||
return { response: user };
|
return { response: user };
|
||||||
@@ -145,10 +143,10 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
let router = new PromiseRouter();
|
let router = new PromiseRouter();
|
||||||
router.route('GET', '/users', req => { return this.handleFind(req); });
|
router.route('GET', '/users', req => { return this.handleFind(req); });
|
||||||
router.route('POST', '/users', req => { return this.handleCreate(req); });
|
router.route('POST', '/users', req => { return this.handleCreate(req); });
|
||||||
|
router.route('GET', '/users/me', req => { return this.handleMe(req); });
|
||||||
router.route('GET', '/users/:objectId', req => { return this.handleGet(req); });
|
router.route('GET', '/users/:objectId', req => { return this.handleGet(req); });
|
||||||
router.route('PUT', '/users/:objectId', req => { return this.handleUpdate(req); });
|
router.route('PUT', '/users/:objectId', req => { return this.handleUpdate(req); });
|
||||||
router.route('DELETE', '/users/:objectId', req => { return this.handleDelete(req); });
|
router.route('DELETE', '/users/:objectId', req => { return this.handleDelete(req); });
|
||||||
router.route('GET', '/users/me', req => { return this.handleMe(req); });
|
|
||||||
router.route('GET', '/login', req => { return this.handleLogIn(req); });
|
router.route('GET', '/login', req => { return this.handleLogIn(req); });
|
||||||
router.route('POST', '/logout', req => { return this.handleLogOut(req); });
|
router.route('POST', '/logout', req => { return this.handleLogOut(req); });
|
||||||
router.route('POST', '/requestPasswordReset', () => {
|
router.route('POST', '/requestPasswordReset', () => {
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ var router = new PromiseRouter();
|
|||||||
|
|
||||||
function handleCloudFunction(req) {
|
function handleCloudFunction(req) {
|
||||||
if (Parse.Cloud.Functions[req.params.functionName]) {
|
if (Parse.Cloud.Functions[req.params.functionName]) {
|
||||||
|
|
||||||
|
const params = Object.assign({}, req.body, req.query);
|
||||||
|
|
||||||
if (Parse.Cloud.Validators[req.params.functionName]) {
|
if (Parse.Cloud.Validators[req.params.functionName]) {
|
||||||
var result = Parse.Cloud.Validators[req.params.functionName](req.body || {});
|
var result = Parse.Cloud.Validators[req.params.functionName](params);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Validation failed.');
|
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Validation failed.');
|
||||||
}
|
}
|
||||||
@@ -19,7 +22,7 @@ function handleCloudFunction(req) {
|
|||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
var response = createResponseObject(resolve, reject);
|
var response = createResponseObject(resolve, reject);
|
||||||
var request = {
|
var request = {
|
||||||
params: req.body || {},
|
params: params,
|
||||||
master: req.auth && req.auth.isMaster,
|
master: req.auth && req.auth.isMaster,
|
||||||
user: req.auth && req.auth.user,
|
user: req.auth && req.auth.user,
|
||||||
installationId: req.info.installationId
|
installationId: req.info.installationId
|
||||||
|
|||||||
Reference in New Issue
Block a user