Unsubscribe deleted users

Fixes #2733
This commit is contained in:
Matt Lott 2015-06-18 15:02:15 -07:00
parent d4d4d7bb25
commit 72e458cc80
4 changed files with 106 additions and 12 deletions

View file

@ -601,7 +601,7 @@ class SubscriptionHandler extends Handler
# Check recipient is currently sponsored
stripeRecipient = recipient.get 'stripe' ? {}
if stripeRecipient?.sponsorID isnt user.id
@logSubscriptionError(user, "Recipient #{req.body.stripe.recipient} not found. ")
@logSubscriptionError(user, "Recipient #{recipient.id} not sponsored by #{user.id}. ")
return done({res: 'Can only unsubscribe sponsored subscriptions.', code: 403})
# Find recipient subscription

View file

@ -241,18 +241,53 @@ UserHandler = class UserHandler extends Handler
return @sendDatabaseError res, err if err
return @sendNotFoundError res unless user
return @sendForbiddenError res unless @hasAccessToDocument(req, user)
obj = user.toObject()
for prop, val of obj
user.set(prop, undefined) unless prop is '_id'
user.set('deleted', true)
# Hack to get saving of Users to work. Probably should replace these props with strings
# so that validation doesn't get hung up on Date objects in the documents.
delete obj.dateCreated
# Delete subscriptions attached to this user first
# TODO: check sponsored subscriptions (stripe.recipients)
checkPersonalSubscription = (user, done) =>
try
return done() unless user.get('stripe')?.subscriptionID?
SubscriptionHandler.unsubscribeUser {body: user.toObject()}, user, (err) =>
log.error("User delete check personal sub " + err) if err
done()
catch error
log.error("User delete check personal sub " + error)
done()
checkRecipientSubscription = (user, done) =>
try
return done() unless sponsorID = user.get('stripe')?.sponsorID
User.findById sponsorID, (err, sponsor) =>
if err
log.error("User delete check recipient sub " + err)
return done()
unless sponsor
log.error("User delete check recipient sub no sponsor #{user.get('stripe').sponsorID}")
return done()
sponsorObject = sponsor.toObject()
sponsorObject.stripe.unsubscribeEmail = user.get('email')
SubscriptionHandler.unsubscribeRecipient {body: sponsorObject}, sponsor, (err) =>
log.error("User delete check recipient sub " + err) if err
done()
catch error
log.error("User delete check recipient sub " + error)
done()
deleteSubscriptions = (user, done) =>
checkPersonalSubscription user, (err) =>
checkRecipientSubscription user, done
user.save (err) =>
return @sendDatabaseError(res, err) if err
@sendNoContent res
deleteSubscriptions user, =>
obj = user.toObject()
for prop, val of obj
user.set(prop, undefined) unless prop is '_id'
user.set('deleted', true)
# Hack to get saving of Users to work. Probably should replace these props with strings
# so that validation doesn't get hung up on Date objects in the documents.
delete obj.dateCreated
user.save (err) =>
return @sendDatabaseError(res, err) if err
@sendNoContent res
getByRelationship: (req, res, args...) ->
return @agreeToCLA(req, res) if args[1] is 'agreeToCLA'

View file

@ -519,6 +519,23 @@ describe 'Subscriptions', ->
loginNewUser (user1) ->
subscribeUser user1, token, null, done
it 'User delete unsubscribes', (done) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
subscribeUser user1, token, null, ->
User.findById user1.id, (err, user1) ->
expect(err).toBeNull()
customerID = user1.get('stripe').customerID
subscriptionID = user1.get('stripe').subscriptionID
request.del {uri: "#{userURL}/#{user1.id}"}, (err, res) ->
expect(err).toBeNull()
stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) ->
expect(err).toBeNull()
expect(subscription?.cancel_at_period_end).toEqual(true)
done()
it 'Admin subscribes self with valid prepaid', (done) ->
loginNewUser (user1) ->
user1.set('permissions', ['admin'])
@ -715,6 +732,29 @@ describe 'Subscriptions', ->
subscribeRecipients user1, [user2], token, (updatedUser) ->
verifySponsorship user1.id, user2.id, done
it 'Recipient user delete unsubscribes', (done) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
createNewUser (user2) ->
loginNewUser (user1) ->
subscribeRecipients user1, [user2], token, (updatedUser) ->
customerID = updatedUser.stripe.customerID
subscriptionID = updatedUser.stripe.recipients[0].subscriptionID
loginUser user2, (user2) ->
request.del {uri: "#{userURL}/#{user2.id}"}, (err, res) ->
expect(err).toBeNull()
stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) ->
expect(err).not.toBeNull()
expect(subscription).toBeNull()
User.findById user1.id, (err, user1) ->
expect(err).toBeNull()
expect(_.isEmpty(user1.get('stripe').recipients))
stripe.customers.retrieveSubscription customerID, user1.get('stripe').sponsorSubscriptionID, (err, subscription) ->
expect(err).toBeNull()
expect(subscription.quantity).toEqual(0)
done()
it 'Subscribed user1 subscribes user2, one token', (done) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
@ -1220,7 +1260,9 @@ describe 'Subscriptions', ->
expect(subscription.quantity).toEqual(getSubscribedQuantity(recipientCount - 3))
done()
it 'Unsubscribed user1 subscribes 13 users, unsubcribes 2', (done) ->
xit 'Unsubscribed user1 subscribes 13 users, unsubcribes 2', (done) ->
# TODO: Hits the Stripe error 'Request rate limit exceeded'.
# TODO: Need a better test for 12+ bulk discounts. Or, we could update the bulk disount logic.
# TODO: verify interim invoices?
recipientCount = 13
recipientsToVerify = [0, 1, 10, 11, 12]

View file

@ -328,6 +328,23 @@ describe 'GET /db/user', ->
xit 'can fetch another user with restricted fields'
describe 'DELETE /db/user', ->
it 'can delete a user', (done) ->
loginNewUser (user1) ->
request.del {uri: "#{getURL(urlUser)}/#{user1.id}"}, (err, res) ->
expect(err).toBeNull()
return done() if err
User.findById user1.id, (err, user1) ->
expect(err).toBeNull()
return done() if err
expect(user1.get('deleted')).toBe(true)
for key, value of user1.toObject()
if key is 'deleted'
expect(value).toEqual(true)
else if key isnt '_id'
expect(_.isEmpty(value)).toEqual(true)
done()
describe 'Statistics', ->
LevelSession = require '../../../server/levels/sessions/LevelSession'
Article = require '../../../server/articles/Article'