diff --git a/client/src/Home.js b/client/src/Home.js index 51ffd281..7190fdc8 100644 --- a/client/src/Home.js +++ b/client/src/Home.js @@ -20,7 +20,7 @@ export default class List extends Component { return (

{t('Mailtrain 2 beta')}

-
{t('Build') + ' 2019-07-29-0959'}
+
{t('Build') + ' 2019-08-01-0745'}
); } diff --git a/server/models/campaigns.js b/server/models/campaigns.js index 8cafdcb9..2e6aaa8f 100644 --- a/server/models/campaigns.js +++ b/server/models/campaigns.js @@ -185,7 +185,7 @@ async function listTestUsersDTAjax(context, campaignId, params) { return await dtHelpers.ajaxListWithPermissionsTx( tx, context, - [{ entityTypeId: 'list', requiredOperations: ['viewSubscriptions'], column: 'subs.list_id' }], + [{ entityTypeId: 'list', requiredOperations: ['viewTestSubscriptions'], column: 'subs.list_id' }], params, builder => { return builder.from(function () { @@ -960,7 +960,7 @@ async function fetchRssCampaign(context, cid) { } async function testSend(context, data) { - // Though it's a bit counterintuitive, this handles also test sends of a template (i.e. without any campaign id) + // Though it's a bit counter-intuitive, this handles also test sends of a template (i.e. without any campaign id) await knex.transaction(async tx => { const processSubscriber = async (sendConfigurationId, listId, subscriptionId, messageData) => { @@ -1014,7 +1014,7 @@ async function testSend(context, data) { await enforceSendPermissionTx(tx, context, campaign, true, listId); if (data.subscriptionCid) { - const subscriber = await subscriptions.getByCidTx(tx, context, listId, data.subscriptionCid); + const subscriber = await subscriptions.getByCidTx(tx, context, listId, data.subscriptionCid, true, true); await processSubscriber(sendConfigurationId, listId, subscriber.id, messageData); } else { @@ -1050,7 +1050,7 @@ async function testSend(context, data) { }; const list = await lists.getByCidTx(tx, context, data.listCid); - const subscriber = await subscriptions.getByCidTx(tx, context, list.id, data.subscriptionCid); + const subscriber = await subscriptions.getByCidTx(tx, context, list.id, data.subscriptionCid, true, true); await processSubscriber(data.sendConfigurationId, list.id, subscriber.id, messageData); } }); diff --git a/server/models/subscriptions.js b/server/models/subscriptions.js index 4867f546..2e90be43 100644 --- a/server/models/subscriptions.js +++ b/server/models/subscriptions.js @@ -201,11 +201,15 @@ async function hashByList(listId, entity) { }); } -async function _getByTx(tx, context, listId, key, value, grouped) { - await shares.enforceEntityPermissionTx(tx, context, 'list', listId, 'viewSubscriptions'); +async function _getByTx(tx, context, listId, key, value, grouped, isTest) { + await shares.enforceEntityPermissionTx(tx, context, 'list', listId, isTest ? 'viewTestSubscriptions' : 'viewSubscriptions'); const entity = await tx(getSubscriptionTableName(listId)).where(key, value).first(); + if (isTest && (!entity || !entity.is_test)) { + shares.throwPermissionDenied(); + } + if (!entity) { throw new interoperableErrors.NotFoundError('Subscription not found in this list'); } @@ -219,18 +223,18 @@ async function _getByTx(tx, context, listId, key, value, grouped) { return entity; } -async function _getBy(context, listId, key, value, grouped) { +async function _getBy(context, listId, key, value, grouped, isTest) { return await knex.transaction(async tx => { - return _getByTx(tx, context, listId, key, value, grouped); + return _getByTx(tx, context, listId, key, value, grouped, isTest); }); } async function getById(context, listId, id, grouped = true) { - return await _getBy(context, listId, 'id', id, grouped); + return await _getBy(context, listId, 'id', id, grouped, false); } async function getByEmail(context, listId, email, grouped = true) { - const result = await _getBy(context, listId, 'hash_email', hashEmail(email), grouped); + const result = await _getBy(context, listId, 'hash_email', hashEmail(email), grouped, false); if (result.email === null) { throw new interoperableErrors.NotFoundError('Subscription not found in this list'); } @@ -238,12 +242,12 @@ async function getByEmail(context, listId, email, grouped = true) { return result; } -async function getByCid(context, listId, cid, grouped = true) { - return await _getBy(context, listId, 'cid', cid, grouped); +async function getByCid(context, listId, cid, grouped = true, isTest = true) { + return await _getBy(context, listId, 'cid', cid, grouped, isTest); } -async function getByCidTx(tx, context, listId, cid, grouped = true) { - return await _getByTx(tx, context, listId, 'cid', cid, grouped); +async function getByCidTx(tx, context, listId, cid, grouped = true, isTest = true) { + return await _getByTx(tx, context, listId, 'cid', cid, grouped, isTest); } async function listDTAjax(context, listId, segmentId, params) {