2017-11-04 16:59:48 +00:00
|
|
|
const request = require('request');
|
|
|
|
const AWS = require('aws-sdk');
|
|
|
|
const verifier = require('google-id-token-verifier');
|
|
|
|
|
2018-05-06 00:46:33 +00:00
|
|
|
const {
|
|
|
|
USER_BUCKET_NAME = 'stackedit-users',
|
|
|
|
PAYPAL_URI = 'https://www.paypal.com/cgi-bin/webscr',
|
2018-07-17 20:14:05 +00:00
|
|
|
PAYPAL_RECEIVER_EMAIL = 'stackedit.project@gmail.com',
|
2018-05-06 00:46:33 +00:00
|
|
|
GOOGLE_CLIENT_ID,
|
|
|
|
} = process.env;
|
2017-11-04 16:59:48 +00:00
|
|
|
const s3Client = new AWS.S3();
|
|
|
|
|
|
|
|
const cb = (resolve, reject) => (err, res) => {
|
|
|
|
if (err) {
|
|
|
|
reject(err);
|
|
|
|
} else {
|
|
|
|
resolve(res);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getUser = id => new Promise((resolve, reject) => {
|
|
|
|
s3Client.getObject({
|
2018-05-06 00:46:33 +00:00
|
|
|
Bucket: USER_BUCKET_NAME,
|
2017-11-04 16:59:48 +00:00
|
|
|
Key: id,
|
|
|
|
}, cb(resolve, reject));
|
|
|
|
})
|
|
|
|
.then(
|
2018-05-06 00:46:33 +00:00
|
|
|
res => JSON.parse(`${res.Body}`),
|
|
|
|
(err) => {
|
|
|
|
if (err.code !== 'NoSuchKey') {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
2017-11-04 16:59:48 +00:00
|
|
|
|
|
|
|
exports.putUser = (id, user) => new Promise((resolve, reject) => {
|
|
|
|
s3Client.putObject({
|
2018-05-06 00:46:33 +00:00
|
|
|
Bucket: USER_BUCKET_NAME,
|
2017-11-04 16:59:48 +00:00
|
|
|
Key: id,
|
|
|
|
Body: JSON.stringify(user),
|
|
|
|
}, cb(resolve, reject));
|
|
|
|
});
|
|
|
|
|
|
|
|
exports.removeUser = id => new Promise((resolve, reject) => {
|
|
|
|
s3Client.deleteObject({
|
2018-05-06 00:46:33 +00:00
|
|
|
Bucket: USER_BUCKET_NAME,
|
2017-11-04 16:59:48 +00:00
|
|
|
Key: id,
|
|
|
|
}, cb(resolve, reject));
|
|
|
|
});
|
|
|
|
|
2018-05-06 00:46:33 +00:00
|
|
|
exports.getUserFromToken = idToken => new Promise((resolve, reject) => verifier
|
|
|
|
.verify(idToken, GOOGLE_CLIENT_ID, cb(resolve, reject)))
|
2017-11-04 16:59:48 +00:00
|
|
|
.then(tokenInfo => exports.getUser(tokenInfo.sub));
|
|
|
|
|
|
|
|
exports.userInfo = (req, res) => exports.getUserFromToken(req.query.idToken)
|
2018-05-06 00:46:33 +00:00
|
|
|
.then(
|
|
|
|
user => res.send(Object.assign({
|
|
|
|
sponsorUntil: 0,
|
|
|
|
}, user)),
|
|
|
|
err => res
|
|
|
|
.status(400)
|
|
|
|
.send(err ? err.message || err.toString() : 'invalid_token'),
|
|
|
|
);
|
2017-11-04 16:59:48 +00:00
|
|
|
|
|
|
|
exports.paypalIpn = (req, res, next) => Promise.resolve()
|
|
|
|
.then(() => {
|
|
|
|
const userId = req.body.custom;
|
|
|
|
const paypalEmail = req.body.payer_email;
|
|
|
|
const gross = parseFloat(req.body.mc_gross);
|
|
|
|
let sponsorUntil;
|
|
|
|
if (gross === 5) {
|
|
|
|
sponsorUntil = Date.now() + (3 * 31 * 24 * 60 * 60 * 1000); // 3 months
|
|
|
|
} else if (gross === 15) {
|
|
|
|
sponsorUntil = Date.now() + (366 * 24 * 60 * 60 * 1000); // 1 year
|
|
|
|
} else if (gross === 25) {
|
|
|
|
sponsorUntil = Date.now() + (2 * 366 * 24 * 60 * 60 * 1000); // 2 years
|
|
|
|
} else if (gross === 50) {
|
|
|
|
sponsorUntil = Date.now() + (5 * 366 * 24 * 60 * 60 * 1000); // 5 years
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
req.body.receiver_email !== PAYPAL_RECEIVER_EMAIL ||
|
|
|
|
req.body.payment_status !== 'Completed' ||
|
|
|
|
req.body.mc_currency !== 'USD' ||
|
|
|
|
(req.body.txn_type !== 'web_accept' && req.body.txn_type !== 'subscr_payment') ||
|
|
|
|
!userId || !sponsorUntil
|
|
|
|
) {
|
|
|
|
// Ignoring PayPal IPN
|
|
|
|
return res.end();
|
|
|
|
}
|
|
|
|
// Processing PayPal IPN
|
|
|
|
req.body.cmd = '_notify-validate';
|
|
|
|
return new Promise((resolve, reject) => request.post({
|
|
|
|
uri: PAYPAL_URI,
|
|
|
|
form: req.body,
|
|
|
|
}, (err, response, body) => {
|
|
|
|
if (err) {
|
|
|
|
reject(err);
|
|
|
|
} else if (body !== 'VERIFIED') {
|
|
|
|
reject(new Error('PayPal IPN unverified'));
|
|
|
|
} else {
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
.then(() => exports.putUser(userId, {
|
|
|
|
paypalEmail,
|
|
|
|
sponsorUntil,
|
|
|
|
}))
|
|
|
|
.then(() => res.end());
|
|
|
|
})
|
|
|
|
.catch(next);
|
|
|
|
|
|
|
|
exports.checkSponsor = (idToken) => {
|
|
|
|
if (!idToken) {
|
|
|
|
return Promise.resolve(false);
|
|
|
|
}
|
|
|
|
return exports.getUserFromToken(idToken)
|
|
|
|
.then(userInfo => userInfo && userInfo.sponsorUntil > Date.now(), () => false);
|
|
|
|
};
|