overleaf/services/web/app/coffee/Features/Subscription/FeaturesUpdater.coffee

95 lines
3.8 KiB
CoffeeScript

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")
InstitutionsFeatures = require '../Institutions/InstitutionsFeatures'
oneMonthInSeconds = 60 * 60 * 24 * 30
module.exports = FeaturesUpdater =
refreshFeatures: (user_id, notifyV1 = true, callback = () ->)->
if typeof notifyV1 == 'function'
callback = notifyV1
notifyV1 = true
if notifyV1
V1SubscriptionManager.notifyV1OfFeaturesChange user_id, (error) ->
if error?
logger.err {err: error, user_id}, "error notifying v1 about updated features"
jobs =
individualFeatures: (cb) -> FeaturesUpdater._getIndividualFeatures user_id, cb
groupFeatureSets: (cb) -> FeaturesUpdater._getGroupFeatureSets user_id, cb
institutionFeatures:(cb) -> InstitutionsFeatures.getInstitutionsFeatures 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, institutionFeatures, v1Features, bonusFeatures} = results
logger.log {user_id, individualFeatures, groupFeatureSets, institutionFeatures, v1Features, bonusFeatures}, 'merging user features'
featureSets = groupFeatureSets.concat [individualFeatures, institutionFeatures, 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