From e4c30ca1ea4c4ac8635b5c7b923fd1b59e0075ba Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Thu, 28 Sep 2023 12:33:41 +0300 Subject: [PATCH] api.js added endpoint for generating openapi docs. added new info to one route in mailboxes.js and messages.js files so that the api docs generation can be done at all --- api.js | 96 ++++++++++++++++++++++++++++++++++++++++++++ lib/api/mailboxes.js | 28 ++++++++----- lib/api/messages.js | 34 ++++++++++++---- 3 files changed, 142 insertions(+), 16 deletions(-) diff --git a/api.js b/api.js index 96302417..9f846f48 100644 --- a/api.js +++ b/api.js @@ -573,6 +573,102 @@ module.exports = done => { ); } + server.get( + { path: '/openapi', name: 'openapi-docs-generation' }, + tools.responseWrapper(async (req, res) => { + res.charSet('utf-8'); + + const testRoute = server.router.getRoutes().postusersusermailboxesmailboxmessages; + + console.log(testRoute.spec.pathParams); + console.log(testRoute.spec.requestBody); + console.log(testRoute.spec.queryParams); + + // const docs = ` + // openapi: 3.0.0 + // info: + // title: WildDuck API + // description: WildDuck API docs + // version: 1.0.0 + // contact: + // url: 'https://github.com/nodemailer/wildduck' + + // servers: + // - url: 'https://api.wildduck.email' + + // tags: + // - name: Addresses + // - name: ApplicationPasswords + // - name: Archive + // description: Archive includes all deleted messages. Once messages are old enough then these are permanenetly deleted from the archive as well. Until then you can restore the deleted messages. + // - name: Audit + // description: 'Auditing allows to monitor an email account. All existing, deleted and new emails are copied to the auditing system. See also https://github.com/nodemailer/wildduck-audit-manager' + // - name: Authentication + // - name: Autoreplies + // - name: Certs + // description: WildDuck allows to register TLS certificates to be used with SNI connections. These certificates are used by IMAP, POP3, API and SMTP servers when a SNI capable client establishes a TLS connection. This does not apply for MX servers. + // - name: DKIM + // description: Whenever an email is sent WildDuck checks if there is a DKIM key registered for the domain name of the sender address and uses it to sign the message. + // - name: DomainAccess + // description: Add sender domain names to allowlist (messages are all accepted) or blocklist (messages are sent to Spam folder) + // - name: DomainAliases + // - name: Filters + // - name: Mailboxes + // - name: Messages + // - name: Settings + // - name: Storage + // description: Storage allows easier attachment handling when composing Draft messages. Instead of uploading the attachmnent with every draft update, you store the attachment to the Storage and then link stored file for the Draft. + // - name: Submission + // - name: TwoFactorAuth + // - name: Users + // - name: Webhooks`; + // console.log(docs); + + // console.info(testRoute.spec.pathParams.user._flags, testRoute.spec.pathParams.user._singleRules); + // const isRequired = testRoute.spec.pathParams.user._flags.presence === 'required'; + // const description = testRoute.spec.pathParams.user._flags.description || null; + // const originalType = testRoute.spec.pathParams.user.type; + + /** + * tags: tags + * summary: description + * operationId: name? + * method: spec.method + * url: spec.path + * parameters: if query then in: query, if path then in: path + * name: name of key + * description: joi description + * schema: + * type: joi type + * default: get from joi + * + * requestBody: spec.requestBody + * content: + * application/json: + * schema: + * + * required: + * + * type: joi type + * properties: + * + * + * responses: + * + */ + + // console.log( + // isRequired, + // description, + // originalType, + // testRoute.spec.description, + // testRoute.spec.method.toLowerCase(), + // testRoute.spec.path, + // testRoute.spec.tags + // ); + }) + ); + server.on('error', err => { if (!started) { started = true; diff --git a/lib/api/mailboxes.js b/lib/api/mailboxes.js index 3aed88cc..25ad8967 100644 --- a/lib/api/mailboxes.js +++ b/lib/api/mailboxes.js @@ -246,19 +246,29 @@ module.exports = (db, server, mailboxHandler) => { ); server.post( - '/users/:user/mailboxes', - tools.responseWrapper(async (req, res) => { - res.charSet('utf-8'); - - const schema = Joi.object().keys({ - user: Joi.string().hex().lowercase().length(24).required(), + { + path: '/users/:user/mailboxes', + pathParams: { user: Joi.string().hex().lowercase().length(24).required().description('This is the user path param') }, + description: 'Some description for the API path', + requestBody: { path: Joi.string() .regex(/\/{2,}|\/$/, { invert: true }) .required(), hidden: booleanSchema.default(false), - retention: Joi.number().min(0), - sess: sessSchema, - ip: sessIPSchema + retention: Joi.number().min(0) + }, + queryParams: { sess: sessSchema, ip: sessIPSchema }, + tags: ['Mailboxes'] + }, + tools.responseWrapper(async (req, res) => { + res.charSet('utf-8'); + + const { pathParams, requestBody, queryParams } = req.route.spec; + + const schema = Joi.object({ + ...pathParams, + ...requestBody, + ...queryParams }); const result = schema.validate(req.params, { diff --git a/lib/api/messages.js b/lib/api/messages.js index 03e99c3a..718fe77b 100644 --- a/lib/api/messages.js +++ b/lib/api/messages.js @@ -1529,13 +1529,16 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti ); server.post( - '/users/:user/mailboxes/:mailbox/messages', - tools.responseWrapper(async (req, res) => { - res.charSet('utf-8'); - - const schema = Joi.object().keys({ + { + path: '/users/:user/mailboxes/:mailbox/messages', + pathParams: { user: Joi.string().hex().lowercase().length(24).required(), - mailbox: Joi.string().hex().lowercase().length(24).required(), + mailbox: Joi.string().hex().lowercase().length(24).required() + }, + summary: 'Upload Message', + description: + 'This method allows to upload either an RFC822 formatted message or a message structure to a mailbox. Raw message is stored unmodified, no headers are added or removed. If you want to generate the uploaded message from structured data fields, then do not use the raw property.', + requestBody: { date: Joi.date(), unseen: booleanSchema.default(false), flagged: booleanSchema.default(false), @@ -1629,11 +1632,28 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti bimi: Joi.object().keys({ domain: Joi.string().domain().required(), - selector: Joi.string().empty('').max(255) + selector: Joi.string().empty('').max(255), + bimi: Joi.object().keys({ + domain: Joi.string().domain().required(), + selector: Joi.string().empty('').max(255) + }) }), sess: sessSchema, ip: sessIPSchema + }, + queryParams: {}, + tags: ['Messages'] + }, + tools.responseWrapper(async (req, res) => { + res.charSet('utf-8'); + + const { pathParams, requestBody, queryParams } = req.route.spec; + + const schema = Joi.object({ + ...pathParams, + ...requestBody, + ...queryParams }); if (!req.params.raw && req.body && (Buffer.isBuffer(req.body) || typeof req.body === 'string')) {