mirror of
https://github.com/overleaf/overleaf.git
synced 2024-09-23 02:55:13 -04:00
3f5e90078e
Decaffeinate Institutions Code GitOrigin-RevId: 520565d58518e499d2522653ba1ff9c232ebdb88
187 lines
5.3 KiB
JavaScript
187 lines
5.3 KiB
JavaScript
const async = require('async')
|
|
const _ = require('underscore')
|
|
const { ObjectId } = require('../../infrastructure/mongojs')
|
|
const { getInstitutionAffiliations } = require('./InstitutionsAPI')
|
|
const FeaturesUpdater = require('../Subscription/FeaturesUpdater')
|
|
const UserGetter = require('../User/UserGetter')
|
|
const SAMLIdentityManager = require('../User/SAMLIdentityManager')
|
|
const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
|
|
const SubscriptionLocator = require('../Subscription/SubscriptionLocator')
|
|
const { Institution } = require('../../models/Institution')
|
|
const { Subscription } = require('../../models/Subscription')
|
|
|
|
const ASYNC_LIMIT = 10
|
|
module.exports = {
|
|
upgradeInstitutionUsers(institutionId, callback) {
|
|
async.waterfall(
|
|
[
|
|
cb => fetchInstitutionAndAffiliations(institutionId, cb),
|
|
function(institution, affiliations, cb) {
|
|
affiliations = _.map(affiliations, function(affiliation) {
|
|
affiliation.institutionName = institution.name
|
|
affiliation.institutionId = institutionId
|
|
return affiliation
|
|
})
|
|
async.eachLimit(affiliations, ASYNC_LIMIT, refreshFeatures, err =>
|
|
cb(err)
|
|
)
|
|
}
|
|
],
|
|
callback
|
|
)
|
|
},
|
|
|
|
checkInstitutionUsers(institutionId, callback) {
|
|
getInstitutionAffiliations(institutionId, (error, affiliations) => {
|
|
if (error) {
|
|
return callback(error)
|
|
}
|
|
UserGetter.getUsersByAnyConfirmedEmail(
|
|
affiliations.map(affiliation => affiliation.email),
|
|
{ features: 1, samlIdentifiers: 1 },
|
|
(error, users) => callback(error, checkFeatures(institutionId, users))
|
|
)
|
|
})
|
|
},
|
|
|
|
getInstitutionUsersSubscriptions(institutionId, callback) {
|
|
getInstitutionAffiliations(institutionId, function(error, affiliations) {
|
|
if (error) {
|
|
return callback(error)
|
|
}
|
|
const userIds = affiliations.map(affiliation =>
|
|
ObjectId(affiliation.user_id)
|
|
)
|
|
Subscription.find({
|
|
admin_id: userIds,
|
|
planCode: { $not: /trial/ }
|
|
})
|
|
.populate('admin_id', 'email')
|
|
.exec(callback)
|
|
})
|
|
}
|
|
}
|
|
|
|
var fetchInstitutionAndAffiliations = (institutionId, callback) =>
|
|
async.waterfall(
|
|
[
|
|
cb =>
|
|
Institution.findOne({ v1Id: institutionId }, (err, institution) =>
|
|
cb(err, institution)
|
|
),
|
|
(institution, cb) =>
|
|
institution.fetchV1Data((err, institution) => cb(err, institution)),
|
|
(institution, cb) =>
|
|
getInstitutionAffiliations(institutionId, (err, affiliations) =>
|
|
cb(err, institution, affiliations)
|
|
)
|
|
],
|
|
callback
|
|
)
|
|
|
|
var refreshFeatures = function(affiliation, callback) {
|
|
const userId = ObjectId(affiliation.user_id)
|
|
async.waterfall(
|
|
[
|
|
cb =>
|
|
FeaturesUpdater.refreshFeatures(
|
|
userId,
|
|
(err, features, featuresChanged) => cb(err, featuresChanged)
|
|
),
|
|
(featuresChanged, cb) =>
|
|
getUserInfo(userId, (error, user, subscription) =>
|
|
cb(error, user, subscription, featuresChanged)
|
|
),
|
|
(user, subscription, featuresChanged, cb) =>
|
|
notifyUser(user, affiliation, subscription, featuresChanged, cb)
|
|
],
|
|
callback
|
|
)
|
|
}
|
|
|
|
var getUserInfo = (userId, callback) =>
|
|
async.waterfall(
|
|
[
|
|
cb => UserGetter.getUser(userId, cb),
|
|
(user, cb) =>
|
|
SubscriptionLocator.getUsersSubscription(user, (err, subscription) =>
|
|
cb(err, user, subscription)
|
|
)
|
|
],
|
|
callback
|
|
)
|
|
|
|
var notifyUser = (user, affiliation, subscription, featuresChanged, callback) =>
|
|
async.parallel(
|
|
[
|
|
function(cb) {
|
|
if (featuresChanged) {
|
|
NotificationsBuilder.featuresUpgradedByAffiliation(
|
|
affiliation,
|
|
user
|
|
).create(cb)
|
|
} else {
|
|
cb()
|
|
}
|
|
},
|
|
function(cb) {
|
|
if (
|
|
subscription &&
|
|
!subscription.planCode.match(/(free|trial)/) &&
|
|
!subscription.groupPlan
|
|
) {
|
|
NotificationsBuilder.redundantPersonalSubscription(
|
|
affiliation,
|
|
user
|
|
).create(cb)
|
|
} else {
|
|
cb()
|
|
}
|
|
}
|
|
],
|
|
callback
|
|
)
|
|
|
|
var checkFeatures = function(institutionId, users) {
|
|
const usersSummary = {
|
|
confirmedEmailUsers: {
|
|
total: users.length, // all users are confirmed email users
|
|
totalProUsers: 0,
|
|
totalNonProUsers: 0,
|
|
nonProUsers: []
|
|
},
|
|
entitledSSOUsers: {
|
|
total: 0,
|
|
totalProUsers: 0,
|
|
totalNonProUsers: 0,
|
|
nonProUsers: []
|
|
}
|
|
}
|
|
users.forEach(function(user) {
|
|
let isSSOEntitled = SAMLIdentityManager.userHasEntitlement(
|
|
user,
|
|
institutionId
|
|
)
|
|
|
|
if (isSSOEntitled) {
|
|
usersSummary.entitledSSOUsers.total += 1
|
|
}
|
|
|
|
if (user.features.collaborators === -1 && user.features.trackChanges) {
|
|
// user is on Pro
|
|
usersSummary.confirmedEmailUsers.totalProUsers += 1
|
|
if (isSSOEntitled) {
|
|
usersSummary.entitledSSOUsers.totalProUsers += 1
|
|
}
|
|
} else {
|
|
// user is not on Pro
|
|
usersSummary.confirmedEmailUsers.totalNonProUsers += 1
|
|
usersSummary.confirmedEmailUsers.nonProUsers.push(user._id)
|
|
if (isSSOEntitled) {
|
|
usersSummary.entitledSSOUsers.totalNonProUsers += 1
|
|
usersSummary.entitledSSOUsers.nonProUsers.push(user._id)
|
|
}
|
|
}
|
|
})
|
|
return usersSummary
|
|
}
|