chore: License v3 - create default restrictions if there is no license (#30808)
parent
d20c79aa31
commit
2f40971a65
@ -0,0 +1,49 @@ |
||||
import { LicenseImp } from '../src'; |
||||
|
||||
describe('Community Restrictions', () => { |
||||
describe('Apps from marketplace', () => { |
||||
it('should respect the default if there is no license applied', async () => { |
||||
const license = new LicenseImp(); |
||||
|
||||
license.setLicenseLimitCounter('marketplaceApps', () => 1); |
||||
|
||||
await expect(await license.shouldPreventAction('marketplaceApps')).toBe(false); |
||||
|
||||
license.setLicenseLimitCounter('marketplaceApps', () => 10); |
||||
|
||||
await expect(await license.shouldPreventAction('marketplaceApps')).toBe(true); |
||||
}); |
||||
}); |
||||
|
||||
describe('Private Apps', () => { |
||||
it('should respect the default if there is no license applied', async () => { |
||||
const license = new LicenseImp(); |
||||
|
||||
license.setLicenseLimitCounter('privateApps', () => 1); |
||||
|
||||
await expect(await license.shouldPreventAction('privateApps')).toBe(false); |
||||
|
||||
license.setLicenseLimitCounter('privateApps', () => 10); |
||||
|
||||
await expect(await license.shouldPreventAction('privateApps')).toBe(true); |
||||
}); |
||||
}); |
||||
|
||||
describe('Active Users', () => { |
||||
it('should respect the default if there is no license applied', async () => { |
||||
const license = new LicenseImp(); |
||||
|
||||
license.setLicenseLimitCounter('activeUsers', () => 1); |
||||
|
||||
await expect(await license.shouldPreventAction('activeUsers')).toBe(false); |
||||
|
||||
license.setLicenseLimitCounter('activeUsers', () => 10); |
||||
|
||||
await expect(await license.shouldPreventAction('activeUsers')).toBe(false); |
||||
|
||||
license.setLicenseLimitCounter('activeUsers', () => 100000); |
||||
|
||||
await expect(await license.shouldPreventAction('activeUsers')).toBe(false); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,28 @@ |
||||
import type { BehaviorWithContext } from '../definition/LicenseBehavior'; |
||||
import type { LicenseLimit } from '../definition/LicenseLimit'; |
||||
import type { LicenseValidationOptions } from '../definition/LicenseValidationOptions'; |
||||
import type { LicenseManager } from '../license'; |
||||
import { validateLimits } from './validateLimits'; |
||||
|
||||
export const defaultLimits: { |
||||
privateApps: LicenseLimit[]; |
||||
marketplaceApps: LicenseLimit[]; |
||||
// monthlyActiveContacts?: LicenseLimit[];
|
||||
} = { |
||||
privateApps: [ |
||||
{ |
||||
behavior: 'prevent_action', |
||||
max: 3, |
||||
}, |
||||
], |
||||
marketplaceApps: [ |
||||
{ |
||||
behavior: 'prevent_action', |
||||
max: 5, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
export async function validateDefaultLimits(this: LicenseManager, options: LicenseValidationOptions): Promise<BehaviorWithContext[]> { |
||||
return validateLimits.call(this, defaultLimits, options); |
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
import type { LicenseBehavior } from '../definition/LicenseBehavior'; |
||||
|
||||
/** |
||||
* Validates if the current value is over the limit |
||||
* @param max The maximum value allowed |
||||
* @param currentValue The current value |
||||
* @param behavior The behavior to be applied if the limit is reached |
||||
* @param extraCount The extra count to be added to the current value |
||||
* @returns |
||||
* - true if the limit is reached |
||||
* - false if the limit is not reached |
||||
*/ |
||||
export function validateLimit(max: number, currentValue: number, behavior: LicenseBehavior, extraCount = 0) { |
||||
switch (behavior) { |
||||
case 'invalidate_license': |
||||
case 'prevent_installation': |
||||
case 'disable_modules': |
||||
case 'start_fair_policy': |
||||
default: |
||||
return currentValue > max; |
||||
case 'prevent_action': |
||||
/** |
||||
* if we are validating the current count the limit should be equal or over the max, if we are validating the future count the limit should be over the max |
||||
*/ |
||||
|
||||
return extraCount ? currentValue > max : currentValue >= max; |
||||
} |
||||
} |
||||
@ -0,0 +1,44 @@ |
||||
import type { ILicenseV3, LicenseLimitKind } from '../definition/ILicenseV3'; |
||||
import type { BehaviorWithContext } from '../definition/LicenseBehavior'; |
||||
import type { LicenseValidationOptions } from '../definition/LicenseValidationOptions'; |
||||
import { isLimitAllowed, isBehaviorAllowed } from '../isItemAllowed'; |
||||
import type { LicenseManager } from '../license'; |
||||
import { logger } from '../logger'; |
||||
import { getCurrentValueForLicenseLimit } from './getCurrentValueForLicenseLimit'; |
||||
import { getResultingBehavior } from './getResultingBehavior'; |
||||
import { validateLimit } from './validateLimit'; |
||||
|
||||
export async function validateLimits( |
||||
this: LicenseManager, |
||||
limits: ILicenseV3['limits'], |
||||
options: LicenseValidationOptions, |
||||
): Promise<BehaviorWithContext[]> { |
||||
const limitKeys = (Object.keys(limits) as LicenseLimitKind[]).filter((limit) => isLimitAllowed(limit, options)); |
||||
return ( |
||||
await Promise.all( |
||||
limitKeys.map(async (limitKey) => { |
||||
// Filter the limit list before running any query in the database so we don't end up loading some value we won't use.
|
||||
const limitList = limits[limitKey]?.filter(({ behavior, max }) => max >= 0 && isBehaviorAllowed(behavior, options)); |
||||
if (!limitList?.length) { |
||||
return []; |
||||
} |
||||
|
||||
const extraCount = options.context?.[limitKey]?.extraCount ?? 0; |
||||
const currentValue = (await getCurrentValueForLicenseLimit.call(this, limitKey, options.context?.[limitKey])) + extraCount; |
||||
|
||||
return limitList |
||||
.filter(({ max, behavior }) => validateLimit(max, currentValue, behavior, extraCount)) |
||||
.map((limit) => { |
||||
if (!options.suppressLog) { |
||||
logger.error({ |
||||
msg: 'Limit validation failed', |
||||
kind: limitKey, |
||||
limit, |
||||
}); |
||||
} |
||||
return getResultingBehavior(limit, { reason: 'limit', limit: limitKey }); |
||||
}); |
||||
}), |
||||
) |
||||
).flat(); |
||||
} |
||||
Loading…
Reference in new issue