Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 79 additions & 46 deletions forge/ee/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,99 @@
const fp = require('fastify-plugin')

// common features across all higher tier (enterpise, hub, edge, fleet)
async function commonFeatures(app, opts) {
app.decorate('sso', await require('./sso').init(app))
await require('./teamBroker').init(app)
// Set the MFA Feature Flag
app.config.features.register('mfa', true, true)
// Set the Project History timeline Feature Flag
app.config.features.register('projectHistory', true, true)
// Set the Bill of Materials Feature Flag
app.config.features.register('bom', true, true)
if (app.config.npmRegistry?.enabled) {
// Set npm Feature Flag
app.config.features.register('npm', true, true)
}
if (app.config.tables?.enabled) {
app.decorate('tables', await require('./tables').init(app))
}
app.config.features.register('certifiedNodes', true, true)
app.config.features.register('ffNodes', true, true)
// Application level RBAC
app.config.features.register('rbacApplication', true, true)
require('./autoUpdateStacks').init(app)

// Expert
await app.register(require('./expert'))

// Set the AI Features Flag (global gate for all AI features)
const isAiEnabled = !!(app.config?.ai?.enabled ?? true)
app.config.features.register('ai', isAiEnabled, true)

// Set the Generate Snapshot Description Feature Flag
const isAssistantConfigured = isAiEnabled && app.config.assistant?.enabled === true && !!app.config.assistant?.service?.url
app.config.features.register('generatedSnapshotDescription', isAssistantConfigured, true)

// Set the assistant inline completions Feature Flag
app.config.features.register('assistantInlineCompletions', isAssistantConfigured, true)

// Set the expert platform automation Feature Flag (MCP platform tools server)
app.config.features.register('expertPlatformAutomation', isAiEnabled && (app.config?.expert?.enabled ?? false), true)

// Set the expert assistant Feature Flag
app.config.features.register('expertAssistant', isAiEnabled && (app.config?.expert?.enabled ?? false), true)

// Set the Expert Insights flag
const isInsightsEnabled = isAiEnabled &&
!!app.config?.expert?.enabled &&
(Object.prototype.hasOwnProperty.call(app.config?.expert ?? {}, 'insights') ? !!app.config?.expert?.insights?.enabled : true)

app.config.features.register('expertInsights', isInsightsEnabled ?? false, true)
}

