mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-12-27 02:10:52 +08:00
fix(api-domainaccess): Added all DomainAccess endpoints to api docs generation ZMS-144 (#670)
* added add domain to whitelist/blocklist api endpoints to api docs generation * added all get and del domainaccess endpoints to api docs generation
This commit is contained in:
parent
6e251c5bae
commit
c846b66e17
1 changed files with 315 additions and 23 deletions
|
@ -5,22 +5,49 @@ const ObjectId = require('mongodb').ObjectId;
|
||||||
const tools = require('../tools');
|
const tools = require('../tools');
|
||||||
const roles = require('../roles');
|
const roles = require('../roles');
|
||||||
const { sessSchema, sessIPSchema } = require('../schemas');
|
const { sessSchema, sessIPSchema } = require('../schemas');
|
||||||
|
const { successRes } = require('../schemas/response/general-schemas');
|
||||||
|
|
||||||
module.exports = (db, server) => {
|
module.exports = (db, server) => {
|
||||||
server.post(
|
server.post(
|
||||||
'/domainaccess/:tag/:action',
|
{
|
||||||
|
path: '/domainaccess/:tag/allow',
|
||||||
|
tags: ['DomainAccess'],
|
||||||
|
summary: 'Add domain to allowlist',
|
||||||
|
description: 'If an email is sent from a domain that is listed in the allowlist then it is never marked as spam. Lists apply for tagged users.',
|
||||||
|
validationObjs: {
|
||||||
|
requestBody: {
|
||||||
|
domain: Joi.string()
|
||||||
|
.max(255)
|
||||||
|
//.hostname()
|
||||||
|
.required()
|
||||||
|
.description('Domain name to allowlist for users/addresses that include this tag'),
|
||||||
|
sess: sessSchema,
|
||||||
|
ip: sessIPSchema
|
||||||
|
},
|
||||||
|
queryParams: {},
|
||||||
|
pathParams: {
|
||||||
|
tag: Joi.string().trim().max(128).required().description('Tag to look for')
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
200: {
|
||||||
|
description: 'Success',
|
||||||
|
model: Joi.object({
|
||||||
|
success: successRes,
|
||||||
|
id: Joi.string().required().description('ID for the created record')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
tools.responseWrapper(async (req, res) => {
|
tools.responseWrapper(async (req, res) => {
|
||||||
res.charSet('utf-8');
|
res.charSet('utf-8');
|
||||||
|
|
||||||
const schema = Joi.object().keys({
|
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
|
||||||
tag: Joi.string().trim().max(128).required(),
|
|
||||||
domain: Joi.string()
|
const schema = Joi.object({
|
||||||
.max(255)
|
...pathParams,
|
||||||
//.hostname()
|
...requestBody,
|
||||||
.required(),
|
...queryParams
|
||||||
action: Joi.string().valid('allow', 'block').required(),
|
|
||||||
sess: sessSchema,
|
|
||||||
ip: sessIPSchema
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = schema.validate(req.params, {
|
const result = schema.validate(req.params, {
|
||||||
|
@ -43,7 +70,110 @@ module.exports = (db, server) => {
|
||||||
let domain = tools.normalizeDomain(result.value.domain);
|
let domain = tools.normalizeDomain(result.value.domain);
|
||||||
let tag = result.value.tag;
|
let tag = result.value.tag;
|
||||||
let tagview = tag.toLowerCase();
|
let tagview = tag.toLowerCase();
|
||||||
let action = result.value.action;
|
let action = 'allow';
|
||||||
|
|
||||||
|
let r;
|
||||||
|
try {
|
||||||
|
r = await db.database.collection('domainaccess').findOneAndUpdate(
|
||||||
|
{
|
||||||
|
tagview,
|
||||||
|
domain
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$setOnInsert: {
|
||||||
|
tag,
|
||||||
|
tagview,
|
||||||
|
domain
|
||||||
|
},
|
||||||
|
|
||||||
|
$set: {
|
||||||
|
action
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
upsert: true,
|
||||||
|
projection: { _id: true },
|
||||||
|
returnDocument: 'after'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500);
|
||||||
|
return res.json({
|
||||||
|
error: 'MongoDB Error: ' + err.message,
|
||||||
|
code: 'InternalDatabaseError'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: !!(r && r.value),
|
||||||
|
id: ((r && r.value && r.value._id) || '').toString()
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
server.post(
|
||||||
|
{
|
||||||
|
path: '/domainaccess/:tag/block',
|
||||||
|
tags: ['DomainAccess'],
|
||||||
|
summary: 'Add domain to blocklist',
|
||||||
|
description: 'If an email is sent from a domain that is listed in the blocklist then it is always marked as spam. Lists apply for tagged users.',
|
||||||
|
validationObjs: {
|
||||||
|
requestBody: {
|
||||||
|
domain: Joi.string()
|
||||||
|
.max(255)
|
||||||
|
//.hostname()
|
||||||
|
.required()
|
||||||
|
.description('Domain name to blocklist for users/addresses that include this tag'),
|
||||||
|
sess: sessSchema,
|
||||||
|
ip: sessIPSchema
|
||||||
|
},
|
||||||
|
queryParams: {},
|
||||||
|
pathParams: {
|
||||||
|
tag: Joi.string().trim().max(128).required().description('Tag to look for')
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
200: {
|
||||||
|
description: 'Success',
|
||||||
|
model: Joi.object({
|
||||||
|
success: successRes,
|
||||||
|
id: Joi.string().required().description('ID for the created record')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tools.responseWrapper(async (req, res) => {
|
||||||
|
res.charSet('utf-8');
|
||||||
|
|
||||||
|
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
|
||||||
|
|
||||||
|
const schema = Joi.object({
|
||||||
|
...pathParams,
|
||||||
|
...requestBody,
|
||||||
|
...queryParams
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = schema.validate(req.params, {
|
||||||
|
abortEarly: false,
|
||||||
|
convert: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
res.status(400);
|
||||||
|
return res.json({
|
||||||
|
error: result.error.message,
|
||||||
|
code: 'InputValidationError',
|
||||||
|
details: tools.validationErrors(result)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// permissions check
|
||||||
|
req.validate(roles.can(req.role).createAny('domainaccess'));
|
||||||
|
|
||||||
|
let domain = tools.normalizeDomain(result.value.domain);
|
||||||
|
let tag = result.value.tag;
|
||||||
|
let tagview = tag.toLowerCase();
|
||||||
|
let action = 'block';
|
||||||
|
|
||||||
let r;
|
let r;
|
||||||
try {
|
try {
|
||||||
|
@ -85,16 +215,50 @@ module.exports = (db, server) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
server.get(
|
server.get(
|
||||||
'/domainaccess/:tag/:action',
|
{
|
||||||
|
path: '/domainaccess/:tag/allow',
|
||||||
|
tags: ['DomainAccess'],
|
||||||
|
summary: 'List allowlisted domains',
|
||||||
|
validationObjs: {
|
||||||
|
requestBody: {},
|
||||||
|
queryParams: {
|
||||||
|
ess: sessSchema,
|
||||||
|
ip: sessIPSchema
|
||||||
|
},
|
||||||
|
pathParams: {
|
||||||
|
tag: Joi.string().trim().max(128).required().description('Tag to look for')
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
200: {
|
||||||
|
description: 'Success',
|
||||||
|
model: Joi.object({
|
||||||
|
success: successRes,
|
||||||
|
results: Joi.array()
|
||||||
|
.items(
|
||||||
|
Joi.object({
|
||||||
|
id: Joi.string().required().description('Entry ID'),
|
||||||
|
domain: Joi.string().required().description('Allowlisted domain name'),
|
||||||
|
action: Joi.string().required().description('Action: `allow`').example('allow')
|
||||||
|
})
|
||||||
|
.required()
|
||||||
|
.$_setFlag('objectName', 'GetAllowedDomainResult')
|
||||||
|
)
|
||||||
|
.description('Domain list')
|
||||||
|
.required()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
tools.responseWrapper(async (req, res) => {
|
tools.responseWrapper(async (req, res) => {
|
||||||
res.charSet('utf-8');
|
res.charSet('utf-8');
|
||||||
|
|
||||||
const schema = Joi.object().keys({
|
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
|
||||||
tag: Joi.string().trim().max(128).required(),
|
|
||||||
action: Joi.string().valid('allow', 'block').required(),
|
|
||||||
|
|
||||||
sess: sessSchema,
|
const schema = Joi.object({
|
||||||
ip: sessIPSchema
|
...pathParams,
|
||||||
|
...requestBody,
|
||||||
|
...queryParams
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = schema.validate(req.params, {
|
const result = schema.validate(req.params, {
|
||||||
|
@ -116,7 +280,110 @@ module.exports = (db, server) => {
|
||||||
|
|
||||||
let tag = result.value.tag;
|
let tag = result.value.tag;
|
||||||
let tagview = tag.toLowerCase();
|
let tagview = tag.toLowerCase();
|
||||||
let action = result.value.action;
|
let action = 'action';
|
||||||
|
|
||||||
|
let domains;
|
||||||
|
try {
|
||||||
|
domains = await db.database
|
||||||
|
.collection('domainaccess')
|
||||||
|
.find({
|
||||||
|
tagview,
|
||||||
|
action
|
||||||
|
})
|
||||||
|
.sort({
|
||||||
|
domain: 1
|
||||||
|
})
|
||||||
|
.toArray();
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500);
|
||||||
|
return res.json({
|
||||||
|
error: 'MongoDB Error: ' + err.message,
|
||||||
|
code: 'InternalDatabaseError'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!domains) {
|
||||||
|
domains = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
results: domains.map(domainData => ({
|
||||||
|
id: domainData._id.toString(),
|
||||||
|
domain: domainData.domain,
|
||||||
|
action
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
server.get(
|
||||||
|
{
|
||||||
|
path: '/domainaccess/:tag/block',
|
||||||
|
tags: ['DomainAccess'],
|
||||||
|
summary: 'List blocklisted domains',
|
||||||
|
validationObjs: {
|
||||||
|
requestBody: {},
|
||||||
|
queryParams: {
|
||||||
|
ess: sessSchema,
|
||||||
|
ip: sessIPSchema
|
||||||
|
},
|
||||||
|
pathParams: {
|
||||||
|
tag: Joi.string().trim().max(128).required().description('Tag to look for')
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
200: {
|
||||||
|
description: 'Success',
|
||||||
|
model: Joi.object({
|
||||||
|
success: successRes,
|
||||||
|
results: Joi.array()
|
||||||
|
.items(
|
||||||
|
Joi.object({
|
||||||
|
id: Joi.string().required().description('Entry ID'),
|
||||||
|
domain: Joi.string().required().description('Blocklisted domain name'),
|
||||||
|
action: Joi.string().required().description('Action: `block`').example('block')
|
||||||
|
})
|
||||||
|
.required()
|
||||||
|
.$_setFlag('objectName', 'GetBlockedDomainResult')
|
||||||
|
)
|
||||||
|
.description('Domain list')
|
||||||
|
.required()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tools.responseWrapper(async (req, res) => {
|
||||||
|
res.charSet('utf-8');
|
||||||
|
|
||||||
|
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
|
||||||
|
|
||||||
|
const schema = Joi.object({
|
||||||
|
...pathParams,
|
||||||
|
...requestBody,
|
||||||
|
...queryParams
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = schema.validate(req.params, {
|
||||||
|
abortEarly: false,
|
||||||
|
convert: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
res.status(400);
|
||||||
|
return res.json({
|
||||||
|
error: result.error.message,
|
||||||
|
code: 'InputValidationError',
|
||||||
|
details: tools.validationErrors(result)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// permissions check
|
||||||
|
req.validate(roles.can(req.role).readAny('domainaccess'));
|
||||||
|
|
||||||
|
let tag = result.value.tag;
|
||||||
|
let tagview = tag.toLowerCase();
|
||||||
|
let action = 'block';
|
||||||
|
|
||||||
let domains;
|
let domains;
|
||||||
try {
|
try {
|
||||||
|
@ -154,14 +421,39 @@ module.exports = (db, server) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
server.del(
|
server.del(
|
||||||
'/domainaccess/:domain',
|
{
|
||||||
|
path: '/domainaccess/:domain',
|
||||||
|
tags: ['DomainAccess'],
|
||||||
|
summary: 'Delete a Domain from listing',
|
||||||
|
validationObjs: {
|
||||||
|
requestBody: {},
|
||||||
|
queryParams: {
|
||||||
|
sess: sessSchema,
|
||||||
|
ip: sessIPSchema
|
||||||
|
},
|
||||||
|
pathParams: {
|
||||||
|
domain: Joi.string().hex().lowercase().length(24).required().description("Listed domain's unique ID")
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
200: {
|
||||||
|
description: 'Success',
|
||||||
|
model: Joi.object({
|
||||||
|
success: successRes,
|
||||||
|
deleted: Joi.string().required().description("Deleted domain's unique ID")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
tools.responseWrapper(async (req, res) => {
|
tools.responseWrapper(async (req, res) => {
|
||||||
res.charSet('utf-8');
|
res.charSet('utf-8');
|
||||||
|
|
||||||
const schema = Joi.object().keys({
|
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
|
||||||
domain: Joi.string().hex().lowercase().length(24).required(),
|
|
||||||
sess: sessSchema,
|
const schema = Joi.object({
|
||||||
ip: sessIPSchema
|
...pathParams,
|
||||||
|
...requestBody,
|
||||||
|
...queryParams
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = schema.validate(req.params, {
|
const result = schema.validate(req.params, {
|
||||||
|
|
Loading…
Reference in a new issue