Merge pull request #15726 from overleaf/ab-managed-users-module-cleanup

[web] Managed users / Group SSO module cleanup

GitOrigin-RevId: a24d3278667059248d9563afe44cafca5f87a7c0
This commit is contained in:
Brian Gough 2023-11-20 09:25:38 +00:00 committed by Copybot
parent 26fe632a22
commit 1ff830027f
16 changed files with 58 additions and 632 deletions

View file

@ -4,7 +4,7 @@ const {
getUserCapabilities,
getUserRestrictions,
} = require('./PermissionsManager')
const ManagedUsersHandler = require('../Subscription/ManagedUsersHandler')
const Modules = require('../../infrastructure/Modules')
/**
* Function that returns middleware to add an `assertPermission` function to the request object to check if the user has a specific capability.
@ -26,19 +26,26 @@ function useCapabilities() {
return next()
}
try {
// get the group policy applying to the user
const { groupPolicy, managedBy, isManagedGroupAdmin } =
await ManagedUsersHandler.promises.getEnrollmentForUser(req.user)
// attach the subscription ID to the request object
req.managedBy = managedBy
// attach the subscription admin status to the request object
req.isManagedGroupAdmin = isManagedGroupAdmin
// attach the new capabilities to the request object
for (const cap of getUserCapabilities(groupPolicy)) {
req.capabilitySet.add(cap)
const result = (
await Modules.promises.hooks.fire(
'getManagedUsersEnrollmentForUser',
req.user
)
)[0]
if (result) {
// get the group policy applying to the user
const { groupPolicy, managedBy, isManagedGroupAdmin } = result
// attach the subscription ID to the request object
req.managedBy = managedBy
// attach the subscription admin status to the request object
req.isManagedGroupAdmin = isManagedGroupAdmin
// attach the new capabilities to the request object
for (const cap of getUserCapabilities(groupPolicy)) {
req.capabilitySet.add(cap)
}
// also attach the user's restrictions (the capabilities they don't have)
req.userRestrictions = getUserRestrictions(groupPolicy)
}
// also attach the user's restrictions (the capabilities they don't have)
req.userRestrictions = getUserRestrictions(groupPolicy)
next()
} catch (error) {
if (error instanceof UserNotFoundError) {
@ -69,10 +76,14 @@ function requirePermission(...requiredCapabilities) {
return next(new Error('no user'))
}
try {
// get the group policy applying to the user
const { groupPolicy, managedUsersEnabled } =
await ManagedUsersHandler.promises.getEnrollmentForUser(req.user)
const result =
(
await Modules.promises.hooks.fire(
'getManagedUsersEnrollmentForUser',
req.user
)
)[0] || {}
const { groupPolicy, managedUsersEnabled } = result
if (!managedUsersEnabled) {
return next()
}

View file

@ -1,210 +0,0 @@
const { callbackify } = require('util')
const { Subscription } = require('../../models/Subscription')
const { GroupPolicy } = require('../../models/GroupPolicy')
const { User } = require('../../models/User')
const ManagedUsersPolicy = require('./ManagedUsersPolicy')
const OError = require('@overleaf/o-error')
const settings = require('@overleaf/settings')
const {
UserNotFoundError,
SubscriptionNotFoundError,
} = require('../Errors/Errors')
const UserGetter = require('../User/UserGetter')
const UserUpdater = require('../User/UserUpdater')
const EmailHandler = require('../Email/EmailHandler')
const logger = require('@overleaf/logger')
/**
* This module contains functions for handling managed users in a
* group subscription.
*/
/**
* Enables managed users for a given subscription by creating a new
* group policy with default settings for managed users and updating
* the subscription to use the new policy.
* @async
* @function
* @param {string} subscriptionId - The ID of the subscription to enable
* managed users for.
* @returns {Promise<void>} - A Promise that resolves when the subscription
* has been updated with the new group policy.
*/
async function enableManagedUsers(subscriptionId) {
const subscription = await Subscription.findById(subscriptionId).exec()
// create a new Group policy with the default settings for managed users
const policy = ManagedUsersPolicy.getDefaultPolicy()
const groupPolicy = new GroupPolicy(policy)
await groupPolicy.save()
// update the subscription to use the new policy
subscription.groupPolicy = groupPolicy._id
subscription.managedUsersEnabled = true
await subscription.save()
await _sendEmailToGroupMembers(subscriptionId)
}
/**
* Disables managed users for a given subscription by removing the
* group policy and deleting enrolment information for all managed users.
* @async
* @function
* @param {string} subscriptionId - The ID of the subscription to disable
* managed users for.
* @returns {Promise<void>} - A Promise that resolves when the subscription and
* users have been updated.
*/
async function disableManagedUsers(subscriptionId) {
const subscription = await Subscription.findById(subscriptionId).exec()
for (const userId of subscription.member_ids || []) {
const user = await UserGetter.promises.getUser(userId, { enrollment: 1 })
if (
user.enrollment?.managedBy?.toString() === subscription._id.toString()
) {
await UserUpdater.promises.updateUser(userId, {
$unset: { enrollment: 1 },
})
}
}
subscription.groupPolicy = undefined
subscription.managedUsersEnabled = false
await subscription.save()
}
/**
* Retrieves the group policy for a user enrolled in a managed group.
* @async
* @function
* @param {Object} requestedUser - The user object to retrieve the group policy for.
* @returns {Promise<Object>} - A Promise that resolves with the group policy
* and subscription objects for the user's enrollment, or null if it does not exist.
*/
async function getEnrollmentForUser(requestedUser) {
// Don't rely on the user being populated, it may be a session user without
// the enrollment property. Force the user to be loaded from mongo.
const user = await User.findById(requestedUser._id, 'enrollment')
if (!user) {
throw new UserNotFoundError({ info: { userId: requestedUser._id } })
}
// Now we are sure the user exists and we have the full contents
if (user.enrollment?.managedBy == null) {
return {}
}
// retrieve the subscription and the group policy (without the _id field)
const subscription = await Subscription.findById(user.enrollment.managedBy)
.populate('groupPolicy', '-_id')
.exec()
if (!subscription) {
throw new SubscriptionNotFoundError({
info: { subscriptionId: user.enrollment.managedBy, userId: user._id },
})
}
// check whether the user is an admin of the subscription
const isManagedGroupAdmin = user._id.equals(subscription.admin_id)
// return the group policy as a plain object (without the __v field)
const groupPolicy = subscription.groupPolicy.toObject({
versionKey: false,
})
return {
groupPolicy,
managedUsersEnabled: subscription.managedUsersEnabled,
managedBy: user.enrollment.managedBy,
isManagedGroupAdmin,
}
}
async function enrollInSubscription(userId, subscription) {
// check whether the user is already enrolled in a subscription
const user = await User.findOne(
{
_id: userId,
'enrollment.managedBy': { $exists: true },
},
{ _id: 1 }
).exec()
if (user != null) {
throw new OError('User is already enrolled in a subscription', {
userId,
subscriptionId: subscription._id,
})
}
// update the user to be enrolled in the subscription
const updatedUser = await User.findOneAndUpdate(
{ _id: userId, 'enrollment.managedBy': { $exists: false } },
{
enrollment: {
managedBy: subscription._id,
enrolledAt: new Date(),
},
},
{ new: true }
).exec()
// check whether the enrollment succeeded
if (
!updatedUser ||
!subscription.equals(updatedUser?.enrollment?.managedBy)
) {
throw new OError('Failed to enroll user in subscription', {
userId,
subscriptionId: subscription._id,
})
}
}
/**
* Send email to all group members, irregardless of the member status.
* @async
* @function
* @param {string} subscriptionId - The ID of the subscription to enable
* managed users for.
* @returns {Promise<void>} - A Promise that resolves when all the `sendEmail` function has been sent,
* irregardless of whether they're successful or failed.
*/
async function _sendEmailToGroupMembers(subscriptionId) {
const EMAIL_DELAY_IN_MS = 0
const subscription = await Subscription.findById(subscriptionId)
.populate('member_ids', 'email')
.populate('admin_id', ['first_name', 'last_name', 'email'])
.exec()
// On failure, log the error and carry on so that one email failing does not prevent other emails sending
for (const recipient of subscription.member_ids) {
try {
const opts = {
to: recipient.email,
admin: subscription.admin_id,
groupName: subscription.teamName,
acceptInviteUrl: `${settings.siteUrl}/subscription/${subscriptionId}/enrollment/`,
}
EmailHandler.sendDeferredEmail(
'surrenderAccountForManagedUsers',
opts,
EMAIL_DELAY_IN_MS
)
} catch (err) {
logger.error(
{ err, userId: recipient._id },
'could not send notification email to surrender account'
)
}
}
}
module.exports = {
promises: {
enableManagedUsers,
disableManagedUsers,
getEnrollmentForUser,
enrollInSubscription,
},
enableManagedUsers: callbackify(enableManagedUsers),
getEnrollmentForUser: callbackify(getEnrollmentForUser),
enrollInSubscription: callbackify(enrollInSubscription),
disableManagedUsers: callbackify(disableManagedUsers),
}

