2018-02-13 22:50:13 +00:00
'use strict' ;
const knex = require ( '../lib/knex' ) ;
const hasher = require ( 'node-object-hash' ) ( ) ;
const { enforce , filterObject } = require ( '../lib/helpers' ) ;
const dtHelpers = require ( '../lib/dt-helpers' ) ;
2018-11-18 14:38:52 +00:00
const interoperableErrors = require ( '../../shared/interoperable-errors' ) ;
2018-02-13 22:50:13 +00:00
const namespaceHelpers = require ( '../lib/namespace-helpers' ) ;
const shares = require ( './shares' ) ;
2018-09-29 11:30:29 +00:00
const files = require ( './files' ) ;
2018-09-29 18:08:49 +00:00
const dependencyHelpers = require ( '../lib/dependency-helpers' ) ;
2019-02-18 20:36:44 +00:00
const { convertFileURLs } = require ( '../lib/campaign-content' ) ;
2019-07-16 15:33:37 +00:00
const { allTagLanguages } = require ( '../../shared/templates' ) ;
const messageSender = require ( '../lib/message-sender' ) ;
2019-06-25 05:18:06 +00:00
2019-07-03 09:58:58 +00:00
const allowedKeys = new Set ( [ 'name' , 'description' , 'type' , 'tag_language' , 'data' , 'html' , 'text' , 'namespace' ] ) ;
2018-02-13 22:50:13 +00:00
function hash ( entity ) {
return hasher . hash ( filterObject ( entity , allowedKeys ) ) ;
}
2018-08-02 10:19:27 +00:00
async function getByIdTx ( tx , context , id , withPermissions = true ) {
await shares . enforceEntityPermissionTx ( tx , context , 'template' , id , 'view' ) ;
const entity = await tx ( 'templates' ) . where ( 'id' , id ) . first ( ) ;
entity . data = JSON . parse ( entity . data ) ;
2018-04-02 09:58:32 +00:00
2018-08-02 10:19:27 +00:00
if ( withPermissions ) {
entity . permissions = await shares . getPermissionsTx ( tx , context , 'template' , id ) ;
}
2018-05-09 02:07:01 +00:00
2018-08-02 10:19:27 +00:00
return entity ;
}
async function getById ( context , id , withPermissions = true ) {
return await knex . transaction ( async tx => {
return await getByIdTx ( tx , context , id , withPermissions ) ;
2018-02-13 22:50:13 +00:00
} ) ;
}
2019-03-26 23:41:18 +00:00
async function _listDTAjax ( context , namespaceId , params ) {
2018-02-13 22:50:13 +00:00
return await dtHelpers . ajaxListWithPermissions (
context ,
[ { entityTypeId : 'template' , requiredOperations : [ 'view' ] } ] ,
params ,
2019-03-26 23:41:18 +00:00
builder => {
builder = builder . from ( 'templates' ) . innerJoin ( 'namespaces' , 'namespaces.id' , 'templates.namespace' ) ;
if ( namespaceId ) {
builder = builder . where ( 'namespaces.id' , namespaceId ) ;
}
return builder ;
} ,
2019-07-03 09:58:58 +00:00
[ 'templates.id' , 'templates.name' , 'templates.description' , 'templates.type' , 'templates.tag_language' , 'templates.created' , 'namespaces.name' ]
2018-02-13 22:50:13 +00:00
) ;
}
2019-03-26 23:41:18 +00:00
async function listDTAjax ( context , params ) {
return await _listDTAjax ( context , undefined , params ) ;
}
async function listByNamespaceDTAjax ( context , namespaceId , params ) {
return await _listDTAjax ( context , namespaceId , params ) ;
2019-03-20 07:57:06 +00:00
}
2018-04-02 17:05:22 +00:00
async function _validateAndPreprocess ( tx , entity ) {
2018-07-31 04:34:28 +00:00
await namespaceHelpers . validateEntity ( tx , entity ) ;
2019-07-03 09:58:58 +00:00
enforce ( allTagLanguages . includes ( entity . tag _language ) , ` Invalid tag language ' ${ entity . tag _language } ' ` ) ;
2018-07-31 04:34:28 +00:00
// We don't check contents of the "data" because it is processed solely on the client. The client generates the HTML code we use when sending out campaigns.
2018-04-02 09:58:32 +00:00
}
2018-02-13 22:50:13 +00:00
async function create ( context , entity ) {
return await knex . transaction ( async tx => {
await shares . enforceEntityPermissionTx ( tx , context , 'namespace' , entity . namespace , 'createTemplate' ) ;
2018-04-02 09:58:32 +00:00
2019-07-26 11:18:26 +00:00
if ( entity . fromExistingEntity ) {
const existing = await getByIdTx ( tx , context , entity . existingEntity , false ) ;
2019-08-07 12:29:58 +00:00
2019-07-26 11:18:26 +00:00
entity . type = existing . type ;
entity . tag _language = existing . tag _language ;
entity . data = existing . data ;
entity . html = existing . html ;
entity . text = existing . text ;
2019-02-18 20:36:44 +00:00
}
2018-04-02 17:05:22 +00:00
await _validateAndPreprocess ( tx , entity ) ;
2018-04-02 09:58:32 +00:00
2019-08-07 12:29:58 +00:00
const filteredEntityWithUnstringifiedData = filterObject ( entity , allowedKeys ) ;
const filteredEntity = {
... filteredEntityWithUnstringifiedData ,
data : JSON . stringify ( filteredEntityWithUnstringifiedData . data )
} ;
const ids = await tx ( 'templates' ) . insert ( filteredEntity ) ;
2018-02-13 22:50:13 +00:00
const id = ids [ 0 ] ;
await shares . rebuildPermissionsTx ( tx , { entityTypeId : 'template' , entityId : id } ) ;
2019-08-06 07:25:22 +00:00
if ( entity . fromExistingEntity ) {
2019-07-26 11:18:26 +00:00
await files . copyAllTx ( tx , context , 'template' , 'file' , entity . existingEntity , 'template' , 'file' , id ) ;
2019-08-07 12:29:58 +00:00
convertFileURLs ( filteredEntityWithUnstringifiedData , 'template' , entity . existingEntity , 'template' , id ) ;
const filteredEntity = {
... filteredEntityWithUnstringifiedData ,
data : JSON . stringify ( filteredEntityWithUnstringifiedData . data )
} ;
await tx ( 'templates' ) . update ( filteredEntity ) . where ( 'id' , id ) ;
2019-08-06 07:25:22 +00:00
}
2019-02-18 20:36:44 +00:00
2018-02-13 22:50:13 +00:00
return id ;
} ) ;
}
async function updateWithConsistencyCheck ( context , entity ) {
await knex . transaction ( async tx => {
await shares . enforceEntityPermissionTx ( tx , context , 'template' , entity . id , 'edit' ) ;
const existing = await tx ( 'templates' ) . where ( 'id' , entity . id ) . first ( ) ;
if ( ! existing ) {
throw new interoperableErrors . NotFoundError ( ) ;
}
2018-04-02 09:58:32 +00:00
existing . data = JSON . parse ( existing . data ) ;
2018-02-13 22:50:13 +00:00
const existingHash = hash ( existing ) ;
if ( existingHash !== entity . originalHash ) {
throw new interoperableErrors . ChangedError ( ) ;
}
2018-04-02 17:05:22 +00:00
await _validateAndPreprocess ( tx , entity ) ;
2019-08-07 12:29:58 +00:00
entity . data = JSON . stringify ( entity . data ) ;
2018-04-02 09:58:32 +00:00
2018-02-13 22:50:13 +00:00
await namespaceHelpers . validateMove ( context , entity , existing , 'template' , 'createTemplate' , 'delete' ) ;
2019-08-07 12:29:58 +00:00
const filteredEntity = filterObject ( entity , allowedKeys ) ;
await tx ( 'templates' ) . where ( 'id' , entity . id ) . update ( filteredEntity ) ;
2018-02-13 22:50:13 +00:00
await shares . rebuildPermissionsTx ( tx , { entityTypeId : 'template' , entityId : entity . id } ) ;
} ) ;
}
async function remove ( context , id ) {
await knex . transaction ( async tx => {
await shares . enforceEntityPermissionTx ( tx , context , 'template' , id , 'delete' ) ;
2018-09-29 18:08:49 +00:00
await dependencyHelpers . ensureNoDependencies ( tx , context , id , [
{
entityTypeId : 'campaign' ,
query : tx => tx ( 'template_dep_campaigns' )
. where ( 'template_dep_campaigns.template' , id )
. innerJoin ( 'campaigns' , 'template_dep_campaigns.campaign' , 'campaigns.id' )
. select ( [ 'campaigns.id' , 'campaigns.name' ] )
}
] ) ;
2018-09-29 11:30:29 +00:00
await files . removeAllTx ( tx , context , 'template' , 'file' , id ) ;
2018-02-13 22:50:13 +00:00
await tx ( 'templates' ) . where ( 'id' , id ) . del ( ) ;
} ) ;
}
2019-07-16 15:33:37 +00:00
async function sendAsTransactionalEmail ( context , templateId , sendConfigurationId , emails , subject , mergeTags , attachments ) {
const template = await getById ( context , templateId , false ) ;
2019-06-25 05:18:06 +00:00
2019-07-16 15:33:37 +00:00
await shares . enforceEntityPermission ( context , 'sendConfiguration' , sendConfigurationId , 'sendWithoutOverrides' ) ;
2019-06-25 05:18:06 +00:00
2019-07-16 15:33:37 +00:00
for ( const email of emails ) {
await messageSender . queueAPITransactionalMessage ( sendConfigurationId , email , subject , template . html , template . text , template . tag _language , { ... mergeTags , EMAIL : email } , attachments ) ;
}
2019-06-25 05:18:06 +00:00
}
2018-09-09 22:55:44 +00:00
module . exports . hash = hash ;
module . exports . getByIdTx = getByIdTx ;
module . exports . getById = getById ;
module . exports . listDTAjax = listDTAjax ;
2019-03-20 07:57:06 +00:00
module . exports . listByNamespaceDTAjax = listByNamespaceDTAjax ;
2018-09-09 22:55:44 +00:00
module . exports . create = create ;
module . exports . updateWithConsistencyCheck = updateWithConsistencyCheck ;
module . exports . remove = remove ;
2019-06-25 05:18:06 +00:00
module . exports . sendAsTransactionalEmail = sendAsTransactionalEmail ;