mirror of
https://github.com/n8n-io/n8n.git
synced 2026-09-21 12:51:16 +08:00
feat(core): Add user email parameter when activating EULA license (#23350)
Co-authored-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.5
parent
5567b91f6c
commit
3d71a6d9d9
@@ -112,7 +112,7 @@
|
||||
"@n8n/typeorm": "catalog:",
|
||||
"@n8n/utils": "workspace:*",
|
||||
"@n8n_io/ai-assistant-sdk": "catalog:",
|
||||
"@n8n_io/license-sdk": "2.24.1",
|
||||
"@n8n_io/license-sdk": "2.25.0",
|
||||
"@parcel/watcher": "^2.5.1",
|
||||
"@rudderstack/rudder-sdk-node": "3.0.0",
|
||||
"@sentry/node": "catalog:",
|
||||
|
||||
@@ -101,17 +101,24 @@ describe('License', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('attempts to activate license with provided key', async () => {
|
||||
test('attempts to activate license with provided key (initial activation)', async () => {
|
||||
await license.activate(MOCK_ACTIVATION_KEY);
|
||||
|
||||
expect(LicenseManager.prototype.activate).toHaveBeenCalledWith(MOCK_ACTIVATION_KEY, undefined);
|
||||
expect(LicenseManager.prototype.activate).toHaveBeenCalledWith(MOCK_ACTIVATION_KEY, {
|
||||
eulaUri: undefined,
|
||||
email: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
test('attempts to activate license with eulaUri', async () => {
|
||||
test('attempts to activate license with eulaUri and userEmail (EULA acceptance)', async () => {
|
||||
const eulaUri = 'https://n8n.io/legal/eula/';
|
||||
await license.activate(MOCK_ACTIVATION_KEY, eulaUri);
|
||||
const userEmail = 'user@example.com';
|
||||
await license.activate(MOCK_ACTIVATION_KEY, eulaUri, userEmail);
|
||||
|
||||
expect(LicenseManager.prototype.activate).toHaveBeenCalledWith(MOCK_ACTIVATION_KEY, eulaUri);
|
||||
expect(LicenseManager.prototype.activate).toHaveBeenCalledWith(MOCK_ACTIVATION_KEY, {
|
||||
eulaUri,
|
||||
email: userEmail,
|
||||
});
|
||||
});
|
||||
|
||||
test('renews license', async () => {
|
||||
|
||||
@@ -198,12 +198,14 @@ export class License implements LicenseProvider {
|
||||
}
|
||||
}
|
||||
|
||||
async activate(activationKey: string, eulaUri?: string): Promise<void> {
|
||||
async activate(activationKey: string): Promise<void>;
|
||||
async activate(activationKey: string, eulaUri: string, userEmail: string): Promise<void>;
|
||||
async activate(activationKey: string, eulaUri?: string, userEmail?: string): Promise<void> {
|
||||
if (!this.manager) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.manager.activate(activationKey, eulaUri);
|
||||
await this.manager.activate(activationKey, { eulaUri, email: userEmail });
|
||||
this.logger.debug('License activated');
|
||||
}
|
||||
|
||||
|
||||
@@ -65,16 +65,24 @@ describe('LicenseService', () => {
|
||||
});
|
||||
|
||||
describe('activateLicense', () => {
|
||||
it('should activate license without eulaUri', async () => {
|
||||
it('should activate license without eulaUri (initial activation)', async () => {
|
||||
license.activate.mockResolvedValueOnce();
|
||||
await licenseService.activateLicense('activation-key');
|
||||
expect(license.activate).toHaveBeenCalledWith('activation-key', undefined);
|
||||
expect(license.activate).toHaveBeenCalledWith('activation-key');
|
||||
});
|
||||
|
||||
it('should activate license with eulaUri', async () => {
|
||||
it('should activate license with eulaUri and userEmail (EULA acceptance)', async () => {
|
||||
license.activate.mockResolvedValueOnce();
|
||||
await licenseService.activateLicense('activation-key', 'https://n8n.io/legal/eula/');
|
||||
expect(license.activate).toHaveBeenCalledWith('activation-key', 'https://n8n.io/legal/eula/');
|
||||
await licenseService.activateLicense(
|
||||
'activation-key',
|
||||
'https://n8n.io/legal/eula/',
|
||||
'user@example.com',
|
||||
);
|
||||
expect(license.activate).toHaveBeenCalledWith(
|
||||
'activation-key',
|
||||
'https://n8n.io/legal/eula/',
|
||||
'user@example.com',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw LicenseEulaRequiredError when EULA_REQUIRED error occurs', async () => {
|
||||
|
||||
@@ -59,7 +59,11 @@ export class LicenseController {
|
||||
@GlobalScope('license:manage')
|
||||
async activateLicense(req: LicenseRequest.Activate) {
|
||||
const { activationKey, eulaUri } = req.body;
|
||||
await this.licenseService.activateLicense(activationKey, eulaUri);
|
||||
if (eulaUri) {
|
||||
await this.licenseService.activateLicense(activationKey, eulaUri, req.user.email);
|
||||
} else {
|
||||
await this.licenseService.activateLicense(activationKey);
|
||||
}
|
||||
return await this.getTokenAndData();
|
||||
}
|
||||
|
||||
|
||||
@@ -109,9 +109,23 @@ export class LicenseService {
|
||||
return this.license.getManagementJwt();
|
||||
}
|
||||
|
||||
async activateLicense(activationKey: string, eulaUri?: string) {
|
||||
// Overload signatures
|
||||
async activateLicense(activationKey: string): Promise<void>;
|
||||
async activateLicense(activationKey: string, eulaUri: string, userEmail: string): Promise<void>;
|
||||
// Implementation signature
|
||||
async activateLicense(
|
||||
activationKey: string,
|
||||
eulaUri?: string,
|
||||
userEmail?: string,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await this.license.activate(activationKey, eulaUri);
|
||||
if (eulaUri && userEmail) {
|
||||
await this.license.activate(activationKey, eulaUri, userEmail);
|
||||
} else if (!eulaUri && !userEmail) {
|
||||
await this.license.activate(activationKey);
|
||||
} else {
|
||||
throw new BadRequestError('When providing eulaUri, userEmail is required');
|
||||
}
|
||||
} catch (e) {
|
||||
// Check if this is a EULA_REQUIRED error from license server
|
||||
if (this.isEulaRequiredError(e)) {
|
||||
|
||||
Generated
+5
-5
@@ -1680,8 +1680,8 @@ importers:
|
||||
specifier: 'catalog:'
|
||||
version: 1.20.0
|
||||
'@n8n_io/license-sdk':
|
||||
specifier: 2.24.1
|
||||
version: 2.24.1
|
||||
specifier: 2.25.0
|
||||
version: 2.25.0
|
||||
'@parcel/watcher':
|
||||
specifier: ^2.5.1
|
||||
version: 2.5.1
|
||||
@@ -6520,8 +6520,8 @@ packages:
|
||||
resolution: {integrity: sha512-uXa6EDufQIV46tvqQ222441dWZYLnT219HC5H8grfAVd6Mpp2Rs4NoBM6YPWnGFWBp8XVsgXUud0EKRbJsw0eA==}
|
||||
engines: {node: '>=20.15', pnpm: '>=8.14'}
|
||||
|
||||
'@n8n_io/license-sdk@2.24.1':
|
||||
resolution: {integrity: sha512-nrITEzOmFonFXD5XtzHjpY/s1kpKksYQoY5HBqhzRkGq3ldEO3nLKDl6RG9AEtkKKlKkid3lzviZJCIDINZlQw==}
|
||||
'@n8n_io/license-sdk@2.25.0':
|
||||
resolution: {integrity: sha512-6pNo09XHhBb+igaHfpuvLez+IxcerzRWMFUH1eqAOOE0Uf5orQp8j5p5RE7ohNZYtxlMoL/PcsQIXK5uHBycwg==}
|
||||
engines: {node: '>=18.12.1'}
|
||||
|
||||
'@n8n_io/riot-tmpl@4.0.1':
|
||||
@@ -23037,7 +23037,7 @@ snapshots:
|
||||
|
||||
'@n8n_io/ai-assistant-sdk@1.20.0': {}
|
||||
|
||||
'@n8n_io/license-sdk@2.24.1':
|
||||
'@n8n_io/license-sdk@2.25.0':
|
||||
dependencies:
|
||||
crypto-js: 4.2.0
|
||||
node-machine-id: 1.1.12
|
||||
|
||||
Reference in New Issue
Block a user