@@ -6,12 +6,11 @@ import axios, { AxiosError } from 'axios';
66import { ensureError } from 'n8n-workflow' ;
77
88import { BadRequestError } from '@/errors/response-errors/bad-request.error' ;
9+ import { LicenseEulaRequiredError } from '@/errors/response-errors/license-eula-required.error' ;
910import { EventService } from '@/events/event.service' ;
1011import { License } from '@/license' ;
1112import { UrlService } from '@/services/url.service' ;
1213
13- type LicenseError = Error & { errorId ?: keyof typeof LicenseErrors } ;
14-
1514export const LicenseErrors = {
1615 SCHEMA_VALIDATION : 'Activation key is in the wrong format' ,
1716 RESERVATION_EXHAUSTED : 'Activation key has been used too many times' ,
@@ -110,22 +109,47 @@ export class LicenseService {
110109 return this . license . getManagementJwt ( ) ;
111110 }
112111
113- async activateLicense ( activationKey : string ) {
112+ async activateLicense ( activationKey : string , eulaUri ?: string ) {
114113 try {
115- await this . license . activate ( activationKey ) ;
114+ await this . license . activate ( activationKey , eulaUri ) ;
116115 } catch ( e ) {
117- const message = this . mapErrorMessage ( e as LicenseError , 'activate' ) ;
116+ // Check if this is a EULA_REQUIRED error from license server
117+ if ( this . isEulaRequiredError ( e ) ) {
118+ throw new LicenseEulaRequiredError ( 'License activation requires EULA acceptance' , {
119+ eulaUrl : e . info . eula . uri ,
120+ } ) ;
121+ }
122+
123+ const message = this . mapErrorMessage ( ensureError ( e ) , 'activate' ) ;
118124 throw new BadRequestError ( message ) ;
119125 }
120126 }
121127
128+ private isEulaRequiredError (
129+ error : unknown ,
130+ ) : error is Error & { errorId : string ; info : { eula : { uri : string } } } {
131+ return (
132+ error instanceof Error &&
133+ 'errorId' in error &&
134+ error . errorId === 'EULA_REQUIRED' &&
135+ 'info' in error &&
136+ typeof error . info === 'object' &&
137+ error . info !== null &&
138+ 'eula' in error . info &&
139+ typeof error . info . eula === 'object' &&
140+ error . info . eula !== null &&
141+ 'uri' in error . info . eula &&
142+ typeof error . info . eula . uri === 'string'
143+ ) ;
144+ }
145+
122146 async renewLicense ( ) {
123147 if ( this . license . getPlanName ( ) === 'Community' ) return ; // unlicensed, nothing to renew
124148
125149 try {
126150 await this . license . renew ( ) ;
127151 } catch ( e ) {
128- const message = this . mapErrorMessage ( e as LicenseError , 'renew' ) ;
152+ const message = this . mapErrorMessage ( ensureError ( e ) , 'renew' ) ;
129153
130154 this . eventService . emit ( 'license-renewal-attempted' , { success : false } ) ;
131155 throw new BadRequestError ( message ) ;
@@ -134,12 +158,21 @@ export class LicenseService {
134158 this . eventService . emit ( 'license-renewal-attempted' , { success : true } ) ;
135159 }
136160
137- private mapErrorMessage ( error : LicenseError , action : 'activate' | 'renew' ) {
138- let message = error . errorId && LicenseErrors [ error . errorId ] ;
161+ private mapErrorMessage ( error : Error , action : 'activate' | 'renew' ) {
162+ let message : string | undefined ;
163+
164+ if ( this . isLicenseError ( error ) && error . errorId in LicenseErrors ) {
165+ message = LicenseErrors [ error . errorId as keyof typeof LicenseErrors ] ;
166+ }
167+
139168 if ( ! message ) {
140169 message = `Failed to ${ action } license: ${ error . message } ` ;
141170 this . logger . error ( message , { stack : error . stack ?? 'n/a' } ) ;
142171 }
143172 return message ;
144173 }
174+
175+ private isLicenseError ( error : Error ) : error is Error & { errorId : string } {
176+ return 'errorId' in error && typeof error . errorId === 'string' ;
177+ }
145178}
0 commit comments