Merge pull request #1030 from sharelatex/spd-bonus-program

Implement bonus program

GitOrigin-RevId: a18dd8a916c6f317a11661f106cdb4a2983c4ad8
This commit is contained in:
Simon Detheridge
2018-10-23 11:36:17 +00:00
committed by sharelatex
parent 24a2cafc33
commit 8b55643f7e
8 changed files with 102 additions and 24 deletions
@@ -7,13 +7,17 @@ FeaturesUpdater = require "../Subscription/FeaturesUpdater"
module.exports = ReferalAllocator =
allocate: (referal_id, new_user_id, referal_source, referal_medium, callback = ->)->
if !referal_id?
return logger.log new_user_id:new_user_id, "no referal for user"
logger.log referal_id:referal_id, new_user_id:new_user_id, "allocating users referal"
logger.log new_user_id:new_user_id, "no referal for user"
return callback(null)
logger.log referal_id:referal_id, new_user_id:new_user_id, referal_source:referal_source, referal_medium:referal_medium, "allocating users referal"
query = {"referal_id":referal_id}
User.findOne query, (error, user) ->
return callback(error) if error?
return callback(new Error("user not found")) if !user? or !user._id?
if !user? or !user._id?
logger.log new_user_id:new_user_id, referal_id:referal_id, "no user found for referal id"
return callback(null)
if referal_source == "bonus"
User.update query, {
@@ -25,6 +29,7 @@ module.exports = ReferalAllocator =
if err?
logger.err err:err, referal_id:referal_id, new_user_id:new_user_id, "something went wrong allocating referal"
return callback(err)
FeaturesUpdater.refreshFeatures user._id, callback
else
callback()
@@ -5,8 +5,8 @@ AuthenticationController = require('../Authentication/AuthenticationController')
module.exports =
bonus: (req, res)->
user_id = AuthenticationController.getLoggedInUserId(req)
ReferalHandler.getReferedUserIds user_id, (err, refered_users)->
ReferalHandler.getReferedUsers user_id, (err, refered_users, refered_user_count)->
res.render "referal/bonus",
title: "bonus_please_recommend_us"
refered_users: refered_users
refered_user_count: (refered_users or []).length
refered_user_count: refered_user_count
@@ -1,7 +1,8 @@
User = require('../../models/User').User
module.exports =
getReferedUserIds: (user_id, callback)->
getReferedUsers: (user_id, callback)->
User.findById user_id, (err, user)->
refered_users = user.refered_users || []
callback "null", refered_users
refered_user_count= user.refered_user_count || refered_users.length
callback null, refered_users, refered_user_count
@@ -7,7 +7,8 @@ settings = require "settings-sharelatex"
redis = require "./helpers/redis"
_ = require 'lodash'
# Currently this is testing registration via the 'public-registration' module,
# whereas in production we're using the 'overleaf-integration' module.
# Expectations
expectProjectAccess = (user, projectId, callback=(err,result)->) ->
@@ -78,7 +79,6 @@ describe "CSRF protection", ->
afterEach ->
@user.full_delete_user(@email)
it 'should register with the csrf token', (done) ->
@user.request.get '/login', (err, res, body) =>
@@ -142,6 +142,22 @@ describe "Register", ->
user.emails[0].email.should.equal @user.email
done()
describe "Register with bonus referal id", ->
before (done) ->
@user1 = new User()
@user2 = new User()
async.series [
(cb) => @user1.register cb
(cb) => @user2.registerWithQuery '?r=' + @user1.referal_id + '&rm=d&rs=b', cb
], done
it 'Adds a referal when an id is supplied and the referal source is "bonus"', (done) ->
@user1.get (error, user) =>
expect(error).to.not.exist
user.refered_user_count.should.eql 1
done()
describe "LoginViaRegistration", ->
before (done) ->
@@ -36,11 +36,14 @@ class User
db.users.update {_id: ObjectId(@_id)}, updateOp, callback
register: (callback = (error, user) ->) ->
@registerWithQuery('', callback)
registerWithQuery: (query, callback = (error, user) ->) ->
return callback(new Error('User already registered')) if @_id?
@getCsrfToken (error) =>
return callback(error) if error?
@request.post {
url: '/register'
url: '/register' + query
json: { @email, @password }
}, (error, response, body) =>
return callback(error) if error?
@@ -149,7 +152,7 @@ class User
return callback()
user_id = user._id
db.projects.remove owner_ref:ObjectId(user_id), {multi:true}, (err)->
if err?
if err?
callback(err)
db.users.remove {_id: ObjectId(user_id)}, callback
@@ -3,6 +3,11 @@ v1Api =
module.exports =
enableSubscriptions: true
# for registration via SL, set enableLegacyRegistration to true
# for registration via Overleaf v1, set enableLegacyLogin to true
# Currently, acceptance tests require enableLegacyRegistration.
enableLegacyRegistration: true
features: features =
@@ -19,14 +19,14 @@ describe 'ReferalAllocator', ->
@referal_medium = "twitter"
@user_id = "user-id-123"
@new_user_id = "new-user-id-123"
@FeaturesUpdater.refreshFeatures = sinon.stub().yields()
@User.update = sinon.stub().callsArgWith 3, null
@User.findOne = sinon.stub().callsArgWith 1, null, { _id: @user_id }
describe "allocate", ->
describe "when the referal was a bonus referal", ->
beforeEach ->
@referal_source = "bonus"
@User.update = sinon.stub().callsArgWith 3, null
@User.findOne = sinon.stub().callsArgWith 1, null, { _id: @user_id }
@FeaturesUpdater.refreshFeatures = sinon.stub().yields()
@ReferalAllocator.allocate @referal_id, @new_user_id, @referal_source, @referal_medium, @callback
it 'should update the referring user with the refered users id', ->
@@ -43,7 +43,7 @@ describe 'ReferalAllocator', ->
@User.findOne
.calledWith( referal_id: @referal_id )
.should.equal true
it "should refresh the user's subscription", ->
@FeaturesUpdater.refreshFeatures
.calledWith(@user_id)
@@ -52,12 +52,31 @@ describe 'ReferalAllocator', ->
it "should call the callback", ->
@callback.called.should.equal true
describe "when there is no user for the referal id", ->
beforeEach ->
@referal_source = "bonus"
@referal_id = "wombat"
@User.findOne = sinon.stub().callsArgWith 1, null, null
@ReferalAllocator.allocate @referal_id, @new_user_id, @referal_source, @referal_medium, @callback
it "should find the referring users id", ->
@User.findOne
.calledWith( referal_id: @referal_id )
.should.equal true
it 'should not update the referring user with the refered users id', ->
@User.update.called.should.equal false
it "should not assign the user a bonus", ->
@FeaturesUpdater.refreshFeatures.called.should.equal false
it "should call the callback", ->
@callback.called.should.equal true
describe "when the referal is not a bonus referal", ->
beforeEach ->
@referal_source = "public_share"
@User.update = sinon.stub().callsArgWith 3, null
@User.findOne = sinon.stub().callsArgWith 1, null, { _id: @user_id }
@FeaturesUpdater.refreshFeatures = sinon.stub().yields()
@ReferalAllocator.allocate @referal_id, @new_user_id, @referal_source, @referal_medium, @callback
it 'should not update the referring user with the refered users id', ->
@@ -67,7 +86,7 @@ describe 'ReferalAllocator', ->
@User.findOne
.calledWith( referal_id: @referal_id )
.should.equal true
it "should not assign the user a bonus", ->
@FeaturesUpdater.refreshFeatures.called.should.equal false
@@ -13,23 +13,52 @@ describe 'Referal handler', ->
log:->
err:->
'../../models/User': User:@User
@user_id = "12313"
describe 'getting refered user_ids', ->
user_id = "12313"
it 'should get the user from mongo and return the refered users array', (done)->
user =
user =
refered_users : ["1234", "312312", "3213129"]
refered_user_count : 3
@User.findById.callsArgWith(1, null, user)
@handler.getReferedUserIds user_id, (err, passedReferedUserIds)->
@handler.getReferedUsers @user_id, (err, passedReferedUserIds, passedReferedUserCount)->
passedReferedUserIds.should.deep.equal user.refered_users
passedReferedUserCount.should.equal 3
done()
it 'should return an empty array if it is not set', (done)->
user = {}
@User.findById.callsArgWith(1, null, user)
@handler.getReferedUserIds user_id, (err, passedReferedUserIds)->
@handler.getReferedUsers @user_id, (err, passedReferedUserIds, passedReferedUserCount)->
passedReferedUserIds.length.should.equal 0
done()
it 'should return a zero count if netither it or the array are set', (done)->
user = {}
@User.findById.callsArgWith(1, null, user)
@handler.getReferedUsers @user_id, (err, passedReferedUserIds, passedReferedUserCount)->
passedReferedUserCount.should.equal 0
done()
it 'should return the array length if count is not set', (done)->
user =
refered_users : ["1234", "312312", "3213129"]
@User.findById.callsArgWith(1, null, user)
@handler.getReferedUsers @user_id, (err, passedReferedUserIds, passedReferedUserCount)->
passedReferedUserCount.should.equal 3
done()
it 'should return the count if it differs from the array length', (done)->
user =
refered_users : ["1234", "312312", "3213129"]
refered_user_count : 5
@User.findById.callsArgWith(1, null, user)
@handler.getReferedUsers @user_id, (err, passedReferedUserIds, passedReferedUserCount)->
passedReferedUserCount.should.equal 5
done()