mirror of
https://github.com/nodemailer/wildduck.git
synced 2025-09-08 14:15:40 +08:00
fix: ZMS-210 API and docs fallback values updates (#802)
* in APIs remove fallbacks to false and fallback to undefined. Update documentation * update docs * Updae autoreply test. Don't account for undefined fields (not present in response)
This commit is contained in:
parent
f0f35e1b67
commit
5ce9989313
8 changed files with 63 additions and 103 deletions
|
@ -6,7 +6,7 @@
|
|||
"contact": {
|
||||
"url": "https://github.com/zone-eu/wildduck"
|
||||
},
|
||||
"version": "1.45.4"
|
||||
"version": "1.45.5"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
|
@ -278,6 +278,10 @@
|
|||
},
|
||||
"description": "An array of forwarding targets. The value could either be an email address or a relay url to next MX server (\"smtp://mx2.zone.eu:25\") or an URL where mail contents are POSTed to"
|
||||
},
|
||||
"mtaRelay": {
|
||||
"type": "string",
|
||||
"description": "An address of an SMTP MTA relay. The value should be a relay url. If specified uses the this relay as the outbound MTA."
|
||||
},
|
||||
"spamLevel": {
|
||||
"type": "number",
|
||||
"description": "Relative scale for detecting spam. 0 means that everything is spam, 100 means that nothing is spam",
|
||||
|
@ -592,6 +596,10 @@
|
|||
},
|
||||
"description": "An array of forwarding targets. The value could either be an email address or a relay url to next MX server (\"smtp://mx2.zone.eu:25\") or an URL where mail contents are POSTed to"
|
||||
},
|
||||
"mtaRelay": {
|
||||
"type": "string",
|
||||
"description": "An address of an SMTP MTA relay. The value should be a relay url. If specified uses the this relay as the outbound MTA."
|
||||
},
|
||||
"spamLevel": {
|
||||
"type": "number",
|
||||
"description": "Relative scale for detecting spam. 0 means that everything is spam, 100 means that nothing is spam"
|
||||
|
@ -9339,7 +9347,7 @@
|
|||
},
|
||||
"retention": {
|
||||
"type": "number",
|
||||
"description": "Default retention time (in ms). false if not enabled"
|
||||
"description": "Default retention time (in ms). Not present if not enabled"
|
||||
},
|
||||
"enabled2fa": {
|
||||
"type": "array",
|
||||
|
@ -9384,6 +9392,10 @@
|
|||
},
|
||||
"description": "List of forwarding targets"
|
||||
},
|
||||
"mtaRelay": {
|
||||
"type": "string",
|
||||
"description": "MTA Relay url"
|
||||
},
|
||||
"spamLevel": {
|
||||
"type": "number",
|
||||
"description": "Relative scale for detecting spam. 0 means that everything is spam, 100 means that nothing is spam"
|
||||
|
@ -9440,7 +9452,6 @@
|
|||
"username",
|
||||
"name",
|
||||
"address",
|
||||
"retention",
|
||||
"enabled2fa",
|
||||
"autoreply",
|
||||
"encryptMessages",
|
||||
|
@ -9723,7 +9734,6 @@
|
|||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"address",
|
||||
"user",
|
||||
"forwarded",
|
||||
|
@ -9853,7 +9863,6 @@
|
|||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"address",
|
||||
"main",
|
||||
"created",
|
||||
|
@ -9931,7 +9940,6 @@
|
|||
"required": [
|
||||
"success",
|
||||
"id",
|
||||
"name",
|
||||
"address",
|
||||
"main",
|
||||
"created",
|
||||
|
@ -10079,11 +10087,7 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"status",
|
||||
"name",
|
||||
"subject",
|
||||
"text",
|
||||
"html"
|
||||
"status"
|
||||
]
|
||||
},
|
||||
"GetForwardedAddressResponse": {
|
||||
|
@ -10150,7 +10154,6 @@
|
|||
"success",
|
||||
"id",
|
||||
"address",
|
||||
"name",
|
||||
"limits",
|
||||
"autoreply",
|
||||
"created",
|
||||
|
@ -11542,26 +11545,12 @@
|
|||
"description": "File ID"
|
||||
},
|
||||
"filename": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"description": "Filename. False if none"
|
||||
"type": "string",
|
||||
"description": "Filename"
|
||||
},
|
||||
"contentType": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"description": "Content-Type of the file. False if none"
|
||||
"type": "string",
|
||||
"description": "Content-Type of the file"
|
||||
},
|
||||
"cid": {
|
||||
"type": "string",
|
||||
|
@ -11583,8 +11572,6 @@
|
|||
},
|
||||
"required": [
|
||||
"id",
|
||||
"filename",
|
||||
"contentType",
|
||||
"size",
|
||||
"created",
|
||||
"md5"
|
||||
|
@ -12136,18 +12123,14 @@
|
|||
"properties": {
|
||||
"time": {
|
||||
"type": "string",
|
||||
"description": "Datestring of last use or false if password has not been used",
|
||||
"description": "Datestring of last use or not present if password has not been used",
|
||||
"format": "date-time"
|
||||
},
|
||||
"event": {
|
||||
"type": "string",
|
||||
"description": "Event ID of the security log for the last authentication"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"time",
|
||||
"event"
|
||||
]
|
||||
}
|
||||
},
|
||||
"GetASPsResult": {
|
||||
"type": "object",
|
||||
|
@ -12978,18 +12961,12 @@
|
|||
"start": {
|
||||
"type": "string",
|
||||
"description": "Datestring of the start of the autoreply or boolean false to disable start checks",
|
||||
"format": "date-time",
|
||||
"enum": [
|
||||
false
|
||||
]
|
||||
"format": "date-time"
|
||||
},
|
||||
"end": {
|
||||
"type": "string",
|
||||
"description": "Datestring of the end of the autoreply or boolean false to disable end checks",
|
||||
"format": "date-time",
|
||||
"enum": [
|
||||
false
|
||||
]
|
||||
"format": "date-time"
|
||||
},
|
||||
"created": {
|
||||
"type": "string",
|
||||
|
@ -12998,8 +12975,7 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"success",
|
||||
"created"
|
||||
"success"
|
||||
]
|
||||
},
|
||||
"Reference": {
|
||||
|
|
|
@ -245,7 +245,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
results: (listing.results || []).map(addressData => {
|
||||
let values = {
|
||||
id: addressData._id.toString(),
|
||||
name: addressData.name || false,
|
||||
name: addressData.name || undefined,
|
||||
address: addressData.address,
|
||||
user: addressData.user && addressData.user.toString(),
|
||||
forwarded: !!addressData.targets,
|
||||
|
@ -704,7 +704,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
results: addresses.map(addressData => {
|
||||
let values = {
|
||||
id: addressData._id.toString(),
|
||||
name: addressData.name || false,
|
||||
name: addressData.name || undefined,
|
||||
address: addressData.address,
|
||||
main: addressData.address === userData.address,
|
||||
tags: addressData.tags || [],
|
||||
|
@ -747,7 +747,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
model: Joi.object({
|
||||
success: successRes,
|
||||
id: addressId,
|
||||
name: Joi.string().required().description('Identity name'),
|
||||
name: Joi.string().description('Identity name'),
|
||||
address: addressEmail,
|
||||
main: booleanSchema.required().description('Indicates if this is the default address for the User'),
|
||||
created: Joi.date().required().description('Datestring of the time the address was created'),
|
||||
|
@ -850,7 +850,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
let value = {
|
||||
success: true,
|
||||
id: addressData._id.toString(),
|
||||
name: addressData.name || false,
|
||||
name: addressData.name || undefined,
|
||||
address: addressData.address,
|
||||
main: addressData.address === userData.address,
|
||||
tags: addressData.tags || [],
|
||||
|
@ -1428,7 +1428,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
success: true,
|
||||
|
||||
results: addresses.map(addressData => {
|
||||
let name = addressData.name || false;
|
||||
let name = addressData.name || undefined;
|
||||
try {
|
||||
// try to decode
|
||||
if (name) {
|
||||
|
@ -1439,7 +1439,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
}
|
||||
return {
|
||||
id: addressData._id.toString(),
|
||||
name: addressData.name || false,
|
||||
name: addressData.name || undefined,
|
||||
address: addressData.address
|
||||
};
|
||||
})
|
||||
|
@ -2167,7 +2167,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
success: successRes,
|
||||
id: addressId,
|
||||
address: addressEmail,
|
||||
name: Joi.string().required().description('Identity name'),
|
||||
name: Joi.string().description('Identity name'),
|
||||
targets: Joi.array().items(Joi.string()).description('List of forwarding targets'),
|
||||
limits: AddressLimits,
|
||||
autoreply: AutoreplyInfo,
|
||||
|
@ -2254,7 +2254,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
const values = {
|
||||
success: true,
|
||||
id: addressData._id.toString(),
|
||||
name: addressData.name || false,
|
||||
name: addressData.name || undefined,
|
||||
address: addressData.address,
|
||||
targets: addressData.targets && addressData.targets.map(t => t.value),
|
||||
limits: {
|
||||
|
|
|
@ -50,8 +50,8 @@ module.exports = (db, server, userHandler) => {
|
|||
.required()
|
||||
.description('Allowed scopes for the Application Password'),
|
||||
lastUse: Joi.object({
|
||||
time: Joi.date().required().description('Datestring of last use or false if password has not been used'),
|
||||
event: Joi.string().required().description('Event ID of the security log for the last authentication')
|
||||
time: Joi.date().description('Datestring of last use or not present if password has not been used'),
|
||||
event: Joi.string().description('Event ID of the security log for the last authentication')
|
||||
})
|
||||
.required()
|
||||
.$_setFlag('objectName', 'LastUse')
|
||||
|
@ -170,8 +170,8 @@ module.exports = (db, server, userHandler) => {
|
|||
description: asp.description,
|
||||
scopes: asp.scopes.includes('*') ? [...consts.SCOPES] : asp.scopes,
|
||||
lastUse: {
|
||||
time: asp.used || false,
|
||||
event: asp.authEvent || false
|
||||
time: asp.used || undefined,
|
||||
event: asp.authEvent || undefined
|
||||
},
|
||||
expires: asp.expires,
|
||||
created: asp.created
|
||||
|
@ -209,8 +209,8 @@ module.exports = (db, server, userHandler) => {
|
|||
.required()
|
||||
.description('Allowed scopes for the Application Password'),
|
||||
lastUse: Joi.object({
|
||||
time: Joi.date().required().description('Datestring of last use or false if password has not been used'),
|
||||
event: Joi.string().required().description('Event ID of the security log for the last authentication')
|
||||
time: Joi.date().description('Datestring of last use or not present if password has not been used'),
|
||||
event: Joi.string().description('Event ID of the security log for the last authentication')
|
||||
})
|
||||
.required()
|
||||
.$_setFlag('objectName', 'LastUse')
|
||||
|
@ -286,8 +286,8 @@ module.exports = (db, server, userHandler) => {
|
|||
description: aspData.description,
|
||||
scopes: aspData.scopes.includes('*') ? [...consts.SCOPES] : aspData.scopes,
|
||||
lastUse: {
|
||||
time: aspData.used || false,
|
||||
event: aspData.authEvent || false
|
||||
time: aspData.used || undefined,
|
||||
event: aspData.authEvent || undefined
|
||||
},
|
||||
expires: asp.expires,
|
||||
created: aspData.created
|
||||
|
|
|
@ -181,12 +181,9 @@ module.exports = (db, server) => {
|
|||
.trim()
|
||||
.max(128 * 1024)
|
||||
.description('HTML formatted content of the autoreply message'),
|
||||
start: Joi.date()
|
||||
.empty('')
|
||||
.allow(false)
|
||||
.description('Datestring of the start of the autoreply or boolean false to disable start checks'),
|
||||
end: Joi.date().empty('').allow(false).description('Datestring of the end of the autoreply or boolean false to disable end checks'),
|
||||
created: Joi.date().required().description('Datestring of when the Autoreply was created')
|
||||
start: Joi.date().empty('').description('Datestring of the start of the autoreply or boolean false to disable start checks'),
|
||||
end: Joi.date().empty('').description('Datestring of the end of the autoreply or boolean false to disable end checks'),
|
||||
created: Joi.date().description('Datestring of when the Autoreply was created')
|
||||
}).$_setFlag('objectName', 'GetAutoreplyResponse')
|
||||
}
|
||||
}
|
||||
|
@ -236,9 +233,9 @@ module.exports = (db, server) => {
|
|||
subject: entry.subject || '',
|
||||
text: entry.text || '',
|
||||
html: entry.html || '',
|
||||
start: entry.start || false,
|
||||
end: entry.end || false,
|
||||
created: entry.created || entry._id?.getTimestamp() || false
|
||||
start: entry.start || undefined,
|
||||
end: entry.end || undefined,
|
||||
created: entry.created || entry._id?.getTimestamp() || undefined
|
||||
});
|
||||
})
|
||||
);
|
||||
|
|
|
@ -6,7 +6,7 @@ const ObjectId = require('mongodb').ObjectId;
|
|||
const tools = require('../tools');
|
||||
const roles = require('../roles');
|
||||
const consts = require('../consts');
|
||||
const { nextPageCursorSchema, previousPageCursorSchema, pageNrSchema, sessSchema, sessIPSchema, booleanSchema } = require('../schemas');
|
||||
const { nextPageCursorSchema, previousPageCursorSchema, pageNrSchema, sessSchema, sessIPSchema } = require('../schemas');
|
||||
const { userId } = require('../schemas/request/general-schemas');
|
||||
const { successRes, totalRes, pageRes, previousCursorRes, nextCursorRes } = require('../schemas/response/general-schemas');
|
||||
|
||||
|
@ -157,14 +157,8 @@ module.exports = (db, server, storageHandler) => {
|
|||
.items(
|
||||
Joi.object({
|
||||
id: Joi.string().required().description('File ID'),
|
||||
filename: Joi.alternatives()
|
||||
.try(Joi.string().required(), booleanSchema.required())
|
||||
.required()
|
||||
.description('Filename. False if none'),
|
||||
contentType: Joi.alternatives()
|
||||
.try(Joi.string().required(), booleanSchema.required())
|
||||
.required()
|
||||
.description('Content-Type of the file. False if none'),
|
||||
filename: Joi.string().description('Filename'),
|
||||
contentType: Joi.string().description('Content-Type of the file'),
|
||||
cid: Joi.string().description('Content ID'),
|
||||
size: Joi.number().required().description('File size'),
|
||||
created: Joi.date().required().description('Created datestring'),
|
||||
|
@ -297,8 +291,8 @@ module.exports = (db, server, storageHandler) => {
|
|||
nextCursor: listing.hasNext ? listing.next : false,
|
||||
results: (listing.results || []).map(fileData => ({
|
||||
id: fileData._id.toString(),
|
||||
filename: fileData.filename || false,
|
||||
contentType: fileData.contentType || false,
|
||||
filename: fileData.filename || undefined,
|
||||
contentType: fileData.contentType || undefined,
|
||||
cid: fileData.metadata?.cid,
|
||||
size: fileData.length,
|
||||
created: fileData.uploadDate.toISOString(),
|
||||
|
|
|
@ -793,7 +793,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
username: Joi.string().required().description('Username of the User'),
|
||||
name: Joi.string().required().description('Name of the User'),
|
||||
address: Joi.string().required().description('Main email address of the User'),
|
||||
retention: Joi.number().required().description('Default retention time (in ms). false if not enabled'),
|
||||
retention: Joi.number().description('Default retention time (in ms). Not present if not enabled'),
|
||||
enabled2fa: Joi.array().items(Joi.string()).required().description('List of enabled 2FA methods'),
|
||||
autoreply: booleanSchema
|
||||
.required()
|
||||
|
@ -814,7 +814,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
.required()
|
||||
.description('Custom internal metadata object set for this user. Not available for user-role tokens'),
|
||||
targets: Joi.array().items(Joi.string()).required().description('List of forwarding targets'),
|
||||
mtaRelay: Joi.string().required().description('MTA Relay url'),
|
||||
mtaRelay: Joi.string().description('MTA Relay url'),
|
||||
spamLevel: Joi.number()
|
||||
.required()
|
||||
.description('Relative scale for detecting spam. 0 means that everything is spam, 100 means that nothing is spam'),
|
||||
|
@ -1073,7 +1073,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
address: userData.address,
|
||||
|
||||
language: userData.language,
|
||||
retention: userData.retention || false,
|
||||
retention: userData.retention || undefined,
|
||||
|
||||
enabled2fa: tools.getEnabled2fa(userData.enabled2fa),
|
||||
autoreply: !!userData.autoreply,
|
||||
|
@ -1092,7 +1092,7 @@ module.exports = (db, server, userHandler, settingsHandler) => {
|
|||
.map(target => target.value)
|
||||
.filter(target => target),
|
||||
|
||||
mtaRelay: userData.mtaRelay?.value || false,
|
||||
mtaRelay: userData.mtaRelay?.value || undefined,
|
||||
|
||||
limits: {
|
||||
quota: {
|
||||
|
|
|
@ -6,7 +6,7 @@ const { addressId, addressEmail } = require('../request/general-schemas');
|
|||
|
||||
const GetAddressesResult = Joi.object({
|
||||
id: Joi.string().required().description('ID of the Address'),
|
||||
name: Joi.string().required().description('Identity name'),
|
||||
name: Joi.string().description('Identity name'),
|
||||
address: Joi.string().required().description('E-mail address string'),
|
||||
user: Joi.string().required().description('User ID this address belongs to if this is a User address'),
|
||||
forwarded: booleanSchema.required().description('If true then it is a forwarded address'),
|
||||
|
@ -19,7 +19,7 @@ const GetAddressesResult = Joi.object({
|
|||
|
||||
const GetUserAddressesResult = Joi.object({
|
||||
id: addressId,
|
||||
name: Joi.string().required().description('Identity name'),
|
||||
name: Joi.string().description('Identity name'),
|
||||
address: addressEmail,
|
||||
main: booleanSchema.required().description('Indicates if this is the default address for the User'),
|
||||
created: Joi.date().required().description('Datestring of the time the address was created'),
|
||||
|
@ -50,10 +50,10 @@ const AddressLimits = Joi.object({
|
|||
|
||||
const AutoreplyInfo = Joi.object({
|
||||
status: booleanSchema.required().description('If true, then autoreply is enabled for this address'),
|
||||
name: Joi.string().required().description('Name that is used for the From: header in autoreply message'),
|
||||
subject: Joi.string().required().description('Autoreply subject line'),
|
||||
text: Joi.string().required().description('Autoreply plaintext content'),
|
||||
html: Joi.string().required().description('Autoreply HTML content')
|
||||
name: Joi.string().description('Name that is used for the From: header in autoreply message'),
|
||||
subject: Joi.string().description('Autoreply subject line'),
|
||||
text: Joi.string().description('Autoreply plaintext content'),
|
||||
html: Joi.string().description('Autoreply HTML content')
|
||||
})
|
||||
.required()
|
||||
.description('Autoreply information')
|
||||
|
|
|
@ -415,10 +415,7 @@ describe('API tests', function () {
|
|||
name: '',
|
||||
subject: '',
|
||||
text: '',
|
||||
html: '',
|
||||
start: false,
|
||||
end: false,
|
||||
created: false
|
||||
html: ''
|
||||
});
|
||||
|
||||
r = await server
|
||||
|
@ -467,7 +464,6 @@ describe('API tests', function () {
|
|||
subject: '',
|
||||
text: 'Away from office until Dec.19',
|
||||
html: '',
|
||||
start: false,
|
||||
end: '2017-12-19T00:00:00.000Z',
|
||||
created: r.body.created // created might have been changed to new date
|
||||
});
|
||||
|
@ -480,10 +476,7 @@ describe('API tests', function () {
|
|||
name: '',
|
||||
subject: '',
|
||||
text: '',
|
||||
html: '',
|
||||
start: false,
|
||||
end: false,
|
||||
created: false
|
||||
html: ''
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue