mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Split FeaturesUpdater out of SubscriptionUpdater
This commit is contained in:
parent
0830c473ad
commit
50bd60dd51
7 changed files with 284 additions and 256 deletions
|
@ -0,0 +1,83 @@
|
||||||
|
async = require("async")
|
||||||
|
PlansLocator = require("./PlansLocator")
|
||||||
|
_ = require("underscore")
|
||||||
|
SubscriptionLocator = require("./SubscriptionLocator")
|
||||||
|
UserFeaturesUpdater = require("./UserFeaturesUpdater")
|
||||||
|
Settings = require("settings-sharelatex")
|
||||||
|
logger = require("logger-sharelatex")
|
||||||
|
ReferalFeatures = require("../Referal/ReferalFeatures")
|
||||||
|
V1SubscriptionManager = require("./V1SubscriptionManager")
|
||||||
|
|
||||||
|
oneMonthInSeconds = 60 * 60 * 24 * 30
|
||||||
|
|
||||||
|
module.exports = FeaturesUpdater =
|
||||||
|
refreshFeatures: (user_id, callback)->
|
||||||
|
jobs =
|
||||||
|
individualFeatures: (cb) -> FeaturesUpdater._getIndividualFeatures user_id, cb
|
||||||
|
groupFeatureSets: (cb) -> FeaturesUpdater._getGroupFeatureSets user_id, cb
|
||||||
|
v1Features: (cb) -> FeaturesUpdater._getV1Features user_id, cb
|
||||||
|
bonusFeatures: (cb) -> ReferalFeatures.getBonusFeatures user_id, cb
|
||||||
|
async.series jobs, (err, results)->
|
||||||
|
if err?
|
||||||
|
logger.err err:err, user_id:user_id,
|
||||||
|
"error getting subscription or group for refreshFeatures"
|
||||||
|
return callback(err)
|
||||||
|
|
||||||
|
{individualFeatures, groupFeatureSets, v1Features, bonusFeatures} = results
|
||||||
|
logger.log {user_id, individualFeatures, groupFeatureSets, v1Features, bonusFeatures}, 'merging user features'
|
||||||
|
featureSets = groupFeatureSets.concat [individualFeatures, v1Features, bonusFeatures]
|
||||||
|
features = _.reduce(featureSets, FeaturesUpdater._mergeFeatures, Settings.defaultFeatures)
|
||||||
|
|
||||||
|
logger.log {user_id, features}, 'updating user features'
|
||||||
|
UserFeaturesUpdater.updateFeatures user_id, features, callback
|
||||||
|
|
||||||
|
_getIndividualFeatures: (user_id, callback = (error, features = {}) ->) ->
|
||||||
|
SubscriptionLocator.getUsersSubscription user_id, (err, sub)->
|
||||||
|
callback err, FeaturesUpdater._subscriptionToFeatures(sub)
|
||||||
|
|
||||||
|
_getGroupFeatureSets: (user_id, callback = (error, featureSets = []) ->) ->
|
||||||
|
SubscriptionLocator.getGroupSubscriptionsMemberOf user_id, (err, subs) ->
|
||||||
|
callback err, (subs or []).map FeaturesUpdater._subscriptionToFeatures
|
||||||
|
|
||||||
|
_getV1Features: (user_id, callback = (error, features = {}) ->) ->
|
||||||
|
V1SubscriptionManager.getPlanCodeFromV1 user_id, (err, planCode) ->
|
||||||
|
callback err, FeaturesUpdater._planCodeToFeatures(planCode)
|
||||||
|
|
||||||
|
_mergeFeatures: (featuresA, featuresB) ->
|
||||||
|
features = Object.assign({}, featuresA)
|
||||||
|
for key, value of featuresB
|
||||||
|
# Special merging logic for non-boolean features
|
||||||
|
if key == 'compileGroup'
|
||||||
|
if features['compileGroup'] == 'priority' or featuresB['compileGroup'] == 'priority'
|
||||||
|
features['compileGroup'] = 'priority'
|
||||||
|
else
|
||||||
|
features['compileGroup'] = 'standard'
|
||||||
|
else if key == 'collaborators'
|
||||||
|
if features['collaborators'] == -1 or featuresB['collaborators'] == -1
|
||||||
|
features['collaborators'] = -1
|
||||||
|
else
|
||||||
|
features['collaborators'] = Math.max(
|
||||||
|
features['collaborators'] or 0,
|
||||||
|
featuresB['collaborators'] or 0
|
||||||
|
)
|
||||||
|
else if key == 'compileTimeout'
|
||||||
|
features['compileTimeout'] = Math.max(
|
||||||
|
features['compileTimeout'] or 0,
|
||||||
|
featuresB['compileTimeout'] or 0
|
||||||
|
)
|
||||||
|
else
|
||||||
|
# Boolean keys, true is better
|
||||||
|
features[key] = features[key] or featuresB[key]
|
||||||
|
return features
|
||||||
|
|
||||||
|
_subscriptionToFeatures: (subscription) ->
|
||||||
|
FeaturesUpdater._planCodeToFeatures(subscription?.planCode)
|
||||||
|
|
||||||
|
_planCodeToFeatures: (planCode) ->
|
||||||
|
if !planCode?
|
||||||
|
return {}
|
||||||
|
plan = PlansLocator.findLocalPlanInSettings planCode
|
||||||
|
if !plan?
|
||||||
|
return {}
|
||||||
|
else
|
||||||
|
return plan.features
|
|
@ -9,7 +9,7 @@ logger = require('logger-sharelatex')
|
||||||
GeoIpLookup = require("../../infrastructure/GeoIpLookup")
|
GeoIpLookup = require("../../infrastructure/GeoIpLookup")
|
||||||
SubscriptionDomainHandler = require("./SubscriptionDomainHandler")
|
SubscriptionDomainHandler = require("./SubscriptionDomainHandler")
|
||||||
UserGetter = require "../User/UserGetter"
|
UserGetter = require "../User/UserGetter"
|
||||||
SubscriptionUpdater = require './SubscriptionUpdater'
|
FeaturesUpdater = require './FeaturesUpdater'
|
||||||
|
|
||||||
module.exports = SubscriptionController =
|
module.exports = SubscriptionController =
|
||||||
|
|
||||||
|
@ -241,6 +241,6 @@ module.exports = SubscriptionController =
|
||||||
|
|
||||||
refreshUserFeatures: (req, res, next) ->
|
refreshUserFeatures: (req, res, next) ->
|
||||||
{user_id} = req.params
|
{user_id} = req.params
|
||||||
SubscriptionUpdater.refreshFeatures user_id, (error) ->
|
FeaturesUpdater.refreshFeatures user_id, (error) ->
|
||||||
return next(error) if error?
|
return next(error) if error?
|
||||||
res.sendStatus 200
|
res.sendStatus 200
|
|
@ -2,27 +2,26 @@ async = require("async")
|
||||||
_ = require("underscore")
|
_ = require("underscore")
|
||||||
Subscription = require('../../models/Subscription').Subscription
|
Subscription = require('../../models/Subscription').Subscription
|
||||||
SubscriptionLocator = require("./SubscriptionLocator")
|
SubscriptionLocator = require("./SubscriptionLocator")
|
||||||
UserFeaturesUpdater = require("./UserFeaturesUpdater")
|
|
||||||
PlansLocator = require("./PlansLocator")
|
PlansLocator = require("./PlansLocator")
|
||||||
Settings = require("settings-sharelatex")
|
Settings = require("settings-sharelatex")
|
||||||
logger = require("logger-sharelatex")
|
logger = require("logger-sharelatex")
|
||||||
ObjectId = require('mongoose').Types.ObjectId
|
ObjectId = require('mongoose').Types.ObjectId
|
||||||
ReferalFeatures = require("../Referal/ReferalFeatures")
|
FeaturesUpdater = require('./FeaturesUpdater')
|
||||||
V1SubscriptionManager = require("./V1SubscriptionManager")
|
|
||||||
|
|
||||||
oneMonthInSeconds = 60 * 60 * 24 * 30
|
oneMonthInSeconds = 60 * 60 * 24 * 30
|
||||||
|
|
||||||
module.exports = SubscriptionUpdater =
|
module.exports = SubscriptionUpdater =
|
||||||
|
|
||||||
syncSubscription: (recurlySubscription, adminUser_id, callback) ->
|
syncSubscription: (recurlySubscription, adminUser_id, callback) ->
|
||||||
logger.log adminUser_id:adminUser_id, recurlySubscription:recurlySubscription, "syncSubscription, creating new if subscription does not exist"
|
logger.log adminUser_id:adminUser_id, recurlySubscription:recurlySubscription, "syncSubscription, creating new if subscription does not exist"
|
||||||
SubscriptionLocator.getUsersSubscription adminUser_id, (err, subscription)->
|
SubscriptionLocator.getUsersSubscription adminUser_id, (err, subscription)->
|
||||||
|
return callback(err) if err?
|
||||||
if subscription?
|
if subscription?
|
||||||
logger.log adminUser_id:adminUser_id, recurlySubscription:recurlySubscription, "subscription does exist"
|
logger.log adminUser_id:adminUser_id, recurlySubscription:recurlySubscription, "subscription does exist"
|
||||||
SubscriptionUpdater._updateSubscriptionFromRecurly recurlySubscription, subscription, callback
|
SubscriptionUpdater._updateSubscriptionFromRecurly recurlySubscription, subscription, callback
|
||||||
else
|
else
|
||||||
logger.log adminUser_id:adminUser_id, recurlySubscription:recurlySubscription, "subscription does not exist, creating a new one"
|
logger.log adminUser_id:adminUser_id, recurlySubscription:recurlySubscription, "subscription does not exist, creating a new one"
|
||||||
SubscriptionUpdater._createNewSubscription adminUser_id, (err, subscription)->
|
SubscriptionUpdater._createNewSubscription adminUser_id, (err, subscription)->
|
||||||
|
return callback(err) if err?
|
||||||
SubscriptionUpdater._updateSubscriptionFromRecurly recurlySubscription, subscription, callback
|
SubscriptionUpdater._updateSubscriptionFromRecurly recurlySubscription, subscription, callback
|
||||||
|
|
||||||
addUserToGroup: (adminUser_id, user_id, callback)->
|
addUserToGroup: (adminUser_id, user_id, callback)->
|
||||||
|
@ -35,7 +34,7 @@ module.exports = SubscriptionUpdater =
|
||||||
if err?
|
if err?
|
||||||
logger.err err:err, searchOps:searchOps, insertOperation:insertOperation, "error findy and modify add user to group"
|
logger.err err:err, searchOps:searchOps, insertOperation:insertOperation, "error findy and modify add user to group"
|
||||||
return callback(err)
|
return callback(err)
|
||||||
UserFeaturesUpdater.updateFeatures user_id, subscription.planCode, callback
|
FeaturesUpdater.refreshFeatures user_id, callback
|
||||||
|
|
||||||
addEmailInviteToGroup: (adminUser_id, email, callback) ->
|
addEmailInviteToGroup: (adminUser_id, email, callback) ->
|
||||||
logger.log {adminUser_id, email}, "adding email into mongo subscription"
|
logger.log {adminUser_id, email}, "adding email into mongo subscription"
|
||||||
|
@ -54,7 +53,7 @@ module.exports = SubscriptionUpdater =
|
||||||
if err?
|
if err?
|
||||||
logger.err err:err, searchOps:searchOps, removeOperation:removeOperation, "error removing user from group"
|
logger.err err:err, searchOps:searchOps, removeOperation:removeOperation, "error removing user from group"
|
||||||
return callback(err)
|
return callback(err)
|
||||||
SubscriptionUpdater.refreshFeatures user_id, callback
|
FeaturesUpdater.refreshFeatures user_id, callback
|
||||||
|
|
||||||
removeEmailInviteFromGroup: (adminUser_id, email, callback)->
|
removeEmailInviteFromGroup: (adminUser_id, email, callback)->
|
||||||
Subscription.update {
|
Subscription.update {
|
||||||
|
@ -70,7 +69,7 @@ module.exports = SubscriptionUpdater =
|
||||||
logger.log {subscription_id, affected_user_ids}, "deleting subscription and downgrading users"
|
logger.log {subscription_id, affected_user_ids}, "deleting subscription and downgrading users"
|
||||||
Subscription.remove {_id: ObjectId(subscription_id)}, (err) ->
|
Subscription.remove {_id: ObjectId(subscription_id)}, (err) ->
|
||||||
return callback(err) if err?
|
return callback(err) if err?
|
||||||
async.mapSeries affected_user_ids, SubscriptionUpdater.refreshFeatures, callback
|
async.mapSeries affected_user_ids, FeaturesUpdater.refreshFeatures, callback
|
||||||
|
|
||||||
_createNewSubscription: (adminUser_id, callback)->
|
_createNewSubscription: (adminUser_id, callback)->
|
||||||
logger.log adminUser_id:adminUser_id, "creating new subscription"
|
logger.log adminUser_id:adminUser_id, "creating new subscription"
|
||||||
|
@ -98,76 +97,5 @@ module.exports = SubscriptionUpdater =
|
||||||
allIds = _.union subscription.member_ids, [subscription.admin_id]
|
allIds = _.union subscription.member_ids, [subscription.admin_id]
|
||||||
jobs = allIds.map (user_id)->
|
jobs = allIds.map (user_id)->
|
||||||
return (cb)->
|
return (cb)->
|
||||||
SubscriptionUpdater.refreshFeatures user_id, cb
|
FeaturesUpdater.refreshFeatures user_id, cb
|
||||||
async.series jobs, callback
|
async.series jobs, callback
|
||||||
|
|
||||||
refreshFeatures: (user_id, callback)->
|
|
||||||
jobs =
|
|
||||||
individualFeatures: (cb) -> SubscriptionUpdater._getIndividualFeatures user_id, cb
|
|
||||||
groupFeatureSets: (cb) -> SubscriptionUpdater._getGroupFeatureSets user_id, cb
|
|
||||||
v1Features: (cb) -> SubscriptionUpdater._getV1Features user_id, cb
|
|
||||||
bonusFeatures: (cb) -> ReferalFeatures.getBonusFeatures user_id, cb
|
|
||||||
async.series jobs, (err, results)->
|
|
||||||
if err?
|
|
||||||
logger.err err:err, user_id:user_id,
|
|
||||||
"error getting subscription or group for refreshFeatures"
|
|
||||||
return callback(err)
|
|
||||||
|
|
||||||
{individualFeatures, groupFeatureSets, v1Features, bonusFeatures} = results
|
|
||||||
logger.log {user_id, individualFeatures, groupFeatureSets, v1Features, bonusFeatures}, 'merging user features'
|
|
||||||
featureSets = groupFeatureSets.concat [individualFeatures, v1Features, bonusFeatures]
|
|
||||||
features = _.reduce(featureSets, SubscriptionUpdater._mergeFeatures, Settings.defaultFeatures)
|
|
||||||
|
|
||||||
logger.log {user_id, features}, 'updating user features'
|
|
||||||
UserFeaturesUpdater.updateFeatures user_id, features, callback
|
|
||||||
|
|
||||||
_getIndividualFeatures: (user_id, callback = (error, features = {}) ->) ->
|
|
||||||
SubscriptionLocator.getUsersSubscription user_id, (err, sub)->
|
|
||||||
callback err, SubscriptionUpdater._subscriptionToFeatures(sub)
|
|
||||||
|
|
||||||
_getGroupFeatureSets: (user_id, callback = (error, featureSets = []) ->) ->
|
|
||||||
SubscriptionLocator.getGroupSubscriptionsMemberOf user_id, (err, subs) ->
|
|
||||||
callback err, (subs or []).map SubscriptionUpdater._subscriptionToFeatures
|
|
||||||
|
|
||||||
_getV1Features: (user_id, callback = (error, features = {}) ->) ->
|
|
||||||
V1SubscriptionManager.getPlanCodeFromV1 user_id, (err, planCode) ->
|
|
||||||
callback err, SubscriptionUpdater._planCodeToFeatures(planCode)
|
|
||||||
|
|
||||||
_mergeFeatures: (featuresA, featuresB) ->
|
|
||||||
features = Object.assign({}, featuresA)
|
|
||||||
for key, value of featuresB
|
|
||||||
# Special merging logic for non-boolean features
|
|
||||||
if key == 'compileGroup'
|
|
||||||
if features['compileGroup'] == 'priority' or featuresB['compileGroup'] == 'priority'
|
|
||||||
features['compileGroup'] = 'priority'
|
|
||||||
else
|
|
||||||
features['compileGroup'] = 'standard'
|
|
||||||
else if key == 'collaborators'
|
|
||||||
if features['collaborators'] == -1 or featuresB['collaborators'] == -1
|
|
||||||
features['collaborators'] = -1
|
|
||||||
else
|
|
||||||
features['collaborators'] = Math.max(
|
|
||||||
features['collaborators'] or 0,
|
|
||||||
featuresB['collaborators'] or 0
|
|
||||||
)
|
|
||||||
else if key == 'compileTimeout'
|
|
||||||
features['compileTimeout'] = Math.max(
|
|
||||||
features['compileTimeout'] or 0,
|
|
||||||
featuresB['compileTimeout'] or 0
|
|
||||||
)
|
|
||||||
else
|
|
||||||
# Boolean keys, true is better
|
|
||||||
features[key] = features[key] or featuresB[key]
|
|
||||||
return features
|
|
||||||
|
|
||||||
_subscriptionToFeatures: (subscription) ->
|
|
||||||
SubscriptionUpdater._planCodeToFeatures(subscription?.planCode)
|
|
||||||
|
|
||||||
_planCodeToFeatures: (planCode) ->
|
|
||||||
if !planCode?
|
|
||||||
return {}
|
|
||||||
plan = PlansLocator.findLocalPlanInSettings planCode
|
|
||||||
if !plan?
|
|
||||||
return {}
|
|
||||||
else
|
|
||||||
return plan.features
|
|
|
@ -1,10 +1,4 @@
|
||||||
module.exports =
|
module.exports =
|
||||||
apis:
|
|
||||||
v1:
|
|
||||||
url: "http://localhost:5000"
|
|
||||||
user: 'overleaf'
|
|
||||||
pass: 'password'
|
|
||||||
|
|
||||||
enableSubscriptions: true
|
enableSubscriptions: true
|
||||||
|
|
||||||
features: features =
|
features: features =
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
SandboxedModule = require('sandboxed-module')
|
||||||
|
should = require('chai').should()
|
||||||
|
expect = require('chai').expect
|
||||||
|
sinon = require 'sinon'
|
||||||
|
modulePath = "../../../../app/js/Features/Subscription/FeaturesUpdater"
|
||||||
|
assert = require("chai").assert
|
||||||
|
ObjectId = require('mongoose').Types.ObjectId
|
||||||
|
|
||||||
|
describe "FeaturesUpdater", ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@user_id = ObjectId().toString()
|
||||||
|
|
||||||
|
@FeaturesUpdater = SandboxedModule.require modulePath, requires:
|
||||||
|
'./UserFeaturesUpdater': @UserFeaturesUpdater = {}
|
||||||
|
'./SubscriptionLocator': @SubscriptionLocator = {}
|
||||||
|
'./PlansLocator': @PlansLocator = {}
|
||||||
|
"logger-sharelatex": log:->
|
||||||
|
'settings-sharelatex': @Settings = {}
|
||||||
|
"../Referal/ReferalFeatures" : @ReferalFeatures = {}
|
||||||
|
"./V1SubscriptionManager": @V1SubscriptionManager = {}
|
||||||
|
|
||||||
|
describe "refreshFeatures", ->
|
||||||
|
beforeEach ->
|
||||||
|
@UserFeaturesUpdater.updateFeatures = sinon.stub().yields()
|
||||||
|
@FeaturesUpdater._getIndividualFeatures = sinon.stub().yields(null, { 'individual': 'features' })
|
||||||
|
@FeaturesUpdater._getGroupFeatureSets = sinon.stub().yields(null, [{ 'group': 'features' }, { 'group': 'features2' }])
|
||||||
|
@FeaturesUpdater._getV1Features = sinon.stub().yields(null, { 'v1': 'features' })
|
||||||
|
@ReferalFeatures.getBonusFeatures = sinon.stub().yields(null, { 'bonus': 'features' })
|
||||||
|
@FeaturesUpdater._mergeFeatures = sinon.stub().returns({'merged': 'features'})
|
||||||
|
@callback = sinon.stub()
|
||||||
|
@FeaturesUpdater.refreshFeatures @user_id, @callback
|
||||||
|
|
||||||
|
it "should get the individual features", ->
|
||||||
|
@FeaturesUpdater._getIndividualFeatures
|
||||||
|
.calledWith(@user_id)
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
|
it "should get the group features", ->
|
||||||
|
@FeaturesUpdater._getGroupFeatureSets
|
||||||
|
.calledWith(@user_id)
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
|
it "should get the v1 features", ->
|
||||||
|
@FeaturesUpdater._getV1Features
|
||||||
|
.calledWith(@user_id)
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
|
it "should get the bonus features", ->
|
||||||
|
@ReferalFeatures.getBonusFeatures
|
||||||
|
.calledWith(@user_id)
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
|
it "should merge from the default features", ->
|
||||||
|
@FeaturesUpdater._mergeFeatures.calledWith(@Settings.defaultFeatures).should.equal true
|
||||||
|
|
||||||
|
it "should merge the individual features", ->
|
||||||
|
@FeaturesUpdater._mergeFeatures.calledWith(sinon.match.any, { 'individual': 'features' }).should.equal true
|
||||||
|
|
||||||
|
it "should merge the group features", ->
|
||||||
|
@FeaturesUpdater._mergeFeatures.calledWith(sinon.match.any, { 'group': 'features' }).should.equal true
|
||||||
|
@FeaturesUpdater._mergeFeatures.calledWith(sinon.match.any, { 'group': 'features2' }).should.equal true
|
||||||
|
|
||||||
|
it "should merge the v1 features", ->
|
||||||
|
@FeaturesUpdater._mergeFeatures.calledWith(sinon.match.any, { 'v1': 'features' }).should.equal true
|
||||||
|
|
||||||
|
it "should merge the bonus features", ->
|
||||||
|
@FeaturesUpdater._mergeFeatures.calledWith(sinon.match.any, { 'bonus': 'features' }).should.equal true
|
||||||
|
|
||||||
|
it "should update the user with the merged features", ->
|
||||||
|
@UserFeaturesUpdater.updateFeatures
|
||||||
|
.calledWith(@user_id, {'merged': 'features'})
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
|
describe "_mergeFeatures", ->
|
||||||
|
it "should prefer priority over standard for compileGroup", ->
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
compileGroup: 'priority'
|
||||||
|
}, {
|
||||||
|
compileGroup: 'standard'
|
||||||
|
})).to.deep.equal({
|
||||||
|
compileGroup: 'priority'
|
||||||
|
})
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
compileGroup: 'standard'
|
||||||
|
}, {
|
||||||
|
compileGroup: 'priority'
|
||||||
|
})).to.deep.equal({
|
||||||
|
compileGroup: 'priority'
|
||||||
|
})
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
compileGroup: 'priority'
|
||||||
|
}, {
|
||||||
|
compileGroup: 'priority'
|
||||||
|
})).to.deep.equal({
|
||||||
|
compileGroup: 'priority'
|
||||||
|
})
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
compileGroup: 'standard'
|
||||||
|
}, {
|
||||||
|
compileGroup: 'standard'
|
||||||
|
})).to.deep.equal({
|
||||||
|
compileGroup: 'standard'
|
||||||
|
})
|
||||||
|
|
||||||
|
it "should prefer -1 over any other for collaborators", ->
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
collaborators: -1
|
||||||
|
}, {
|
||||||
|
collaborators: 10
|
||||||
|
})).to.deep.equal({
|
||||||
|
collaborators: -1
|
||||||
|
})
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
collaborators: 10
|
||||||
|
}, {
|
||||||
|
collaborators: -1
|
||||||
|
})).to.deep.equal({
|
||||||
|
collaborators: -1
|
||||||
|
})
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
collaborators: 4
|
||||||
|
}, {
|
||||||
|
collaborators: 10
|
||||||
|
})).to.deep.equal({
|
||||||
|
collaborators: 10
|
||||||
|
})
|
||||||
|
|
||||||
|
it "should prefer the higher of compileTimeout", ->
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
compileTimeout: 20
|
||||||
|
}, {
|
||||||
|
compileTimeout: 10
|
||||||
|
})).to.deep.equal({
|
||||||
|
compileTimeout: 20
|
||||||
|
})
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
compileTimeout: 10
|
||||||
|
}, {
|
||||||
|
compileTimeout: 20
|
||||||
|
})).to.deep.equal({
|
||||||
|
compileTimeout: 20
|
||||||
|
})
|
||||||
|
|
||||||
|
it "should prefer the true over false for other keys", ->
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
github: true
|
||||||
|
}, {
|
||||||
|
github: false
|
||||||
|
})).to.deep.equal({
|
||||||
|
github: true
|
||||||
|
})
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
github: false
|
||||||
|
}, {
|
||||||
|
github: true
|
||||||
|
})).to.deep.equal({
|
||||||
|
github: true
|
||||||
|
})
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
github: true
|
||||||
|
}, {
|
||||||
|
github: true
|
||||||
|
})).to.deep.equal({
|
||||||
|
github: true
|
||||||
|
})
|
||||||
|
expect(@FeaturesUpdater._mergeFeatures({
|
||||||
|
github: false
|
||||||
|
}, {
|
||||||
|
github: false
|
||||||
|
})).to.deep.equal({
|
||||||
|
github: false
|
||||||
|
})
|
|
@ -75,7 +75,7 @@ describe "SubscriptionController", ->
|
||||||
"./SubscriptionDomainHandler":@SubscriptionDomainHandler
|
"./SubscriptionDomainHandler":@SubscriptionDomainHandler
|
||||||
"../User/UserGetter": @UserGetter
|
"../User/UserGetter": @UserGetter
|
||||||
"./RecurlyWrapper": @RecurlyWrapper = {}
|
"./RecurlyWrapper": @RecurlyWrapper = {}
|
||||||
"./SubscriptionUpdater": @SubscriptionUpdater = {}
|
"./FeaturesUpdater": @FeaturesUpdater = {}
|
||||||
|
|
||||||
|
|
||||||
@res = new MockResponse()
|
@res = new MockResponse()
|
||||||
|
|
|
@ -67,9 +67,7 @@ describe "SubscriptionUpdater", ->
|
||||||
'./PlansLocator': @PlansLocator
|
'./PlansLocator': @PlansLocator
|
||||||
"logger-sharelatex": log:->
|
"logger-sharelatex": log:->
|
||||||
'settings-sharelatex': @Settings
|
'settings-sharelatex': @Settings
|
||||||
"../Referal/ReferalFeatures" : @ReferalFeatures
|
"./FeaturesUpdater": @FeaturesUpdater = {}
|
||||||
'../../infrastructure/Modules': @Modules
|
|
||||||
"./V1SubscriptionManager": @V1SubscriptionManager = {}
|
|
||||||
|
|
||||||
|
|
||||||
describe "syncSubscription", ->
|
describe "syncSubscription", ->
|
||||||
|
@ -100,7 +98,7 @@ describe "SubscriptionUpdater", ->
|
||||||
|
|
||||||
describe "_updateSubscriptionFromRecurly", ->
|
describe "_updateSubscriptionFromRecurly", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@SubscriptionUpdater.refreshFeatures = sinon.stub().callsArgWith(1)
|
@FeaturesUpdater.refreshFeatures = sinon.stub().callsArgWith(1)
|
||||||
|
|
||||||
it "should update the subscription with token etc when not expired", (done)->
|
it "should update the subscription with token etc when not expired", (done)->
|
||||||
@SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
|
@SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
|
||||||
|
@ -111,7 +109,7 @@ describe "SubscriptionUpdater", ->
|
||||||
assert.equal(@subscription.freeTrial.expiresAt, undefined)
|
assert.equal(@subscription.freeTrial.expiresAt, undefined)
|
||||||
assert.equal(@subscription.freeTrial.planCode, undefined)
|
assert.equal(@subscription.freeTrial.planCode, undefined)
|
||||||
@subscription.save.called.should.equal true
|
@subscription.save.called.should.equal true
|
||||||
@SubscriptionUpdater.refreshFeatures.calledWith(@adminUser._id).should.equal true
|
@FeaturesUpdater.refreshFeatures.calledWith(@adminUser._id).should.equal true
|
||||||
done()
|
done()
|
||||||
|
|
||||||
it "should remove the recurlySubscription_id when expired", (done)->
|
it "should remove the recurlySubscription_id when expired", (done)->
|
||||||
|
@ -120,15 +118,15 @@ describe "SubscriptionUpdater", ->
|
||||||
@SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
|
@SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
|
||||||
assert.equal(@subscription.recurlySubscription_id, undefined)
|
assert.equal(@subscription.recurlySubscription_id, undefined)
|
||||||
@subscription.save.called.should.equal true
|
@subscription.save.called.should.equal true
|
||||||
@SubscriptionUpdater.refreshFeatures.calledWith(@adminUser._id).should.equal true
|
@FeaturesUpdater.refreshFeatures.calledWith(@adminUser._id).should.equal true
|
||||||
done()
|
done()
|
||||||
|
|
||||||
it "should update all the users features", (done)->
|
it "should update all the users features", (done)->
|
||||||
@SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
|
@SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
|
||||||
@SubscriptionUpdater.refreshFeatures.calledWith(@adminUser._id).should.equal true
|
@FeaturesUpdater.refreshFeatures.calledWith(@adminUser._id).should.equal true
|
||||||
@SubscriptionUpdater.refreshFeatures.calledWith(@allUserIds[0]).should.equal true
|
@FeaturesUpdater.refreshFeatures.calledWith(@allUserIds[0]).should.equal true
|
||||||
@SubscriptionUpdater.refreshFeatures.calledWith(@allUserIds[1]).should.equal true
|
@FeaturesUpdater.refreshFeatures.calledWith(@allUserIds[1]).should.equal true
|
||||||
@SubscriptionUpdater.refreshFeatures.calledWith(@allUserIds[2]).should.equal true
|
@FeaturesUpdater.refreshFeatures.calledWith(@allUserIds[2]).should.equal true
|
||||||
done()
|
done()
|
||||||
|
|
||||||
it "should set group to true and save how many members can be added to group", (done)->
|
it "should set group to true and save how many members can be added to group", (done)->
|
||||||
|
@ -155,6 +153,9 @@ describe "SubscriptionUpdater", ->
|
||||||
done()
|
done()
|
||||||
|
|
||||||
describe "addUserToGroup", ->
|
describe "addUserToGroup", ->
|
||||||
|
beforeEach ->
|
||||||
|
@FeaturesUpdater.refreshFeatures = sinon.stub().callsArgWith(1)
|
||||||
|
|
||||||
it "should add the users id to the group as a set", (done)->
|
it "should add the users id to the group as a set", (done)->
|
||||||
@SubscriptionUpdater.addUserToGroup @adminUser._id, @otherUserId, =>
|
@SubscriptionUpdater.addUserToGroup @adminUser._id, @otherUserId, =>
|
||||||
searchOps =
|
searchOps =
|
||||||
|
@ -166,12 +167,12 @@ describe "SubscriptionUpdater", ->
|
||||||
|
|
||||||
it "should update the users features", (done)->
|
it "should update the users features", (done)->
|
||||||
@SubscriptionUpdater.addUserToGroup @adminUser._id, @otherUserId, =>
|
@SubscriptionUpdater.addUserToGroup @adminUser._id, @otherUserId, =>
|
||||||
@UserFeaturesUpdater.updateFeatures.calledWith(@otherUserId, @subscription.planCode).should.equal true
|
@FeaturesUpdater.refreshFeatures.calledWith(@otherUserId).should.equal true
|
||||||
done()
|
done()
|
||||||
|
|
||||||
describe "removeUserFromGroup", ->
|
describe "removeUserFromGroup", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@SubscriptionUpdater.refreshFeatures = sinon.stub().callsArgWith(1)
|
@FeaturesUpdater.refreshFeatures = sinon.stub().callsArgWith(1)
|
||||||
|
|
||||||
it "should pull the users id from the group", (done)->
|
it "should pull the users id from the group", (done)->
|
||||||
@SubscriptionUpdater.removeUserFromGroup @adminUser._id, @otherUserId, =>
|
@SubscriptionUpdater.removeUserFromGroup @adminUser._id, @otherUserId, =>
|
||||||
|
@ -184,160 +185,9 @@ describe "SubscriptionUpdater", ->
|
||||||
|
|
||||||
it "should update the users features", (done)->
|
it "should update the users features", (done)->
|
||||||
@SubscriptionUpdater.removeUserFromGroup @adminUser._id, @otherUserId, =>
|
@SubscriptionUpdater.removeUserFromGroup @adminUser._id, @otherUserId, =>
|
||||||
@SubscriptionUpdater.refreshFeatures.calledWith(@otherUserId).should.equal true
|
@FeaturesUpdater.refreshFeatures.calledWith(@otherUserId).should.equal true
|
||||||
done()
|
done()
|
||||||
|
|
||||||
describe "refreshFeatures", ->
|
|
||||||
beforeEach ->
|
|
||||||
@SubscriptionUpdater._getIndividualFeatures = sinon.stub().yields(null, { 'individual': 'features' })
|
|
||||||
@SubscriptionUpdater._getGroupFeatureSets = sinon.stub().yields(null, [{ 'group': 'features' }, { 'group': 'features2' }])
|
|
||||||
@SubscriptionUpdater._getV1Features = sinon.stub().yields(null, { 'v1': 'features' })
|
|
||||||
@ReferalFeatures.getBonusFeatures = sinon.stub().yields(null, { 'bonus': 'features' })
|
|
||||||
@SubscriptionUpdater._mergeFeatures = sinon.stub().returns({'merged': 'features'})
|
|
||||||
@callback = sinon.stub()
|
|
||||||
@SubscriptionUpdater.refreshFeatures @user_id, @callback
|
|
||||||
|
|
||||||
it "should get the individual features", ->
|
|
||||||
@SubscriptionUpdater._getIndividualFeatures
|
|
||||||
.calledWith(@user_id)
|
|
||||||
.should.equal true
|
|
||||||
|
|
||||||
it "should get the group features", ->
|
|
||||||
@SubscriptionUpdater._getGroupFeatureSets
|
|
||||||
.calledWith(@user_id)
|
|
||||||
.should.equal true
|
|
||||||
|
|
||||||
it "should get the v1 features", ->
|
|
||||||
@SubscriptionUpdater._getV1Features
|
|
||||||
.calledWith(@user_id)
|
|
||||||
.should.equal true
|
|
||||||
|
|
||||||
it "should get the bonus features", ->
|
|
||||||
@ReferalFeatures.getBonusFeatures
|
|
||||||
.calledWith(@user_id)
|
|
||||||
.should.equal true
|
|
||||||
|
|
||||||
it "should merge from the default features", ->
|
|
||||||
@SubscriptionUpdater._mergeFeatures.calledWith(@Settings.defaultFeatures).should.equal true
|
|
||||||
|
|
||||||
it "should merge the individual features", ->
|
|
||||||
@SubscriptionUpdater._mergeFeatures.calledWith(sinon.match.any, { 'individual': 'features' }).should.equal true
|
|
||||||
|
|
||||||
it "should merge the group features", ->
|
|
||||||
@SubscriptionUpdater._mergeFeatures.calledWith(sinon.match.any, { 'group': 'features' }).should.equal true
|
|
||||||
@SubscriptionUpdater._mergeFeatures.calledWith(sinon.match.any, { 'group': 'features2' }).should.equal true
|
|
||||||
|
|
||||||
it "should merge the v1 features", ->
|
|
||||||
@SubscriptionUpdater._mergeFeatures.calledWith(sinon.match.any, { 'v1': 'features' }).should.equal true
|
|
||||||
|
|
||||||
it "should merge the bonus features", ->
|
|
||||||
@SubscriptionUpdater._mergeFeatures.calledWith(sinon.match.any, { 'bonus': 'features' }).should.equal true
|
|
||||||
|
|
||||||
it "should update the user with the merged features", ->
|
|
||||||
@UserFeaturesUpdater.updateFeatures
|
|
||||||
.calledWith(@user_id, {'merged': 'features'})
|
|
||||||
.should.equal true
|
|
||||||
|
|
||||||
describe "_mergeFeatures", ->
|
|
||||||
it "should prefer priority over standard for compileGroup", ->
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
compileGroup: 'priority'
|
|
||||||
}, {
|
|
||||||
compileGroup: 'standard'
|
|
||||||
})).to.deep.equal({
|
|
||||||
compileGroup: 'priority'
|
|
||||||
})
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
compileGroup: 'standard'
|
|
||||||
}, {
|
|
||||||
compileGroup: 'priority'
|
|
||||||
})).to.deep.equal({
|
|
||||||
compileGroup: 'priority'
|
|
||||||
})
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
compileGroup: 'priority'
|
|
||||||
}, {
|
|
||||||
compileGroup: 'priority'
|
|
||||||
})).to.deep.equal({
|
|
||||||
compileGroup: 'priority'
|
|
||||||
})
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
compileGroup: 'standard'
|
|
||||||
}, {
|
|
||||||
compileGroup: 'standard'
|
|
||||||
})).to.deep.equal({
|
|
||||||
compileGroup: 'standard'
|
|
||||||
})
|
|
||||||
|
|
||||||
it "should prefer -1 over any other for collaborators", ->
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
collaborators: -1
|
|
||||||
}, {
|
|
||||||
collaborators: 10
|
|
||||||
})).to.deep.equal({
|
|
||||||
collaborators: -1
|
|
||||||
})
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
collaborators: 10
|
|
||||||
}, {
|
|
||||||
collaborators: -1
|
|
||||||
})).to.deep.equal({
|
|
||||||
collaborators: -1
|
|
||||||
})
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
collaborators: 4
|
|
||||||
}, {
|
|
||||||
collaborators: 10
|
|
||||||
})).to.deep.equal({
|
|
||||||
collaborators: 10
|
|
||||||
})
|
|
||||||
|
|
||||||
it "should prefer the higher of compileTimeout", ->
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
compileTimeout: 20
|
|
||||||
}, {
|
|
||||||
compileTimeout: 10
|
|
||||||
})).to.deep.equal({
|
|
||||||
compileTimeout: 20
|
|
||||||
})
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
compileTimeout: 10
|
|
||||||
}, {
|
|
||||||
compileTimeout: 20
|
|
||||||
})).to.deep.equal({
|
|
||||||
compileTimeout: 20
|
|
||||||
})
|
|
||||||
|
|
||||||
it "should prefer the true over false for other keys", ->
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
github: true
|
|
||||||
}, {
|
|
||||||
github: false
|
|
||||||
})).to.deep.equal({
|
|
||||||
github: true
|
|
||||||
})
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
github: false
|
|
||||||
}, {
|
|
||||||
github: true
|
|
||||||
})).to.deep.equal({
|
|
||||||
github: true
|
|
||||||
})
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
github: true
|
|
||||||
}, {
|
|
||||||
github: true
|
|
||||||
})).to.deep.equal({
|
|
||||||
github: true
|
|
||||||
})
|
|
||||||
expect(@SubscriptionUpdater._mergeFeatures({
|
|
||||||
github: false
|
|
||||||
}, {
|
|
||||||
github: false
|
|
||||||
})).to.deep.equal({
|
|
||||||
github: false
|
|
||||||
})
|
|
||||||
|
|
||||||
describe "deleteSubscription", ->
|
describe "deleteSubscription", ->
|
||||||
beforeEach (done) ->
|
beforeEach (done) ->
|
||||||
@subscription_id = ObjectId().toString()
|
@subscription_id = ObjectId().toString()
|
||||||
|
@ -347,7 +197,7 @@ describe "SubscriptionUpdater", ->
|
||||||
member_ids: [ ObjectId(), ObjectId(), ObjectId() ]
|
member_ids: [ ObjectId(), ObjectId(), ObjectId() ]
|
||||||
}
|
}
|
||||||
@SubscriptionLocator.getSubscription = sinon.stub().yields(null, @subscription)
|
@SubscriptionLocator.getSubscription = sinon.stub().yields(null, @subscription)
|
||||||
@SubscriptionUpdater.refreshFeatures = sinon.stub().yields()
|
@FeaturesUpdater.refreshFeatures = sinon.stub().yields()
|
||||||
@SubscriptionUpdater.deleteSubscription @subscription_id, done
|
@SubscriptionUpdater.deleteSubscription @subscription_id, done
|
||||||
|
|
||||||
it "should look up the subscription", ->
|
it "should look up the subscription", ->
|
||||||
|
@ -361,12 +211,12 @@ describe "SubscriptionUpdater", ->
|
||||||
.should.equal true
|
.should.equal true
|
||||||
|
|
||||||
it "should downgrade the admin_id", ->
|
it "should downgrade the admin_id", ->
|
||||||
@SubscriptionUpdater.refreshFeatures
|
@FeaturesUpdater.refreshFeatures
|
||||||
.calledWith(@subscription.admin_id)
|
.calledWith(@subscription.admin_id)
|
||||||
.should.equal true
|
.should.equal true
|
||||||
|
|
||||||
it "should downgrade all of the members", ->
|
it "should downgrade all of the members", ->
|
||||||
for user_id in @subscription.member_ids
|
for user_id in @subscription.member_ids
|
||||||
@SubscriptionUpdater.refreshFeatures
|
@FeaturesUpdater.refreshFeatures
|
||||||
.calledWith(user_id)
|
.calledWith(user_id)
|
||||||
.should.equal true
|
.should.equal true
|
||||||
|
|
Loading…
Reference in a new issue