Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
207 lines
7.6 KiB
TypeScript
207 lines
7.6 KiB
TypeScript
/**
|
|
* @jest-environment node
|
|
*/
|
|
|
|
import { LicenseImp } from '../src';
|
|
import { MockedLicenseBuilder, getReadyLicenseManager } from './MockedLicenseBuilder';
|
|
import { DuplicatedLicenseError } from '../src/errors/DuplicatedLicenseError';
|
|
import { InvalidLicenseError } from '../src/errors/InvalidLicenseError';
|
|
import { NotReadyForValidation } from '../src/errors/NotReadyForValidation';
|
|
|
|
// Same license used on ci tasks so no I didnt leak it
|
|
const VALID_LICENSE =
|
|
process.env.ENTERPRISE_LICENSE ||
|
|
'MK+bpK5NveUuNlWGaQXGoy+8b74Luet82M3ZGcBB8b5P9Y+m67NEtpW64dc1d5lEWi6d0nFjCjtCMneVD7bKxodz/Cml8URKEo5P7cQb/9wmeT0MzAhYNaRFZlIGkZ3ITF59pDV2u4HZuosEDJikVRwnaJ5ZoU/pOsHSPUPhTyGNIqLeKynODtUpfwDdIKEmHxpf2yVkKjgRiIJmbWjM6A4k+MNNYXWVXHzye7GggqWVg/ZcT7nKU1CCadpLhTJiIrgrrPzil1G5DQ4xnLs3Q2tu2dILSDiW5OYw/ywu2yCMicTjMq4MLL5SXDQJj6WoJzZ54HosbvsDzOXvsdC9gI1CjhPL2uRuvC8XLrzn3vL2UgXnifzD1VrLTtdZ+aSADveqtlzYlRWtqoUFBbNw8o+YVHdhbZGR0beMoAyRbHi5EMpxpad3L+NyztUIT/Uh/IjQ/C2SQZ6jB0GKPBOPxFLN56FNhTGrffLFR++TVoBu0Iquc7kajWkNit3bVbZvbx+oFcVW2PcjQ/+i2jpJjbgtUFUKrTKxGMAXTWoDzIQQ35zNzGAy268IM4Ymp5JmsVEnBOEUkbF9yx6fzkO6xZhpsHf0muklnW0kA+Tlore/TUrBWh1/RwWlQeZlxM5NyWoRM5onQmr/k/4BmObtL1Hpmbk8oMG29z89xtE9y/4=';
|
|
|
|
describe('License set license procedures', () => {
|
|
describe('Invalid formats', () => {
|
|
it('should have no license by default', async () => {
|
|
const license = new LicenseImp();
|
|
|
|
expect(license.hasValidLicense()).toBe(false);
|
|
expect(license.getLicense()).toBeUndefined();
|
|
});
|
|
|
|
it('should throw an error if the license applied is empty', async () => {
|
|
const license = new LicenseImp();
|
|
await expect(license.setLicense('')).rejects.toThrow(InvalidLicenseError);
|
|
});
|
|
|
|
it('should throw an error if the license applied is invalid', async () => {
|
|
const license = new LicenseImp();
|
|
await expect(license.setLicense('invalid')).rejects.toThrow(InvalidLicenseError);
|
|
});
|
|
});
|
|
|
|
describe('Invalid periods', () => {
|
|
it('should throw an error if the license is expired', async () => {
|
|
const license = await getReadyLicenseManager();
|
|
|
|
const mocked = new MockedLicenseBuilder();
|
|
const token = await mocked.withExpiredDate().sign();
|
|
|
|
await license.setLicense(token);
|
|
expect(license.hasValidLicense()).toBe(false);
|
|
});
|
|
|
|
describe('license that is not not started yet is applied', () => {
|
|
it('should throw an error if the license is not started yet', async () => {
|
|
const license = await getReadyLicenseManager();
|
|
|
|
const mocked = new MockedLicenseBuilder();
|
|
const token = await mocked.withNotStartedDate().sign();
|
|
|
|
await license.setLicense(token);
|
|
expect(license.hasValidLicense()).toBe(false);
|
|
});
|
|
|
|
it('should be allowed to set the same license again if the license is not started yet', async () => {
|
|
const license = await getReadyLicenseManager();
|
|
|
|
const mocked = new MockedLicenseBuilder();
|
|
const as = mocked.resetValidPeriods().withNotStartedDate();
|
|
const token = await as.sign();
|
|
|
|
await license.setLicense(token);
|
|
|
|
expect(license.hasValidLicense()).toBe(false);
|
|
|
|
// 5 minutes in the future
|
|
|
|
const mockedData = new Date();
|
|
|
|
mockedData.setMinutes(mockedData.getMinutes() + 5);
|
|
|
|
jest.useFakeTimers();
|
|
jest.setSystemTime(mockedData);
|
|
|
|
await license.setLicense(token);
|
|
|
|
jest.useRealTimers();
|
|
|
|
expect(license.hasValidLicense()).toBe(true);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should throw an error if the license is duplicated', async () => {
|
|
const license = await getReadyLicenseManager();
|
|
|
|
await expect(license.setLicense(VALID_LICENSE)).resolves.toBe(true);
|
|
await expect(license.setLicense(VALID_LICENSE)).rejects.toThrow(DuplicatedLicenseError);
|
|
});
|
|
|
|
it('should keep a valid license if a new invalid formatted license is applied', async () => {
|
|
const license = await getReadyLicenseManager();
|
|
|
|
await expect(license.setLicense(VALID_LICENSE)).resolves.toBe(true);
|
|
expect(license.hasValidLicense()).toBe(true);
|
|
|
|
await expect(license.setLicense('invalid')).rejects.toThrow(InvalidLicenseError);
|
|
expect(license.hasValidLicense()).toBe(true);
|
|
});
|
|
|
|
describe('Pending cases', () => {
|
|
it('should return an error if the license is not ready for validation yet - missing workspace url', async () => {
|
|
const license = new LicenseImp();
|
|
await expect(license.setLicense(VALID_LICENSE)).rejects.toThrow(NotReadyForValidation);
|
|
});
|
|
|
|
it('should return an error if the license is not ready for validation yet - missing counters', async () => {
|
|
const license = new LicenseImp();
|
|
await license.setWorkspaceUrl('http://localhost:3000');
|
|
|
|
expect(license.getWorkspaceUrl()).toBe('localhost:3000');
|
|
|
|
await expect(license.setLicense(VALID_LICENSE)).rejects.toThrow(NotReadyForValidation);
|
|
|
|
expect(license.hasValidLicense()).toBe(false);
|
|
});
|
|
|
|
it('should return a valid license if the license is ready for validation', async () => {
|
|
const license = await getReadyLicenseManager();
|
|
|
|
await expect(license.setLicense(VALID_LICENSE)).resolves.toBe(true);
|
|
expect(license.hasValidLicense()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('License V3', () => {
|
|
it('should return a valid license if the license is ready for validation', async () => {
|
|
const license = await getReadyLicenseManager();
|
|
const token = await new MockedLicenseBuilder().sign();
|
|
|
|
await expect(license.setLicense(token)).resolves.toBe(true);
|
|
expect(license.hasValidLicense()).toBe(true);
|
|
});
|
|
|
|
it('should accept new licenses', async () => {
|
|
const license = await getReadyLicenseManager();
|
|
const mocked = new MockedLicenseBuilder();
|
|
const oldToken = await mocked.sign();
|
|
|
|
const newToken = await mocked.withGrantedModules(['livechat-enterprise', 'chat.rocket.test-addon']).sign();
|
|
|
|
await expect(license.setLicense(oldToken)).resolves.toBe(true);
|
|
expect(license.hasValidLicense()).toBe(true);
|
|
|
|
expect(license.hasModule('livechat-enterprise')).toBe(false);
|
|
expect(license.hasModule('chat.rocket.test-addon')).toBe(false);
|
|
|
|
await expect(license.setLicense(newToken)).resolves.toBe(true);
|
|
expect(license.hasValidLicense()).toBe(true);
|
|
expect(license.hasModule('livechat-enterprise')).toBe(true);
|
|
expect(license.hasModule('chat.rocket.test-addon')).toBe(true);
|
|
});
|
|
|
|
it('should call a validated event after set a valid license', async () => {
|
|
const license = await getReadyLicenseManager();
|
|
const validateCallback = jest.fn();
|
|
license.onValidateLicense(validateCallback);
|
|
await expect(license.setLicense(VALID_LICENSE)).resolves.toBe(true);
|
|
expect(license.hasValidLicense()).toBe(true);
|
|
expect(validateCallback).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
describe('License limits', () => {
|
|
describe('invalidate license', () => {
|
|
it('should trigger an invalidation event when a license with invalid limits is set after a valid one', async () => {
|
|
const invalidationCallback = jest.fn();
|
|
|
|
const licenseManager = await getReadyLicenseManager();
|
|
const mocked = new MockedLicenseBuilder();
|
|
const oldToken = await mocked
|
|
.withLimits('activeUsers', [
|
|
{
|
|
max: 10,
|
|
behavior: 'invalidate_license',
|
|
},
|
|
])
|
|
.sign();
|
|
|
|
const newToken = await mocked
|
|
.withLimits('activeUsers', [
|
|
{
|
|
max: 1,
|
|
behavior: 'invalidate_license',
|
|
},
|
|
])
|
|
.sign();
|
|
|
|
licenseManager.onInvalidateLicense(invalidationCallback);
|
|
|
|
licenseManager.setLicenseLimitCounter('activeUsers', () => 5);
|
|
|
|
await expect(licenseManager.setLicense(oldToken)).resolves.toBe(true);
|
|
expect(licenseManager.hasValidLicense()).toBe(true);
|
|
|
|
await expect(licenseManager.setLicense(newToken)).resolves.toBe(true);
|
|
expect(licenseManager.hasValidLicense()).toBe(false);
|
|
|
|
expect(invalidationCallback).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|