diff --git a/.bowerrc b/.bowerrc
index 9c9ea40600..20772d5d24 100644
--- a/.bowerrc
+++ b/.bowerrc
@@ -1,3 +1,8 @@
{
- "directory": "public/bower_components"
+ "directory": "public/bower_components",
+ "storage": {
+ "packages": ".bower-cache",
+ "registry": ".bower-registry"
+ },
+ "tmp": ".bower-tmp"
}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index a7d8e7d2e6..ef989eaea0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ npm-debug.log
lib
public/bower_components
build
+newrelic_agent.log
src/*/*.map
src/*/*/*.map
diff --git a/.nodemonignore b/.nodemonignore
index 216c52f8b0..f4e0b53926 100644
--- a/.nodemonignore
+++ b/.nodemonignore
@@ -6,3 +6,4 @@ Gruntfile.js
CHANGELOG.md
.idea*
.git*
+newrelic_agent.log
diff --git a/config.json.example b/config.json.example
index 5cf560aae6..634d22c7a7 100644
--- a/config.json.example
+++ b/config.json.example
@@ -13,5 +13,6 @@
"SMTP_SERVICE":"Gmail",
"STRIPE_API_KEY":"aaaabbbbccccddddeeeeffff00001111",
"STRIPE_PUB_KEY":"22223333444455556666777788889999",
- "PAYPAL_MERCHANT":"paypal-merchant@gmail.com"
+ "PAYPAL_MERCHANT":"paypal-merchant@gmail.com",
+ "NEW_RELIC_LICENSE_KEY":"NEW_RELIC_LICENSE_KEY"
}
diff --git a/newrelic.js b/newrelic.js
new file mode 100644
index 0000000000..682f608e42
--- /dev/null
+++ b/newrelic.js
@@ -0,0 +1,25 @@
+/**
+ * New Relic agent configuration.
+ *
+ * See lib/config.defaults.js in the agent distribution for a more complete
+ * description of configuration variables and their potential values.
+ */
+var nconf = require('nconf')
+exports.config = {
+ /**
+ * Array of application names.
+ */
+ app_name : ['HabitRPG'],
+ /**
+ * Your New Relic license key.
+ */
+ license_key : nconf.get('NEW_RELIC_LICENSE_KEY'),
+ logging : {
+ /**
+ * Level at which to log. 'trace' is most useful to New Relic when diagnosing
+ * issues with the agent, 'info' and higher will impose the least overhead on
+ * production applications.
+ */
+ level : 'warning'
+ }
+};
diff --git a/package.json b/package.json
index 2ecac913bc..9e3e9a52d4 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,8 @@
"domain-middleware": "~0.1.0",
"swagger-node-express": "git://github.com/lefnire/swagger-node-express#habitrpg",
"passport": "~0.1.18",
- "passport-facebook": "~1.0.2"
+ "passport-facebook": "~1.0.2",
+ "newrelic": "~1.3.0"
},
"private": true,
"subdomain": "habitrpg",
diff --git a/src/controllers/user.js b/src/controllers/user.js
index 5174d6f955..063aa5cceb 100644
--- a/src/controllers/user.js
+++ b/src/controllers/user.js
@@ -166,6 +166,9 @@ acceptablePUTPaths = _.reduce(require('./../models/user').schema.paths, function
if (found) m[leaf]=true;
return m;
}, {})
+_.each('stats.gp'.split(' '), function(removePath){
+ delete acceptablePUTPaths[removePath];
+})
/**
* Update user
@@ -257,6 +260,8 @@ api.addTenGems = function(req, res) {
})
}
+// TODO delete plan
+
/*
Setup Stripe response when posting payment
*/
@@ -264,20 +269,39 @@ api.buyGems = function(req, res) {
var api_key = nconf.get('STRIPE_API_KEY');
var stripe = require("stripe")(api_key);
var token = req.body.id;
- // console.dir {token:token, req:req}, 'stripe'
+ var user = res.locals.user;
async.waterfall([
function(cb){
- stripe.charges.create({
- amount: "500", // $5
- currency: "usd",
- card: token
- }, cb);
+ if (req.query.plan) {
+ stripe.customers.create({
+ email: req.body.email,
+ metadata: {uuid: res.locals.user._id},
+ card: token,
+ plan: req.query.plan,
+ }, cb);
+ } else {
+ stripe.charges.create({
+ amount: "500", // $5
+ currency: "usd",
+ card: token
+ }, cb);
+ }
},
function(response, cb) {
- res.locals.user.balance += 5;
- res.locals.user.purchased.ads = true;
- res.locals.user.save(cb);
+ //user.purchased.ads = true;
+ if (req.query.plan) {
+ user.purchased.plan = {
+ planId:'basic_earned',
+ customerId: response.id,
+ dateCreated: new Date,
+ dateUpdated: new Date,
+ gemsBought: 0
+ };
+ } else {
+ user.balance += 5;
+ }
+ user.save(cb);
}
], function(err, saved){
if (err) return res.send(500, err.toString()); // don't json this, let toString() handle errors
@@ -285,6 +309,29 @@ api.buyGems = function(req, res) {
});
};
+api.cancelSubscription = function(req, res) {
+ var api_key = nconf.get('STRIPE_API_KEY');
+ var stripe = require("stripe")(api_key);
+ var user = res.locals.user;
+ if (!user.purchased.plan.customerId)
+ return res.json(401, {err: "User does not have a plan subscription"});
+
+ async.waterfall([
+ function(cb) {
+ stripe.customers.del(user.purchased.plan.customerId, cb);
+ },
+ function(response, cb) {
+ user.purchased.plan = {};
+ user.markModified('purchased.plan');
+ user.save(cb);
+ }
+ ], function(err, saved){
+ if (err) return res.send(500, err.toString()); // don't json this, let toString() handle errors
+ res.send(200, saved);
+ });
+
+}
+
api.buyGemsPaypalIPN = function(req, res, next) {
res.send(200);
ipn.verify(req.body, function callback(err, msg) {
@@ -298,7 +345,7 @@ api.buyGemsPaypalIPN = function(req, res, next) {
if (_.isEmpty(user)) err = "user not found with uuid " + uuid + " when completing paypal transaction";
if (err) return nex(err);
user.balance += 5;
- user.purchased.ads = true;
+ //user.purchased.ads = true;
user.save();
console.log('PayPal transaction completed and user updated');
});
diff --git a/src/models/user.js b/src/models/user.js
index ef8a8b3e18..391810fb54 100644
--- a/src/models/user.js
+++ b/src/models/user.js
@@ -78,6 +78,13 @@ var UserSchema = new Schema({
skin: {type: Schema.Types.Mixed, 'default': {}}, // eg, {skeleton: true, pumpkin: true, eb052b: true}
hair: {type: Schema.Types.Mixed, 'default': {}},
shirt: {type: Schema.Types.Mixed, 'default': {}},
+ plan: {
+ planId: String,
+ customerId: String,
+ dateCreated: Date,
+ dateUpdated: Date,
+ gemsBought: {type: Number, 'default': 0}
+ }
},
flags: {
diff --git a/src/routes/apiv2.coffee b/src/routes/apiv2.coffee
index 2d8bc073ab..513fb7e312 100644
--- a/src/routes/apiv2.coffee
+++ b/src/routes/apiv2.coffee
@@ -304,6 +304,11 @@ module.exports = (swagger, v2) ->
middleware: auth.auth
action:user.buyGems
+ "/user/cancel-subscription":
+ spec: method: 'POST', description: "Do not use this route"
+ middleware: auth.auth
+ action:user.cancelSubscription
+
"/user/buy-gems/paypal-ipn":
spec:
method: 'POST'
diff --git a/src/server.js b/src/server.js
index a5013dcc44..fb76862fad 100644
--- a/src/server.js
+++ b/src/server.js
@@ -1,5 +1,6 @@
-// Only do the minimal amount of work before forking just in case of a dyno restart
var nconf = require('nconf');
+var utils = require('./utils');
+utils.setupConfig();
require('coffee-script') // remove this once we've fully converted over
var express = require("express");
@@ -8,16 +9,12 @@ var path = require("path");
var domainMiddleware = require('domain-middleware');
var swagger = require("swagger-node-express");
-var utils = require('./utils');
var middleware = require('./middleware');
var TWO_WEEKS = 1000 * 60 * 60 * 24 * 14;
var app = express();
var server;
-// ------------ Setup configurations ------------
-utils.setupConfig();
-
// ------------ MongoDB Configuration ------------
mongoose = require('mongoose');
require('./models/user'); //load up the user schema - TODO is this necessary?
@@ -74,7 +71,8 @@ passport.use(new FacebookStrategy({
// ------------ Server Configuration ------------
app.set("port", nconf.get('PORT'));
-if (!process.env.SUPPRESS) app.use(express.logger("dev"));
+if (nconf.get('NODE_ENV') !== 'production')
+ app.use(express.logger("dev"));
app.use(express.compress());
app.set("views", __dirname + "/../views");
app.set("view engine", "jade");
diff --git a/src/utils.js b/src/utils.js
index 791ba3c57c..e903b3b91c 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -56,6 +56,7 @@ module.exports.setupConfig = function(){
if (nconf.get('NODE_ENV') === "development") {
Error.stackTraceLimit = Infinity;
}
+ if (nconf.get('NODE_ENV') === 'production') require('newrelic');
};
diff --git a/views/shared/modals/new-stuff.jade b/views/shared/modals/new-stuff.jade
index 096590cbce..9eb471415b 100644
--- a/views/shared/modals/new-stuff.jade
+++ b/views/shared/modals/new-stuff.jade
@@ -42,7 +42,7 @@ div(modal='modals.newStuff')
tr
td
h5 Spread The Word Challenge Update
- p We have 2k+ submissions, holy cow! Great job everyone! Now, we need to go through these manually, so it will take a few days to a couple weeks to process. The challenge will stay open until we're done choosing our winners, but be sure to edit the To-Do with your submission URL before 1/31, as that's the cut-off date for processing. We'll send a Tweet out when the winner has been selected, so follow @habitrpg and stay tuned.
+ p We have 1k+ submissions, holy cow! Great job everyone! Now, we need to go through these manually, so it will take a few days to a couple weeks to process. The challenge will stay open until we're done choosing our winners, but be sure to edit the To-Do with your submission URL before 1/31, as that's the cut-off date for processing. We'll send a Tweet out when the winner has been selected, so follow @habitrpg and stay tuned.