mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-20 11:03:40 +00:00
Merge pull request #23972 from overleaf/jdt-grant-assist-via-wf-set-trait
enable granting of premium error assist based on WF entitlement to bu… GitOrigin-RevId: 9d21cf8755c881bdc698c0cf9891076ecefd34eb
This commit is contained in:
parent
19eefebe95
commit
80abd0ac2c
5 changed files with 91 additions and 1 deletions
|
@ -15,6 +15,7 @@ const metrics = require('@overleaf/metrics')
|
|||
const { User } = require('../../models/User')
|
||||
const SubscriptionLocator = require('../Subscription/SubscriptionLocator')
|
||||
const LimitationsManager = require('../Subscription/LimitationsManager')
|
||||
const FeaturesHelper = require('../Subscription/FeaturesHelper')
|
||||
const Settings = require('@overleaf/settings')
|
||||
const AuthorizationManager = require('../Authorization/AuthorizationManager')
|
||||
const InactiveProjectManager = require('../InactiveData/InactiveProjectManager')
|
||||
|
@ -760,6 +761,20 @@ const _ProjectController = {
|
|||
const isOverleafAssistBundleEnabled =
|
||||
splitTestAssignments['overleaf-assist-bundle']?.variant === 'enabled'
|
||||
|
||||
let fullFeatureSet = user?.features
|
||||
if (!anonymous) {
|
||||
// generate users feature set including features added, or overriden via modules
|
||||
const moduleFeatures =
|
||||
(await Modules.promises.hooks.fire(
|
||||
'getModuleProvidedFeatures',
|
||||
userId
|
||||
)) || []
|
||||
fullFeatureSet = FeaturesHelper.computeFeatureSet([
|
||||
user.features,
|
||||
...moduleFeatures,
|
||||
])
|
||||
}
|
||||
|
||||
const isPaywallChangeCompileTimeoutEnabled =
|
||||
splitTestAssignments['paywall-change-compile-timeout']?.variant ===
|
||||
'enabled'
|
||||
|
@ -802,7 +817,7 @@ const _ProjectController = {
|
|||
allowedFreeTrial,
|
||||
hasRecurlySubscription: subscription?.recurlySubscription_id != null,
|
||||
featureSwitches: user.featureSwitches,
|
||||
features: user.features,
|
||||
features: fullFeatureSet,
|
||||
featureUsage,
|
||||
refProviders: _.mapValues(user.refProviders, Boolean),
|
||||
writefull: {
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
const _ = require('lodash')
|
||||
const Settings = require('@overleaf/settings')
|
||||
|
||||
/**
|
||||
* merges an array of feature sets to produce a final feature set
|
||||
*/
|
||||
function computeFeatureSet(featureSets) {
|
||||
return featureSets.reduce(mergeFeatures, {})
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge feature sets coming from different sources
|
||||
*/
|
||||
|
@ -108,6 +115,7 @@ function getMatchedFeatureSet(features) {
|
|||
|
||||
module.exports = {
|
||||
mergeFeatures,
|
||||
computeFeatureSet,
|
||||
isFeatureSetBetter,
|
||||
compareFeatures,
|
||||
getMatchedFeatureSet,
|
||||
|
|
|
@ -194,6 +194,7 @@ const UserSchema = new Schema(
|
|||
writefull: {
|
||||
enabled: { type: Boolean, default: null },
|
||||
autoCreatedAccount: { type: Boolean, default: false },
|
||||
isPremium: { type: Boolean, default: false },
|
||||
},
|
||||
aiErrorAssistant: {
|
||||
enabled: { type: Boolean, default: true },
|
||||
|
|
|
@ -1121,6 +1121,44 @@ describe('ProjectController', function () {
|
|||
this.ProjectController.loadEditor(this.req, this.res)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when fetching the users featureSet', function () {
|
||||
beforeEach(function () {
|
||||
this.Modules.promises.hooks.fire = sinon.stub().resolves()
|
||||
this.user.features = {}
|
||||
})
|
||||
|
||||
it('should take into account features overrides from modules', function (done) {
|
||||
// this case occurs when the user has bought the ai bundle on WF, which should include our error assistant
|
||||
const bundleFeatures = { aiErrorAssistant: true }
|
||||
this.user.features = { aiErrorAssistant: false }
|
||||
this.Modules.promises.hooks.fire = sinon
|
||||
.stub()
|
||||
.resolves([bundleFeatures])
|
||||
this.res.render = (pageName, opts) => {
|
||||
expect(opts.user.features).to.deep.equal(bundleFeatures)
|
||||
this.Modules.promises.hooks.fire.should.have.been.calledWith(
|
||||
'getModuleProvidedFeatures',
|
||||
this.user._id
|
||||
)
|
||||
done()
|
||||
}
|
||||
this.ProjectController.loadEditor(this.req, this.res)
|
||||
})
|
||||
|
||||
it('should handle modules not returning any features', function (done) {
|
||||
this.Modules.promises.hooks.fire = sinon.stub().resolves([])
|
||||
this.res.render = (pageName, opts) => {
|
||||
expect(opts.user.features).to.deep.equal({})
|
||||
this.Modules.promises.hooks.fire.should.have.been.calledWith(
|
||||
'getModuleProvidedFeatures',
|
||||
this.user._id
|
||||
)
|
||||
done()
|
||||
}
|
||||
this.ProjectController.loadEditor(this.req, this.res)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('userProjectsJson', function () {
|
||||
|
|
|
@ -88,6 +88,34 @@ describe('FeaturesHelper', function () {
|
|||
})
|
||||
})
|
||||
|
||||
describe('computeFeatureSet', function () {
|
||||
it('should handle only one featureSet', function () {
|
||||
expect(
|
||||
this.FeaturesHelper.computeFeatureSet([
|
||||
{ github: true, feat1: true, feat2: false },
|
||||
])
|
||||
).to.deep.equal({ github: true, feat1: true, feat2: false })
|
||||
})
|
||||
it('should handle an empty array of featureSets', function () {
|
||||
expect(this.FeaturesHelper.computeFeatureSet([])).to.deep.equal({})
|
||||
})
|
||||
|
||||
it('should handle 3+ featureSets', function () {
|
||||
const featureSets = [
|
||||
{ github: true, feat1: false, feat2: false },
|
||||
{ github: false, feat1: true, feat2: false, feat3: false },
|
||||
{ github: false, feat1: false, feat2: true, feat4: true },
|
||||
]
|
||||
expect(this.FeaturesHelper.computeFeatureSet(featureSets)).to.deep.equal({
|
||||
github: true,
|
||||
feat1: true,
|
||||
feat2: true,
|
||||
feat3: false,
|
||||
feat4: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('isFeatureSetBetter', function () {
|
||||
it('simple comparisons', function () {
|
||||
const result1 = this.FeaturesHelper.isFeatureSetBetter(
|
||||
|
|
Loading…
Add table
Reference in a new issue