2016-05-07 11:28:24 +00:00
'use strict' ;
2019-07-26 15:05:49 +00:00
const config = require ( '../lib/config' ) ;
2018-01-28 22:59:05 +00:00
const lists = require ( '../models/lists' ) ;
2018-04-29 16:13:40 +00:00
const tools = require ( '../lib/tools' ) ;
2018-01-28 22:59:05 +00:00
const blacklist = require ( '../models/blacklist' ) ;
const fields = require ( '../models/fields' ) ;
2018-11-18 14:38:52 +00:00
const { SubscriptionStatus , SubscriptionSource } = require ( '../../shared/lists' ) ;
2018-01-28 22:59:05 +00:00
const subscriptions = require ( '../models/subscriptions' ) ;
const confirmations = require ( '../models/confirmations' ) ;
2018-09-27 19:32:35 +00:00
const log = require ( '../lib/log' ) ;
2017-07-08 13:48:34 +00:00
const router = require ( '../lib/router-async' ) . create ( ) ;
2018-01-28 22:59:05 +00:00
const mailHelpers = require ( '../lib/subscription-mail-helpers' ) ;
2018-11-18 14:38:52 +00:00
const interoperableErrors = require ( '../../shared/interoperable-errors' ) ;
2018-01-28 22:59:05 +00:00
const contextHelpers = require ( '../lib/context-helpers' ) ;
const shares = require ( '../models/shares' ) ;
const slugify = require ( 'slugify' ) ;
2018-05-21 17:41:10 +00:00
const passport = require ( '../lib/passport' ) ;
2019-06-25 05:18:06 +00:00
const templates = require ( '../models/templates' ) ;
2018-12-29 14:12:42 +00:00
const campaigns = require ( '../models/campaigns' ) ;
2019-06-25 05:18:06 +00:00
const { castToInteger } = require ( '../lib/helpers' ) ;
const { getSystemSendConfigurationId } = require ( '../../shared/send-configurations' ) ;
2018-01-28 22:59:05 +00:00
class APIError extends Error {
constructor ( msg , status ) {
super ( msg ) ;
this . status = status ;
}
}
2016-05-07 11:28:24 +00:00
2018-01-28 22:59:05 +00:00
2018-05-21 17:41:10 +00:00
router . postAsync ( '/subscribe/:listCid' , passport . loggedIn , async ( req , res ) => {
const list = await lists . getByCid ( req . context , req . params . listCid ) ;
await shares . enforceEntityPermission ( req . context , 'list' , list . id , 'manageSubscriptions' ) ;
2018-01-28 22:59:05 +00:00
const input = { } ;
2016-05-07 11:28:24 +00:00
Object . keys ( req . body ) . forEach ( key => {
input [ ( key || '' ) . toString ( ) . trim ( ) . toUpperCase ( ) ] = ( req . body [ key ] || '' ) . toString ( ) . trim ( ) ;
} ) ;
2018-01-28 22:59:05 +00:00
if ( ! input . EMAIL ) {
throw new APIError ( 'Missing EMAIL' , 400 ) ;
}
2016-05-07 11:28:24 +00:00
2018-09-01 19:29:10 +00:00
const emailErr = await tools . validateEmail ( input . EMAIL ) ;
2018-01-28 22:59:05 +00:00
if ( emailErr ) {
2019-07-09 22:06:56 +00:00
const errMsg = tools . validateEmailGetMessage ( emailErr , input . email , null ) ;
2018-01-28 22:59:05 +00:00
log . error ( 'API' , errMsg ) ;
throw new APIError ( errMsg , 400 ) ;
}
2016-05-07 11:28:24 +00:00
2018-09-01 19:29:10 +00:00
const subscription = await fields . fromAPI ( req . context , list . id , input ) ;
2018-05-21 17:41:10 +00:00
2018-01-28 22:59:05 +00:00
if ( input . TIMEZONE ) {
subscription . tz = ( input . TIMEZONE || '' ) . toString ( ) . trim ( ) ;
}
if ( /^(yes|true|1)$/i . test ( input . FORCE _SUBSCRIBE ) ) {
subscription . status = SubscriptionStatus . SUBSCRIBED ;
}
2018-02-13 22:50:13 +00:00
if ( /^(yes|true|1)$/i . test ( input . REQUIRE _CONFIRMATION ) ) { // if REQUIRE_CONFIRMATION is set, we assume that the user is not subscribed and will be subscribed
2018-01-28 22:59:05 +00:00
const data = {
2018-05-21 17:41:10 +00:00
email : input . EMAIL ,
2018-01-28 22:59:05 +00:00
subscriptionData : subscription
} ;
2016-05-07 11:28:24 +00:00
2018-05-21 17:41:10 +00:00
const confirmCid = await confirmations . addConfirmation ( list . id , 'subscribe' , req . ip , data ) ;
2018-12-15 14:15:48 +00:00
await mailHelpers . sendConfirmSubscription ( req . locale , list , input . EMAIL , confirmCid , subscription ) ;
2018-01-28 22:59:05 +00:00
res . status ( 200 ) ;
res . json ( {
data : {
id : confirmCid
}
2016-05-07 11:28:24 +00:00
} ) ;
2018-01-28 22:59:05 +00:00
} else {
2018-02-13 22:50:13 +00:00
subscription . email = input . EMAIL ;
const meta = {
2018-05-21 17:41:10 +00:00
updateAllowed : true ,
subscribeIfNoExisting : true
2018-02-13 22:50:13 +00:00
} ;
2018-08-06 14:54:51 +00:00
await subscriptions . create ( req . context , list . id , subscription , SubscriptionSource . API , meta ) ;
2018-01-28 22:59:05 +00:00
res . status ( 200 ) ;
res . json ( {
data : {
id : meta . cid
}
} ) ;
}
2016-05-07 11:28:24 +00:00
} ) ;
2018-01-28 22:59:05 +00:00
2018-05-21 17:41:10 +00:00
router . postAsync ( '/unsubscribe/:listCid' , passport . loggedIn , async ( req , res ) => {
const list = await lists . getByCid ( req . context , req . params . listCid ) ;
2018-01-28 22:59:05 +00:00
const input = { } ;
2016-05-07 11:28:24 +00:00
Object . keys ( req . body ) . forEach ( key => {
input [ ( key || '' ) . toString ( ) . trim ( ) . toUpperCase ( ) ] = ( req . body [ key ] || '' ) . toString ( ) . trim ( ) ;
} ) ;
2017-05-06 10:35:32 +00:00
2018-01-28 22:59:05 +00:00
if ( ! input . EMAIL ) {
throw new APIError ( 'Missing EMAIL' , 400 ) ;
}
2017-05-06 10:35:32 +00:00
2018-05-21 17:41:10 +00:00
const subscription = await subscriptions . unsubscribeByEmailAndGet ( req . context , list . id , input . EMAIL ) ;
2017-05-06 10:35:32 +00:00
2018-01-28 22:59:05 +00:00
res . status ( 200 ) ;
res . json ( {
data : {
id : subscription . id ,
unsubscribed : true
}
2016-05-07 11:28:24 +00:00
} ) ;
} ) ;
2018-01-28 22:59:05 +00:00
2018-05-21 17:41:10 +00:00
router . postAsync ( '/delete/:listCid' , passport . loggedIn , async ( req , res ) => {
const list = await lists . getByCid ( req . context , req . params . listCid ) ;
2018-01-28 22:59:05 +00:00
const input = { } ;
2016-06-24 11:29:07 +00:00
Object . keys ( req . body ) . forEach ( key => {
input [ ( key || '' ) . toString ( ) . trim ( ) . toUpperCase ( ) ] = ( req . body [ key ] || '' ) . toString ( ) . trim ( ) ;
} ) ;
2018-01-28 22:59:05 +00:00
if ( ! input . EMAIL ) {
throw new APIError ( 'Missing EMAIL' , 400 ) ;
}
2018-05-21 17:41:10 +00:00
const subscription = await subscriptions . removeByEmailAndGet ( req . context , list . id , input . EMAIL ) ;
2018-01-28 22:59:05 +00:00
res . status ( 200 ) ;
res . json ( {
data : {
id : subscription . id ,
deleted : true
2016-06-24 11:29:07 +00:00
}
2018-01-28 22:59:05 +00:00
} ) ;
} ) ;
2018-05-21 17:41:10 +00:00
router . getAsync ( '/subscriptions/:listCid' , passport . loggedIn , async ( req , res ) => {
const list = await lists . getByCid ( req . context , req . params . listCid ) ;
2018-01-28 22:59:05 +00:00
const start = parseInt ( req . query . start || 0 , 10 ) ;
const limit = parseInt ( req . query . limit || 10000 , 10 ) ;
2019-08-23 11:56:22 +00:00
const result = await subscriptions . list ( req . context , list . id , false , start , limit ) ;
2018-01-28 22:59:05 +00:00
res . status ( 200 ) ;
res . json ( {
data : {
2019-08-23 11:56:22 +00:00
total : result . total ,
2018-01-28 22:59:05 +00:00
start : start ,
limit : limit ,
2019-08-23 11:56:22 +00:00
subscriptions : result . subscriptions
2016-06-24 11:29:07 +00:00
}
} ) ;
} ) ;
2018-05-21 17:41:10 +00:00
router . getAsync ( '/lists/:email' , passport . loggedIn , async ( req , res ) => {
2018-01-28 22:59:05 +00:00
const lists = await subscriptions . getListsWithEmail ( req . context , req . params . email ) ;
res . status ( 200 ) ;
res . json ( {
data : lists
} ) ;
} ) ;
2018-05-21 17:41:10 +00:00
router . postAsync ( '/field/:listCid' , passport . loggedIn , async ( req , res ) => {
const list = await lists . getByCid ( req . context , req . params . listCid ) ;
2018-01-28 22:59:05 +00:00
const input = { } ;
2016-08-29 09:27:14 +00:00
Object . keys ( req . body ) . forEach ( key => {
input [ ( key || '' ) . toString ( ) . trim ( ) . toUpperCase ( ) ] = ( req . body [ key ] || '' ) . toString ( ) . trim ( ) ;
} ) ;
2018-01-28 22:59:05 +00:00
const key = ( input . NAME || '' ) . toString ( ) . trim ( ) || slugify ( 'merge ' + name , '_' ) . toUpperCase ( ) ;
const visible = [ 'false' , 'no' , '0' , '' ] . indexOf ( ( input . VISIBLE || '' ) . toString ( ) . toLowerCase ( ) . trim ( ) ) < 0 ;
const groupTemplate = ( input . GROUP _TEMPLATE || '' ) . toString ( ) . toLowerCase ( ) . trim ( ) ;
let type = ( input . TYPE || '' ) . toString ( ) . toLowerCase ( ) . trim ( ) ;
const settings = { } ;
if ( type === 'checkbox' ) {
type = 'checkbox-grouped' ;
settings . groupTemplate = groupTemplate ;
} else if ( type === 'dropdown' ) {
type = 'dropdown-grouped' ;
settings . groupTemplate = groupTemplate ;
} else if ( type === 'radio' ) {
type = 'radio-grouped' ;
settings . groupTemplate = groupTemplate ;
} else if ( type === 'json' ) {
settings . groupTemplate = groupTemplate ;
} else if ( type === 'date-us' ) {
type = 'date' ;
settings . dateFormat = 'us' ;
} else if ( type === 'date-eur' ) {
type = 'date' ;
settings . dateFormat = 'eur' ;
} else if ( type === 'birthday-us' ) {
type = 'birthday' ;
settings . birthdayFormat = 'us' ;
} else if ( type === 'birthday-eur' ) {
type = 'birthday' ;
settings . birthdayFormat = 'eur' ;
}
2016-08-29 09:27:14 +00:00
2018-01-28 22:59:05 +00:00
const field = {
name : ( input . NAME || '' ) . toString ( ) . trim ( ) ,
key ,
default _value : ( input . DEFAULT || '' ) . toString ( ) . trim ( ) || null ,
type ,
settings ,
group : Number ( input . GROUP ) || null ,
orderListBefore : visible ? 'end' : 'none' ,
orderSubscribeBefore : visible ? 'end' : 'none' ,
orderManageBefore : visible ? 'end' : 'none'
} ;
2018-05-21 17:41:10 +00:00
const id = await fields . create ( req . context , list . id , field ) ;
2018-01-28 22:59:05 +00:00
res . status ( 200 ) ;
res . json ( {
data : {
id ,
tag : key
}
2016-08-29 09:27:14 +00:00
} ) ;
} ) ;
2018-01-28 22:59:05 +00:00
2018-05-21 17:41:10 +00:00
router . postAsync ( '/blacklist/add' , passport . loggedIn , async ( req , res ) => {
2017-04-10 17:09:40 +00:00
let input = { } ;
Object . keys ( req . body ) . forEach ( key => {
input [ ( key || '' ) . toString ( ) . trim ( ) . toUpperCase ( ) ] = ( req . body [ key ] || '' ) . toString ( ) . trim ( ) ;
} ) ;
if ( ! ( input . EMAIL ) || ( input . EMAIL === '' ) ) {
2019-06-25 05:18:06 +00:00
throw new APIError ( 'EMAIL argument is required' , 400 ) ;
2017-04-10 17:09:40 +00:00
}
2017-12-10 20:44:35 +00:00
await blacklist . add ( req . context , input . EMAIL ) ;
res . json ( {
data : [ ]
2017-04-10 17:09:40 +00:00
} ) ;
} ) ;
2018-01-28 22:59:05 +00:00
2018-05-21 17:41:10 +00:00
router . postAsync ( '/blacklist/delete' , passport . loggedIn , async ( req , res ) => {
2017-04-10 17:09:40 +00:00
let input = { } ;
Object . keys ( req . body ) . forEach ( key => {
input [ ( key || '' ) . toString ( ) . trim ( ) . toUpperCase ( ) ] = ( req . body [ key ] || '' ) . toString ( ) . trim ( ) ;
} ) ;
2017-12-10 20:44:35 +00:00
if ( ! ( input . EMAIL ) || ( input . EMAIL === '' ) ) {
2019-06-25 05:18:06 +00:00
throw new APIError ( 'EMAIL argument is required' , 400 ) ;
2017-04-10 17:09:40 +00:00
}
2017-12-10 20:44:35 +00:00
await blacklist . remove ( req . oontext , input . EMAIL ) ;
res . json ( {
data : [ ]
2017-04-10 17:09:40 +00:00
} ) ;
} ) ;
2018-01-28 22:59:05 +00:00
2018-05-21 17:41:10 +00:00
router . getAsync ( '/blacklist/get' , passport . loggedIn , async ( req , res ) => {
2017-04-10 17:09:40 +00:00
let start = parseInt ( req . query . start || 0 , 10 ) ;
let limit = parseInt ( req . query . limit || 10000 , 10 ) ;
let search = req . query . search || '' ;
2017-12-10 20:44:35 +00:00
const { emails , total } = await blacklist . search ( req . context , start , limit , search ) ;
return res . json ( {
data : {
total ,
2017-04-10 17:09:40 +00:00
start : start ,
limit : limit ,
2017-12-10 20:44:35 +00:00
emails
}
2017-04-10 17:09:40 +00:00
} ) ;
} ) ;
2018-12-29 14:12:42 +00:00
router . getAsync ( '/rss/fetch/:campaignCid' , passport . loggedIn , async ( req , res ) => {
await campaigns . fetchRssCampaign ( req . context , req . params . campaignCid ) ;
return res . json ( ) ;
} ) ;
2019-03-24 12:27:56 +00:00
router . postAsync ( '/templates/:templateId/send' , async ( req , res ) => {
const input = { } ;
2019-06-25 05:18:06 +00:00
for ( const key in req . body ) {
const sanitizedKey = key . toString ( ) . trim ( ) . toUpperCase ( ) ;
input [ sanitizedKey ] = req . body [ key ] || '' ;
}
const templateId = castToInteger ( req . params . templateId , 'Invalid template ID' ) ;
let sendConfigurationId ;
if ( ! ( 'SEND_CONFIGURATION_ID' in input ) ) {
sendConfigurationId = getSystemSendConfigurationId ( ) ;
} else {
sendConfigurationId = castToInteger ( input . SEND _CONFIGURATION _ID , 'Invalid send configuration ID' ) ;
}
if ( ! input . EMAIL || input . EMAIL === 0 ) {
throw new APIError ( 'Missing email(s)' , 400 ) ;
2019-03-24 12:27:56 +00:00
}
2019-06-25 05:18:06 +00:00
const emails = input . EMAIL . split ( ',' ) ;
2019-07-16 15:33:37 +00:00
const mergeTags = input . TAGS || { } ;
const subject = input . SUBJECT || '' ;
const attachments = input . ATTACHMENTS || [ ] ;
2019-06-25 05:18:06 +00:00
2019-07-16 15:33:37 +00:00
const result = await templates . sendAsTransactionalEmail ( req . context , templateId , sendConfigurationId , emails , subject , mergeTags , attachments ) ;
res . json ( { data : result } ) ;
2019-03-24 12:27:56 +00:00
} ) ;
2018-01-28 22:59:05 +00:00
2016-05-07 11:28:24 +00:00
module . exports = router ;