emailengine-app 2.68.0 → 2.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/codeql/codeql-config.yml +16 -0
- package/.github/workflows/codeql.yml +102 -0
- package/.github/workflows/deploy.yml +8 -0
- package/.github/workflows/release.yaml +4 -0
- package/.github/workflows/test.yml +3 -0
- package/CHANGELOG.md +49 -0
- package/SECURITY.md +80 -0
- package/SECURITY.txt +27 -0
- package/config/default.toml +2 -0
- package/data/google-crawlers.json +13 -1
- package/lib/account.js +62 -25
- package/lib/api-routes/account-routes.js +493 -75
- package/lib/api-routes/blocklist-routes.js +337 -0
- package/lib/api-routes/delivery-test-routes.js +321 -0
- package/lib/api-routes/export-routes.js +1 -12
- package/lib/api-routes/gateway-routes.js +376 -0
- package/lib/api-routes/license-routes.js +142 -0
- package/lib/api-routes/mailbox-routes.js +318 -0
- package/lib/api-routes/message-routes.js +21 -129
- package/lib/api-routes/oauth2-app-routes.js +631 -0
- package/lib/api-routes/outbox-routes.js +173 -0
- package/lib/api-routes/pubsub-routes.js +98 -0
- package/lib/api-routes/route-helpers.js +45 -0
- package/lib/api-routes/settings-routes.js +331 -0
- package/lib/api-routes/stats-routes.js +77 -0
- package/lib/api-routes/submit-routes.js +472 -0
- package/lib/api-routes/template-routes.js +7 -55
- package/lib/api-routes/token-routes.js +297 -0
- package/lib/api-routes/webhook-route-routes.js +152 -0
- package/lib/email-client/gmail-client.js +14 -0
- package/lib/email-client/imap/mailbox.js +34 -11
- package/lib/email-client/imap/subconnection.js +20 -12
- package/lib/email-client/imap/sync-operations.js +130 -2
- package/lib/email-client/imap-client.js +116 -58
- package/lib/email-client/outlook-client.js +85 -13
- package/lib/export.js +60 -19
- package/lib/imapproxy/imap-core/lib/commands/starttls.js +18 -0
- package/lib/imapproxy/imap-core/lib/imap-command.js +7 -2
- package/lib/imapproxy/imap-core/lib/imap-connection.js +113 -23
- package/lib/imapproxy/imap-core/lib/imap-server.js +25 -1
- package/lib/imapproxy/imap-core/lib/imap-stream.js +26 -0
- package/lib/imapproxy/imap-server.js +92 -29
- package/lib/message-port-stream.js +113 -16
- package/lib/reject-worker-calls.js +42 -0
- package/lib/routes-ui.js +37 -8778
- package/lib/schemas.js +26 -1
- package/lib/tools.js +73 -0
- package/lib/ui-routes/account-routes.js +40 -210
- package/lib/ui-routes/admin-config-routes.js +913 -487
- package/lib/ui-routes/admin-entities-routes.js +1 -0
- package/lib/ui-routes/auth-routes.js +1339 -0
- package/lib/ui-routes/dashboard-routes.js +188 -0
- package/lib/ui-routes/document-store-routes.js +800 -0
- package/lib/ui-routes/export-routes.js +217 -0
- package/lib/ui-routes/internals-routes.js +354 -0
- package/lib/ui-routes/network-config-routes.js +759 -0
- package/lib/ui-routes/{oauth-routes.js → oauth-config-routes.js} +371 -91
- package/lib/ui-routes/route-helpers.js +316 -0
- package/lib/ui-routes/smtp-test-routes.js +236 -0
- package/lib/ui-routes/unsubscribe-routes.js +234 -0
- package/lib/webhook-request.js +36 -0
- package/package.json +17 -17
- package/sbom.json +1 -1
- package/server.js +217 -19
- package/static/licenses.html +52 -182
- package/translations/messages.pot +131 -151
- package/views/dashboard.hbs +7 -26
- package/views/internals/index.hbs +15 -0
- package/views/tokens/index.hbs +9 -0
- package/workers/api.js +198 -4401
- package/workers/export.js +87 -54
- package/workers/imap.js +29 -13
- package/workers/submit.js +20 -11
- package/workers/webhooks.js +6 -20
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Joi = require('joi');
|
|
4
|
+
const { redis } = require('../db');
|
|
5
|
+
const { Gateway } = require('../gateway');
|
|
6
|
+
const getSecret = require('../get-secret');
|
|
7
|
+
const { failAction } = require('../tools');
|
|
8
|
+
const { handleError } = require('./route-helpers');
|
|
9
|
+
const { lastErrorSchema } = require('../schemas');
|
|
10
|
+
|
|
11
|
+
async function init(args) {
|
|
12
|
+
const { server, call, CORS_CONFIG } = args;
|
|
13
|
+
|
|
14
|
+
server.route({
|
|
15
|
+
method: 'GET',
|
|
16
|
+
path: '/v1/gateways',
|
|
17
|
+
|
|
18
|
+
async handler(request) {
|
|
19
|
+
try {
|
|
20
|
+
let gatewayObject = new Gateway({ redis, gateway: request.params.gateway, call, secret: await getSecret() });
|
|
21
|
+
|
|
22
|
+
return await gatewayObject.listGateways(request.query.page, request.query.pageSize);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
handleError(request, err);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
options: {
|
|
29
|
+
description: 'List gateways',
|
|
30
|
+
notes: 'Lists registered gateways',
|
|
31
|
+
tags: ['api', 'SMTP Gateway'],
|
|
32
|
+
|
|
33
|
+
plugins: {},
|
|
34
|
+
|
|
35
|
+
auth: {
|
|
36
|
+
strategy: 'api-token',
|
|
37
|
+
mode: 'required'
|
|
38
|
+
},
|
|
39
|
+
cors: CORS_CONFIG,
|
|
40
|
+
|
|
41
|
+
validate: {
|
|
42
|
+
options: {
|
|
43
|
+
stripUnknown: false,
|
|
44
|
+
abortEarly: false,
|
|
45
|
+
convert: true
|
|
46
|
+
},
|
|
47
|
+
failAction,
|
|
48
|
+
|
|
49
|
+
query: Joi.object({
|
|
50
|
+
page: Joi.number()
|
|
51
|
+
.integer()
|
|
52
|
+
.min(0)
|
|
53
|
+
.max(1024 * 1024)
|
|
54
|
+
.default(0)
|
|
55
|
+
.example(0)
|
|
56
|
+
.description('Page number (zero indexed, so use 0 for first page)')
|
|
57
|
+
.label('PageNumber'),
|
|
58
|
+
pageSize: Joi.number().integer().min(1).max(1000).default(20).example(20).description('How many entries per page').label('PageSize')
|
|
59
|
+
}).label('GatewaysFilter')
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
response: {
|
|
63
|
+
schema: Joi.object({
|
|
64
|
+
total: Joi.number().integer().example(120).description('How many matching entries').label('TotalNumber'),
|
|
65
|
+
page: Joi.number().integer().example(0).description('Current page (0-based index)').label('PageNumber'),
|
|
66
|
+
pages: Joi.number().integer().example(24).description('Total page count').label('PagesNumber'),
|
|
67
|
+
|
|
68
|
+
gateways: Joi.array()
|
|
69
|
+
.items(
|
|
70
|
+
Joi.object({
|
|
71
|
+
gateway: Joi.string().max(256).required().example('example').description('Gateway ID'),
|
|
72
|
+
name: Joi.string().max(256).example('My Email Gateway').description('Display name for the gateway'),
|
|
73
|
+
deliveries: Joi.number().integer().empty('').example(100).description('Count of email deliveries using this gateway'),
|
|
74
|
+
lastUse: Joi.date().iso().example('2021-02-17T13:43:18.860Z').description('Last delivery time'),
|
|
75
|
+
lastError: lastErrorSchema.allow(null)
|
|
76
|
+
}).label('GatewayResponseItem')
|
|
77
|
+
)
|
|
78
|
+
.label('GatewayEntries')
|
|
79
|
+
}).label('GatewaysFilterResponse'),
|
|
80
|
+
failAction: 'log'
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
server.route({
|
|
86
|
+
method: 'GET',
|
|
87
|
+
path: '/v1/gateway/{gateway}',
|
|
88
|
+
|
|
89
|
+
async handler(request) {
|
|
90
|
+
let gatewayObject = new Gateway({ redis, gateway: request.params.gateway, call, secret: await getSecret() });
|
|
91
|
+
try {
|
|
92
|
+
let gatewayData = await gatewayObject.loadGatewayData();
|
|
93
|
+
|
|
94
|
+
// remove secrets
|
|
95
|
+
if (gatewayData.pass) {
|
|
96
|
+
gatewayData.pass = '******';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let result = {};
|
|
100
|
+
|
|
101
|
+
for (let key of ['gateway', 'name', 'host', 'port', 'user', 'pass', 'secure', 'deliveries', 'lastUse', 'lastError']) {
|
|
102
|
+
if (key in gatewayData) {
|
|
103
|
+
result[key] = gatewayData[key];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return result;
|
|
108
|
+
} catch (err) {
|
|
109
|
+
handleError(request, err);
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
options: {
|
|
113
|
+
description: 'Get gateway info',
|
|
114
|
+
notes: 'Returns stored information about the gateway. Passwords are not included.',
|
|
115
|
+
tags: ['api', 'SMTP Gateway'],
|
|
116
|
+
|
|
117
|
+
auth: {
|
|
118
|
+
strategy: 'api-token',
|
|
119
|
+
mode: 'required'
|
|
120
|
+
},
|
|
121
|
+
cors: CORS_CONFIG,
|
|
122
|
+
|
|
123
|
+
validate: {
|
|
124
|
+
options: {
|
|
125
|
+
stripUnknown: false,
|
|
126
|
+
abortEarly: false,
|
|
127
|
+
convert: true
|
|
128
|
+
},
|
|
129
|
+
failAction,
|
|
130
|
+
|
|
131
|
+
params: Joi.object({
|
|
132
|
+
gateway: Joi.string().max(256).required().example('example').description('Gateway ID')
|
|
133
|
+
})
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
response: {
|
|
137
|
+
schema: Joi.object({
|
|
138
|
+
gateway: Joi.string().max(256).required().example('example').description('Gateway ID'),
|
|
139
|
+
|
|
140
|
+
name: Joi.string().max(256).required().example('My Email Gateway').description('Display name for the gateway'),
|
|
141
|
+
deliveries: Joi.number().integer().empty('').example(100).description('Count of email deliveries using this gateway'),
|
|
142
|
+
lastUse: Joi.date().iso().example('2021-02-17T13:43:18.860Z').description('Last delivery time'),
|
|
143
|
+
|
|
144
|
+
user: Joi.string().empty('').trim().max(1024).description('SMTP authentication username').label('UserName'),
|
|
145
|
+
pass: Joi.string().empty('').max(1024).description('SMTP authentication password').label('Password'),
|
|
146
|
+
|
|
147
|
+
host: Joi.string().hostname().example('smtp.gmail.com').description('Hostname to connect to').label('Hostname'),
|
|
148
|
+
port: Joi.number()
|
|
149
|
+
.integer()
|
|
150
|
+
.min(1)
|
|
151
|
+
.max(64 * 1024)
|
|
152
|
+
.example(465)
|
|
153
|
+
.description('Service port number')
|
|
154
|
+
.label('Port'),
|
|
155
|
+
|
|
156
|
+
secure: Joi.boolean()
|
|
157
|
+
.truthy('Y', 'true', '1', 'on')
|
|
158
|
+
.falsy('N', 'false', 0, '')
|
|
159
|
+
.default(false)
|
|
160
|
+
.example(true)
|
|
161
|
+
.description('Should connection use TLS. Usually true for port 465')
|
|
162
|
+
.label('GatewayTlsOptions'),
|
|
163
|
+
|
|
164
|
+
lastError: lastErrorSchema.allow(null)
|
|
165
|
+
}).label('GatewayResponse'),
|
|
166
|
+
failAction: 'log'
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
server.route({
|
|
172
|
+
method: 'POST',
|
|
173
|
+
path: '/v1/gateway',
|
|
174
|
+
|
|
175
|
+
async handler(request) {
|
|
176
|
+
let gatewayObject = new Gateway({ redis, call, secret: await getSecret() });
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
let result = await gatewayObject.create(request.payload);
|
|
180
|
+
return result;
|
|
181
|
+
} catch (err) {
|
|
182
|
+
handleError(request, err);
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
options: {
|
|
187
|
+
description: 'Register new gateway',
|
|
188
|
+
notes: 'Registers a new SMP gateway',
|
|
189
|
+
tags: ['api', 'SMTP Gateway'],
|
|
190
|
+
|
|
191
|
+
plugins: {},
|
|
192
|
+
|
|
193
|
+
auth: {
|
|
194
|
+
strategy: 'api-token',
|
|
195
|
+
mode: 'required'
|
|
196
|
+
},
|
|
197
|
+
cors: CORS_CONFIG,
|
|
198
|
+
|
|
199
|
+
validate: {
|
|
200
|
+
options: {
|
|
201
|
+
stripUnknown: false,
|
|
202
|
+
abortEarly: false,
|
|
203
|
+
convert: true
|
|
204
|
+
},
|
|
205
|
+
failAction,
|
|
206
|
+
|
|
207
|
+
payload: Joi.object({
|
|
208
|
+
gateway: Joi.string().empty('').trim().max(256).default(null).example('sendgun').description('Gateway ID').label('Gateway ID').required(),
|
|
209
|
+
|
|
210
|
+
name: Joi.string().empty('').max(256).example('John Smith').description('Account Name').label('Gateway Name').required(),
|
|
211
|
+
|
|
212
|
+
user: Joi.string().empty('').trim().default(null).max(1024).description('SMTP authentication username').label('UserName'),
|
|
213
|
+
pass: Joi.string().empty('').max(1024).default(null).description('SMTP authentication password').label('Password'),
|
|
214
|
+
|
|
215
|
+
host: Joi.string().hostname().example('smtp.gmail.com').description('Hostname to connect to').label('Hostname').required(),
|
|
216
|
+
port: Joi.number()
|
|
217
|
+
.integer()
|
|
218
|
+
.min(1)
|
|
219
|
+
.max(64 * 1024)
|
|
220
|
+
.example(465)
|
|
221
|
+
.description('Service port number')
|
|
222
|
+
.label('Port')
|
|
223
|
+
.required(),
|
|
224
|
+
|
|
225
|
+
secure: Joi.boolean()
|
|
226
|
+
.truthy('Y', 'true', '1', 'on')
|
|
227
|
+
.falsy('N', 'false', 0, '')
|
|
228
|
+
.default(false)
|
|
229
|
+
.example(true)
|
|
230
|
+
.description('Should connection use TLS. Usually true for port 465')
|
|
231
|
+
.label('GatewayCreateTlsOptions')
|
|
232
|
+
}).label('CreateGateway')
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
response: {
|
|
236
|
+
schema: Joi.object({
|
|
237
|
+
gateway: Joi.string().max(256).required().example('example').description('Gateway ID'),
|
|
238
|
+
state: Joi.string()
|
|
239
|
+
.required()
|
|
240
|
+
.valid('existing', 'new')
|
|
241
|
+
.example('new')
|
|
242
|
+
.description('Is the gateway new or updated existing')
|
|
243
|
+
.label('CreateGatewayState')
|
|
244
|
+
}).label('CreateGatewayResponse'),
|
|
245
|
+
failAction: 'log'
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
server.route({
|
|
251
|
+
method: 'PUT',
|
|
252
|
+
path: '/v1/gateway/edit/{gateway}',
|
|
253
|
+
|
|
254
|
+
async handler(request) {
|
|
255
|
+
let gatewayObject = new Gateway({ redis, gateway: request.params.gateway, call, secret: await getSecret() });
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
return await gatewayObject.update(request.payload);
|
|
259
|
+
} catch (err) {
|
|
260
|
+
handleError(request, err);
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
options: {
|
|
264
|
+
description: 'Update gateway info',
|
|
265
|
+
notes: 'Updates gateway information',
|
|
266
|
+
tags: ['api', 'SMTP Gateway'],
|
|
267
|
+
|
|
268
|
+
plugins: {},
|
|
269
|
+
|
|
270
|
+
auth: {
|
|
271
|
+
strategy: 'api-token',
|
|
272
|
+
mode: 'required'
|
|
273
|
+
},
|
|
274
|
+
cors: CORS_CONFIG,
|
|
275
|
+
|
|
276
|
+
validate: {
|
|
277
|
+
options: {
|
|
278
|
+
stripUnknown: false,
|
|
279
|
+
abortEarly: false,
|
|
280
|
+
convert: true
|
|
281
|
+
},
|
|
282
|
+
failAction,
|
|
283
|
+
|
|
284
|
+
params: Joi.object({
|
|
285
|
+
gateway: Joi.string().max(256).required().example('example').description('Gateway ID')
|
|
286
|
+
}),
|
|
287
|
+
|
|
288
|
+
payload: Joi.object({
|
|
289
|
+
name: Joi.string().empty('').max(256).example('John Smith').description('Account Name').label('Gateway Name'),
|
|
290
|
+
|
|
291
|
+
user: Joi.string().empty('').trim().max(1024).allow(null).description('SMTP authentication username').label('UserName'),
|
|
292
|
+
pass: Joi.string().empty('').max(1024).allow(null).description('SMTP authentication password').label('Password'),
|
|
293
|
+
|
|
294
|
+
host: Joi.string().hostname().empty('').example('smtp.gmail.com').description('Hostname to connect to').label('Hostname'),
|
|
295
|
+
port: Joi.number()
|
|
296
|
+
.integer()
|
|
297
|
+
.min(1)
|
|
298
|
+
.empty('')
|
|
299
|
+
.max(64 * 1024)
|
|
300
|
+
.example(465)
|
|
301
|
+
.description('Service port number')
|
|
302
|
+
.label('Port'),
|
|
303
|
+
|
|
304
|
+
secure: Joi.boolean()
|
|
305
|
+
.truthy('Y', 'true', '1', 'on')
|
|
306
|
+
.falsy('N', 'false', 0, '')
|
|
307
|
+
.example(true)
|
|
308
|
+
.description('Should connection use TLS. Usually true for port 465')
|
|
309
|
+
.label('GatewayUpdateTlsOptions')
|
|
310
|
+
}).label('UpdateGateway')
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
response: {
|
|
314
|
+
schema: Joi.object({
|
|
315
|
+
gateway: Joi.string().max(256).required().example('example').description('Gateway ID')
|
|
316
|
+
}).label('UpdateGatewayResponse'),
|
|
317
|
+
failAction: 'log'
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
server.route({
|
|
323
|
+
method: 'DELETE',
|
|
324
|
+
path: '/v1/gateway/{gateway}',
|
|
325
|
+
|
|
326
|
+
async handler(request) {
|
|
327
|
+
let gatewayObject = new Gateway({
|
|
328
|
+
redis,
|
|
329
|
+
gateway: request.params.gateway,
|
|
330
|
+
secret: await getSecret()
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
try {
|
|
334
|
+
return await gatewayObject.delete();
|
|
335
|
+
} catch (err) {
|
|
336
|
+
handleError(request, err);
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
options: {
|
|
340
|
+
description: 'Remove SMTP gateway',
|
|
341
|
+
notes: 'Delete SMTP gateway data',
|
|
342
|
+
tags: ['api', 'SMTP Gateway'],
|
|
343
|
+
|
|
344
|
+
plugins: {},
|
|
345
|
+
|
|
346
|
+
auth: {
|
|
347
|
+
strategy: 'api-token',
|
|
348
|
+
mode: 'required'
|
|
349
|
+
},
|
|
350
|
+
cors: CORS_CONFIG,
|
|
351
|
+
|
|
352
|
+
validate: {
|
|
353
|
+
options: {
|
|
354
|
+
stripUnknown: false,
|
|
355
|
+
abortEarly: false,
|
|
356
|
+
convert: true
|
|
357
|
+
},
|
|
358
|
+
failAction,
|
|
359
|
+
|
|
360
|
+
params: Joi.object({
|
|
361
|
+
gateway: Joi.string().max(256).required().example('example').description('Gateway ID')
|
|
362
|
+
}).label('DeleteRequest')
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
response: {
|
|
366
|
+
schema: Joi.object({
|
|
367
|
+
gateway: Joi.string().max(256).required().example('example').description('Gateway ID'),
|
|
368
|
+
deleted: Joi.boolean().truthy('Y', 'true', '1').falsy('N', 'false', 0).default(true).description('Was the gateway deleted')
|
|
369
|
+
}).label('DeleteGatewayResponse'),
|
|
370
|
+
failAction: 'log'
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
module.exports = init;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Joi = require('joi');
|
|
4
|
+
const { failAction } = require('../tools');
|
|
5
|
+
const { handleError } = require('./route-helpers');
|
|
6
|
+
const { licenseSchema } = require('../schemas');
|
|
7
|
+
|
|
8
|
+
async function init(args) {
|
|
9
|
+
const { server, call, CORS_CONFIG } = args;
|
|
10
|
+
|
|
11
|
+
server.route({
|
|
12
|
+
method: 'GET',
|
|
13
|
+
path: '/v1/license',
|
|
14
|
+
|
|
15
|
+
async handler(request) {
|
|
16
|
+
try {
|
|
17
|
+
const licenseInfo = await call({ cmd: 'license', timeout: request.headers['x-ee-timeout'] });
|
|
18
|
+
if (!licenseInfo) {
|
|
19
|
+
let err = new Error('Failed to load license info');
|
|
20
|
+
err.statusCode = 403;
|
|
21
|
+
throw err;
|
|
22
|
+
}
|
|
23
|
+
return licenseInfo;
|
|
24
|
+
} catch (err) {
|
|
25
|
+
handleError(request, err);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
options: {
|
|
29
|
+
description: 'Request license info',
|
|
30
|
+
notes: 'Get active license information',
|
|
31
|
+
tags: ['api', 'License'],
|
|
32
|
+
|
|
33
|
+
auth: {
|
|
34
|
+
strategy: 'api-token',
|
|
35
|
+
mode: 'required'
|
|
36
|
+
},
|
|
37
|
+
cors: CORS_CONFIG,
|
|
38
|
+
|
|
39
|
+
response: {
|
|
40
|
+
schema: licenseSchema.label('LicenseResponse'),
|
|
41
|
+
failAction: 'log'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
server.route({
|
|
47
|
+
method: 'DELETE',
|
|
48
|
+
path: '/v1/license',
|
|
49
|
+
|
|
50
|
+
async handler(request) {
|
|
51
|
+
try {
|
|
52
|
+
const licenseInfo = await call({ cmd: 'removeLicense', timeout: request.headers['x-ee-timeout'] });
|
|
53
|
+
if (!licenseInfo) {
|
|
54
|
+
let err = new Error('Failed to clear license info');
|
|
55
|
+
err.statusCode = 403;
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
return licenseInfo;
|
|
59
|
+
} catch (err) {
|
|
60
|
+
handleError(request, err);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
options: {
|
|
64
|
+
description: 'Remove license',
|
|
65
|
+
notes: 'Remove registered active license',
|
|
66
|
+
tags: ['api', 'License'],
|
|
67
|
+
|
|
68
|
+
plugins: {},
|
|
69
|
+
|
|
70
|
+
auth: {
|
|
71
|
+
strategy: 'api-token',
|
|
72
|
+
mode: 'required'
|
|
73
|
+
},
|
|
74
|
+
cors: CORS_CONFIG,
|
|
75
|
+
|
|
76
|
+
response: {
|
|
77
|
+
schema: Joi.object({
|
|
78
|
+
active: Joi.boolean().example(false),
|
|
79
|
+
details: Joi.boolean().example(false),
|
|
80
|
+
type: Joi.string().example('SSPL-1.0-or-later')
|
|
81
|
+
}).label('EmptyLicenseResponse'),
|
|
82
|
+
failAction: 'log'
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
server.route({
|
|
88
|
+
method: 'POST',
|
|
89
|
+
path: '/v1/license',
|
|
90
|
+
|
|
91
|
+
async handler(request) {
|
|
92
|
+
try {
|
|
93
|
+
const licenseInfo = await call({ cmd: 'updateLicense', license: request.payload.license, timeout: request.headers['x-ee-timeout'] });
|
|
94
|
+
if (!licenseInfo) {
|
|
95
|
+
let err = new Error('Failed to update license. Check license file contents.');
|
|
96
|
+
err.statusCode = 403;
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
return licenseInfo;
|
|
100
|
+
} catch (err) {
|
|
101
|
+
handleError(request, err);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
options: {
|
|
105
|
+
description: 'Register a license',
|
|
106
|
+
notes: 'Set up a license for EmailEngine to unlock all features',
|
|
107
|
+
tags: ['api', 'License'],
|
|
108
|
+
|
|
109
|
+
plugins: {},
|
|
110
|
+
|
|
111
|
+
auth: {
|
|
112
|
+
strategy: 'api-token',
|
|
113
|
+
mode: 'required'
|
|
114
|
+
},
|
|
115
|
+
cors: CORS_CONFIG,
|
|
116
|
+
|
|
117
|
+
validate: {
|
|
118
|
+
options: {
|
|
119
|
+
stripUnknown: false,
|
|
120
|
+
abortEarly: false,
|
|
121
|
+
convert: true
|
|
122
|
+
},
|
|
123
|
+
failAction,
|
|
124
|
+
|
|
125
|
+
payload: Joi.object({
|
|
126
|
+
license: Joi.string()
|
|
127
|
+
.max(10 * 1024)
|
|
128
|
+
.required()
|
|
129
|
+
.example('-----BEGIN LICENSE-----\r\n...')
|
|
130
|
+
.description('License file')
|
|
131
|
+
}).label('RegisterLicense')
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
response: {
|
|
135
|
+
schema: licenseSchema.label('LicenseResponse'),
|
|
136
|
+
failAction: 'log'
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
module.exports = init;
|