Created
November 25, 2015 12:48
-
-
Save AlexeyKhristov/951a0423b9759ce70de8 to your computer and use it in GitHub Desktop.
simple API example && mailer daemon
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var pmx = require('./common/pmx')('mailer'); | |
const config = require('config'); | |
var co = require('co'); | |
var fs = require('fs'); | |
var nodemailer = require('nodemailer'); | |
var signer = require('nodemailer-dkim').signer; | |
var debug = require('debug')('mailer'); | |
var MAIL_LIMIT = 20; | |
var TEN_SECONDS = 10 * 1000; | |
var THIRTY_SECONDS = 30 * 1000; | |
co(function *init() { | |
var initResults = yield { | |
'checkConfig': checkConfig, | |
'mongoose': new Promise(function (resolve, reject) { | |
var mongoose = require('./common/mongoose'); | |
mongoose.connection.once('open', function () { | |
resolve(mongoose); | |
}); | |
mongoose.connection.once('error', function (err) { | |
reject(err); | |
}); | |
}), | |
'MailModel': require('./apps/email').MailModel.bind(null, null), | |
'transporter': function mailer(cb) { | |
// create reusable transporter object using SMTP transport | |
var transporter = nodemailer.createTransport({ | |
service: 'yandex', | |
auth: { | |
user: config.mail.auth.user, | |
pass: config.mail.auth.password | |
} | |
}); | |
//DKIM | |
transporter.use('stream', signer({ | |
domainName: config.API.domain, | |
keySelector: 'mail', | |
privateKey: fs.readFileSync('config/yandex.ppd.private.pem') | |
})); | |
cb(null, transporter); | |
} | |
}; | |
var mongoose = initResults.mongoose; | |
var transporter = initResults.transporter; | |
var MailModel = initResults.MailModel; | |
console.log('Start mailer'); | |
debug('Start mailer for domain "%s" with pair: %s/%s', config.API.domain, config.mail.auth.user, config.mail.auth.password); | |
var isMongodbOk = true; | |
mongoose.connection.on('error', function (err) { | |
isMongodbOk = false; | |
}); | |
mongoose.connection.on('reconnected', function (err) { | |
isMongodbOk = true; | |
}); | |
function forever() { | |
if (!isMongodbOk) { // test mongo | |
console.error('Mongo is down, wait 30 seconds'); | |
return setTimeout(forever, THIRTY_SECONDS); | |
} | |
co(function *loop() { | |
var models = yield MailModel.find({ | |
'status': MailModel.CONSTS.STATUSES.READY, | |
'mailType': MailModel.CONSTS.MAIL_TYPES.REGISTRATION | |
}).limit(MAIL_LIMIT).exec(); | |
if (models.length === 0) { | |
return setTimeout(forever, TEN_SECONDS); | |
} | |
for (let i in models) { | |
let mailModel = models[i]; | |
yield new Promise(function sendEmail(resolve, reject) { | |
var mailOptions = { | |
from: config.mail.from, | |
to: mailModel.email, | |
subject: 'subject', | |
html: 'body' | |
}; | |
transporter.sendMail(mailOptions, function (err, info) { | |
if (err) { | |
return reject(err); | |
} | |
debug('sent email for "%s", response: %s', mailModel.email, info.response); | |
resolve(); | |
}); | |
}); | |
mailModel.status = MailModel.CONSTS.STATUSES.SEND; | |
yield new Promise(function saveStatus(resolve, reject) { | |
mailModel.save(function (err) { | |
if (err) { | |
return reject(err); | |
} | |
resolve(); | |
}); | |
}); | |
} | |
process.nextTick(forever); | |
}).catch(function (err) { | |
console.error('Send email / Save email model error, retry after 30 seconds: ', err); | |
pmx.notify(err); | |
setTimeout(forever, THIRTY_SECONDS); | |
}); | |
} | |
process.nextTick(forever); | |
}).catch(function initError(err) { | |
console.error('Catch init error', err); | |
pmx.notify(err); | |
}); | |
function checkConfig(cb) { | |
fs.readFile('config/yandex.ppd.private.pem', function (err, data) { | |
if (err) { | |
console.error('Mail Yandex PPD private key file not exists, application stopped'); | |
process.exit(1); | |
} | |
cb(null, true); | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const config = require('config'); | |
var mount = require('koa-mount'); | |
var koa = require('koa'); | |
var app = koa(); | |
require('./initializers')(app); | |
// routes | |
var AuthAPI = require('./apps/auth'); | |
var UsersAPI = require('./apps/users'); | |
app | |
.use(mount('/auth', AuthAPI.middleware())) | |
.use(mount('/users', UsersAPI.middleware())); | |
app.use(function *notFoundRoute() { | |
app.pmx.Inc404HttpCalls(); | |
this.status = 404; | |
this.body = { | |
error: `Route not found for '${this.method}: ${this.request.url}'` | |
}; | |
}); | |
var http = require('http'); | |
var mongoose = require('mongoose'); | |
var server = http.createServer(app.callback()); | |
console.log('Start with environment %s', app.env); | |
mongoose.connection.once('open', function () { | |
console.log('Mongoose connected'); | |
server.listen(config.API.port, function () { | |
console.log('server started on port: %d', config.API.port); | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var Router = require('koa-router'); | |
var appRouter = new Router(); | |
var bodyParser = require('koa-bodyparser')(); | |
var debug = require('debug')('app:auth:index'); | |
/* internal deps */ | |
var LocalController = require('./controller.local'); | |
var FacebookController = require('./controller.facebook'); | |
var VkController = require('./controller.vk'); | |
/* external deps */ | |
module.exports.checkUserAuthentification = require('./check.user.authentification.middleware'); | |
appRouter.post('/local', bodyParser, LocalController.loginLocal); | |
appRouter.post('/registration', bodyParser, LocalController.registrationLocal); | |
appRouter.post('/logout', LocalController.logout); | |
appRouter.post('/authenticate', LocalController.isAuthenticated); | |
appRouter.get('/facebook', FacebookController.loginFacebook); | |
appRouter.get('/facebook/callback', FacebookController.callbackFacebook); | |
appRouter.post('/facebook/deauthorize', bodyParser, FacebookController.deauthorizeFacebook); | |
appRouter.get('/vk', VkController.loginVk); | |
appRouter.get('/vk/callback', VkController.callbackVk); | |
module.exports.middleware = appRouter.middleware.bind(appRouter); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var passport = require('koa-passport'); | |
var debug = require('debug')('app:auth:vk-controller'); | |
var Controller = {}; | |
Controller.loginVk = function *(next) { | |
yield* passport.authenticate('vkontakte').call(this, next); | |
}; | |
Controller.callbackVk = function *(next) { | |
var ctx = this; | |
yield passport.authenticate('vkontakte', function *(err, user, options) { | |
if (err) { | |
console.error('Vk passport strategy callback return error: ', err); | |
ctx.throw(500); | |
} | |
try { | |
yield ctx.login(user); | |
user.lastLogin = Date.now(); | |
yield user.save(); | |
ctx.redirect('/'); | |
} catch (e) { | |
console.error('Passport vk user login/save error: ', e); | |
ctx.throw(500); | |
} | |
}).call(this, next); | |
}; | |
module.exports = Controller; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment