mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
171 lines
No EOL
7.2 KiB
CoffeeScript
171 lines
No EOL
7.2 KiB
CoffeeScript
async = require("async")
|
|
_ = require("underscore")
|
|
Subscription = require('../../models/Subscription').Subscription
|
|
SubscriptionLocator = require("./SubscriptionLocator")
|
|
UserFeaturesUpdater = require("./UserFeaturesUpdater")
|
|
PlansLocator = require("./PlansLocator")
|
|
Settings = require("settings-sharelatex")
|
|
logger = require("logger-sharelatex")
|
|
ObjectId = require('mongoose').Types.ObjectId
|
|
ReferalAllocator = require("../Referal/ReferalAllocator")
|
|
V1SubscriptionManager = require("./V1SubscriptionManager")
|
|
|
|
oneMonthInSeconds = 60 * 60 * 24 * 30
|
|
|
|
module.exports = SubscriptionUpdater =
|
|
|
|
syncSubscription: (recurlySubscription, adminUser_id, callback) ->
|
|
logger.log adminUser_id:adminUser_id, recurlySubscription:recurlySubscription, "syncSubscription, creating new if subscription does not exist"
|
|
SubscriptionLocator.getUsersSubscription adminUser_id, (err, subscription)->
|
|
if subscription?
|
|
logger.log adminUser_id:adminUser_id, recurlySubscription:recurlySubscription, "subscription does exist"
|
|
SubscriptionUpdater._updateSubscriptionFromRecurly recurlySubscription, subscription, callback
|
|
else
|
|
logger.log adminUser_id:adminUser_id, recurlySubscription:recurlySubscription, "subscription does not exist, creating a new one"
|
|
SubscriptionUpdater._createNewSubscription adminUser_id, (err, subscription)->
|
|
SubscriptionUpdater._updateSubscriptionFromRecurly recurlySubscription, subscription, callback
|
|
|
|
addUserToGroup: (adminUser_id, user_id, callback)->
|
|
logger.log adminUser_id:adminUser_id, user_id:user_id, "adding user into mongo subscription"
|
|
searchOps =
|
|
admin_id: adminUser_id
|
|
insertOperation =
|
|
"$addToSet": {member_ids:user_id}
|
|
Subscription.findAndModify searchOps, insertOperation, (err, subscription)->
|
|
if err?
|
|
logger.err err:err, searchOps:searchOps, insertOperation:insertOperation, "error findy and modify add user to group"
|
|
return callback(err)
|
|
UserFeaturesUpdater.updateFeatures user_id, subscription.planCode, callback
|
|
|
|
addEmailInviteToGroup: (adminUser_id, email, callback) ->
|
|
logger.log {adminUser_id, email}, "adding email into mongo subscription"
|
|
searchOps =
|
|
admin_id: adminUser_id
|
|
insertOperation =
|
|
"$addToSet": {invited_emails: email}
|
|
Subscription.findAndModify searchOps, insertOperation, callback
|
|
|
|
removeUserFromGroup: (adminUser_id, user_id, callback)->
|
|
searchOps =
|
|
admin_id: adminUser_id
|
|
removeOperation =
|
|
"$pull": {member_ids:user_id}
|
|
Subscription.update searchOps, removeOperation, (err)->
|
|
if err?
|
|
logger.err err:err, searchOps:searchOps, removeOperation:removeOperation, "error removing user from group"
|
|
return callback(err)
|
|
SubscriptionUpdater._setUsersMinimumFeatures user_id, callback
|
|
|
|
removeEmailInviteFromGroup: (adminUser_id, email, callback)->
|
|
Subscription.update {
|
|
admin_id: adminUser_id
|
|
}, "$pull": {
|
|
invited_emails: email
|
|
}, callback
|
|
|
|
refreshSubscription: (user_id, callback=(err)->) ->
|
|
SubscriptionUpdater._setUsersMinimumFeatures user_id, callback
|
|
|
|
deleteSubscription: (subscription_id, callback = (error) ->) ->
|
|
SubscriptionLocator.getSubscription subscription_id, (err, subscription) ->
|
|
return callback(err) if err?
|
|
affected_user_ids = [subscription.admin_id].concat(subscription.member_ids or [])
|
|
logger.log {subscription_id, affected_user_ids}, "deleting subscription and downgrading users"
|
|
Subscription.remove {_id: ObjectId(subscription_id)}, (err) ->
|
|
return callback(err) if err?
|
|
async.mapSeries affected_user_ids, SubscriptionUpdater._setUsersMinimumFeatures, callback
|
|
|
|
_createNewSubscription: (adminUser_id, callback)->
|
|
logger.log adminUser_id:adminUser_id, "creating new subscription"
|
|
subscription = new Subscription(admin_id:adminUser_id)
|
|
subscription.freeTrial.allowed = false
|
|
subscription.save (err)->
|
|
callback err, subscription
|
|
|
|
_updateSubscriptionFromRecurly: (recurlySubscription, subscription, callback)->
|
|
logger.log recurlySubscription:recurlySubscription, subscription:subscription, "updaing subscription"
|
|
plan = PlansLocator.findLocalPlanInSettings(recurlySubscription.plan.plan_code)
|
|
if recurlySubscription.state == "expired"
|
|
subscription.recurlySubscription_id = undefined
|
|
subscription.planCode = Settings.defaultPlanCode
|
|
else
|
|
subscription.recurlySubscription_id = recurlySubscription.uuid
|
|
subscription.freeTrial.expiresAt = undefined
|
|
subscription.freeTrial.planCode = undefined
|
|
subscription.freeTrial.allowed = true
|
|
subscription.planCode = recurlySubscription.plan.plan_code
|
|
if plan.groupPlan
|
|
subscription.groupPlan = true
|
|
subscription.membersLimit = plan.membersLimit
|
|
subscription.save ->
|
|
allIds = _.union subscription.member_ids, [subscription.admin_id]
|
|
jobs = allIds.map (user_id)->
|
|
return (cb)->
|
|
SubscriptionUpdater._setUsersMinimumFeatures user_id, cb
|
|
async.series jobs, callback
|
|
|
|
_setUsersMinimumFeatures: (user_id, callback)->
|
|
jobs =
|
|
individualFeatures: (cb)->
|
|
SubscriptionLocator.getUsersSubscription user_id, (err, sub)->
|
|
cb err, SubscriptionUpdater._subscriptionToFeatures(sub)
|
|
groupFeatures: (cb) ->
|
|
SubscriptionLocator.getGroupSubscriptionsMemberOf user_id, (err, subs) ->
|
|
cb err, (subs or []).map SubscriptionUpdater._subscriptionToFeatures
|
|
v1Features: (cb) ->
|
|
V1SubscriptionManager.getPlanCodeFromV1 user_id, (err, planCode) ->
|
|
cb err, SubscriptionUpdater._planCodeToFeatures(planCode)
|
|
bonusFeatures: (cb) ->
|
|
ReferalAllocator.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 _setUsersMinimumFeatures"
|
|
return callback(err)
|
|
|
|
{individualFeatures, groupFeatures, v1Features, bonusFeatures} = results
|
|
logger.log {user_id, individualFeatures, groupFeatures, v1Features, bonusFeatures}, 'merging user features'
|
|
featureSets = groupFeatures.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
|
|
|
|
_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 |