module.exports = fp(async function (app, opts) {
if (app.config.billing) {
app.decorate('billing', await require('./billing').init(app))
}
// common features for all license levels (inc Pro)
require('./projectComms').init(app)
require('./deviceEditor').init(app)
require('./alerts').init(app)

if (app.license.get('tier') === 'enterprise') {
await commonFeatures(app, opts)
// HA
require('./ha').init(app)
// Protected Instances
require('./protectedInstance').init(app)
// Git Opps
app.decorate('gitops', await require('./gitops').init(app))
require('./customHostnames').init(app)
app.decorate('sso', await require('./sso').init(app))
await require('./teamBroker').init(app)

// Set the Device Groups Feature Flag
app.config.features.register('deviceGroups', true, true)

} else if (app.license.get('tier') === 'hub') {
await commonFeatures(app, opts)
// HA
require('./ha').init(app)
// Protected Instances
require('./protectedInstance').init(app)
// Git Opps
app.decorate('gitops', await require('./gitops').init(app))
// Set the MFA Feature Flag
app.config.features.register('mfa', true, true)

} else if (app.license.get('tier') === 'edge') {
await commonFeatures(app, opts)
// Set the Device Groups Feature Flag
app.config.features.register('deviceGroups', true, true)
// Set the Project History timeline Feature Flag
app.config.features.register('projectHistory', true, true)
// Set the Bill of Materials Feature Flag
app.config.features.register('bom', true, true)
if (app.config.npmRegistry?.enabled) {
// Set npm Feature Flag
app.config.features.register('npm', true, true)
}
if (app.config.tables?.enabled) {
app.decorate('tables', await require('./tables').init(app))
}
app.config.features.register('certifiedNodes', true, true)
app.config.features.register('ffNodes', true, true)
app.config.features.register('rbacApplication', true, true)
require('./autoUpdateStacks').init(app)

// Expert
await app.register(require('./expert'))

// Set the AI Features Flag (global gate for all AI features)
const isAiEnabled = !!(app.config?.ai?.enabled ?? true)
app.config.features.register('ai', isAiEnabled, true)

// Set the Generate Snapshot Description Feature Flag
const isAssistantConfigured = isAiEnabled && app.config.assistant?.enabled === true && !!app.config.assistant?.service?.url
app.config.features.register('generatedSnapshotDescription', isAssistantConfigured, true)

// Set the assistant inline completions Feature Flag
app.config.features.register('assistantInlineCompletions', isAssistantConfigured, true)

// Set the expert platform automation Feature Flag (MCP platform tools server)
app.config.features.register('expertPlatformAutomation', isAiEnabled && (app.config?.expert?.enabled ?? false), true)

// Set the expert assistant Feature Flag
app.config.features.register('expertAssistant', isAiEnabled && (app.config?.expert?.enabled ?? false), true)

// Set the Expert Insights flag
const isInsightsEnabled = isAiEnabled &&
!!app.config?.expert?.enabled &&
(Object.prototype.hasOwnProperty.call(app.config?.expert ?? {}, 'insights') ? !!app.config?.expert?.insights?.enabled : true)

app.config.features.register('expertInsights', isInsightsEnabled ?? false, true)

} else if (app.license.get('tier') === 'fleet') {
await commonFeatures(app, opts)
// Set the Device Groups Feature Flag
app.config.features.register('deviceGroups', true, true)

} else {
// old "Pro" license
}

// Set the Team Library Feature Flag
Expand Down
67 changes: 49 additions & 18 deletions forge/ee/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,35 @@
* @namespace api
* @memberof forge.ee
*/

// common features across all higher tier (enterpise, hub, edge, fleet)
async function commonFeatures(app) {
await app.register(require('./expert'), { prefix: '/api/v1/expert', logLevel: app.config.logging.http })
await app.register(require('./mcp'), { logLevel: app.config.logging.http })
await app.register(require('./teamBroker'), { prefix: '/api/v1/teams/:teamId/broker', logLevel: app.config.logging.http })
await app.register(require('./teamBroker/3rdPartyBroker'), { prefix: '/api/v1/teams/:teamId/brokers', logLevel: app.config.logging.http })
if (app.config.npmRegistry?.enabled) {
await app.register(require('./catalogues'), { prefix: '/api/v1/teams/:teamId', logLevel: app.config.logging.http })
}
await app.register(require('./mfa'), { prefix: '/api/v1', logLevel: app.config.logging.http })
if (app.config.tables?.enabled) {
await app.register(require('./tables'), { prefix: '/api/v1/teams/:teamId/databases', logLevel: app.config.logging.http })
}
await app.register(require('./resource'), { prefix: '/api/v1/projects/:instanceId/resources', logLevel: app.config.logging.http })
await app.register(require('./autoUpdateStacks'), { prefix: '/api/v1/projects/:projectId/autoUpdateStack', logLevel: app.config.logging.http })
await app.register(require('./httpTokens'), { prefix: '/api/v1', logLevel: app.config.logging.http })
await app.register(require('./customHostnames'), { prefix: '/api/v1/projects/:projectId/customHostname', logLevel: app.config.logging.http })
await app.register(require('./staticAssets'), { prefix: '/api/v1/projects/:projectId/files', logLevel: app.config.logging.http })
await app.register(require('./projectHistory'), { prefix: '/api/v1/projects/:instanceId/history', logLevel: app.config.logging.http })
await app.register(require('./deviceHistory'), { prefix: '/api/v1/devices/:deviceId/history', logLevel: app.config.logging.http })
}

module.exports = async function (app) {
app.addHook('preHandler', app.verifySession)
if (app.config.billing) {
await app.register(require('./billing'), { prefix: '/ee/billing', logLevel: app.config.logging.http })
}
// Features provied to any license level (inc pro)
await app.register(require('./sharedLibrary'), { logLevel: app.config.logging.http })
await app.register(require('./pipeline'), { prefix: '/api/v1', logLevel: app.config.logging.http })
await app.register(require('./pipeline/teamPipelines.js'), { prefix: '/api/v1/teams/:teamId/pipelines', logLevel: app.config.logging.http })
Expand All @@ -19,31 +43,38 @@ module.exports = async function (app) {
await app.register(require('./flowBlueprints'), { prefix: '/api/v1/flow-blueprints', logLevel: app.config.logging.http })

if (app.license.get('tier') === 'enterprise') {
await commonFeatures(app)
await app.register(require('./applicationDeviceGroups'), { prefix: '/api/v1/applications/:applicationId/device-groups', logLevel: app.config.logging.http })
await app.register(require('./teamDeviceGroups'), { prefix: '/api/v1/teams/:teamId/device-groups', logLevel: app.config.logging.http })
await app.register(require('./ha'), { prefix: '/api/v1/projects/:projectId/ha', logLevel: app.config.logging.http })
await app.register(require('./protectedInstance'), { prefix: '/api/v1/projects/:projectId/protectInstance', logLevel: app.config.logging.http })
await app.register(require('./mfa'), { prefix: '/api/v1', logLevel: app.config.logging.http })
await app.register(require('./httpTokens'), { prefix: '/api/v1', logLevel: app.config.logging.http })
await app.register(require('./customHostnames'), { prefix: '/api/v1/projects/:projectId/customHostname', logLevel: app.config.logging.http })
await app.register(require('./staticAssets'), { prefix: '/api/v1/projects/:projectId/files', logLevel: app.config.logging.http })
await app.register(require('./projectHistory'), { prefix: '/api/v1/projects/:instanceId/history', logLevel: app.config.logging.http })
await app.register(require('./deviceHistory'), { prefix: '/api/v1/devices/:deviceId/history', logLevel: app.config.logging.http })
await app.register(require('./teamBroker'), { prefix: '/api/v1/teams/:teamId/broker', logLevel: app.config.logging.http })
await app.register(require('./teamBroker/3rdPartyBroker'), { prefix: '/api/v1/teams/:teamId/brokers', logLevel: app.config.logging.http })
if (app.config.npmRegistry?.enabled) {
await app.register(require('./catalogues'), { prefix: '/api/v1/teams/:teamId', logLevel: app.config.logging.http })
}
await app.register(require('./gitops'), { prefix: '/api/v1/teams/:teamId/git', logLevel: app.config.logging.http })
await app.register(require('./resource'), { prefix: '/api/v1/projects/:instanceId/resources', logLevel: app.config.logging.http })
if (app.config.tables?.enabled) {
await app.register(require('./tables'), { prefix: '/api/v1/teams/:teamId/databases', logLevel: app.config.logging.http })
}
await app.register(require('./mcp'), { logLevel: app.config.logging.http })
await app.register(require('./autoUpdateStacks'), { prefix: '/api/v1/projects/:projectId/autoUpdateStack', logLevel: app.config.logging.http })
await app.register(require('./expert'), { prefix: '/api/v1/expert', logLevel: app.config.logging.http })

// Important: keep SSO last to avoid its error handling polluting other routes.
await app.register(require('./sso'), { logLevel: app.config.logging.http })
} else if (app.license.get('tier') === 'hub') {
await commonFeatures(app)
await app.register(require('./gitops'), { prefix: '/api/v1/teams/:teamId/git', logLevel: app.config.logging.http })
await app.register(require('./ha'), { prefix: '/api/v1/projects/:projectId/ha', logLevel: app.config.logging.http })
await app.register(require('./protectedInstance'), { prefix: '/api/v1/projects/:projectId/protectInstance', logLevel: app.config.logging.http })

// Important: keep SSO last to avoid its error handling polluting other routes.
await app.register(require('./sso'), { logLevel: app.config.logging.http })
} else if (app.license.get('tier') === 'edge') {
await commonFeatures(app)
await app.register(require('./applicationDeviceGroups'), { prefix: '/api/v1/applications/:applicationId/device-groups', logLevel: app.config.logging.http })
await app.register(require('./teamDeviceGroups'), { prefix: '/api/v1/teams/:teamId/device-groups', logLevel: app.config.logging.http })

// Important: keep SSO last to avoid its error handling polluting other routes.
await app.register(require('./sso'), { logLevel: app.config.logging.http })
} else if (app.license.get('tier') === 'fleet') {
await commonFeatures(app)
await app.register(require('./applicationDeviceGroups'), { prefix: '/api/v1/applications/:applicationId/device-groups', logLevel: app.config.logging.http })
await app.register(require('./teamDeviceGroups'), { prefix: '/api/v1/teams/:teamId/device-groups', logLevel: app.config.logging.http })

// Important: keep SSO last to avoid its error handling polluting other routes.
await app.register(require('./sso'), { logLevel: app.config.logging.http })
} else {
// old Pro license
}
}
Loading