View file

@ -1,173 +0,0 @@
const {
registerCapability,
registerPolicy,
} = require('../Authorization/PermissionsManager')
const { getUsersSubscription, getGroupSubscriptionsMemberOf } =
require('./SubscriptionLocator').promises
const { subscriptionIsCanceledOrExpired } = require('./RecurlyClient')
// This file defines the capabilities and policies that are used to
// determine what managed users can and cannot do.
// Register the capability for a user to delete their own account.
registerCapability('delete-own-account', { default: true })
// Register the capability for a user to add a secondary email to their account.
registerCapability('add-secondary-email', { default: true })
// Register the capability for a user to add an affiliation to their account.
registerCapability('add-affiliation', { default: true })
// Register the capability for a user to endorse an email address.
registerCapability('endorse-email', { default: true })
// Register the capability for a user to sign in with Google to their account
registerCapability('link-google-sso', { default: true })
// Register the capability for a user to link other third party SSO to their account
registerCapability('link-other-third-party-sso', { default: true })
// Register the capability for a user to leave a managed group subscription.
registerCapability('leave-group-subscription', { default: true })
// Register the capability for a user to start a subscription.
registerCapability('start-subscription', { default: true })
// Register the capability for a user to join a subscription.
registerCapability('join-subscription', { default: true })
// Register the capability for a user to reactivate a subscription.
registerCapability('reactivate-subscription', { default: true })
// Register a policy to prevent a user deleting their own account.
registerPolicy('userCannotDeleteOwnAccount', {
'delete-own-account': false,
})
// Register a policy to prevent a user having secondary email addresses on their account.
registerPolicy(
'userCannotHaveSecondaryEmail',
{
'add-secondary-email': false,
'add-affiliation': false,
'endorse-email': false,
},
{
validator: async ({ user }) => {
// return true if the user does not have any secondary emails
return user.emails.length === 1
},
}
)
// Register a policy to prevent a user leaving the group subscription they are managed by.
registerPolicy('userCannotLeaveManagingGroupSubscription', {
'leave-group-subscription': false,
})
// Register a policy to prevent a user having third-party SSO linked to their account.
registerPolicy(
'userCannotHaveGoogleSSO',
{ 'link-google-sso': false },
{
// return true if the user does not have Google SSO linked
validator: async ({ user }) =>
!user.thirdPartyIdentifiers?.some(
identifier => identifier.providerId === 'google'
),
}
)
// Register a policy to prevent a user having third-party SSO linked to their account.
registerPolicy(
'userCannotHaveOtherThirdPartySSO',
{ 'link-other-third-party-sso': false },
{
// return true if the user does not have any other third party SSO linked
validator: async ({ user }) =>
!user.thirdPartyIdentifiers?.some(
identifier => identifier.providerId !== 'google'
),
}
)
// Register a policy to prevent a user having an active subscription or
// being a member of another group subscription.
registerPolicy(
'userCannotHaveSubscription',
{
'start-subscription': false,
'join-subscription': false,
'reactivate-subscription': false,
},
{
validator: async ({ user, subscription }) => {
const usersSubscription = await getUsersSubscription(user)
// The user can be enrolled if:
// 1. they do not have a subscription and are not a member of another subscription (apart from the managed group subscription)
// 2. they have a subscription and it is canceled or expired
// 3. they have a subscription and it is the subscription they are trying to join as a managed user
// The last case is to allow the admin to join their own subscription as a managed user
const userHasSubscription =
Boolean(usersSubscription) &&
!subscriptionIsCanceledOrExpired(usersSubscription)
const userIsThisGroupAdmin =
Boolean(usersSubscription) &&
usersSubscription._id.toString() === subscription._id.toString()
const userMemberOfSubscriptions = await getGroupSubscriptionsMemberOf(
user
)
const isMemberOfOtherSubscriptions = userMemberOfSubscriptions.some(
sub => {
// ignore the subscription of the managed group itself
if (sub._id.toString() === subscription._id.toString()) {
return false
}
// ignore the user's own subscription
if (
usersSubscription &&
sub._id.toString() === usersSubscription._id.toString()
) {
return false
}
return true
}
)
return (
(!userHasSubscription || userIsThisGroupAdmin) &&
!isMemberOfOtherSubscriptions
)
},
}
)
/**
* Returns the default group policy for managed users.
* Managed users are users who are part of a group subscription, and are
* managed by the group policy. Managed users have limited functionality.
* This method returns an object with boolean values for each policy that
* indicates whether the policy is enforced or not.
*
* @returns {Object} An object with boolean values for each policy that indicates whether it is enforced or not.
* @function
*/
function getDefaultPolicy() {
return {
userCannotDeleteOwnAccount: true,
userCannotHaveSecondaryEmail: true,
userCannotHaveSubscription: true,
userCannotLeaveManagingGroupSubscription: true,
userCannotHaveGoogleSSO: false, // we want to allow google SSO by default
userCannotHaveOtherThirdPartySSO: true,
}
}
module.exports = {
getDefaultPolicy,
}

