| FROM n8nio/n8n:latest |
|
|
| USER root |
|
|
| # ============================== |
| # 1. 覆盖 license-state.js(你提供的原版 + 全功能解锁) |
| # ============================== |
| RUN cat > /usr/local/lib/node_modules/n8n/node_modules/@n8n/backend-common/dist/license-state.js <<'EOF' |
| "use strict"; |
| var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { |
| var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; |
| if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); |
| else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; |
| return c > 3 && r && Object.defineProperty(target, key, r), r; |
| }; |
| Object.defineProperty(exports, "__esModule", { value: true }); |
| exports.LicenseState = void 0; |
| const constants_1 = require("@n8n/constants"); |
| const di_1 = require("@n8n/di"); |
| const n8n_workflow_1 = require("n8n-workflow"); |
| class ProviderNotSetError extends n8n_workflow_1.UnexpectedError { |
| constructor() { |
| super('Cannot query license state because license provider has not been set'); |
| } |
| } |
| let LicenseState = class LicenseState { |
| constructor() { |
| this.licenseProvider = null; |
| } |
| setLicenseProvider(provider) { this.licenseProvider = provider; } |
| assertProvider() {} |
| isLicensed(feature) { return true; } |
| getValue(feature) { return 99999999; } |
| isCustomRolesLicensed() { return true; } |
| isDynamicCredentialsLicensed() { return true; } |
| isPersonalSpacePolicyLicensed() { return true; } |
| isSharingLicensed() { return true; } |
| isLogStreamingLicensed() { return true; } |
| isLdapLicensed() { return true; } |
| isSamlLicensed() { return true; } |
| isOidcLicensed() { return true; } |
| isMFAEnforcementLicensed() { return true; } |
| isApiKeyScopesLicensed() { return true; } |
| isAiAssistantLicensed() { return true; } |
| isAskAiLicensed() { return true; } |
| isAiCreditsLicensed() { return true; } |
| isAdvancedExecutionFiltersLicensed() { return true; } |
| isAdvancedPermissionsLicensed() { return true; } |
| isDebugInEditorLicensed() { return true; } |
| isBinaryDataS3Licensed() { return true; } |
| isMultiMainLicensed() { return true; } |
| isVariablesLicensed() { return true; } |
| isSourceControlLicensed() { return true; } |
| isExternalSecretsLicensed() { return true; } |
| isAPIDisabled() { return false; } |
| isWorkerViewLicensed() { return true; } |
| isProjectRoleAdminLicensed() { return true; } |
| isProjectRoleEditorLicensed() { return true; } |
| isProjectRoleViewerLicensed() { return true; } |
| isCustomNpmRegistryLicensed() { return true; } |
| isFoldersLicensed() { return true; } |
| isInsightsSummaryLicensed() { return true; } |
| isInsightsDashboardLicensed() { return true; } |
| isInsightsHourlyDataLicensed() { return true; } |
| isWorkflowDiffsLicensed() { return true; } |
| isDataRedactionLicensed() { return true; } |
| isProvisioningLicensed() { return true; } |
| getMaxUsers() { return 99999999; } |
| getMaxActiveWorkflows() { return 99999999; } |
| getMaxVariables() { return 99999999; } |
| getMaxAiCredits() { return 99999999; } |
| getWorkflowHistoryPruneQuota() { return 99999999; } |
| getInsightsMaxHistory() { return 3650; } |
| getInsightsRetentionMaxAge() { return 3650; } |
| getInsightsRetentionPruneInterval() { return 1; } |
| getMaxTeamProjects() { return 99999999; } |
| getMaxWorkflowsWithEvaluations() { return 99999999; } |
| }; |
| exports.LicenseState = LicenseState; |
| exports.LicenseState = LicenseState = __decorate([ |
| (0, di_1.Service)() |
| ], LicenseState); |
| EOF |
|
|
| # ============================== |
| # 2. 覆盖 license.js(你提供的原版 + 只改一行 isLicensed 永久返回 true) |
| # ============================== |
| RUN cat > /usr/local/lib/node_modules/n8n/dist/license.js <<'EOF' |
| "use strict"; |
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { |
| if (k2 === undefined) k2 = k; |
| var desc = Object.getOwnPropertyDescriptor(m, k); |
| if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { |
| desc = { enumerable: true, get: function() { return m[k]; } }; |
| } |
| Object.defineProperty(o, k2, desc); |
| }) : (function(o, m, k, k2) { |
| if (k2 === undefined) k2 = k; |
| o[k2] = m[k]; |
| })); |
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { |
| Object.defineProperty(o, "default", { enumerable: true, value: v }); |
| }) : function(o, v) { |
| o["default"] = v; |
| }); |
| var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { |
| var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; |
| if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); |
| else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; |
| return c > 3 && r && Object.defineProperty(target, key, r), r; |
| }; |
| var __importStar = (this && this.__importStar) || (function () { |
| var ownKeys = function(o) { |
| ownKeys = Object.getOwnPropertyNames || function (o) { |
| var ar = []; |
| for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; |
| return ar; |
| }; |
| return ownKeys(o); |
| }; |
| return function (mod) { |
| if (mod && mod.__esModule) return mod; |
| var result = {}; |
| if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); |
| __setModuleDefault(result, mod); |
| return result; |
| }; |
| })(); |
| var __metadata = (this && this.__metadata) || function (k, v) { |
| if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); |
| }; |
| Object.defineProperty(exports, "__esModule", { value: true }); |
| exports.License = void 0; |
| const backend_common_1 = require("@n8n/backend-common"); |
| const config_1 = require("@n8n/config"); |
| const constants_1 = require("@n8n/constants"); |
| const db_1 = require("@n8n/db"); |
| const decorators_1 = require("@n8n/decorators"); |
| const di_1 = require("@n8n/di"); |
| const license_sdk_1 = require("@n8n_io/license-sdk"); |
| const n8n_core_1 = require("n8n-core"); |
| const license_metrics_service_1 = require("./metrics/license-metrics.service"); |
| const constants_2 = require("./constants"); |
| const LICENSE_RENEWAL_DISABLED_WARNING = 'Automatic license renewal is disabled. The license will not renew automatically, and access to licensed features may be lost!'; |
| let License = class License { |
| constructor(logger, instanceSettings, settingsRepository, licenseMetricsService, globalConfig) { |
| this.logger = logger; |
| this.instanceSettings = instanceSettings; |
| this.settingsRepository = settingsRepository; |
| this.licenseMetricsService = licenseMetricsService; |
| this.globalConfig = globalConfig; |
| this.isShuttingDown = false; |
| this.refreshCallbacks = []; |
| this.logger = this.logger.scoped('license'); |
| } |
| async init({ forceRecreate = false, isCli = false, } = {}) { |
| if (this.manager && !forceRecreate) { |
| this.logger.warn('License manager already initialized or shutting down'); |
| return; |
| } |
| if (this.isShuttingDown) { |
| this.logger.warn('License manager already shutting down'); |
| return; |
| } |
| const { instanceType } = this.instanceSettings; |
| const isMainInstance = instanceType === 'main'; |
| const server = this.globalConfig.license.serverUrl; |
| const offlineMode = !isMainInstance; |
| const autoRenewOffset = 72 * constants_1.Time.hours.toSeconds; |
| const saveCertStr = isMainInstance |
| ? async (value) => await this.saveCertStr(value) |
| : async () => { }; |
| const onFeatureChange = isMainInstance |
| ? async () => await this.onFeatureChange() |
| : async () => { }; |
| const onLicenseRenewed = isMainInstance |
| ? async () => await this.onLicenseRenewed() |
| : async () => { }; |
| const collectUsageMetrics = isMainInstance |
| ? async () => await this.licenseMetricsService.collectUsageMetrics() |
| : async () => []; |
| const collectPassthroughData = isMainInstance |
| ? async () => await this.licenseMetricsService.collectPassthroughData() |
| : async () => ({}); |
| const onExpirySoon = !this.instanceSettings.isLeader ? () => this.onExpirySoon() : undefined; |
| const expirySoonOffsetMins = !this.instanceSettings.isLeader ? 120 : undefined; |
| const { isLeader } = this.instanceSettings; |
| const { autoRenewalEnabled } = this.globalConfig.license; |
| const eligibleToRenew = isCli || isLeader; |
| const shouldRenew = eligibleToRenew && autoRenewalEnabled; |
| if (eligibleToRenew && !autoRenewalEnabled) { |
| this.logger.warn(LICENSE_RENEWAL_DISABLED_WARNING); |
| } |
| try { |
| this.manager = new license_sdk_1.LicenseManager({ |
| server, |
| tenantId: this.globalConfig.license.tenantId, |
| productIdentifier: `n8n-${constants_2.N8N_VERSION}`, |
| autoRenewEnabled: shouldRenew, |
| renewOnInit: shouldRenew, |
| autoRenewOffset, |
| detachFloatingOnShutdown: this.globalConfig.license.detachFloatingOnShutdown, |
| offlineMode, |
| logger: this.logger, |
| loadCertStr: async () => await this.loadCertStr(), |
| saveCertStr, |
| deviceFingerprint: () => this.instanceSettings.instanceId, |
| collectUsageMetrics, |
| collectPassthroughData, |
| onFeatureChange, |
| onLicenseRenewed, |
| onExpirySoon, |
| expirySoonOffsetMins, |
| }); |
| await this.manager.initialize(); |
| this.logger.debug('License initialized'); |
| } |
| catch (error) { |
| if (error instanceof Error) { |
| this.logger.error('Could not initialize license manager sdk', { error }); |
| } |
| } |
| } |
| async loadCertStr() { |
| const ephemeralLicense = this.globalConfig.license.cert; |
| if (ephemeralLicense) { |
| return ephemeralLicense; |
| } |
| const databaseSettings = await this.settingsRepository.findOne({ |
| where: { |
| key: constants_2.SETTINGS_LICENSE_CERT_KEY, |
| }, |
| }); |
| return databaseSettings?.value ?? ''; |
| } |
| async onFeatureChange() { |
| void this.broadcastReloadLicenseCommand(); |
| await this.notifyRefreshCallbacks(); |
| } |
| async onLicenseRenewed() { |
| void this.broadcastReloadLicenseCommand(); |
| await this.notifyRefreshCallbacks(); |
| } |
| async broadcastReloadLicenseCommand() { |
| if (this.globalConfig.executions.mode === 'queue' && this.instanceSettings.isLeader) { |
| const { Publisher } = await Promise.resolve().then(() => __importStar(require('./scaling/pubsub/publisher.service'))); |
| await di_1.Container.get(Publisher).publishCommand({ command: 'reload-license' }); |
| } |
| } |
| async saveCertStr(value) { |
| if (this.globalConfig.license.cert) |
| return; |
| await this.settingsRepository.upsert({ |
| key: constants_2.SETTINGS_LICENSE_CERT_KEY, |
| value, |
| loadOnStartup: false, |
| }, ['key']); |
| } |
| onCertRefresh(refreshCallback) { |
| this.refreshCallbacks.push(refreshCallback); |
| return () => { |
| const index = this.refreshCallbacks.indexOf(refreshCallback); |
| if (index > -1) { |
| this.refreshCallbacks.splice(index, 1); |
| } |
| }; |
| } |
| async notifyRefreshCallbacks() { |
| const cert = await this.loadCertStr(); |
| for (const refreshCallback of this.refreshCallbacks) { |
| try { |
| refreshCallback(cert); |
| } |
| catch (error) { |
| this.logger.error('Error in license refresh callback', { error }); |
| } |
| } |
| } |
| async activate(activationKey, eulaUri, userEmail) { |
| if (!this.manager) { |
| return; |
| } |
| await this.manager.activate(activationKey, { eulaUri, email: userEmail }); |
| this.logger.debug('License activated'); |
| } |
| async reload() { |
| if (!this.manager) { |
| return; |
| } |
| await this.manager.reload(); |
| await this.notifyRefreshCallbacks(); |
| this.logger.debug('License reloaded'); |
| } |
| async renew() { |
| if (!this.manager) { |
| return; |
| } |
| await this.manager.renew(); |
| this.logger.debug('License renewed'); |
| } |
| async clear() { |
| if (!this.manager) { |
| return; |
| } |
| await this.manager.clear(); |
| this.logger.info('License cleared'); |
| } |
| async shutdown() { |
| this.isShuttingDown = true; |
| if (!this.manager) { |
| return; |
| } |
| await this.manager.shutdown(); |
| this.logger.debug('License shut down'); |
| } |
| isLicensed(feature) { return true; } |
| isDynamicCredentialsEnabled() { return true; } |
| isSharingEnabled() { return true; } |
| isLogStreamingEnabled() { return true; } |
| isLdapEnabled() { return true; } |
| isSamlEnabled() { return true; } |
| isAiAssistantEnabled() { return true; } |
| isAskAiEnabled() { return true; } |
| isAiCreditsEnabled() { return true; } |
| isAdvancedExecutionFiltersEnabled() { return true; } |
| isAdvancedPermissionsLicensed() { return true; } |
| isDebugInEditorLicensed() { return true; } |
| isBinaryDataS3Licensed() { return true; } |
| isMultiMainLicensed() { return true; } |
| isVariablesEnabled() { return true; } |
| isSourceControlLicensed() { return true; } |
| isExternalSecretsEnabled() { return true; } |
| isAPIDisabled() { return false; } |
| isWorkerViewLicensed() { return true; } |
| isProjectRoleAdminLicensed() { return true; } |
| isProjectRoleEditorLicensed() { return true; } |
| isProjectRoleViewerLicensed() { return true; } |
| isCustomNpmRegistryEnabled() { return true; } |
| isFoldersEnabled() { return true; } |
| getCurrentEntitlements() { return this.manager?.getCurrentEntitlements() ?? []; } |
| getValue(feature) { return 99999999; } |
| getManagementJwt() { return this.manager?.getManagementJwt() ?? ''; } |
| getMainPlan() { |
| if (!this.manager) return undefined; |
| const entitlements = this.getCurrentEntitlements(); |
| if (!entitlements.length) return undefined; |
| entitlements.sort((a, b) => b.validFrom.getTime() - a.validFrom.getTime()); |
| return entitlements.find((entitlement) => entitlement.productMetadata?.terms?.isMainPlan); |
| } |
| getConsumerId() { return this.manager?.getConsumerId() ?? 'unknown'; } |
| getUsersLimit() { return 99999999; } |
| getTriggerLimit() { return 99999999; } |
| getVariablesLimit() { return 99999999; } |
| getAiCredits() { return 99999999; } |
| getWorkflowHistoryPruneLimit() { return 99999999; } |
| getTeamProjectLimit() { return 99999999; } |
| getPlanName() { return "Enterprise"; } |
| getExpiryDate() { return new Date('3099-12-31'); } |
| getTerminationDate() { return new Date('3099-12-31'); } |
| getExpiringInDays() { return 36500; } |
| getTerminatingInDays() { return 36500; } |
| getInfo() { return 'Enterprise License (Unlimited)'; } |
| isWithinUsersLimit() { return true; } |
| enableAutoRenewals() {} |
| disableAutoRenewals() {} |
| onExpirySoon() {} |
| }; |
| exports.License = License; |
| __decorate([ |
| (0, decorators_1.OnPubSubEvent)('reload-license'), |
| __metadata("design:type", Function), |
| __metadata("design:paramtypes", []), |
| __metadata("design:returntype", Promise) |
| ], License.prototype, "reload", null); |
| __decorate([ |
| (0, decorators_1.OnShutdown)(), |
| __metadata("design:type", Function), |
| __metadata("design:paramtypes", []), |
| __metadata("design:returntype", Promise) |
| ], License.prototype, "shutdown", null); |
| __decorate([ |
| (0, decorators_1.OnLeaderTakeover)(), |
| __metadata("design:type", Function), |
| __metadata("design:paramtypes", []), |
| __metadata("design:returntype", void 0) |
| ], License.prototype, "enableAutoRenewals", null); |
| __decorate([ |
| (0, decorators_1.OnLeaderStepdown)(), |
| __metadata("design:type", Function), |
| __metadata("design:paramtypes", []), |
| __metadata("design:returntype", void 0) |
| ], License.prototype, "disableAutoRenewals", null); |
| exports.License = License = __decorate([ |
| (0, di_1.Service)(), |
| __metadata("design:paramtypes", [backend_common_1.Logger, |
| n8n_core_1.InstanceSettings, |
| db_1.SettingsRepository, |
| license_metrics_service_1.LicenseMetricsService, |
| config_1.GlobalConfig]) |
| ], License); |
| EOF |
|
|
| # ============================== |
| # 启动 n8n |
| # ============================== |
| USER node |
|
|