Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to create classes without creating an object. #267

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
af3ac4c
Add class creation logic with validation
drew-gross Feb 5, 2016
134f4cb
Add and test logic for adding fields to the DB
drew-gross Feb 5, 2016
669923d
More tests
drew-gross Feb 5, 2016
79c2c9f
Updates tests to allow calls that race to create a schema to have
drew-gross Feb 5, 2016
2c59c28
Added ability to add a validation function to a Cloud Code function
codegefluester Jan 31, 2016
ffadae3
Added function validation
codegefluester Feb 3, 2016
f4216bd
Implement GET /schemas/OneSchema
drew-gross Feb 4, 2016
3fe2a30
Add APNS client
wangmengyan95 Feb 4, 2016
69613bd
Correct function response encoding
laullon Feb 4, 2016
8706149
Updated to 2.0.7
gfosco Feb 5, 2016
b582f1a
Add push parameter checking and query installation
wangmengyan95 Feb 3, 2016
9953097
Update CONTRIBUTING.md
drew-gross Feb 5, 2016
9cc091e
Update CONTRIBUTING.md
drew-gross Feb 5, 2016
fe933a7
Update CONTRIBUTING.md
drew-gross Feb 5, 2016
e738d8a
Adding link to parse-server-example
peterdotjs Feb 5, 2016
c1d688d
Remove default master key.
drew-gross Feb 5, 2016
23d2bdb
Add GCM client
wangmengyan95 Feb 3, 2016
2b5eab4
Added ability to add a validation function to a Cloud Code function
codegefluester Jan 31, 2016
7299fad
Added function validation
codegefluester Feb 3, 2016
001b9f7
Add push parameter checking and query installation
wangmengyan95 Feb 3, 2016
ef89226
Added ability to add a validation function to a Cloud Code function
codegefluester Jan 31, 2016
f4c3ed5
Added function validation
codegefluester Feb 3, 2016
62f8054
Address review comments
drew-gross Feb 6, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions APNS.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
var Parse = require('parse/node').Parse;
// TODO: apn does not support the new HTTP/2 protocal. It is fine to use it in V1,
// but probably we will replace it in the future.
var apn = require('apn');

/**
* Create a new connection to the APN service.
* @constructor
* @param {Object} args Arguments to config APNS connection
* @param {String} args.cert The filename of the connection certificate to load from disk, default is cert.pem
* @param {String} args.key The filename of the connection key to load from disk, default is key.pem
* @param {String} args.passphrase The passphrase for the connection key, if required
* @param {Boolean} args.production Specifies which environment to connect to: Production (if true) or Sandbox
*/
function APNS(args) {
this.sender = new apn.connection(args);

this.sender.on('connected', function() {
console.log('APNS Connected');
});

this.sender.on('transmissionError', function(errCode, notification, device) {
console.error('APNS Notification caused error: ' + errCode + ' for device ', device, notification);
// TODO: For error caseud by invalid deviceToken, we should mark those installations.
});

this.sender.on("timeout", function () {
console.log("APNS Connection Timeout");
});

this.sender.on("disconnected", function() {
console.log("APNS Disconnected");
});

this.sender.on("socketError", console.error);
}

/**
* Send apns request.
* @param {Object} data The data we need to send, the format is the same with api request body
* @param {Array} deviceTokens A array of device tokens
* @returns {Object} A promise which is resolved immediately
*/
APNS.prototype.send = function(data, deviceTokens) {
var coreData = data.data;
var expirationTime = data['expiration_time'];
var notification = generateNotification(coreData, expirationTime);
this.sender.pushNotification(notification, deviceTokens);
// TODO: pushNotification will push the notification to apn's queue.
// We do not handle error in V1, we just relies apn to auto retry and send the
// notifications.
return Parse.Promise.as();
}

/**
* Generate the apns notification from the data we get from api request.
* @param {Object} coreData The data field under api request body
* @returns {Object} A apns notification
*/
var generateNotification = function(coreData, expirationTime) {
var notification = new apn.notification();
var payload = {};
for (key in coreData) {
switch (key) {
case 'alert':
notification.setAlertText(coreData.alert);
break;
case 'badge':
notification.badge = coreData.badge;
break;
case 'sound':
notification.sound = coreData.sound;
break;
case 'content-available':
notification.setNewsstandAvailable(true);
var isAvailable = coreData['content-available'] === 1;
notification.setContentAvailable(isAvailable);
break;
case 'category':
notification.category = coreData.category;
break;
default:
payload[key] = coreData[key];
break;
}
}
notification.payload = payload;
notification.expiry = expirationTime;
return notification;
}

if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
APNS.generateNotification = generateNotification;
}
module.exports = APNS;
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ We really want Parse to be yours, to see it grow and thrive in the open source c

##### Please Do's