View file

@ -2,7 +2,6 @@ const { promisify } = require('util')
const { Subscription } = require('../../models/Subscription')
const { DeletedSubscription } = require('../../models/DeletedSubscription')
const logger = require('@overleaf/logger')
const { SSOConfig } = require('../../models/SSOConfig')
require('./GroupPlansData') // make sure dynamic group plans are loaded
const SubscriptionLocator = {
@ -133,11 +132,6 @@ const SubscriptionLocator = {
},
}
async function hasSSOEnabled(subscription) {
const ssoConfig = await SSOConfig.findById(subscription.ssoConfig).exec()
return !!ssoConfig?.enabled
}
SubscriptionLocator.promises = {
getUsersSubscription: promisify(SubscriptionLocator.getUsersSubscription),
getUserIndividualSubscription: promisify(
@ -170,6 +164,5 @@ SubscriptionLocator.promises = {
hasRecurlyGroupSubscription: promisify(
SubscriptionLocator.hasRecurlyGroupSubscription
),
hasSSOEnabled,
}
module.exports = SubscriptionLocator

View file

@ -84,9 +84,9 @@ async function viewInvite(req, res, next) {
personalSubscription.recurlySubscription_id &&
personalSubscription.recurlySubscription_id !== ''
const groupSSOActive = await SubscriptionLocator.promises.hasSSOEnabled(
subscription
)
const groupSSOActive = (
await Modules.promises.hooks.fire('hasGroupSSOEnabled', subscription)
)?.[0]
if (subscription?.groupPolicy) {
if (!subscription.populated('groupPolicy')) {
@ -194,9 +194,9 @@ async function acceptInvite(req, res, next) {
token,
userId
)
const groupSSOActive = await SubscriptionLocator.promises.hasSSOEnabled(
subscription
)
const groupSSOActive = (
await Modules.promises.hooks.fire('hasGroupSSOEnabled', subscription)
)?.[0]
res.json({ groupSSOActive })
}

View file

@ -2,6 +2,7 @@ const logger = require('@overleaf/logger')
const crypto = require('crypto')
const settings = require('@overleaf/settings')
const Modules = require('../../infrastructure/Modules')
const { ObjectId } = require('mongodb')
const { Subscription } = require('../../models/Subscription')
@ -11,7 +12,6 @@ const UserGetter = require('../User/UserGetter')
const SubscriptionLocator = require('./SubscriptionLocator')
const SubscriptionUpdater = require('./SubscriptionUpdater')
const LimitationsManager = require('./LimitationsManager')
const ManagedUsersHandler = require('./ManagedUsersHandler')
const EmailHandler = require('../Email/EmailHandler')
const EmailHelper = require('../Helpers/EmailHelper')
@ -22,7 +22,6 @@ const {
callbackifyMultiResult,
} = require('@overleaf/promise-utils')
const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
const Modules = require('../../infrastructure/Modules')
async function getInvite(token) {
const subscription = await Subscription.findOne({
@ -74,7 +73,8 @@ async function acceptInvite(token, userId) {
await SubscriptionUpdater.promises.addUserToGroup(subscription._id, userId)
if (subscription.managedUsersEnabled) {
await ManagedUsersHandler.promises.enrollInSubscription(
await Modules.promises.hooks.fire(
'enrollInManagedSubscription',
userId,
subscription
)

View file

@ -1,99 +0,0 @@
import GroupSettings from '../../../../modules/managed-users/frontend/js/components/group-settings'
import { useMeta } from '../../hooks/use-meta'
import useFetchMock from '../../hooks/use-fetch-mock'
export const GroupSettingsWithManagedUsersDisabledAndNoSSOFeature = () => {
useMeta({
'ol-managedUsersEnabled': false,
'ol-hasGroupSSOFeature': false,
})
return <GroupSettings />
}
export const GroupSettingsWithManagedUsersDisabledAndSSOFeature = () => {
useFetchMock(fetchMock =>
fetchMock.get('express:/manage/groups/:id/settings/sso', {})
)
useMeta({
'ol-managedUsersEnabled': false,
'ol-hasGroupSSOFeature': true,
})
return <GroupSettings />
}
export const GroupSettingsWithManagedUsersEnabledAndNoSSOFeature = () => {
useMeta({
'ol-managedUsersEnabled': true,
'ol-hasGroupSSOFeature': false,
})
return <GroupSettings />
}
export const GroupSettingsWithManagedUsersEnabledAndSSOFeatureNotConfigured =
() => {
useMeta({
'ol-managedUsersEnabled': true,
'ol-hasGroupSSOFeature': true,
})
useFetchMock(fetchMock => {
fetchMock.get(
'express:/manage/groups/:id/settings/sso',
{},
{
delay: 500,
}
)
})
return <GroupSettings />
}
export const GroupSettingsWithManagedUsersEnabledAndSSOFeatureConfigured =
() => {
const config = {
entryPoint: 'http://idp.example.com/entry_point',
certificate:
'X1JQa2tWQmYzYlN1aUZORVhzZGpURVp3c0U4T3J3bWtjYVZsQ2h4MkRyRUpOVGtxV2hXcG9KbG1WZ2hYclB1YUVNeFVjM0pFZW5Zd1dQRzB5bldxWm5xYm5IdEJ5d1VGQlQ2RWJ1bHdQeJ0VmpoMkFUeHlIaE5KUVBqYm1iUlB1ckZjQnZzRzlZWW5RZVpYU3pKd3V3Z1l3cE5ZeE9XZkx5ZlVJZGVKQk5JkFUeHlIaE5KUV',
signatureAlgorithm: 'sha256',
userIdAttribute: 'email',
enabled: true,
}
useFetchMock(fetchMock => {
fetchMock.get('express:/manage/groups/:id/settings/sso', config, {
delay: 500,
})
})
useMeta({
'ol-managedUsersEnabled': true,
'ol-hasGroupSSOFeature': true,
})
return <GroupSettings />
}
export const GroupSettingsWithManagedUsersDisabledAndSSOFeatureConfigured =
() => {
const config = {
entryPoint: 'http://idp.example.com/entry_point',
certificate:
'X1JQa2tWQmYzYlN1aUZORVhzZGpURVp3c0U4T3J3bWtjYVZsQ2h4MkRyRUpOVGtxV2hXcG9KbG1WZ2hYclB1YUVNeFVjM0pFZW5Zd1dQRzB5bldxWm5xYm5IdEJ5d1VGQlQ2RWJ1bHdQeJ0VmpoMkFUeHlIaE5KUVBqYm1iUlB1ckZjQnZzRzlZWW5RZVpYU3pKd3V3Z1l3cE5ZeE9XZkx5ZlVJZGVKQk5JkFUeHlIaE5KUV',
signatureAlgorithm: 'sha256',
userIdAttribute: 'email',
enabled: false,
}
useFetchMock(fetchMock => {
fetchMock.get('express:/manage/groups/:id/settings/sso', config, {
delay: 500,
})
})
useMeta({
'ol-managedUsersEnabled': true,
'ol-hasGroupSSOFeature': true,
})
return <GroupSettings />
}
export default {
title: 'Subscription / Managed Users',
component: GroupSettings,
}

View file

@ -1,37 +0,0 @@
import SSODisableModal, {
type SSODisableModalProps,
} from '../../../../modules/managed-users/frontend/js/components/modals/sso-disable-modal'
import useFetchMock from '../../hooks/use-fetch-mock'
import { useMeta } from '../../hooks/use-meta'
export const DisableSSOModalDefault = (args: SSODisableModalProps) => {
useMeta({ 'ol-groupId': '123' })
useFetchMock(fetchMock => {
fetchMock.post('express:/manage/groups/:id/settings/disableSSO', 200, {
delay: 500,
})
})
return <SSODisableModal {...args} />
}
export const DisableSSOModalError = (args: SSODisableModalProps) => {
useMeta({ 'ol-groupId': '123' })
useFetchMock(fetchMock => {
fetchMock.post('express:/manage/groups/:id/settings/enableSSO', 500, {
delay: 500,
})
})
return <SSODisableModal {...args} />
}
export default {
title: 'Subscription / SSO / Disable Modal',
component: SSODisableModal,
args: {
show: true,
},
argTypes: {
handleHide: { action: 'close modal' },
onDisableSSO: { action: 'callback' },
},
}

View file

@ -1,37 +0,0 @@
import SSOEnableModal, {
type SSOEnableModalProps,
} from '../../../../modules/managed-users/frontend/js/components/modals/sso-enable-modal'
import useFetchMock from '../../hooks/use-fetch-mock'
import { useMeta } from '../../hooks/use-meta'
export const EnableSSOModalDefault = (args: SSOEnableModalProps) => {
useMeta({ 'ol-groupId': '123' })
useFetchMock(fetchMock => {
fetchMock.post('express:/manage/groups/:id/settings/enableSSO', 200, {
delay: 500,
})
})
return <SSOEnableModal {...args} />
}
export const EnableSSOModalError = (args: SSOEnableModalProps) => {
useMeta({ 'ol-groupId': '123' })
useFetchMock(fetchMock => {
fetchMock.post('express:/manage/groups/:id/settings/enableSSO', 500, {
delay: 500,
})
})
return <SSOEnableModal {...args} />
}
export default {
title: 'Subscription / SSO / Enable Modal',
component: SSOEnableModal,
args: {
show: true,
},
argTypes: {
handleHide: { action: 'close modal' },
onEnableSSO: { action: 'callback' },
},
}

View file

@ -1,27 +0,0 @@
import { useMeta } from '../../hooks/use-meta'
import SSOLinkConfirm from '../../../../modules/managed-users/frontend/js/components/sso-link-confirm'
export const LinkConfirmInterstitial = () => {
return <SSOLinkConfirm />
}
export const LinkConfirmInterstitialWithError = () => {
useMeta({ 'ol-error': 'SAMLInvalidSignatureError' })
return <SSOLinkConfirm />
}
export default {
title: 'Subscription / SSO / Link',
component: SSOLinkConfirm,
decorators: [
(Story: any) => {
useMeta({ 'ol-groupId': '123' })
useMeta({ 'ol-email': 'user@example.com' })
return (
<div className="container">
<Story />
</div>
)
},
],
}

View file

@ -111,7 +111,7 @@
// module styles
// TODO: find a way for modules to add styles dynamically
@import 'modules/symbol-palette.less';
@import 'modules/managed-users.less';
@import 'modules/group-settings.less';
@import 'modules/git-bridge-modal.less';
@import 'modules/admin-panel.less';
@import 'modules/overleaf-integration.less';

View file

@ -144,5 +144,5 @@
@import 'modules/symbol-palette.less';
@import 'modules/admin-panel.less';
@import 'modules/git-bridge-modal.less';
@import 'modules/managed-users.less';
@import 'modules/group-settings.less';
@import 'modules/overleaf-integration.less';

View file

@ -2,13 +2,13 @@ const { db, ObjectId } = require('../../../../app/src/infrastructure/mongodb')
const { expect } = require('chai')
const { promisify } = require('util')
const SubscriptionUpdater = require('../../../../app/src/Features/Subscription/SubscriptionUpdater')
const ManagedUsersHandler = require('../../../../app/src/Features/Subscription/ManagedUsersHandler')
const PermissionsManager = require('../../../../app/src/Features/Authorization/PermissionsManager')
const SSOConfigManager = require('../../../../modules/managed-users/app/src/SSOConfigManager')
const SSOConfigManager = require('../../../../modules/group-settings/app/src/sso/SSOConfigManager')
const SubscriptionModel =
require('../../../../app/src/models/Subscription').Subscription
const DeletedSubscriptionModel =
require('../../../../app/src/models/DeletedSubscription').DeletedSubscription
const Modules = require('../../../../app/src/infrastructure/Modules')
class Subscription {
constructor(options = {}) {
@ -78,11 +78,17 @@ class Subscription {
}
enableManagedUsers(callback) {
ManagedUsersHandler.enableManagedUsers(this._id, callback)
Modules.hooks.fire('enableManagedUsers', this._id, callback)
}
getEnrollmentForUser(user, callback) {
ManagedUsersHandler.getEnrollmentForUser(user, callback)
Modules.hooks.fire(
'getManagedUsersEnrollmentForUser',
user,
(error, [enrollment]) => {
callback(error, enrollment)
}
)
}
getCapabilities(groupPolicy) {
@ -98,7 +104,12 @@ class Subscription {
if (error) {
return callback(error)
}
ManagedUsersHandler.enrollInSubscription(user._id, subscription, callback)
Modules.hooks.fire(
'enrollInManagedSubscription',
user._id,
subscription,
callback
)
})
}

View file

@ -1,4 +1,4 @@
import GroupSettingsSSORoot from '../../../../../../modules/managed-users/frontend/js/components/sso/group-settings-sso-root'
import GroupSettingsSSORoot from '../../../../../../modules/group-settings/frontend/js/components/sso/group-settings-sso-root'
function GroupSettingsSSOComponent() {
return (

View file

@ -76,12 +76,6 @@ describe('TeamInvitesHandler', function () {
},
}
this.ManagedUsersHandler = {
promises: {
enrollInSubscription: sinon.stub().resolves(),
},
}
this.newToken = 'bbbbbbbbb'
this.crypto = {
@ -128,7 +122,6 @@ describe('TeamInvitesHandler', function () {
'./SubscriptionUpdater': this.SubscriptionUpdater,
'./LimitationsManager': this.LimitationsManager,
'../Email/EmailHandler': this.EmailHandler,
'./ManagedUsersHandler': this.ManagedUsersHandler,
'../Notifications/NotificationsBuilder': this.NotificationsBuilder,
'../../infrastructure/Modules': (this.Modules = {
promises: { hooks: { fire: sinon.stub().resolves() } },
@ -393,7 +386,8 @@ describe('TeamInvitesHandler', function () {
this.TeamInvitesHandler.acceptInvite('dddddddd', this.user.id, () => {
sinon.assert.calledWith(
this.ManagedUsersHandler.promises.enrollInSubscription,
this.Modules.promises.hooks.fire,
'enrollInManagedSubscription',
this.user.id,
this.subscription
)