wildduck/lib/api/asps.js
2017-09-17 13:31:02 +03:00

292 lines
8.7 KiB
JavaScript

'use strict';
const config = require('wild-config');
const Joi = require('joi');
const ObjectID = require('mongodb').ObjectID;
const mobileconfig = require('mobileconfig');
const certs = require('../certs').get('api.mobileconfig');
module.exports = (db, server, userHandler) => {
server.get('/users/:user/asps', (req, res, next) => {
res.charSet('utf-8');
const schema = Joi.object().keys({
user: Joi.string()
.hex()
.lowercase()
.length(24)
.required()
});
const result = Joi.validate(req.params, schema, {
abortEarly: false,
convert: true
});
if (result.error) {
res.json({
error: result.error.message
});
return next();
}
let user = new ObjectID(result.value.user);
db.users.collection('users').findOne({
_id: user
}, {
fields: {
address: true
}
}, (err, userData) => {
if (err) {
res.json({
error: 'MongoDB Error: ' + err.message
});
return next();
}
if (!userData) {
res.json({
error: 'This user does not exist'
});
return next();
}
db.users
.collection('asps')
.find({
user
})
.sort({ _id: 1 })
.toArray((err, asps) => {
if (err) {
res.json({
error: 'MongoDB Error: ' + err.message
});
return next();
}
if (!asps) {
asps = [];
}
res.json({
success: true,
results: asps.map(asp => ({
id: asp._id,
description: asp.description,
scopes: asp.scopes,
created: asp.created
}))
});
return next();
});
});
});
server.post('/users/:user/asps', (req, res, next) => {
res.charSet('utf-8');
const schema = Joi.object().keys({
user: Joi.string()
.hex()
.lowercase()
.length(24)
.required(),
description: Joi.string()
.trim()
.max(255)
.required(),
scopes: Joi.array()
.items(
Joi.string()
.valid('imap', 'pop3', 'smtp', 'irc', '*')
.required()
)
.unique(),
generateMobileconfig: Joi.boolean()
.truthy(['Y', 'true', 'yes', 1])
.default(false),
ip: Joi.string().ip({
version: ['ipv4', 'ipv6'],
cidr: 'forbidden'
})
});
if (typeof req.params.scopes === 'string') {
req.params.scopes = req.params.scopes
.split(',')
.map(scope => scope.trim())
.filter(scope => scope);
}
const result = Joi.validate(req.params, schema, {
abortEarly: false,
convert: true
});
if (result.error) {
res.json({
error: result.error.message
});
return next();
}
let user = new ObjectID(result.value.user);
let generateMobileconfig = result.value.generateMobileconfig;
let scopes = result.value.scopes || ['*'];
let description = result.value.description;
if (scopes.includes('*')) {
scopes = ['*'];
}
if (generateMobileconfig && !scopes.includes('*') && (!scopes.includes('imap') || !scopes.includes('smtp'))) {
res.json({
error: 'Profile file requires imap and smtp scopes'
});
return next();
}
db.users.collection('users').findOne({
_id: user
}, {
fields: {
username: true,
name: true,
address: true
}
}, (err, userData) => {
if (err) {
res.json({
error: 'MongoDB Error: ' + err.message
});
return next();
}
if (!userData) {
res.json({
error: 'This user does not exist'
});
return next();
}
userHandler.generateASP(user, result.value, (err, result) => {
if (err) {
res.json({
error: err.message
});
return next();
}
if (!generateMobileconfig) {
res.json({
success: true,
id: result.id,
password: result.password
});
return next();
}
let profileOpts = {};
Object.keys(config.api.mobileconfig || {}).forEach(key => {
profileOpts[key] = (config.api.mobileconfig[key] || '')
.toString()
.replace(/\{email\}/g, userData.address)
.trim();
});
let options = {
displayName: description || profileOpts.displayName,
displayDescription: profileOpts.displayDescription,
accountDescription: profileOpts.accountDescription,
emailAddress: userData.address,
emailAccountName: userData.name,
identifier: profileOpts.identifier + '.' + userData.username,
imap: {
hostname: config.imap.setup.hostname,
port: config.imap.setup.port || config.imap.port,
secure: config.imap.setup.secure,
username: userData.username,
password: result.password
},
smtp: {
hostname: config.smtp.setup.hostname,
port: config.smtp.setup.port || config.smtp.port,
secure: true, //config.setup.smtp.secure,
username: userData.username,
password: false // use the same password as for IMAP
},
keys: certs
};
mobileconfig.getSignedEmailConfig(options, (err, data) => {
if (err) {
res.json({
error: err.message
});
return next();
}
res.json({
success: true,
id: result.id,
password: result.password,
mobileconfig: data.toString('base64')
});
return next();
});
});
});
});
server.del('/users/:user/asps/:asp', (req, res, next) => {
res.charSet('utf-8');
const schema = Joi.object().keys({
user: Joi.string()
.hex()
.lowercase()
.length(24)
.required(),
asp: Joi.string()
.hex()
.lowercase()
.length(24)
.required(),
ip: Joi.string().ip({
version: ['ipv4', 'ipv6'],
cidr: 'forbidden'
})
});
const result = Joi.validate(req.params, schema, {
abortEarly: false,
convert: true
});
if (result.error) {
res.json({
error: result.error.message
});
return next();
}
let user = new ObjectID(result.value.user);
let asp = new ObjectID(result.value.asp);
userHandler.deleteASP(user, asp, result.value, err => {
if (err) {
res.json({
error: err.message
});
return next();
}
res.json({
success: true
});
return next();
});
});
};