* Please write tests to cover new methods.
* Please run the tests and make sure you didn't break anything.
* Take testing seriously! Aim to increase the test coverage with every pull request.
* Run the tests for the file you are working on with `TESTING=1 (repo-root)/node_modules/jasmine/bin/jasmine.js spec/MyFile.spec.js`
* Run the tests for the whole project and look at the coverage report to make sure your tests are exhaustive by running `npm test` and looking at (project-root)/lcov-report/parse-server/FileUnderTest.js.html

##### Code of Conduct

Expand Down
9 changes: 2 additions & 7 deletions ExportAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,7 @@ ExportAdapter.prototype.connect = function() {
var joinRegex = /^_Join:[A-Za-z0-9_]+:[A-Za-z0-9_]+/;
var otherRegex = /^[A-Za-z][A-Za-z0-9_]*$/;
ExportAdapter.prototype.collection = function(className) {
if (className !== '_User' &&
className !== '_Installation' &&
className !== '_Session' &&
className !== '_SCHEMA' &&
className !== '_Role' &&
!joinRegex.test(className) &&
!otherRegex.test(className)) {
if (!Schema.classNameIsValid(className)) {
throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME,
'invalid className: ' + className);
}
Expand Down Expand Up @@ -500,6 +494,7 @@ ExportAdapter.prototype.smartFind = function(coll, where, options) {

var index = {};
index[key] = '2d';
//TODO: condiser moving index creation logic into Schema.js
return coll.createIndex(index).then(() => {
// Retry, but just once.
return coll.find(where, options).toArray();
Expand Down
82 changes: 82 additions & 0 deletions GCM.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
var Parse = require('parse/node').Parse;
var gcm = require('node-gcm');
var randomstring = require('randomstring');

var GCMTimeToLiveMax = 4 * 7 * 24 * 60 * 60; // GCM allows a max of 4 weeks
var GCMRegistrationTokensMax = 1000;

function GCM(apiKey) {
this.sender = new gcm.Sender(apiKey);
}

/**
* Send gcm request.
* @param {Object} data The data we need to send, the format is the same with api request body
* @param {Array} registrationTokens A array of registration tokens
* @returns {Object} A promise which is resolved after we get results from gcm
*/
GCM.prototype.send = function (data, registrationTokens) {
if (registrationTokens.length >= GCMRegistrationTokensMax) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Too many registration tokens for a GCM request.');
}
var pushId = randomstring.generate({
length: 10,
charset: 'alphanumeric'
});
var timeStamp = Date.now();
var expirationTime;
// We handle the expiration_time convertion in push.js, so expiration_time is a valid date
// in Unix epoch time in milliseconds here
if (data['expiration_time']) {
expirationTime = data['expiration_time'];
}
// Generate gcm payload
var gcmPayload = generateGCMPayload(data.data, pushId, timeStamp, expirationTime);
// Make and send gcm request
var message = new gcm.Message(gcmPayload);
var promise = new Parse.Promise();
this.sender.send(message, { registrationTokens: registrationTokens }, 5, function (error, response) {
// TODO: Use the response from gcm to generate and save push report
// TODO: If gcm returns some deviceTokens are invalid, set tombstone for the installation
promise.resolve();
});
return promise;
}

/**
* Generate the gcm payload from the data we get from api request.
* @param {Object} coreData The data field under api request body
* @param {String} pushId A random string
* @param {Number} timeStamp A number whose format is the Unix Epoch
* @param {Number|undefined} expirationTime A number whose format is the Unix Epoch or undefined
* @returns {Object} A promise which is resolved after we get results from gcm
*/
var generateGCMPayload = function(coreData, pushId, timeStamp, expirationTime) {
var payloadData = {
'time': new Date(timeStamp).toISOString(),
'push_id': pushId,
'data': JSON.stringify(coreData)
}
var payload = {
priority: 'normal',
data: payloadData
};
if (expirationTime) {
// The timeStamp and expiration is in milliseconds but gcm requires second
var timeToLive = Math.floor((expirationTime - timeStamp) / 1000);
if (timeToLive < 0) {
timeToLive = 0;
}
if (timeToLive >= GCMTimeToLiveMax) {
timeToLive = GCMTimeToLiveMax;
}
payload.timeToLive = timeToLive;
}
return payload;
}

if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
GCM.generateGCMPayload = generateGCMPayload;
}
module.exports = GCM;
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Read the migration guide here: https://parse.com/docs/server/guide#migrating

There is a development wiki here on GitHub: https://github.com/ParsePlatform/parse-server/wiki

We also have an [example project](https://github.com/ParsePlatform/parse-server-example) using the parse-server module on Express.

---

#### Basic options:
Expand Down Expand Up @@ -58,7 +60,7 @@ var api = new ParseServer({
databaseURI: 'mongodb://localhost:27017/dev',
cloud: '/home/myApp/cloud/main.js', // Provide an absolute path
appId: 'myAppId',
masterKey: 'mySecretMasterKey',
masterKey: '', //Add your master key here. Keep it secret!
fileKey: 'optionalFileKey',
serverURL: 'http://localhost:' + port + '/parse' // Don't forget to change to https if needed
});
Expand Down
Loading