diff --git a/ghost/members-api/lib/repositories/event.js b/ghost/members-api/lib/repositories/event.js index 11a90e5228..c9a34b2830 100644 --- a/ghost/members-api/lib/repositories/event.js +++ b/ghost/members-api/lib/repositories/event.js @@ -36,6 +36,9 @@ module.exports = class EventRepository { if (filters['data.created_at']) { options.filter.push(filters['data.created_at'].replace(/data.created_at:/g, 'created_at:')); } + if (filters['data.source']) { + options.filter.push(filters['data.source'].replace(/data.source:/g, 'source:')); + } if (filters['data.member_id']) { options.filter.push(filters['data.member_id'].replace(/data.member_id:/g, 'member_id:')); } diff --git a/ghost/verification-trigger/lib/verification-trigger.js b/ghost/verification-trigger/lib/verification-trigger.js index 1a3e5824d8..d9c50d42d4 100644 --- a/ghost/verification-trigger/lib/verification-trigger.js +++ b/ghost/verification-trigger/lib/verification-trigger.js @@ -1,4 +1,6 @@ const errors = require('@tryghost/errors'); +const DomainEvents = require('@tryghost/domain-events'); +const {MemberSubscribeEvent} = require('@tryghost/member-events'); const messages = { emailVerificationNeeded: `We're hard at work processing your import. To make sure you get great deliverability on a list of that size, we'll need to enable some extra features for your account. A member of our team will be in touch with you by email to review your account make sure everything is configured correctly so you're ready to go.`, @@ -34,6 +36,24 @@ class VerificationTrigger { this._membersStats = membersStats; this._Settings = Settings; this._eventRepository = eventRepository; + + DomainEvents.subscribe(MemberSubscribeEvent, async (event) => { + if (event.data.source === 'api' && isFinite(this._configThreshold)) { + const createdAt = new Date(); + createdAt.setDate(createdAt.getDate() - 30); + const events = await this._eventRepository.getNewsletterSubscriptionEvents({}, { + 'data.source': 'data.source:api', + 'data.created_at': `data.created_at:>${createdAt.toISOString().replace('T', ' ').substring(0, 19)}` + }); + + if (events.meta.pagination.total > this._configThreshold) { + await this.startVerificationProcess({ + amountImported: events.meta.pagination.total, + throwOnTrigger: false + }); + } + } + }); } async getImportThreshold() { diff --git a/ghost/verification-trigger/test/verification-trigger.test.js b/ghost/verification-trigger/test/verification-trigger.test.js index 8e37bf170e..5c568cb88b 100644 --- a/ghost/verification-trigger/test/verification-trigger.test.js +++ b/ghost/verification-trigger/test/verification-trigger.test.js @@ -3,6 +3,8 @@ const sinon = require('sinon'); require('./utils'); const VerificationTrigger = require('../lib/verification-trigger'); +const DomainEvents = require('@tryghost/domain-events'); +const {MemberSubscribeEvent} = require('@tryghost/member-events'); describe('Import threshold', function () { it('Creates a threshold based on config', async function () { @@ -152,4 +154,40 @@ describe('Email verification flow', function () { amountImported: 10 }); }); -}); + + it('Triggers when a number of API events are dispatched', async function () { + const emailStub = sinon.stub().resolves(null); + const settingsStub = sinon.stub().resolves(null); + const eventStub = sinon.stub().resolves({ + meta: { + pagination: { + total: 10 + } + } + }); + + new VerificationTrigger({ + configThreshold: 2, + Settings: { + edit: settingsStub + }, + isVerified: () => false, + isVerificationRequired: () => false, + sendVerificationEmail: emailStub, + eventRepository: { + getNewsletterSubscriptionEvents: eventStub + } + }); + + DomainEvents.dispatch(MemberSubscribeEvent.create({ + memberId: 'hello!', + source: 'api' + }, new Date())); + + eventStub.callCount.should.eql(1); + eventStub.lastCall.lastArg.should.have.property('data.source'); + eventStub.lastCall.lastArg.should.have.property('data.created_at'); + eventStub.lastCall.lastArg['data.source'].should.eql('data.source:api'); + eventStub.lastCall.lastArg['data.created_at'].should.startWith('data.created_at:>'); + }); +}); \ No newline at end of file