diff --git a/package-lock.json b/package-lock.json index 759bfe2..214fc5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1035,6 +1035,14 @@ "supports-color": "^5.3.0" } }, + "chargebee": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/chargebee/-/chargebee-2.6.5.tgz", + "integrity": "sha512-h11cxGXN+6I47F0Ncj7pemnYO05kLm/vOKPK9mcvdU6K/HByNI/ArlvOLLhpFqjrePfTyCmBTqDYWgYjMP3uJg==", + "requires": { + "q": ">=1.0.1" + } + }, "cheerio": { "version": "0.22.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", @@ -5267,6 +5275,11 @@ } } }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", diff --git a/package.json b/package.json index d1b0c4e..89d63f7 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "async": "2.3.0", "bcryptjs": "2.4.3", "body-parser": "^1.19.0", + "chargebee": "2.6.5", "cheerio": "0.22.0", "config": "1.25.1", "cookie-parser": "~1.4.3", diff --git a/public/javascripts/spacedeck_users.js b/public/javascripts/spacedeck_users.js index 3efa13a..f2c941a 100644 --- a/public/javascripts/spacedeck_users.js +++ b/public/javascripts/spacedeck_users.js @@ -130,9 +130,27 @@ SpacedeckUsers = { $event.stopPropagation(); } - create_user(name, email, password, password_confirmation, invite_code, function(session) { + create_user(name, email, password, password_confirmation, invite_code, function(res) { this.creating_user = false; - this.login_submit(email, password, null, on_success); + + if (res.chargebee_checkout) { + var chargebeeInstance = Chargebee.init({ + site: "spacedeck-test", + enableRedirectMode: true, + enableFriendbuyTracking: false + }); + + chargebeeInstance.openCheckout({ + hostedPage: function() { + return new Promise(function(resolve, reject) { + resolve(res.chargebee_checkout); + }) + } + }); + } else { + // user created, login + this.login_submit(email, password, null, on_success); + } }.bind(this), function(req) { this.creating_user = false; try { diff --git a/routes/api/users.js b/routes/api/users.js index e2e5b2b..59dbc4d 100644 --- a/routes/api/users.js +++ b/routes/api/users.js @@ -23,6 +23,8 @@ var express = require('express'); var router = express.Router(); var glob = require('glob'); +var chargebee = require('chargebee'); + router.get('/current', function(req, res, next) { if (req.user) { var u = _.clone(req.user.dataValues); @@ -39,6 +41,88 @@ router.get('/current', function(req, res, next) { } }); +function createChargebeeCheckout(req, res, plan_id, email, name, company) { + var nameParts = name.split(" "); + var firstName = nameParts.shift(); + var lastName = nameParts.join(" "); + + chargebee.hosted_page.checkout_new({ + subscription: { + plan_id: plan_id + }, + customer: { + first_name: firstName, + last_name: lastName, + email: email, + company: company, + } + }).request(function(error,result) { + if (error) { + console.log(error); + res.status(400).json({"error":error+""}); + } else { + res.status(200).json({"chargebee_checkout":result.hosted_page}); + } + }); +}; + +function createUser(req, res, email, nickname, password) { + bcrypt.genSalt(10, function(err, salt) { + bcrypt.hash(password, salt, function(err, hash) { + crypto.randomBytes(16, function(ex, buf) { + var token = buf.toString('hex'); + + var u = { + _id: uuidv4(), + email: email, + account_type: "email", + nickname: nickname, + password_hash: hash, + prefs_language: req.i18n.locale, + confirmation_token: token + }; + + db.User.create(u) + .error(err => { + res.sendStatus(400); + }) + .then(u => { + var homeFolder = { + _id: uuidv4(), + name: req.i18n.__("home"), + space_type: "folder", + creator_id: u._id + }; + db.Space.create(homeFolder) + .error(err => { + res.sendStatus(400); + }) + .then(homeFolder => { + u.home_folder_id = homeFolder._id; + u.save() + .then(() => { + // home folder created, + // auto accept pending invites + db.Membership.update({ + "state": "active" + }, { + where: { + "email_invited": u.email, + "state": "pending" + } + }); + res.status(201).json({}); + }) + .error(err => { + res.status(400).json(err); + }); + }) + }); + }); + }); + }); +}; + // create user router.post('/', function(req, res) { if (!req.body["email"] || !req.body["password"]) { @@ -51,6 +135,7 @@ router.post('/', function(req, res) { var password = req.body["password"]; var password_confirmation = req.body["password_confirmation"]; var invite_code = req.body["invite_code"]; + var company = req.body["company"] || ""; if (password_confirmation != password) { res.status(400).json({"error":"password_confirmation"}); @@ -67,67 +152,17 @@ router.post('/', function(req, res) { return; } - var createUser = function() { - bcrypt.genSalt(10, function(err, salt) { - bcrypt.hash(password, salt, function(err, hash) { - crypto.randomBytes(16, function(ex, buf) { - var token = buf.toString('hex'); - - var u = { - _id: uuidv4(), - email: email, - account_type: "email", - nickname: nickname, - password_hash: hash, - prefs_language: req.i18n.locale, - confirmation_token: token - }; - - db.User.create(u) - .error(err => { - res.sendStatus(400); - }) - .then(u => { - var homeFolder = { - _id: uuidv4(), - name: req.i18n.__("home"), - space_type: "folder", - creator_id: u._id - }; - db.Space.create(homeFolder) - .error(err => { - res.sendStatus(400); - }) - .then(homeFolder => { - u.home_folder_id = homeFolder._id; - u.save() - .then(() => { - // home folder created, - // auto accept pending invites - db.Membership.update({ - "state": "active" - }, { - where: { - "email_invited": u.email, - "state": "pending" - } - }); - res.status(201).json({}); - }) - .error(err => { - res.status(400).json(err); - }); - }) - }); - }); - }); - }); - }; - db.User.findAll({where: {email: email}}) .then(users => { if (users.length == 0) { - createUser(); + if (config.get('chargebee_integration')) { + // sign up via paid plan trial + createChargebeeCheckout(req, res, config.get('chargebee_default_plan_id'), email, nickname, company); + // TODO: createUser after chargebee checkout + } + else { + createUser(req, res, email, nickname, password); + } } else { res.status(400).json({"error":"user_email_already_used"}); } diff --git a/spacedeck.js b/spacedeck.js index 9e98209..b27d7da 100644 --- a/spacedeck.js +++ b/spacedeck.js @@ -23,6 +23,8 @@ const express = require('express'); const app = express(); const serveStatic = require('serve-static'); +const chargebee = require('chargebee'); + const isProduction = app.get('env') === 'production'; // workaround for libssl_conf.so error triggered by phantomjs @@ -110,6 +112,14 @@ if (app.get('env') == 'development') { module.exports = app; +// ChargeBee Integration (Optional) +if (config.get('chargebee_integration')) { + chargebee.configure({ + site: config.get('chargebee_site'), + api_key: config.get('chargebee_api_key') + }); +} + // CONNECT TO DATABASE db.init(); diff --git a/views/spacedeck.ejs b/views/spacedeck.ejs index d1305bb..5e4577e 100644 --- a/views/spacedeck.ejs +++ b/views/spacedeck.ejs @@ -57,6 +57,9 @@ + + +