wildduck/api.js
2017-03-06 16:13:40 +02:00

180 lines
4.6 KiB
JavaScript

'use strict';
const config = require('config');
const restify = require('restify');
const log = require('npmlog');
const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;
const Joi = require('joi');
const bcrypt = require('bcryptjs');
const punycode = require('punycode');
let database;
const server = restify.createServer();
server.use(restify.bodyParser({
maxBodySize: 0,
mapParams: true,
mapFiles: false,
overrideParams: false
}));
server.post('/user/create', (req, res, next) => {
const schema = Joi.object().keys({
username: Joi.string().email().required(),
password: Joi.string().min(3).max(100).required()
});
const result = Joi.validate(req.params, schema, {
abortEarly: false,
convert: true,
allowUnknown: true
});
if (result.error) {
res.json({
error: result.error.message
});
return next();
}
let username = normalizeAddress(result.value.username);
let password = result.value.password;
database.collection('users').findOne({
username
}, (err, user) => {
if (err) {
return res.json({
error: 'MongoDB Error: ' + err.message,
username
});
}
if (user) {
return res.json({
error: 'This username already exists',
username
});
}
let hash = bcrypt.hashSync(password, 8);
database.collection('users').insertOne({
username,
password: hash
}, (err, result) => {
if (err) {
return res.json({
error: 'MongoDB Error: ' + err.message,
username
});
}
let uidValidity = Math.floor(Date.now() / 1000);
database.collection('mailboxes').insertMany([{
username,
path: 'INBOX',
uidValidity,
uidNext: 1,
modifyIndex: 0,
subscribed: true
}, {
username,
path: 'Sent Mail',
specialUse: '\\Sent',
uidValidity,
uidNext: 1,
modifyIndex: 0,
subscribed: true
}, {
username,
path: 'Trash',
specialUse: '\\Trash',
uidValidity,
uidNext: 1,
modifyIndex: 0,
subscribed: true
}, {
username,
path: 'Junk',
specialUse: '\\Junk',
uidValidity,
uidNext: 1,
modifyIndex: 0,
subscribed: true
}], {
w: 1,
ordered: false
}, err => {
if (err) {
return res.json({
error: 'MongoDB Error: ' + err.message,
username
});
}
res.json({
success: true,
id: result.insertedId,
username
});
return next();
});
});
});
});
function normalizeAddress(address, withNames) {
if (typeof address === 'string') {
address = {
address
};
}
if (!address || !address.address) {
return '';
}
let user = address.address.substr(0, address.address.lastIndexOf('@'));
let domain = address.address.substr(address.address.lastIndexOf('@') + 1);
let addr = user.trim() + '@' + punycode.toASCII(domain.toLowerCase().trim());
if (withNames) {
return {
name: address.name || '',
address: addr
};
}
return addr;
}
module.exports = (imap, done) => {
MongoClient.connect(config.mongo, (err, mongo) => {
if (err) {
log.error('LMTP', 'Could not initialize MongoDB: %s', err.message);
return;
}
database = mongo;
let started = false;
server.on('error', err => {
if (!started) {
started = true;
return done(err);
}
log.error('API', err);
});
server.listen(config.api.port, config.api.host, () => {
if (started) {
return server.close();
}
started = true;
log.info('API', 'Server listening on %s:%s', config.api.host || '0.0.0.0', config.api.port);
done(null, server);
});
});
};