mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-25 02:00:10 +02:00
Merge pull request #13662 from overleaf/bg-managed-users-fix-subscription-validator
fix subscription validator for managed users GitOrigin-RevId: 765c1c11850090f57327fc8b4255d41a16514472
This commit is contained in:
@@ -24,10 +24,10 @@
|
||||
* capability will be removed. A policy can remove more than one capability, and
|
||||
* more than one policy could apply to a user.
|
||||
*
|
||||
* Validator: a function that takes a user and returns a boolean indicating
|
||||
* whether the user satisfies the policy or not. For example, a validator for
|
||||
* the `userCannotHaveSecondaryEmail` policy would check whether the user has
|
||||
* more than one email address.
|
||||
* Validator: a function that takes an object with user and subscription properties
|
||||
* and returns a boolean indicating whether the user satisfies the policy or not.
|
||||
* For example, a validator for the `userCannotHaveSecondaryEmail` policy would
|
||||
* check whether the user has more than one email address.
|
||||
*
|
||||
* Group Policies: a collection of policies with a setting indicating whether
|
||||
* they are enforced or not. Used to place restrictions on managed users in a
|
||||
@@ -265,8 +265,8 @@ function hasPermission(groupPolicy, capability) {
|
||||
|
||||
/**
|
||||
* Asynchronously checks which policies a user complies with using the
|
||||
* applicable validators. Each validator is an async function that takes a user
|
||||
* and returns a boolean.
|
||||
* applicable validators. Each validator is an async function that takes a object
|
||||
* with user and subscription properties and returns a boolean.
|
||||
*
|
||||
* @param {Object} user - The user object to check.
|
||||
* @param {Object} groupPolicy - The group policy object to check.
|
||||
@@ -275,7 +275,7 @@ function hasPermission(groupPolicy, capability) {
|
||||
* enforced policy names, and the values are booleans indicating whether the
|
||||
* user complies with the policy.
|
||||
*/
|
||||
async function getUserValidationStatus(user, groupPolicy) {
|
||||
async function getUserValidationStatus(user, groupPolicy, subscription) {
|
||||
// find all the enforced policies for the user
|
||||
const enforcedPolicyNames = getEnforcedPolicyNames(groupPolicy)
|
||||
// for each enforced policy, we have a list of capabilities with expected values
|
||||
@@ -285,7 +285,10 @@ async function getUserValidationStatus(user, groupPolicy) {
|
||||
for (const enforcedPolicyName of enforcedPolicyNames) {
|
||||
const validator = getValidatorFromPolicy(enforcedPolicyName)
|
||||
if (validator) {
|
||||
userValidationStatus.set(enforcedPolicyName, await validator(user))
|
||||
userValidationStatus.set(
|
||||
enforcedPolicyName,
|
||||
await validator({ user, subscription })
|
||||
)
|
||||
}
|
||||
}
|
||||
return userValidationStatus
|
||||
|
||||
@@ -2,7 +2,8 @@ const {
|
||||
registerCapability,
|
||||
registerPolicy,
|
||||
} = require('../Authorization/PermissionsManager')
|
||||
const SubscriptionLocator = require('./SubscriptionLocator')
|
||||
const { getUsersSubscription, getGroupSubscriptionsMemberOf } =
|
||||
require('./SubscriptionLocator').promises
|
||||
|
||||
// This file defines the capabilities and policies that are used to
|
||||
// determine what managed users can and cannot do.
|
||||
@@ -48,7 +49,7 @@ registerPolicy(
|
||||
'endorse-email': false,
|
||||
},
|
||||
{
|
||||
validator: async user => {
|
||||
validator: async ({ user }) => {
|
||||
// return true if the user does not have any secondary emails
|
||||
return user.emails.length === 1
|
||||
},
|
||||
@@ -66,7 +67,7 @@ registerPolicy(
|
||||
{ 'link-google-sso': false },
|
||||
{
|
||||
// return true if the user does not have Google SSO linked
|
||||
validator: async user =>
|
||||
validator: async ({ user }) =>
|
||||
!user.thirdPartyIdentifiers?.some(
|
||||
identifier => identifier.providerId === 'google'
|
||||
),
|
||||
@@ -79,22 +80,31 @@ registerPolicy(
|
||||
{ 'link-other-third-party-sso': false },
|
||||
{
|
||||
// return true if the user does not have any other third party SSO linked
|
||||
validator: async user =>
|
||||
validator: async ({ user }) =>
|
||||
!user.thirdPartyIdentifiers?.some(
|
||||
identifier => identifier.providerId !== 'google'
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
// Register a policy to prevent a user having an active personal subscription.
|
||||
// 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 },
|
||||
{
|
||||
validator: async user => {
|
||||
return !(await SubscriptionLocator.promises.getUserIndividualSubscription(
|
||||
validator: async ({ user, subscription }) => {
|
||||
const usersSubscription = await getUsersSubscription(user)
|
||||
const userHasSubscription = Boolean(usersSubscription)
|
||||
const userMemberOfSubscriptions = await getGroupSubscriptionsMemberOf(
|
||||
user
|
||||
))
|
||||
)
|
||||
// filter out the subscription of the managed group itself
|
||||
// the user will always be a member of this subscription
|
||||
const isMemberOfOtherSubscriptions = userMemberOfSubscriptions.some(
|
||||
sub => sub._id.toString() !== subscription._id.toString()
|
||||
)
|
||||
return !userHasSubscription && !isMemberOfOtherSubscriptions
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -74,8 +74,13 @@ class Subscription {
|
||||
return PermissionsManager.getUserCapabilities(groupPolicy)
|
||||
}
|
||||
|
||||
getUserValidationStatus(user, groupPolicy, callback) {
|
||||
PermissionsManager.getUserValidationStatus(user, groupPolicy, callback)
|
||||
getUserValidationStatus(user, groupPolicy, subscription, callback) {
|
||||
PermissionsManager.getUserValidationStatus(
|
||||
user,
|
||||
groupPolicy,
|
||||
subscription,
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
enrollManagedUser(user, callback) {
|
||||
|
||||
@@ -277,8 +277,8 @@ describe('PermissionsManager', function () {
|
||||
'policy',
|
||||
{},
|
||||
{
|
||||
validator: async user => {
|
||||
return user.prop === 'allowed'
|
||||
validator: async ({ user, subscription }) => {
|
||||
return user.prop === 'allowed' && subscription.prop === 'managed'
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -286,10 +286,12 @@ describe('PermissionsManager', function () {
|
||||
policy: true,
|
||||
}
|
||||
const user = { prop: 'allowed' }
|
||||
const subscription = { prop: 'managed' }
|
||||
const result =
|
||||
await this.PermissionsManager.promises.getUserValidationStatus(
|
||||
user,
|
||||
groupPolicy
|
||||
groupPolicy,
|
||||
subscription
|
||||
)
|
||||
expect(result).to.deep.equal(new Map([['policy', true]]))
|
||||
})
|
||||
@@ -299,8 +301,8 @@ describe('PermissionsManager', function () {
|
||||
'policy',
|
||||
{},
|
||||
{
|
||||
validator: async user => {
|
||||
return user.prop === 'allowed'
|
||||
validator: async ({ user, subscription }) => {
|
||||
return user.prop === 'allowed' && subscription.prop === 'managed'
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -308,10 +310,12 @@ describe('PermissionsManager', function () {
|
||||
policy: true,
|
||||
}
|
||||
const user = { prop: 'not allowed' }
|
||||
const subscription = { prop: 'managed' }
|
||||
const result =
|
||||
await this.PermissionsManager.promises.getUserValidationStatus(
|
||||
user,
|
||||
groupPolicy
|
||||
groupPolicy,
|
||||
subscription
|
||||
)
|
||||
expect(result).to.deep.equal(new Map([['policy', false]]))
|
||||
})
|
||||
@@ -320,8 +324,8 @@ describe('PermissionsManager', function () {
|
||||
'policy1',
|
||||
{},
|
||||
{
|
||||
validator: async user => {
|
||||
return user.prop === 'allowed'
|
||||
validator: async ({ user, subscription }) => {
|
||||
return user.prop === 'allowed' && subscription.prop === 'managed'
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -329,8 +333,8 @@ describe('PermissionsManager', function () {
|
||||
'policy2',
|
||||
{},
|
||||
{
|
||||
validator: async user => {
|
||||
return user.prop === 'other'
|
||||
validator: async ({ user, subscription }) => {
|
||||
return user.prop === 'other' && subscription.prop === 'managed'
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -338,8 +342,8 @@ describe('PermissionsManager', function () {
|
||||
'policy3',
|
||||
{},
|
||||
{
|
||||
validator: async user => {
|
||||
return user.prop === 'allowed'
|
||||
validator: async ({ user, subscription }) => {
|
||||
return user.prop === 'allowed' && subscription.prop === 'managed'
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -350,10 +354,12 @@ describe('PermissionsManager', function () {
|
||||
policy3: false, // this policy is not enforced
|
||||
}
|
||||
const user = { prop: 'allowed' }
|
||||
const subscription = { prop: 'managed' }
|
||||
const result =
|
||||
await this.PermissionsManager.promises.getUserValidationStatus(
|
||||
user,
|
||||
groupPolicy
|
||||
groupPolicy,
|
||||
subscription
|
||||
)
|
||||
expect(result).to.deep.equal(
|
||||
new Map([
|
||||
|
||||
Reference in New Issue
Block a user