Merge pull request #2119 from overleaf/ta-subscription-deletion

Store Deleted Subscriptions

GitOrigin-RevId: c7004f1807dee6b6ec82eeb2a8fe939801ce3e8b
This commit is contained in:
Eric Mc Sween
2019-09-09 12:05:23 +00:00
committed by sharelatex
parent bc233e6eba
commit d0fc8d90e5
12 changed files with 286 additions and 32 deletions
@@ -0,0 +1,73 @@
const { expect } = require('chai')
const async = require('async')
const request = require('./helpers/request')
const User = require('./helpers/User')
const RecurlySubscription = require('./helpers/RecurlySubscription')
const SubscriptionUpdater = require('../../../app/src/Features/Subscription/SubscriptionUpdater')
require('./helpers/MockV1Api')
describe('Subscriptions', function() {
describe('deletion', function() {
beforeEach(function(done) {
this.adminUser = new User()
this.memberUser = new User()
async.series(
[
cb => this.adminUser.ensureUserExists(cb),
cb => this.memberUser.ensureUserExists(cb),
cb => {
this.recurlySubscription = new RecurlySubscription({
adminId: this.adminUser._id,
memberIds: [this.memberUser._id],
invitedEmails: ['foo@bar.com'],
teamInvites: [{ email: 'foo@baz.com' }],
groupPlan: true,
state: 'expired'
})
this.subscription = this.recurlySubscription.subscription
this.recurlySubscription.ensureExists(cb)
}
],
done
)
})
it('deletes via Recurly callback', function(done) {
let url = '/user/subscription/callback'
let body = this.recurlySubscription.buildCallbackXml()
request.post({ url, body }, (error, { statusCode }) => {
if (error) {
return done(error)
}
expect(statusCode).to.equal(200)
this.subscription.expectDeleted({ ip: '127.0.0.1' }, done)
})
})
it('allows deletion when deletedSubscription exists', function(done) {
let url = '/user/subscription/callback'
let body = this.recurlySubscription.buildCallbackXml()
// create fake deletedSubscription
SubscriptionUpdater._createDeletedSubscription(
this.subscription,
{},
error => {
if (error) {
return done(error)
}
// try deleting the subscription
request.post({ url, body }, (error, { statusCode }) => {
if (error) {
return done(error)
}
expect(statusCode).to.equal(200)
this.subscription.expectDeleted({ ip: '127.0.0.1' }, done)
})
}
)
})
})
})
@@ -26,6 +26,14 @@ module.exports = MockRecurlyApi = {
coupons: {},
addSubscription(subscription) {
this.subscriptions[subscription.uuid] = subscription
},
addAccount(account) {
this.accounts[account.id] = account
},
run() {
app.get('/subscriptions/:id', (req, res, next) => {
const subscription = this.subscriptions[req.params.id]
@@ -0,0 +1,39 @@
const { ObjectId } = require('../../../../app/src/infrastructure/mongojs')
const Subscription = require('./Subscription')
const MockRecurlyApi = require('./MockRecurlyApi')
const RecurlyWrapper = require('../../../../app/src/Features/Subscription/RecurlyWrapper')
class RecurlySubscription {
constructor(options = {}) {
this.subscription = new Subscription(options)
this.uuid = ObjectId().toString()
this.accountId = this.subscription.admin_id.toString()
this.state = options.state || 'active'
}
ensureExists(callback) {
this.subscription.ensureExists(error => {
if (error) {
return callback(error)
}
MockRecurlyApi.addSubscription({
uuid: this.uuid,
account_id: this.accountId,
state: this.state
})
MockRecurlyApi.addAccount({ id: this.accountId })
callback()
})
}
buildCallbackXml() {
return RecurlyWrapper._buildXml('expired_subscription_notification', {
subscription: {
uuid: this.uuid
}
})
}
}
module.exports = RecurlySubscription
@@ -1,12 +1,19 @@
const { ObjectId } = require('../../../../app/src/infrastructure/mongojs')
const { expect } = require('chai')
const SubscriptionModel = require('../../../../app/src/models/Subscription')
.Subscription
const DeletedSubscriptionModel = require(`../../../../app/src/models/DeletedSubscription`)
.DeletedSubscription
class Subscription {
constructor(options = {}) {
this.admin_id = options.adminId || ObjectId()
this.overleaf = options.overleaf || {}
this.groupPlan = options.groupPlan
this.manager_ids = []
this.member_ids = options.memberIds || []
this.invited_emails = options.invitedEmails || []
this.teamInvites = options.teamInvites || []
}
ensureExists(callback) {
@@ -32,6 +39,36 @@ class Subscription {
callback
)
}
expectDeleted(deleterData, callback) {
DeletedSubscriptionModel.find(
{ 'subscription._id': this._id },
(error, deletedSubscriptions) => {
if (error) {
return callback(error)
}
expect(deletedSubscriptions.length).to.equal(1)
const deletedSubscription = deletedSubscriptions[0]
expect(deletedSubscription.subscription.teamInvites).to.be.empty
expect(deletedSubscription.subscription.invited_emails).to.be.empty
expect(deletedSubscription.deleterData.deleterIpAddress).to.equal(
deleterData.ip
)
if (deleterData.id) {
expect(deletedSubscription.deleterData.deleterId.toString()).to.equal(
deleterData.id.toString()
)
} else {
expect(deletedSubscription.deleterData.deleterId).to.be.undefined
}
SubscriptionModel.findById(this._id, (error, subscription) => {
expect(subscription).to.be.null
callback(error)
})
}
)
}
}
module.exports = Subscription