mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-11-11 01:54:04 +08:00
292 lines
8.7 KiB
JavaScript
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();
|
|
});
|
|
});
|
|
};
|