diff --git a/services/web/app/src/Features/Collaborators/CollaboratorsController.mjs b/services/web/app/src/Features/Collaborators/CollaboratorsController.mjs index 5c87e901d6..d2cecbcfad 100644 --- a/services/web/app/src/Features/Collaborators/CollaboratorsController.mjs +++ b/services/web/app/src/Features/Collaborators/CollaboratorsController.mjs @@ -14,7 +14,6 @@ import { hasAdminAccess } from '../Helpers/AdminAuthorizationHelper.js' import TokenAccessHandler from '../TokenAccess/TokenAccessHandler.js' import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.js' import LimitationsManager from '../Subscription/LimitationsManager.js' -import PrivilegeLevels from '../Authorization/PrivilegeLevels.js' const ObjectId = mongodb.ObjectId @@ -80,17 +79,20 @@ async function setCollaboratorInfo(req, res, next) { const userId = req.params.user_id const { privilegeLevel } = req.body - if (privilegeLevel !== PrivilegeLevels.READ_ONLY) { - const allowed = - await LimitationsManager.promises.canAddXEditCollaborators(projectId, 1) - if (!allowed) { - return HttpErrorHandler.forbidden( - req, - res, - 'edit collaborator limit reached' - ) - } + const allowed = + await LimitationsManager.promises.canChangeCollaboratorPrivilegeLevel( + projectId, + userId, + privilegeLevel + ) + if (!allowed) { + return HttpErrorHandler.forbidden( + req, + res, + 'edit collaborator limit reached' + ) } + await CollaboratorsHandler.promises.setCollaboratorPrivilegeLevel( projectId, userId, diff --git a/services/web/app/src/Features/Collaborators/CollaboratorsGetter.js b/services/web/app/src/Features/Collaborators/CollaboratorsGetter.js index 563a6ea6b7..663b1bc654 100644 --- a/services/web/app/src/Features/Collaborators/CollaboratorsGetter.js +++ b/services/web/app/src/Features/Collaborators/CollaboratorsGetter.js @@ -128,12 +128,13 @@ async function getMemberIdPrivilegeLevel(userId, projectId) { } async function getInvitedEditCollaboratorCount(projectId) { - // Only counts invited members with readAndWrite privilege + // Counts invited members with editor or reviewer roles const members = await getMemberIdsWithPrivilegeLevels(projectId) return members.filter( m => m.source === Sources.INVITE && - m.privilegeLevel === PrivilegeLevels.READ_AND_WRITE + (m.privilegeLevel === PrivilegeLevels.READ_AND_WRITE || + m.privilegeLevel === PrivilegeLevels.REVIEW) ).length } diff --git a/services/web/app/src/Features/Subscription/LimitationsManager.js b/services/web/app/src/Features/Subscription/LimitationsManager.js index 346bd0420a..1fc85434a8 100644 --- a/services/web/app/src/Features/Subscription/LimitationsManager.js +++ b/services/web/app/src/Features/Subscription/LimitationsManager.js @@ -1,3 +1,5 @@ +// @ts-check + const logger = require('@overleaf/logger') const ProjectGetter = require('../Project/ProjectGetter') const UserGetter = require('../User/UserGetter') @@ -5,6 +7,7 @@ const SubscriptionLocator = require('./SubscriptionLocator') const Settings = require('@overleaf/settings') const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter') const CollaboratorsInvitesGetter = require('../Collaborators/CollaboratorsInviteGetter') +const PrivilegeLevels = require('../Authorization/PrivilegeLevels') const { callbackify, callbackifyMultiResult, @@ -58,6 +61,54 @@ async function canAddXEditCollaborators( ) } +/** + * Check whether a collaborator can be switched to the given privilege level + * + * @param {string} projectId + * @param {string} userId + * @param {'readOnly' | 'review' | 'readAndWrite'} privilegeLevel + * @return {Promise} + */ +async function canChangeCollaboratorPrivilegeLevel( + projectId, + userId, + privilegeLevel +) { + if (privilegeLevel === PrivilegeLevels.READ_ONLY) { + return true + } + + const currentPrivilegeLevel = + await CollaboratorsGetter.promises.getMemberIdPrivilegeLevel( + userId, + projectId + ) + if ( + [PrivilegeLevels.READ_AND_WRITE, PrivilegeLevels.REVIEW].includes( + currentPrivilegeLevel + ) + ) { + // Current collaborator already takes a slot, so changing the privilege + // level won't increase the collaborator count + return true + } + + const allowedNumber = await allowedNumberOfCollaboratorsInProject(projectId) + if (allowedNumber < 0) { + // -1 means unlimited + return true + } + + const slotsTaken = + await CollaboratorsGetter.promises.getInvitedEditCollaboratorCount( + projectId + ) + const inviteCount = + await CollaboratorsInvitesGetter.promises.getEditInviteCount(projectId) + + return slotsTaken + inviteCount < allowedNumber +} + async function hasPaidSubscription(user) { const { hasSubscription, subscription } = await userHasSubscription(user) const { isMember } = await userIsMemberOfGroupSubscription(user) @@ -122,6 +173,9 @@ const LimitationsManager = { allowedNumberOfCollaboratorsForUser ), canAddXEditCollaborators: callbackify(canAddXEditCollaborators), + canChangeCollaboratorPrivilegeLevel: callbackify( + canChangeCollaboratorPrivilegeLevel + ), hasPaidSubscription: callbackifyMultiResult(hasPaidSubscription, [ 'hasPaidSubscription', 'subscription', @@ -150,6 +204,7 @@ const LimitationsManager = { allowedNumberOfCollaboratorsForUser, canAcceptEditCollaboratorInvite, canAddXEditCollaborators, + canChangeCollaboratorPrivilegeLevel, hasPaidSubscription, userHasSubscriptionOrIsGroupMember, userHasSubscription, diff --git a/services/web/test/unit/src/Collaborators/CollaboratorsControllerTests.mjs b/services/web/test/unit/src/Collaborators/CollaboratorsControllerTests.mjs index e93563ab95..27460da148 100644 --- a/services/web/test/unit/src/Collaborators/CollaboratorsControllerTests.mjs +++ b/services/web/test/unit/src/Collaborators/CollaboratorsControllerTests.mjs @@ -76,6 +76,7 @@ describe('CollaboratorsController', function () { this.LimitationsManager = { promises: { canAddXEditCollaborators: sinon.stub().resolves(), + canChangeCollaboratorPrivilegeLevel: sinon.stub().resolves(true), }, } @@ -310,18 +311,17 @@ describe('CollaboratorsController', function () { }) describe('when owner can add new edit collaborators', function () { - beforeEach(function () { - this.LimitationsManager.promises.canAddXEditCollaborators.resolves( - true - ) - }) - it('should set privilege level after checking collaborators can be added', function (done) { this.res.sendStatus = status => { expect(status).to.equal(204) expect( - this.LimitationsManager.promises.canAddXEditCollaborators - ).to.have.been.calledWith(this.projectId, 1) + this.LimitationsManager.promises + .canChangeCollaboratorPrivilegeLevel + ).to.have.been.calledWith( + this.projectId, + this.user._id, + 'readAndWrite' + ) done() } this.CollaboratorsController.setCollaboratorInfo(this.req, this.res) @@ -330,7 +330,7 @@ describe('CollaboratorsController', function () { describe('when owner cannot add edit collaborators', function () { beforeEach(function () { - this.LimitationsManager.promises.canAddXEditCollaborators.resolves( + this.LimitationsManager.promises.canChangeCollaboratorPrivilegeLevel.resolves( false ) }) @@ -340,8 +340,13 @@ describe('CollaboratorsController', function () { expect(req).to.equal(this.req) expect(res).to.equal(this.res) expect( - this.LimitationsManager.promises.canAddXEditCollaborators - ).to.have.been.calledWith(this.projectId, 1) + this.LimitationsManager.promises + .canChangeCollaboratorPrivilegeLevel + ).to.have.been.calledWith( + this.projectId, + this.user._id, + 'readAndWrite' + ) expect( this.CollaboratorsHandler.promises.setCollaboratorPrivilegeLevel ).to.not.have.been.called diff --git a/services/web/test/unit/src/Collaborators/CollaboratorsGetterTests.js b/services/web/test/unit/src/Collaborators/CollaboratorsGetterTests.js index 0547ef4062..5135dea412 100644 --- a/services/web/test/unit/src/Collaborators/CollaboratorsGetterTests.js +++ b/services/web/test/unit/src/Collaborators/CollaboratorsGetterTests.js @@ -535,12 +535,12 @@ describe('CollaboratorsGetter', function () { }) describe('getInvitedEditCollaboratorCount', function () { - it('should return the count of invited edit collaborators (token, readAndWrite)', async function () { + it('should return the count of invited edit collaborators (readAndWrite, review)', async function () { const count = await this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount( this.project._id ) - expect(count).to.equal(2) + expect(count).to.equal(4) }) }) diff --git a/services/web/test/unit/src/Subscription/LimitationsManagerTests.js b/services/web/test/unit/src/Subscription/LimitationsManagerTests.js index 0ea71ed179..29c97de6b6 100644 --- a/services/web/test/unit/src/Subscription/LimitationsManagerTests.js +++ b/services/web/test/unit/src/Subscription/LimitationsManagerTests.js @@ -1,5 +1,4 @@ const SandboxedModule = require('sandboxed-module') -const assert = require('assert') const sinon = require('sinon') const { expect } = require('chai') const modulePath = require('path').join( @@ -50,13 +49,14 @@ describe('LimitationsManager', function () { this.CollaboratorsGetter = { promises: { - getInvitedEditCollaboratorCount: sinon.stub().resolves(), + getInvitedEditCollaboratorCount: sinon.stub().resolves(0), + getMemberIdPrivilegeLevel: sinon.stub(), }, } this.CollaboratorsInviteGetter = { promises: { - getEditInviteCount: sinon.stub().resolves(), + getEditInviteCount: sinon.stub().resolves(0), }, } @@ -76,76 +76,64 @@ describe('LimitationsManager', function () { describe('allowedNumberOfCollaboratorsInProject', function () { describe('when the project is owned by a user without a subscription', function () { - beforeEach(function (done) { + beforeEach(function () { this.Settings.defaultFeatures = { collaborators: 23 } this.project.owner_ref = this.userId delete this.user.features - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.allowedNumberOfCollaboratorsInProject( - this.projectId, - this.callback - ) }) - it('should return the default number', function () { - this.callback - .calledWith(null, this.Settings.defaultFeatures.collaborators) - .should.equal(true) + it('should return the default number', async function () { + const result = + await this.LimitationsManager.promises.allowedNumberOfCollaboratorsInProject( + this.projectId + ) + expect(result).to.equal(this.Settings.defaultFeatures.collaborators) }) }) describe('when the project is owned by a user with a subscription', function () { - beforeEach(function (done) { + beforeEach(function () { this.project.owner_ref = this.userId this.user.features = { collaborators: 21 } - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.allowedNumberOfCollaboratorsInProject( - this.projectId, - this.callback - ) }) - it('should return the number of collaborators the user is allowed', function () { - this.callback - .calledWith(null, this.user.features.collaborators) - .should.equal(true) + it('should return the number of collaborators the user is allowed', async function () { + const result = + await this.LimitationsManager.promises.allowedNumberOfCollaboratorsInProject( + this.projectId + ) + expect(result).to.equal(this.user.features.collaborators) }) }) }) describe('allowedNumberOfCollaboratorsForUser', function () { describe('when the user has no features', function () { - beforeEach(function (done) { + beforeEach(function () { this.Settings.defaultFeatures = { collaborators: 23 } delete this.user.features - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.allowedNumberOfCollaboratorsForUser( - this.userId, - this.callback - ) }) - it('should return the default number', function () { - this.callback - .calledWith(null, this.Settings.defaultFeatures.collaborators) - .should.equal(true) + it('should return the default number', async function () { + const result = + await this.LimitationsManager.promises.allowedNumberOfCollaboratorsForUser( + this.userId + ) + expect(result).to.equal(this.Settings.defaultFeatures.collaborators) }) }) describe('when the user has features', function () { - beforeEach(function (done) { + beforeEach(async function () { this.user.features = { collaborators: 21 } - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.allowedNumberOfCollaboratorsForUser( - this.userId, - this.callback - ) + this.result = + await this.LimitationsManager.promises.allowedNumberOfCollaboratorsForUser( + this.userId + ) }) it('should return the number of collaborators the user is allowed', function () { - this.callback - .calledWith(null, this.user.features.collaborators) - .should.equal(true) + expect(this.result).to.equal(this.user.features.collaborators) }) }) }) @@ -222,7 +210,7 @@ describe('LimitationsManager', function () { describe('canAddXEditCollaborators', function () { describe('when the project has fewer collaborators than allowed', function () { - beforeEach(function (done) { + beforeEach(function () { this.current_number = 1 this.user.features.collaborators = 2 this.invite_count = 0 @@ -231,21 +219,20 @@ describe('LimitationsManager', function () { this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon .stub() .resolves(this.invite_count) - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.canAddXEditCollaborators( - this.projectId, - 1, - this.callback - ) }) - it('should return true', function () { - this.callback.calledWith(null, true).should.equal(true) + it('should return true', async function () { + const result = + await this.LimitationsManager.promises.canAddXEditCollaborators( + this.projectId, + 1 + ) + expect(result).to.be.true }) }) describe('when the project has fewer collaborators and invites than allowed', function () { - beforeEach(function (done) { + beforeEach(function () { this.current_number = 1 this.user.features.collaborators = 4 this.invite_count = 1 @@ -254,21 +241,20 @@ describe('LimitationsManager', function () { this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon .stub() .resolves(this.invite_count) - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.canAddXEditCollaborators( - this.projectId, - 1, - this.callback - ) }) - it('should return true', function () { - this.callback.calledWith(null, true).should.equal(true) + it('should return true', async function () { + const result = + await this.LimitationsManager.promises.canAddXEditCollaborators( + this.projectId, + 1 + ) + expect(result).to.be.true }) }) describe('when the project has fewer collaborators than allowed but I want to add more than allowed', function () { - beforeEach(function (done) { + beforeEach(function () { this.current_number = 1 this.user.features.collaborators = 2 this.invite_count = 0 @@ -277,21 +263,20 @@ describe('LimitationsManager', function () { this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon .stub() .resolves(this.invite_count) - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.canAddXEditCollaborators( - this.projectId, - 2, - this.callback - ) }) - it('should return false', function () { - this.callback.calledWith(null, false).should.equal(true) + it('should return false', async function () { + const result = + await this.LimitationsManager.promises.canAddXEditCollaborators( + this.projectId, + 2 + ) + expect(result).to.be.false }) }) describe('when the project has more collaborators than allowed', function () { - beforeEach(function (done) { + beforeEach(function () { this.current_number = 3 this.user.features.collaborators = 2 this.invite_count = 0 @@ -300,21 +285,20 @@ describe('LimitationsManager', function () { this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon .stub() .resolves(this.invite_count) - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.canAddXEditCollaborators( - this.projectId, - 1, - this.callback - ) }) - it('should return false', function () { - this.callback.calledWith(null, false).should.equal(true) + it('should return false', async function () { + const result = + await this.LimitationsManager.promises.canAddXEditCollaborators( + this.projectId, + 1 + ) + expect(result).to.be.false }) }) describe('when the project has infinite collaborators', function () { - beforeEach(function (done) { + beforeEach(function () { this.current_number = 100 this.user.features.collaborators = -1 this.invite_count = 0 @@ -323,21 +307,20 @@ describe('LimitationsManager', function () { this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon .stub() .resolves(this.invite_count) - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.canAddXEditCollaborators( - this.projectId, - 1, - this.callback - ) }) - it('should return true', function () { - this.callback.calledWith(null, true).should.equal(true) + it('should return true', async function () { + const result = + await this.LimitationsManager.promises.canAddXEditCollaborators( + this.projectId, + 1 + ) + expect(result).to.be.true }) }) describe('when the project has more invites than allowed', function () { - beforeEach(function (done) { + beforeEach(function () { this.current_number = 0 this.user.features.collaborators = 2 this.invite_count = 2 @@ -346,21 +329,20 @@ describe('LimitationsManager', function () { this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon .stub() .resolves(this.invite_count) - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.canAddXEditCollaborators( - this.projectId, - 1, - this.callback - ) }) - it('should return false', function () { - this.callback.calledWith(null, false).should.equal(true) + it('should return false', async function () { + const result = + await this.LimitationsManager.promises.canAddXEditCollaborators( + this.projectId, + 1 + ) + expect(result).to.be.false }) }) describe('when the project has more invites and collaborators than allowed', function () { - beforeEach(function (done) { + beforeEach(function () { this.current_number = 1 this.user.features.collaborators = 2 this.invite_count = 1 @@ -369,16 +351,67 @@ describe('LimitationsManager', function () { this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon .stub() .resolves(this.invite_count) - this.callback = sinon.stub().callsFake(() => done()) - this.LimitationsManager.canAddXEditCollaborators( - this.projectId, - 1, - this.callback + }) + + it('should return false', async function () { + const result = + await this.LimitationsManager.promises.canAddXEditCollaborators( + this.projectId, + 1 + ) + expect(result).to.be.false + }) + }) + }) + + describe('canChangeCollaboratorPrivilegeLevel', function () { + beforeEach(function () { + this.collaboratorId = 'collaborator-id' + this.CollaboratorsGetter.promises.getMemberIdPrivilegeLevel.resolves( + 'readOnly' + ) + }) + + describe("when the limit hasn't been reached", function () { + it('accepts changing a viewer to an editor', async function () { + const result = + await this.LimitationsManager.promises.canChangeCollaboratorPrivilegeLevel( + this.projectId, + this.collaboratorId, + 'readAndWrite' + ) + expect(result).to.be.true + }) + }) + + describe('when the limit has been reached', function () { + beforeEach(function () { + this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount.resolves( + 1 ) }) - it('should return false', function () { - this.callback.calledWith(null, false).should.equal(true) + it('accepts changing a reviewer to an editor', async function () { + this.CollaboratorsGetter.promises.getMemberIdPrivilegeLevel.resolves( + 'review' + ) + const result = + await this.LimitationsManager.promises.canChangeCollaboratorPrivilegeLevel( + this.projectId, + this.collaboratorId, + 'readAndWrite' + ) + expect(result).to.be.true + }) + + it('rejects changing a viewer to a reviewer', async function () { + const result = + await this.LimitationsManager.promises.canChangeCollaboratorPrivilegeLevel( + this.projectId, + this.collaboratorId, + 'review' + ) + expect(result).to.be.false }) }) }) @@ -390,60 +423,39 @@ describe('LimitationsManager', function () { .resolves() }) - it('should return true if the recurly token is set', function (done) { + it('should return true if the recurly token is set', async function () { this.SubscriptionLocator.promises.getUsersSubscription = sinon .stub() .resolves({ recurlySubscription_id: '1234', }) - this.LimitationsManager.userHasSubscription( - this.user, - (err, hasSubscription) => { - assert.equal(err, null) - hasSubscription.should.equal(true) - done() - } - ) + const { hasSubscription } = + await this.LimitationsManager.promises.userHasSubscription(this.user) + expect(hasSubscription).to.be.true }) - it('should return false if the recurly token is not set', function (done) { + it('should return false if the recurly token is not set', async function () { this.SubscriptionLocator.promises.getUsersSubscription.resolves({}) - this.subscription = {} - this.LimitationsManager.userHasSubscription( - this.user, - (err, hasSubscription) => { - assert.equal(err, null) - hasSubscription.should.equal(false) - done() - } - ) + const { hasSubscription } = + await this.LimitationsManager.promises.userHasSubscription(this.user) + expect(hasSubscription).to.be.false }) - it('should return false if the subscription is undefined', function (done) { + it('should return false if the subscription is undefined', async function () { this.SubscriptionLocator.promises.getUsersSubscription.resolves() - this.LimitationsManager.userHasSubscription( - this.user, - (err, hasSubscription) => { - assert.equal(err, null) - hasSubscription.should.equal(false) - done() - } - ) + const { hasSubscription } = + await this.LimitationsManager.promises.userHasSubscription(this.user) + expect(hasSubscription).to.be.false }) - it('should return the subscription', function (done) { + it('should return the subscription', async function () { const stubbedSubscription = { freeTrial: {}, token: '' } this.SubscriptionLocator.promises.getUsersSubscription.resolves( stubbedSubscription ) - this.LimitationsManager.userHasSubscription( - this.user, - (err, hasSubOrIsGroupMember, subscription) => { - assert.equal(err, null) - subscription.should.deep.equal(stubbedSubscription) - done() - } - ) + const { subscription } = + await this.LimitationsManager.promises.userHasSubscription(this.user) + expect(subscription).to.deep.equal(stubbedSubscription) }) describe('when user has a custom account', function () { @@ -454,26 +466,16 @@ describe('LimitationsManager', function () { ) }) - it('should return true', function (done) { - this.LimitationsManager.userHasSubscription( - this.user, - (err, hasSubscription, subscription) => { - assert.equal(err, null) - hasSubscription.should.equal(true) - done() - } - ) + it('should return true', async function () { + const { hasSubscription } = + await this.LimitationsManager.promises.userHasSubscription(this.user) + expect(hasSubscription).to.be.true }) - it('should return the subscription', function (done) { - this.LimitationsManager.userHasSubscription( - this.user, - (err, hasSubscription, subscription) => { - assert.equal(err, null) - subscription.should.deep.equal(this.fakeSubscription) - done() - } - ) + it('should return the subscription', async function () { + const { subscription } = + await this.LimitationsManager.promises.userHasSubscription(this.user) + expect(subscription).to.deep.equal(this.fakeSubscription) }) }) }) @@ -485,32 +487,26 @@ describe('LimitationsManager', function () { .resolves() }) - it('should return false if there are no groups subcriptions', function (done) { + it('should return false if there are no groups subcriptions', async function () { this.SubscriptionLocator.promises.getMemberSubscriptions.resolves([]) - this.LimitationsManager.userIsMemberOfGroupSubscription( - this.user, - (err, isMember) => { - assert.equal(err, null) - isMember.should.equal(false) - done() - } - ) + const { isMember } = + await this.LimitationsManager.promises.userIsMemberOfGroupSubscription( + this.user + ) + expect(isMember).to.be.false }) - it('should return true if there are no groups subcriptions', function (done) { - let subscriptions + it('should return true if there are no groups subcriptions', async function () { + const subscriptions = ['mock-subscription'] this.SubscriptionLocator.promises.getMemberSubscriptions.resolves( - (subscriptions = ['mock-subscription']) - ) - this.LimitationsManager.userIsMemberOfGroupSubscription( - this.user, - (err, isMember, retSubscriptions) => { - assert.equal(err, null) - isMember.should.equal(true) - retSubscriptions.should.equal(subscriptions) - done() - } + subscriptions ) + const { isMember, subscriptions: retSubscriptions } = + await this.LimitationsManager.promises.userIsMemberOfGroupSubscription( + this.user + ) + expect(isMember).to.be.true + expect(retSubscriptions).to.deep.equal(subscriptions) }) }) @@ -524,54 +520,36 @@ describe('LimitationsManager', function () { .resolves(null) }) - it('should return true if userIsMemberOfGroupSubscription', function (done) { + it('should return true if userIsMemberOfGroupSubscription', async function () { this.SubscriptionLocator.promises.getMemberSubscriptions = sinon .stub() .resolves([{ _id: '123' }]) - this.LimitationsManager.hasPaidSubscription( - this.user, - (err, hasSubOrIsGroupMember) => { - assert.equal(err, null) - hasSubOrIsGroupMember.should.equal(true) - done() - } - ) + const { hasPaidSubscription } = + await this.LimitationsManager.promises.hasPaidSubscription(this.user) + expect(hasPaidSubscription).to.be.true }) - it('should return true if userHasSubscription', function (done) { + it('should return true if userHasSubscription', async function () { this.SubscriptionLocator.promises.getUsersSubscription = sinon .stub() .resolves({ recurlySubscription_id: '123' }) - this.LimitationsManager.hasPaidSubscription( - this.user, - (err, hasSubOrIsGroupMember) => { - assert.equal(err, null) - hasSubOrIsGroupMember.should.equal(true) - done() - } - ) + const { hasPaidSubscription } = + await this.LimitationsManager.promises.hasPaidSubscription(this.user) + expect(hasPaidSubscription).to.be.true }) - it('should return false if none are true', function (done) { - this.LimitationsManager.hasPaidSubscription( - this.user, - (err, hasSubOrIsGroupMember) => { - assert.equal(err, null) - hasSubOrIsGroupMember.should.equal(false) - done() - } - ) + it('should return false if none are true', async function () { + const { hasPaidSubscription } = + await this.LimitationsManager.promises.hasPaidSubscription(this.user) + expect(hasPaidSubscription).to.be.false }) - it('should have userHasSubscriptionOrIsGroupMember alias', function (done) { - this.LimitationsManager.userHasSubscriptionOrIsGroupMember( - this.user, - (err, hasSubOrIsGroupMember) => { - assert.equal(err, null) - hasSubOrIsGroupMember.should.equal(false) - done() - } - ) + it('should have userHasSubscriptionOrIsGroupMember alias', async function () { + const { hasPaidSubscription } = + await this.LimitationsManager.promises.userHasSubscriptionOrIsGroupMember( + this.user + ) + expect(hasPaidSubscription).to.be.false }) }) @@ -587,48 +565,39 @@ describe('LimitationsManager', function () { } }) - it('should return true if the limit is hit (including members and invites)', function (done) { + it('should return true if the limit is hit (including members and invites)', async function () { this.SubscriptionLocator.promises.getSubscription.resolves( this.subscription ) - this.LimitationsManager.hasGroupMembersLimitReached( - this.subscriptionId, - (err, limitReached) => { - assert.equal(err, null) - limitReached.should.equal(true) - done() - } - ) + const { limitReached } = + await this.LimitationsManager.promises.hasGroupMembersLimitReached( + this.subscriptionId + ) + expect(limitReached).to.be.true }) - it('should return false if the limit is not hit (including members and invites)', function (done) { + it('should return false if the limit is not hit (including members and invites)', async function () { this.subscription.membersLimit = 4 this.SubscriptionLocator.promises.getSubscription.resolves( this.subscription ) - this.LimitationsManager.hasGroupMembersLimitReached( - this.subscriptionId, - (err, limitReached) => { - assert.equal(err, null) - limitReached.should.equal(false) - done() - } - ) + const { limitReached } = + await this.LimitationsManager.promises.hasGroupMembersLimitReached( + this.subscriptionId + ) + expect(limitReached).to.be.false }) - it('should return true if the limit has been exceded (including members and invites)', function (done) { + it('should return true if the limit has been exceded (including members and invites)', async function () { this.subscription.membersLimit = 2 this.SubscriptionLocator.promises.getSubscription.resolves( this.subscription ) - this.LimitationsManager.hasGroupMembersLimitReached( - this.subscriptionId, - (err, limitReached) => { - assert.equal(err, null) - limitReached.should.equal(true) - done() - } - ) + const { limitReached } = + await this.LimitationsManager.promises.hasGroupMembersLimitReached( + this.subscriptionId + ) + expect(limitReached).to.be.true }) }) })