@@ -5,22 +5,49 @@ const ObjectId = require('mongodb').ObjectId;
5
5
const tools = require ( '../tools' ) ;
6
6
const roles = require ( '../roles' ) ;
7
7
const { sessSchema, sessIPSchema } = require ( '../schemas' ) ;
8
+ const { successRes } = require ( '../schemas/response/general-schemas' ) ;
8
9
9
10
module . exports = ( db , server ) => {
10
11
server . post (
11
- '/domainaccess/:tag/:action' ,
12
+ {
13
+ path : '/domainaccess/:tag/allow' ,
14
+ tags : [ 'DomainAccess' ] ,
15
+ summary : 'Add domain to allowlist' ,
16
+ 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.' ,
17
+ validationObjs : {
18
+ requestBody : {
19
+ domain : Joi . string ( )
20
+ . max ( 255 )
21
+ //.hostname()
22
+ . required ( )
23
+ . description ( 'Domain name to allowlist for users/addresses that include this tag' ) ,
24
+ sess : sessSchema ,
25
+ ip : sessIPSchema
26
+ } ,
27
+ queryParams : { } ,
28
+ pathParams : {
29
+ tag : Joi . string ( ) . trim ( ) . max ( 128 ) . required ( ) . description ( 'Tag to look for' )
30
+ } ,
31
+ response : {
32
+ 200 : {
33
+ description : 'Success' ,
34
+ model : Joi . object ( {
35
+ success : successRes ,
36
+ id : Joi . string ( ) . required ( ) . description ( 'ID for the created record' )
37
+ } )
38
+ }
39
+ }
40
+ }
41
+ } ,
12
42
tools . responseWrapper ( async ( req , res ) => {
13
43
res . charSet ( 'utf-8' ) ;
14
44
15
- const schema = Joi . object ( ) . keys ( {
16
- tag : Joi . string ( ) . trim ( ) . max ( 128 ) . required ( ) ,
17
- domain : Joi . string ( )
18
- . max ( 255 )
19
- //.hostname()
20
- . required ( ) ,
21
- action : Joi . string ( ) . valid ( 'allow' , 'block' ) . required ( ) ,
22
- sess : sessSchema ,
23
- ip : sessIPSchema
45
+ const { pathParams, requestBody, queryParams } = req . route . spec . validationObjs ;
46
+
47
+ const schema = Joi . object ( {
48
+ ...pathParams ,
49
+ ...requestBody ,
50
+ ...queryParams
24
51
} ) ;
25
52
26
53
const result = schema . validate ( req . params , {
@@ -43,7 +70,7 @@ module.exports = (db, server) => {
43
70
let domain = tools . normalizeDomain ( result . value . domain ) ;
44
71
let tag = result . value . tag ;
45
72
let tagview = tag . toLowerCase ( ) ;
46
- let action = result . value . action ;
73
+ let action = 'allow' ;
47
74
48
75
let r ;
49
76
try {
@@ -84,17 +111,257 @@ module.exports = (db, server) => {
84
111
} )
85
112
) ;
86
113
114
+ server . post (
115
+ {
116
+ path : '/domainaccess/:tag/block' ,
117
+ tags : [ 'DomainAccess' ] ,
118
+ summary : 'Add domain to blocklist' ,
119
+ 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.' ,
120
+ validationObjs : {
121
+ requestBody : {
122
+ domain : Joi . string ( )
123
+ . max ( 255 )
124
+ //.hostname()
125
+ . required ( )
126
+ . description ( 'Domain name to blocklist for users/addresses that include this tag' ) ,
127
+ sess : sessSchema ,
128
+ ip : sessIPSchema
129
+ } ,
130
+ queryParams : { } ,
131
+ pathParams : {
132
+ tag : Joi . string ( ) . trim ( ) . max ( 128 ) . required ( ) . description ( 'Tag to look for' )
133
+ } ,
134
+ response : {
135
+ 200 : {
136
+ description : 'Success' ,
137
+ model : Joi . object ( {
138
+ success : successRes ,
139
+ id : Joi . string ( ) . required ( ) . description ( 'ID for the created record' )
140
+ } )
141
+ }
142
+ }
143
+ }
144
+ } ,
145
+ tools . responseWrapper ( async ( req , res ) => {
146
+ res . charSet ( 'utf-8' ) ;
147
+
148
+ const { pathParams, requestBody, queryParams } = req . route . spec . validationObjs ;
149
+
150
+ const schema = Joi . object ( {
151
+ ...pathParams ,
152
+ ...requestBody ,
153
+ ...queryParams
154
+ } ) ;
155
+
156
+ const result = schema . validate ( req . params , {
157
+ abortEarly : false ,
158
+ convert : true
159
+ } ) ;
160
+
161
+ if ( result . error ) {
162
+ res . status ( 400 ) ;
163
+ return res . json ( {
164
+ error : result . error . message ,
165
+ code : 'InputValidationError' ,
166
+ details : tools . validationErrors ( result )
167
+ } ) ;
168
+ }
169
+
170
+ // permissions check
171
+ req . validate ( roles . can ( req . role ) . createAny ( 'domainaccess' ) ) ;
172
+
173
+ let domain = tools . normalizeDomain ( result . value . domain ) ;
174
+ let tag = result . value . tag ;
175
+ let tagview = tag . toLowerCase ( ) ;
176
+ let action = 'block' ;
177
+
178
+ let r ;
179
+ try {
180
+ r = await db . database . collection ( 'domainaccess' ) . findOneAndUpdate (
181
+ {
182
+ tagview,
183
+ domain
184
+ } ,
185
+ {
186
+ $setOnInsert : {
187
+ tag,
188
+ tagview,
189
+ domain
190
+ } ,
191
+
192
+ $set : {
193
+ action
194
+ }
195
+ } ,
196
+ {
197
+ upsert : true ,
198
+ projection : { _id : true } ,
199
+ returnDocument : 'after'
200
+ }
201
+ ) ;
202
+ } catch ( err ) {
203
+ res . status ( 500 ) ;
204
+ return res . json ( {
205
+ error : 'MongoDB Error: ' + err . message ,
206
+ code : 'InternalDatabaseError'
207
+ } ) ;
208
+ }
209
+
210
+ return res . json ( {
211
+ success : ! ! ( r && r . value ) ,
212
+ id : ( ( r && r . value && r . value . _id ) || '' ) . toString ( )
213
+ } ) ;
214
+ } )
215
+ ) ;
216
+
217
+ server . get (
218
+ {
219
+ path : '/domainaccess/:tag/allow' ,
220
+ tags : [ 'DomainAccess' ] ,
221
+ summary : 'List allowlisted domains' ,
222
+ validationObjs : {
223
+ requestBody : { } ,
224
+ queryParams : {
225
+ ess : sessSchema ,
226
+ ip : sessIPSchema
227
+ } ,
228
+ pathParams : {
229
+ tag : Joi . string ( ) . trim ( ) . max ( 128 ) . required ( ) . description ( 'Tag to look for' )
230
+ } ,
231
+ response : {
232
+ 200 : {
233
+ description : 'Success' ,
234
+ model : Joi . object ( {
235
+ success : successRes ,
236
+ results : Joi . array ( )
237
+ . items (
238
+ Joi . object ( {
239
+ id : Joi . string ( ) . required ( ) . description ( 'Entry ID' ) ,
240
+ domain : Joi . string ( ) . required ( ) . description ( 'Allowlisted domain name' ) ,
241
+ action : Joi . string ( ) . required ( ) . description ( 'Action: `allow`' ) . example ( 'allow' )
242
+ } )
243
+ . required ( )
244
+ . $_setFlag ( 'objectName' , 'GetAllowedDomainResult' )
245
+ )
246
+ . description ( 'Domain list' )
247
+ . required ( )
248
+ } )
249
+ }
250
+ }
251
+ }
252
+ } ,
253
+ tools . responseWrapper ( async ( req , res ) => {
254
+ res . charSet ( 'utf-8' ) ;
255
+
256
+ const { pathParams, requestBody, queryParams } = req . route . spec . validationObjs ;
257
+
258
+ const schema = Joi . object ( {
259
+ ...pathParams ,
260
+ ...requestBody ,
261
+ ...queryParams
262
+ } ) ;
263
+
264
+ const result = schema . validate ( req . params , {
265
+ abortEarly : false ,
266
+ convert : true
267
+ } ) ;
268
+
269
+ if ( result . error ) {
270
+ res . status ( 400 ) ;
271
+ return res . json ( {
272
+ error : result . error . message ,
273
+ code : 'InputValidationError' ,
274
+ details : tools . validationErrors ( result )
275
+ } ) ;
276
+ }
277
+
278
+ // permissions check
279
+ req . validate ( roles . can ( req . role ) . readAny ( 'domainaccess' ) ) ;
280
+
281
+ let tag = result . value . tag ;
282
+ let tagview = tag . toLowerCase ( ) ;
283
+ let action = 'action' ;
284
+
285
+ let domains ;
286
+ try {
287
+ domains = await db . database
288
+ . collection ( 'domainaccess' )
289
+ . find ( {
290
+ tagview,
291
+ action
292
+ } )
293
+ . sort ( {
294
+ domain : 1
295
+ } )
296
+ . toArray ( ) ;
297
+ } catch ( err ) {
298
+ res . status ( 500 ) ;
299
+ return res . json ( {
300
+ error : 'MongoDB Error: ' + err . message ,
301
+ code : 'InternalDatabaseError'
302
+ } ) ;
303
+ }
304
+
305
+ if ( ! domains ) {
306
+ domains = [ ] ;
307
+ }
308
+
309
+ return res . json ( {
310
+ success : true ,
311
+ results : domains . map ( domainData => ( {
312
+ id : domainData . _id . toString ( ) ,
313
+ domain : domainData . domain ,
314
+ action
315
+ } ) )
316
+ } ) ;
317
+ } )
318
+ ) ;
319
+
87
320
server . get (
88
- '/domainaccess/:tag/:action' ,
321
+ {
322
+ path : '/domainaccess/:tag/block' ,
323
+ tags : [ 'DomainAccess' ] ,
324
+ summary : 'List blocklisted domains' ,
325
+ validationObjs : {
326
+ requestBody : { } ,
327
+ queryParams : {
328
+ ess : sessSchema ,
329
+ ip : sessIPSchema
330
+ } ,
331
+ pathParams : {
332
+ tag : Joi . string ( ) . trim ( ) . max ( 128 ) . required ( ) . description ( 'Tag to look for' )
333
+ } ,
334
+ response : {
335
+ 200 : {
336
+ description : 'Success' ,
337
+ model : Joi . object ( {
338
+ success : successRes ,
339
+ results : Joi . array ( )
340
+ . items (
341
+ Joi . object ( {
342
+ id : Joi . string ( ) . required ( ) . description ( 'Entry ID' ) ,
343
+ domain : Joi . string ( ) . required ( ) . description ( 'Blocklisted domain name' ) ,
344
+ action : Joi . string ( ) . required ( ) . description ( 'Action: `block`' ) . example ( 'block' )
345
+ } )
346
+ . required ( )
347
+ . $_setFlag ( 'objectName' , 'GetBlockedDomainResult' )
348
+ )
349
+ . description ( 'Domain list' )
350
+ . required ( )
351
+ } )
352
+ }
353
+ }
354
+ }
355
+ } ,
89
356
tools . responseWrapper ( async ( req , res ) => {
90
357
res . charSet ( 'utf-8' ) ;
91
358
92
- const schema = Joi . object ( ) . keys ( {
93
- tag : Joi . string ( ) . trim ( ) . max ( 128 ) . required ( ) ,
94
- action : Joi . string ( ) . valid ( 'allow' , 'block' ) . required ( ) ,
359
+ const { pathParams, requestBody, queryParams } = req . route . spec . validationObjs ;
95
360
96
- sess : sessSchema ,
97
- ip : sessIPSchema
361
+ const schema = Joi . object ( {
362
+ ...pathParams ,
363
+ ...requestBody ,
364
+ ...queryParams
98
365
} ) ;
99
366
100
367
const result = schema . validate ( req . params , {
@@ -116,7 +383,7 @@ module.exports = (db, server) => {
116
383
117
384
let tag = result . value . tag ;
118
385
let tagview = tag . toLowerCase ( ) ;
119
- let action = result . value . action ;
386
+ let action = 'block' ;
120
387
121
388
let domains ;
122
389
try {
@@ -154,14 +421,39 @@ module.exports = (db, server) => {
154
421
) ;
155
422
156
423
server . del (
157
- '/domainaccess/:domain' ,
424
+ {
425
+ path : '/domainaccess/:domain' ,
426
+ tags : [ 'DomainAccess' ] ,
427
+ summary : 'Delete a Domain from listing' ,
428
+ validationObjs : {
429
+ requestBody : { } ,
430
+ queryParams : {
431
+ sess : sessSchema ,
432
+ ip : sessIPSchema
433
+ } ,
434
+ pathParams : {
435
+ domain : Joi . string ( ) . hex ( ) . lowercase ( ) . length ( 24 ) . required ( ) . description ( "Listed domain's unique ID" )
436
+ } ,
437
+ response : {
438
+ 200 : {
439
+ description : 'Success' ,
440
+ model : Joi . object ( {
441
+ success : successRes ,
442
+ deleted : Joi . string ( ) . required ( ) . description ( "Deleted domain's unique ID" )
443
+ } )
444
+ }
445
+ }
446
+ }
447
+ } ,
158
448
tools . responseWrapper ( async ( req , res ) => {
159
449
res . charSet ( 'utf-8' ) ;
160
450
161
- const schema = Joi . object ( ) . keys ( {
162
- domain : Joi . string ( ) . hex ( ) . lowercase ( ) . length ( 24 ) . required ( ) ,
163
- sess : sessSchema ,
164
- ip : sessIPSchema
451
+ const { pathParams, requestBody, queryParams } = req . route . spec . validationObjs ;
452
+
453
+ const schema = Joi . object ( {
454
+ ...pathParams ,
455
+ ...requestBody ,
456
+ ...queryParams
165
457
} ) ;
166
458
167
459
const result = schema . validate ( req . params , {
0 commit comments