Merge pull request #13591 from overleaf/ab-account-enrollment

[web] Managed users - account enrollment

GitOrigin-RevId: 6fc9ef8c44394eb92d3afd2022433b0b6d508503
This commit is contained in:
Davinder Singh
2023-07-17 10:59:02 +00:00
committed by Copybot
parent bc3d6c3636
commit 9e8e124113
17 changed files with 268 additions and 22 deletions
@@ -133,8 +133,16 @@ function registerPolicy(name, capabilities, options = {}) {
* @returns {Array} An array of policy names that are enforced.
*/
function getEnforcedPolicyNames(groupPolicy = {}) {
return Object.keys(groupPolicy).filter(
policyName => groupPolicy[policyName] !== false
if (!groupPolicy) {
return []
}
return Object.keys(
typeof groupPolicy.toObject === 'function'
? groupPolicy.toObject()
: groupPolicy
).filter(
policyName =>
!['__v', '_id'].includes(policyName) && groupPolicy[policyName] !== false
) // filter out the policies that are not enforced
}
@@ -32,7 +32,6 @@ const SplitTestHandler = require('../SplitTests/SplitTestHandler')
/** @typedef {import("../../../../types/project/dashboard/api").Sort} Sort */
/** @typedef {import("./types").AllUsersProjects} AllUsersProjects */
/** @typedef {import("./types").MongoProject} MongoProject */
/** @typedef {import("../Tags/types").Tag} Tag */
const _ssoAvailable = (affiliation, session, linkedInstitutionIds) => {
@@ -90,6 +89,10 @@ async function projectListPage(req, res, next) {
// - object - the subscription data object
let usersBestSubscription
let survey
let userIsMemberOfGroupSubscription = false
let groupSubscriptionsPendingEnrollment = []
const isSaas = Features.hasFeature('saas')
const userId = SessionManager.getLoggedInUserId(req.session)
const projectsBlobPending = _getProjects(userId).catch(err => {
@@ -98,7 +101,9 @@ async function projectListPage(req, res, next) {
})
const user = await User.findById(
userId,
'email emails features lastPrimaryEmailCheck signUpDate'
`email emails features lastPrimaryEmailCheck signUpDate${
isSaas ? ' enrollment' : ''
}`
)
// Handle case of deleted user
@@ -107,7 +112,7 @@ async function projectListPage(req, res, next) {
return
}
if (Features.hasFeature('saas')) {
if (isSaas) {
try {
usersBestSubscription =
await SubscriptionViewModelBuilder.promises.getBestSubscription({
@@ -119,6 +124,24 @@ async function projectListPage(req, res, next) {
"Failed to get user's best subscription"
)
}
try {
const { isMember, subscriptions } =
await LimitationsManager.promises.userIsMemberOfGroupSubscription(user)
userIsMemberOfGroupSubscription = isMember
// TODO use helper function
if (!user.enrollment?.managedBy) {
groupSubscriptionsPendingEnrollment = subscriptions.filter(
subscription => subscription.groupPlan && subscription.groupPolicy
)
}
} catch (error) {
logger.error(
{ err: error },
'Failed to check whether user is a member of group subscription'
)
}
try {
survey = await SurveyHandler.promises.getSurvey(userId)
@@ -280,20 +303,6 @@ async function projectListPage(req, res, next) {
status: prefetchedProjectsBlob ? 'success' : 'too-slow',
})
let userIsMemberOfGroupSubscription = false
try {
const userIsMemberOfGroupSubscriptionPromise =
await LimitationsManager.promises.userIsMemberOfGroupSubscription(user)
userIsMemberOfGroupSubscription =
userIsMemberOfGroupSubscriptionPromise.isMember
} catch (error) {
logger.error(
{ err: error },
'Failed to check whether user is a member of group subscription'
)
}
// in v2 add notifications for matching university IPs
if (Settings.overleaf != null && req.ip !== user.lastLoginIp) {
try {
@@ -395,6 +404,11 @@ async function projectListPage(req, res, next) {
showINRBanner,
projectDashboardReact: true, // used in navbar
welcomePageRedesignVariant: welcomePageRedesignAssignment.variant,
groupSubscriptionsPendingEnrollment:
groupSubscriptionsPendingEnrollment.map(subscription => ({
groupId: subscription._id,
groupName: subscription.teamName,
})),
})
}
@@ -126,6 +126,7 @@ async function settingsPage(req, res) {
showPersonalAccessToken,
personalAccessTokens,
emailAddressLimit: Settings.emailAddressLimit,
isManagedAccount: !!user.enrollment?.managedBy,
})
}
@@ -22,5 +22,16 @@ const UserMembershipAuthorization = {
)
}
},
isEntityMember() {
return req => {
if (!req.entity) {
return false
}
return req.entity[req.entityConfig.fields.membership].some(accessUserId =>
accessUserId.equals(req.user._id)
)
}
},
}
module.exports = UserMembershipAuthorization
@@ -8,6 +8,7 @@ module.exports = {
read: ['invited_emails', 'teamInvites', 'member_ids'],
write: null,
access: 'manager_ids',
membership: 'member_ids',
name: 'teamName',
},
baseQuery: {
@@ -47,6 +48,7 @@ module.exports = {
read: ['manager_ids'],
write: 'manager_ids',
access: 'manager_ids',
membership: 'member_ids',
name: 'teamName',
},
baseQuery: {
@@ -72,6 +74,7 @@ module.exports = {
read: ['managerIds'],
write: 'managerIds',
access: 'managerIds',
membership: 'member_ids',
name: 'name',
},
translations: {
@@ -95,6 +98,7 @@ module.exports = {
read: ['managerIds'],
write: 'managerIds',
access: 'managerIds',
membership: 'member_ids',
name: 'name',
},
translations: {
@@ -22,6 +22,15 @@ const UserMembershipMiddleware = {
]),
],
requireGroup: [fetchEntityConfig('group'), fetchEntity(), requireEntity()],
requireGroupAccess: [
AuthenticationController.requireLogin(),
fetchEntityConfig('group'),
fetchEntity(),
requireEntity(),
],
requireGroupManagementAccess: [
AuthenticationController.requireLogin(),
fetchEntityConfig('group'),