FeaturesUpdater.coffee 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. async = require("async")
  2. PlansLocator = require("./PlansLocator")
  3. _ = require("underscore")
  4. SubscriptionLocator = require("./SubscriptionLocator")
  5. UserFeaturesUpdater = require("./UserFeaturesUpdater")
  6. Settings = require("settings-sharelatex")
  7. logger = require("logger-sharelatex")
  8. ReferalFeatures = require("../Referal/ReferalFeatures")
  9. V1SubscriptionManager = require("./V1SubscriptionManager")
  10. InstitutionsFeatures = require '../Institutions/InstitutionsFeatures'
  11. oneMonthInSeconds = 60 * 60 * 24 * 30
  12. module.exports = FeaturesUpdater =
  13. refreshFeatures: (user_id, notifyV1 = true, callback = (error, features, featuresChanged) ->)->
  14. if typeof notifyV1 == 'function'
  15. callback = notifyV1
  16. notifyV1 = true
  17. if notifyV1
  18. V1SubscriptionManager.notifyV1OfFeaturesChange user_id, (error) ->
  19. if error?
  20. logger.err {err: error, user_id}, "error notifying v1 about updated features"
  21. jobs =
  22. individualFeatures: (cb) -> FeaturesUpdater._getIndividualFeatures user_id, cb
  23. groupFeatureSets: (cb) -> FeaturesUpdater._getGroupFeatureSets user_id, cb
  24. institutionFeatures:(cb) -> InstitutionsFeatures.getInstitutionsFeatures user_id, cb
  25. v1Features: (cb) -> FeaturesUpdater._getV1Features user_id, cb
  26. bonusFeatures: (cb) -> ReferalFeatures.getBonusFeatures user_id, cb
  27. async.series jobs, (err, results)->
  28. if err?
  29. logger.err err:err, user_id:user_id,
  30. "error getting subscription or group for refreshFeatures"
  31. return callback(err)
  32. {individualFeatures, groupFeatureSets, institutionFeatures, v1Features, bonusFeatures} = results
  33. logger.log {user_id, individualFeatures, groupFeatureSets, institutionFeatures, v1Features, bonusFeatures}, 'merging user features'
  34. featureSets = groupFeatureSets.concat [individualFeatures, institutionFeatures, v1Features, bonusFeatures]
  35. features = _.reduce(featureSets, FeaturesUpdater._mergeFeatures, Settings.defaultFeatures)
  36. logger.log {user_id, features}, 'updating user features'
  37. UserFeaturesUpdater.updateFeatures user_id, features, callback
  38. _getIndividualFeatures: (user_id, callback = (error, features = {}) ->) ->
  39. SubscriptionLocator.getUsersSubscription user_id, (err, sub)->
  40. callback err, FeaturesUpdater._subscriptionToFeatures(sub)
  41. _getGroupFeatureSets: (user_id, callback = (error, featureSets = []) ->) ->
  42. SubscriptionLocator.getGroupSubscriptionsMemberOf user_id, (err, subs) ->
  43. callback err, (subs or []).map FeaturesUpdater._subscriptionToFeatures
  44. _getV1Features: (user_id, callback = (error, features = {}) ->) ->
  45. V1SubscriptionManager.getPlanCodeFromV1 user_id, (err, planCode, v1Id) ->
  46. if err?
  47. return callback(null, []) if err?.name == 'NotFoundError'
  48. return callback(err)
  49. callback(err, FeaturesUpdater._mergeFeatures(
  50. V1SubscriptionManager.getGrandfatheredFeaturesForV1User(v1Id) or {},
  51. FeaturesUpdater._planCodeToFeatures(planCode)
  52. ))
  53. _mergeFeatures: (featuresA, featuresB) ->
  54. features = Object.assign({}, featuresA)
  55. for key, value of featuresB
  56. # Special merging logic for non-boolean features
  57. if key == 'compileGroup'
  58. if features['compileGroup'] == 'priority' or featuresB['compileGroup'] == 'priority'
  59. features['compileGroup'] = 'priority'
  60. else
  61. features['compileGroup'] = 'standard'
  62. else if key == 'collaborators'
  63. if features['collaborators'] == -1 or featuresB['collaborators'] == -1
  64. features['collaborators'] = -1
  65. else
  66. features['collaborators'] = Math.max(
  67. features['collaborators'] or 0,
  68. featuresB['collaborators'] or 0
  69. )
  70. else if key == 'compileTimeout'
  71. features['compileTimeout'] = Math.max(
  72. features['compileTimeout'] or 0,
  73. featuresB['compileTimeout'] or 0
  74. )
  75. else
  76. # Boolean keys, true is better
  77. features[key] = features[key] or featuresB[key]
  78. return features
  79. _subscriptionToFeatures: (subscription) ->
  80. FeaturesUpdater._planCodeToFeatures(subscription?.planCode)
  81. _planCodeToFeatures: (planCode) ->
  82. if !planCode?
  83. return {}
  84. plan = PlansLocator.findLocalPlanInSettings planCode
  85. if !plan?
  86. return {}
  87. else
  88. return plan.features