@friggframework/core 2.0.0-next.45 → 2.0.0-next.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/application/commands/integration-commands.js +19 -0
- package/core/Worker.js +8 -21
- package/credential/repositories/credential-repository-mongo.js +14 -8
- package/credential/repositories/credential-repository-postgres.js +14 -8
- package/credential/repositories/credential-repository.js +3 -8
- package/database/MONGODB_TRANSACTION_FIX.md +198 -0
- package/database/adapters/lambda-invoker.js +97 -0
- package/database/config.js +11 -2
- package/database/models/WebsocketConnection.js +11 -10
- package/database/prisma.js +63 -3
- package/database/repositories/health-check-repository-mongodb.js +3 -0
- package/database/repositories/migration-status-repository-s3.js +137 -0
- package/database/use-cases/check-database-state-use-case.js +81 -0
- package/database/use-cases/check-encryption-health-use-case.js +3 -2
- package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
- package/database/use-cases/get-migration-status-use-case.js +93 -0
- package/database/use-cases/run-database-migration-use-case.js +137 -0
- package/database/use-cases/trigger-database-migration-use-case.js +157 -0
- package/database/utils/mongodb-collection-utils.js +91 -0
- package/database/utils/mongodb-schema-init.js +106 -0
- package/database/utils/prisma-runner.js +400 -0
- package/database/utils/prisma-schema-parser.js +182 -0
- package/encrypt/Cryptor.js +14 -16
- package/generated/prisma-mongodb/client.d.ts +1 -0
- package/generated/prisma-mongodb/client.js +4 -0
- package/generated/prisma-mongodb/default.d.ts +1 -0
- package/generated/prisma-mongodb/default.js +4 -0
- package/generated/prisma-mongodb/edge.d.ts +1 -0
- package/generated/prisma-mongodb/edge.js +334 -0
- package/generated/prisma-mongodb/index-browser.js +316 -0
- package/generated/prisma-mongodb/index.d.ts +22897 -0
- package/generated/prisma-mongodb/index.js +359 -0
- package/generated/prisma-mongodb/package.json +183 -0
- package/generated/prisma-mongodb/query-engine-debian-openssl-3.0.x +0 -0
- package/generated/prisma-mongodb/query-engine-rhel-openssl-3.0.x +0 -0
- package/generated/prisma-mongodb/runtime/binary.d.ts +1 -0
- package/generated/prisma-mongodb/runtime/binary.js +289 -0
- package/generated/prisma-mongodb/runtime/edge-esm.js +34 -0
- package/generated/prisma-mongodb/runtime/edge.js +34 -0
- package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-mongodb/runtime/index-browser.js +16 -0
- package/generated/prisma-mongodb/runtime/library.d.ts +3977 -0
- package/generated/prisma-mongodb/runtime/react-native.js +83 -0
- package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +84 -0
- package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +36 -0
- package/generated/prisma-mongodb/schema.prisma +362 -0
- package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +4 -0
- package/generated/prisma-mongodb/wasm-worker-loader.mjs +4 -0
- package/generated/prisma-mongodb/wasm.d.ts +1 -0
- package/generated/prisma-mongodb/wasm.js +341 -0
- package/generated/prisma-postgresql/client.d.ts +1 -0
- package/generated/prisma-postgresql/client.js +4 -0
- package/generated/prisma-postgresql/default.d.ts +1 -0
- package/generated/prisma-postgresql/default.js +4 -0
- package/generated/prisma-postgresql/edge.d.ts +1 -0
- package/generated/prisma-postgresql/edge.js +356 -0
- package/generated/prisma-postgresql/index-browser.js +338 -0
- package/generated/prisma-postgresql/index.d.ts +25071 -0
- package/generated/prisma-postgresql/index.js +381 -0
- package/generated/prisma-postgresql/package.json +183 -0
- package/generated/prisma-postgresql/query-engine-debian-openssl-3.0.x +0 -0
- package/generated/prisma-postgresql/query-engine-rhel-openssl-3.0.x +0 -0
- package/generated/prisma-postgresql/query_engine_bg.js +2 -0
- package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
- package/generated/prisma-postgresql/runtime/binary.d.ts +1 -0
- package/generated/prisma-postgresql/runtime/binary.js +289 -0
- package/generated/prisma-postgresql/runtime/edge-esm.js +34 -0
- package/generated/prisma-postgresql/runtime/edge.js +34 -0
- package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-postgresql/runtime/index-browser.js +16 -0
- package/generated/prisma-postgresql/runtime/library.d.ts +3977 -0
- package/generated/prisma-postgresql/runtime/react-native.js +83 -0
- package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +84 -0
- package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +36 -0
- package/generated/prisma-postgresql/schema.prisma +345 -0
- package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +4 -0
- package/generated/prisma-postgresql/wasm-worker-loader.mjs +4 -0
- package/generated/prisma-postgresql/wasm.d.ts +1 -0
- package/generated/prisma-postgresql/wasm.js +363 -0
- package/handlers/database-migration-handler.js +227 -0
- package/handlers/routers/auth.js +1 -1
- package/handlers/routers/db-migration.handler.js +29 -0
- package/handlers/routers/db-migration.js +256 -0
- package/handlers/routers/health.js +41 -6
- package/handlers/routers/integration-webhook-routers.js +2 -2
- package/handlers/use-cases/check-integrations-health-use-case.js +22 -10
- package/handlers/workers/db-migration.js +352 -0
- package/index.js +12 -0
- package/integrations/integration-router.js +60 -70
- package/integrations/repositories/integration-repository-interface.js +12 -0
- package/integrations/repositories/integration-repository-mongo.js +32 -0
- package/integrations/repositories/integration-repository-postgres.js +33 -0
- package/integrations/repositories/process-repository-postgres.js +2 -2
- package/integrations/tests/doubles/test-integration-repository.js +2 -2
- package/logs/logger.js +0 -4
- package/modules/entity.js +0 -1
- package/modules/repositories/module-repository-mongo.js +3 -12
- package/modules/repositories/module-repository-postgres.js +0 -11
- package/modules/repositories/module-repository.js +1 -12
- package/modules/use-cases/get-entity-options-by-id.js +1 -1
- package/modules/use-cases/get-module.js +1 -2
- package/modules/use-cases/refresh-entity-options.js +1 -1
- package/modules/use-cases/test-module-auth.js +1 -1
- package/package.json +82 -66
- package/prisma-mongodb/schema.prisma +21 -21
- package/prisma-postgresql/schema.prisma +15 -15
- package/queues/queuer-util.js +24 -21
- package/types/core/index.d.ts +2 -2
- package/types/module-plugin/index.d.ts +0 -2
- package/user/use-cases/authenticate-user.js +127 -0
- package/user/use-cases/authenticate-with-shared-secret.js +48 -0
- package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
- package/user/use-cases/get-user-from-x-frigg-headers.js +106 -0
- package/user/user.js +16 -0
- package/websocket/repositories/websocket-connection-repository-mongo.js +11 -10
- package/websocket/repositories/websocket-connection-repository-postgres.js +11 -10
- package/websocket/repositories/websocket-connection-repository.js +11 -10
- package/application/commands/integration-commands.test.js +0 -123
- package/database/encryption/encryption-integration.test.js +0 -553
- package/database/encryption/encryption-schema-registry.test.js +0 -392
- package/database/encryption/field-encryption-service.test.js +0 -525
- package/database/encryption/mongo-decryption-fix-verification.test.js +0 -348
- package/database/encryption/postgres-decryption-fix-verification.test.js +0 -371
- package/database/encryption/postgres-relation-decryption.test.js +0 -245
- package/database/encryption/prisma-encryption-extension.test.js +0 -439
- package/errors/base-error.test.js +0 -32
- package/errors/fetch-error.test.js +0 -79
- package/errors/halt-error.test.js +0 -11
- package/errors/validation-errors.test.js +0 -120
- package/handlers/auth-flow.integration.test.js +0 -147
- package/handlers/integration-event-dispatcher.test.js +0 -209
- package/handlers/routers/health.test.js +0 -210
- package/handlers/routers/integration-webhook-routers.test.js +0 -126
- package/handlers/webhook-flow.integration.test.js +0 -356
- package/handlers/workers/integration-defined-workers.test.js +0 -184
- package/integrations/tests/use-cases/create-integration.test.js +0 -131
- package/integrations/tests/use-cases/delete-integration-for-user.test.js +0 -150
- package/integrations/tests/use-cases/find-integration-context-by-external-entity-id.test.js +0 -92
- package/integrations/tests/use-cases/get-integration-for-user.test.js +0 -150
- package/integrations/tests/use-cases/get-integration-instance.test.js +0 -176
- package/integrations/tests/use-cases/get-integrations-for-user.test.js +0 -176
- package/integrations/tests/use-cases/get-possible-integrations.test.js +0 -188
- package/integrations/tests/use-cases/update-integration-messages.test.js +0 -142
- package/integrations/tests/use-cases/update-integration-status.test.js +0 -103
- package/integrations/tests/use-cases/update-integration.test.js +0 -141
- package/integrations/use-cases/create-process.test.js +0 -178
- package/integrations/use-cases/get-process.test.js +0 -190
- package/integrations/use-cases/load-integration-context-full.test.js +0 -329
- package/integrations/use-cases/load-integration-context.test.js +0 -114
- package/integrations/use-cases/update-process-metrics.test.js +0 -308
- package/integrations/use-cases/update-process-state.test.js +0 -256
- package/lambda/TimeoutCatcher.test.js +0 -68
- package/logs/logger.test.js +0 -76
- package/modules/module-hydration.test.js +0 -205
- package/modules/requester/requester.test.js +0 -28
- package/user/tests/use-cases/create-individual-user.test.js +0 -24
- package/user/tests/use-cases/create-organization-user.test.js +0 -28
- package/user/tests/use-cases/create-token-for-user-id.test.js +0 -19
- package/user/tests/use-cases/get-user-from-bearer-token.test.js +0 -64
- package/user/tests/use-cases/login-user.test.js +0 -220
- package/user/tests/user-password-encryption-isolation.test.js +0 -237
- package/user/tests/user-password-hashing.test.js +0 -235
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Migration Router
|
|
3
|
+
*
|
|
4
|
+
* HTTP API for triggering and monitoring database migrations.
|
|
5
|
+
*
|
|
6
|
+
* Endpoints:
|
|
7
|
+
* - GET /db-migrate/status - Check if migrations are pending
|
|
8
|
+
* - POST /db-migrate - Trigger async migration (queues job)
|
|
9
|
+
* - GET /db-migrate/:processId - Check migration status
|
|
10
|
+
*
|
|
11
|
+
* Security:
|
|
12
|
+
* - Requires ADMIN_API_KEY header for all requests
|
|
13
|
+
*
|
|
14
|
+
* Architecture:
|
|
15
|
+
* - Router (Adapter Layer) → Use Cases (Domain) → Repositories (Infrastructure)
|
|
16
|
+
* - Follows DDD/Hexagonal architecture
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const { Router } = require('express');
|
|
20
|
+
const catchAsyncError = require('express-async-handler');
|
|
21
|
+
const { MigrationStatusRepositoryS3 } = require('../../database/repositories/migration-status-repository-s3');
|
|
22
|
+
const {
|
|
23
|
+
TriggerDatabaseMigrationUseCase,
|
|
24
|
+
ValidationError: TriggerValidationError,
|
|
25
|
+
} = require('../../database/use-cases/trigger-database-migration-use-case');
|
|
26
|
+
const {
|
|
27
|
+
GetMigrationStatusUseCase,
|
|
28
|
+
ValidationError: GetValidationError,
|
|
29
|
+
NotFoundError,
|
|
30
|
+
} = require('../../database/use-cases/get-migration-status-use-case');
|
|
31
|
+
const { LambdaInvoker } = require('../../database/adapters/lambda-invoker');
|
|
32
|
+
const {
|
|
33
|
+
GetDatabaseStateViaWorkerUseCase,
|
|
34
|
+
} = require('../../database/use-cases/get-database-state-via-worker-use-case');
|
|
35
|
+
|
|
36
|
+
const router = Router();
|
|
37
|
+
|
|
38
|
+
// Dependency injection
|
|
39
|
+
// Use S3 repository to avoid User table dependency (chicken-and-egg problem)
|
|
40
|
+
const bucketName = process.env.S3_BUCKET_NAME || process.env.MIGRATION_STATUS_BUCKET;
|
|
41
|
+
const migrationStatusRepository = new MigrationStatusRepositoryS3(bucketName);
|
|
42
|
+
|
|
43
|
+
const triggerMigrationUseCase = new TriggerDatabaseMigrationUseCase({
|
|
44
|
+
migrationStatusRepository,
|
|
45
|
+
// Note: QueuerUtil is used directly in the use case (static utility)
|
|
46
|
+
});
|
|
47
|
+
const getStatusUseCase = new GetMigrationStatusUseCase({ migrationStatusRepository });
|
|
48
|
+
|
|
49
|
+
// Lambda invocation for database state check (keeps router lightweight)
|
|
50
|
+
const lambdaInvoker = new LambdaInvoker();
|
|
51
|
+
const workerFunctionName = process.env.WORKER_FUNCTION_NAME ||
|
|
52
|
+
`${process.env.SERVICE || 'unknown'}-${process.env.STAGE || 'production'}-dbMigrationWorker`;
|
|
53
|
+
|
|
54
|
+
const getDatabaseStateUseCase = new GetDatabaseStateViaWorkerUseCase({
|
|
55
|
+
lambdaInvoker,
|
|
56
|
+
workerFunctionName,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Admin API key validation middleware
|
|
61
|
+
* Matches pattern from health.js:72-88
|
|
62
|
+
*/
|
|
63
|
+
const validateApiKey = (req, res, next) => {
|
|
64
|
+
const apiKey = req.headers['x-frigg-admin-api-key'];
|
|
65
|
+
|
|
66
|
+
if (!apiKey || apiKey !== process.env.ADMIN_API_KEY) {
|
|
67
|
+
console.error('Unauthorized access attempt to db-migrate endpoint');
|
|
68
|
+
return res.status(401).json({
|
|
69
|
+
status: 'error',
|
|
70
|
+
message: 'Unauthorized - x-frigg-admin-api-key header required',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
next();
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Apply API key validation to all routes
|
|
78
|
+
router.use(validateApiKey);
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* POST /db-migrate
|
|
82
|
+
*
|
|
83
|
+
* Trigger database migration (async via SQS queue)
|
|
84
|
+
*
|
|
85
|
+
* Request body:
|
|
86
|
+
* {
|
|
87
|
+
* userId: string (optional, defaults to 'admin'),
|
|
88
|
+
* dbType: 'postgresql' | 'mongodb',
|
|
89
|
+
* stage: string (e.g., 'production', 'dev')
|
|
90
|
+
* }
|
|
91
|
+
*
|
|
92
|
+
* Response (202 Accepted):
|
|
93
|
+
* {
|
|
94
|
+
* success: true,
|
|
95
|
+
* processId: string,
|
|
96
|
+
* state: 'INITIALIZING',
|
|
97
|
+
* statusUrl: string,
|
|
98
|
+
* message: string
|
|
99
|
+
* }
|
|
100
|
+
*/
|
|
101
|
+
router.post(
|
|
102
|
+
'/db-migrate',
|
|
103
|
+
catchAsyncError(async (req, res) => {
|
|
104
|
+
// Migration infrastructure is PostgreSQL-only, so hardcode dbType
|
|
105
|
+
const dbType = 'postgresql';
|
|
106
|
+
const { stage } = req.body;
|
|
107
|
+
// TODO: Extract userId from JWT token when auth is implemented
|
|
108
|
+
const userId = req.body.userId || 'admin';
|
|
109
|
+
|
|
110
|
+
console.log(`Migration trigger request: dbType=${dbType}, stage=${stage || 'auto-detect'}, userId=${userId}`);
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const result = await triggerMigrationUseCase.execute({
|
|
114
|
+
userId,
|
|
115
|
+
dbType,
|
|
116
|
+
stage,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// 202 Accepted - request accepted but not completed
|
|
120
|
+
res.status(202).json(result);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
// Handle validation errors (400 Bad Request)
|
|
123
|
+
if (error instanceof TriggerValidationError) {
|
|
124
|
+
return res.status(400).json({
|
|
125
|
+
success: false,
|
|
126
|
+
error: error.message,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Re-throw other errors for global error handler
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* GET /db-migrate/status
|
|
138
|
+
*
|
|
139
|
+
* Check if database has pending migrations
|
|
140
|
+
*
|
|
141
|
+
* Query params:
|
|
142
|
+
* - stage: string (optional, defaults to STAGE env var or 'production')
|
|
143
|
+
*
|
|
144
|
+
* Response (200 OK):
|
|
145
|
+
* {
|
|
146
|
+
* upToDate: boolean,
|
|
147
|
+
* pendingMigrations: number,
|
|
148
|
+
* dbType: 'postgresql',
|
|
149
|
+
* stage: string,
|
|
150
|
+
* recommendation?: string (if migrations pending),
|
|
151
|
+
* error?: string (if database check failed)
|
|
152
|
+
* }
|
|
153
|
+
*/
|
|
154
|
+
router.get(
|
|
155
|
+
'/db-migrate/status',
|
|
156
|
+
catchAsyncError(async (req, res) => {
|
|
157
|
+
const stage = req.query.stage || process.env.STAGE || 'production';
|
|
158
|
+
|
|
159
|
+
console.log(`Checking database state: stage=${stage}, worker=${workerFunctionName}`);
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
// Invoke worker Lambda to check database state
|
|
163
|
+
const status = await getDatabaseStateUseCase.execute(stage);
|
|
164
|
+
|
|
165
|
+
res.status(200).json(status);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
// Log full error for debugging
|
|
168
|
+
console.error('Database state check failed:', error);
|
|
169
|
+
|
|
170
|
+
// Return sanitized error to client
|
|
171
|
+
return res.status(500).json({
|
|
172
|
+
success: false,
|
|
173
|
+
error: 'Failed to check database state',
|
|
174
|
+
details: error.message,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* GET /db-migrate/:migrationId
|
|
182
|
+
*
|
|
183
|
+
* Get migration status by migration ID
|
|
184
|
+
*
|
|
185
|
+
* Response (200 OK):
|
|
186
|
+
* {
|
|
187
|
+
* processId: string,
|
|
188
|
+
* type: 'DATABASE_MIGRATION',
|
|
189
|
+
* state: 'INITIALIZING' | 'RUNNING' | 'COMPLETED' | 'FAILED',
|
|
190
|
+
* context: {
|
|
191
|
+
* dbType: string,
|
|
192
|
+
* stage: string,
|
|
193
|
+
* migrationCommand: string (if started)
|
|
194
|
+
* },
|
|
195
|
+
* results: {
|
|
196
|
+
* success: boolean (if completed),
|
|
197
|
+
* duration: string (if completed),
|
|
198
|
+
* error: string (if failed)
|
|
199
|
+
* },
|
|
200
|
+
* createdAt: string,
|
|
201
|
+
* updatedAt: string
|
|
202
|
+
* }
|
|
203
|
+
*/
|
|
204
|
+
router.get(
|
|
205
|
+
'/db-migrate/:migrationId',
|
|
206
|
+
catchAsyncError(async (req, res) => {
|
|
207
|
+
const { migrationId } = req.params;
|
|
208
|
+
const stage = req.query.stage || process.env.STAGE || 'production';
|
|
209
|
+
|
|
210
|
+
console.log(`Migration status request: migrationId=${migrationId}, stage=${stage}`);
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const status = await getStatusUseCase.execute(migrationId, stage);
|
|
214
|
+
|
|
215
|
+
res.status(200).json(status);
|
|
216
|
+
} catch (error) {
|
|
217
|
+
// Handle not found errors (404 Not Found)
|
|
218
|
+
if (error instanceof NotFoundError) {
|
|
219
|
+
return res.status(404).json({
|
|
220
|
+
success: false,
|
|
221
|
+
error: error.message,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Handle validation errors (400 Bad Request)
|
|
226
|
+
if (error instanceof GetValidationError) {
|
|
227
|
+
return res.status(400).json({
|
|
228
|
+
success: false,
|
|
229
|
+
error: error.message,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Re-throw other errors for global error handler
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
// Minimal Lambda handler (avoids app-handler-helpers which loads core/index.js → user/**)
|
|
240
|
+
const serverlessHttp = require('serverless-http');
|
|
241
|
+
const express = require('express');
|
|
242
|
+
const cors = require('cors');
|
|
243
|
+
|
|
244
|
+
const app = express();
|
|
245
|
+
app.use(cors());
|
|
246
|
+
app.use(express.json());
|
|
247
|
+
app.use(router);
|
|
248
|
+
app.use((err, req, res, next) => {
|
|
249
|
+
console.error('Migration Router Error:', err);
|
|
250
|
+
res.status(500).json({ message: 'Internal Server Error' });
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const handler = serverlessHttp(app);
|
|
254
|
+
|
|
255
|
+
module.exports = { handler, router };
|
|
256
|
+
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
const { Router } = require('express');
|
|
2
|
-
const { moduleFactory, integrationFactory } = require('./../backend-utils');
|
|
3
2
|
const { createAppHandler } = require('./../app-handler-helpers');
|
|
3
|
+
const { loadAppDefinition } = require('./../app-definition-loader');
|
|
4
|
+
const { ModuleFactory } = require('../../modules/module-factory');
|
|
5
|
+
const {
|
|
6
|
+
getModulesDefinitionFromIntegrationClasses,
|
|
7
|
+
} = require('../../integrations/utils/map-integration-dto');
|
|
8
|
+
const {
|
|
9
|
+
createModuleRepository,
|
|
10
|
+
} = require('../../modules/repositories/module-repository-factory');
|
|
11
|
+
const {
|
|
12
|
+
createIntegrationRepository,
|
|
13
|
+
} = require('../../integrations/repositories/integration-repository-factory');
|
|
4
14
|
const {
|
|
5
15
|
createHealthCheckRepository,
|
|
6
16
|
} = require('../../database/repositories/health-check-repository-factory');
|
|
@@ -22,6 +32,28 @@ const {
|
|
|
22
32
|
|
|
23
33
|
const router = Router();
|
|
24
34
|
const healthCheckRepository = createHealthCheckRepository();
|
|
35
|
+
|
|
36
|
+
// Load integrations and create factories just like auth router does
|
|
37
|
+
// This verifies the system can properly load integrations
|
|
38
|
+
let moduleFactory, integrationClasses;
|
|
39
|
+
try {
|
|
40
|
+
const appDef = loadAppDefinition();
|
|
41
|
+
integrationClasses = appDef.integrations || [];
|
|
42
|
+
|
|
43
|
+
const moduleRepository = createModuleRepository();
|
|
44
|
+
const moduleDefinitions = getModulesDefinitionFromIntegrationClasses(integrationClasses);
|
|
45
|
+
|
|
46
|
+
moduleFactory = new ModuleFactory({
|
|
47
|
+
moduleRepository,
|
|
48
|
+
moduleDefinitions,
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('Failed to load integrations for health check:', error.message);
|
|
52
|
+
// Factories will be undefined, health check will report unhealthy
|
|
53
|
+
moduleFactory = undefined;
|
|
54
|
+
integrationClasses = [];
|
|
55
|
+
}
|
|
56
|
+
|
|
25
57
|
const testEncryptionUseCase = new TestEncryptionUseCase({
|
|
26
58
|
healthCheckRepository,
|
|
27
59
|
});
|
|
@@ -34,11 +66,11 @@ const checkEncryptionHealthUseCase = new CheckEncryptionHealthUseCase({
|
|
|
34
66
|
const checkExternalApisHealthUseCase = new CheckExternalApisHealthUseCase();
|
|
35
67
|
const checkIntegrationsHealthUseCase = new CheckIntegrationsHealthUseCase({
|
|
36
68
|
moduleFactory,
|
|
37
|
-
|
|
69
|
+
integrationClasses,
|
|
38
70
|
});
|
|
39
71
|
|
|
40
72
|
const validateApiKey = (req, res, next) => {
|
|
41
|
-
const apiKey = req.headers['x-api-key'];
|
|
73
|
+
const apiKey = req.headers['x-frigg-health-api-key'];
|
|
42
74
|
|
|
43
75
|
if (req.path === '/health') {
|
|
44
76
|
return next();
|
|
@@ -48,7 +80,7 @@ const validateApiKey = (req, res, next) => {
|
|
|
48
80
|
console.error('Unauthorized access attempt to health endpoint');
|
|
49
81
|
return res.status(401).json({
|
|
50
82
|
status: 'error',
|
|
51
|
-
message: 'Unauthorized',
|
|
83
|
+
message: 'Unauthorized - x-frigg-health-api-key header required',
|
|
52
84
|
});
|
|
53
85
|
}
|
|
54
86
|
|
|
@@ -141,8 +173,11 @@ const detectVpcConfiguration = async () => {
|
|
|
141
173
|
}
|
|
142
174
|
}
|
|
143
175
|
|
|
144
|
-
|
|
145
|
-
|
|
176
|
+
// Check if Lambda is in VPC using VPC_ENABLED env var set by infrastructure
|
|
177
|
+
results.isInVpc = process.env.VPC_ENABLED === 'true' ||
|
|
178
|
+
(!results.hasInternetAccess && results.canResolvePublicDns) ||
|
|
179
|
+
results.vpcEndpoints.length > 0;
|
|
180
|
+
|
|
146
181
|
results.canConnectToAws =
|
|
147
182
|
results.hasInternetAccess || results.vpcEndpoints.length > 0;
|
|
148
183
|
} catch (error) {
|
|
@@ -20,7 +20,7 @@ for (const IntegrationClass of integrationClasses) {
|
|
|
20
20
|
console.log(`\n│ Configuring webhook routes for ${IntegrationClass.Definition.name}:`);
|
|
21
21
|
|
|
22
22
|
// General webhook route (no integration ID)
|
|
23
|
-
router.post(
|
|
23
|
+
router.post(basePath, async (req, res, next) => {
|
|
24
24
|
try {
|
|
25
25
|
const integrationInstance = new IntegrationClass();
|
|
26
26
|
const dispatcher = new IntegrationEventDispatcher(integrationInstance);
|
|
@@ -37,7 +37,7 @@ for (const IntegrationClass of integrationClasses) {
|
|
|
37
37
|
console.log(`│ POST ${basePath}`);
|
|
38
38
|
|
|
39
39
|
// Integration-specific webhook route (with integration ID)
|
|
40
|
-
router.post(
|
|
40
|
+
router.post(`${basePath}/:integrationId`, async (req, res, next) => {
|
|
41
41
|
try {
|
|
42
42
|
const integrationInstance = new IntegrationClass();
|
|
43
43
|
const dispatcher = new IntegrationEventDispatcher(integrationInstance);
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
class CheckIntegrationsHealthUseCase {
|
|
2
|
-
constructor({ moduleFactory,
|
|
2
|
+
constructor({ moduleFactory, integrationClasses }) {
|
|
3
3
|
this.moduleFactory = moduleFactory;
|
|
4
|
-
this.
|
|
4
|
+
this.integrationClasses = integrationClasses;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
execute() {
|
|
8
|
-
const
|
|
9
|
-
? this.moduleFactory.
|
|
8
|
+
const moduleDefinitions = (this.moduleFactory && this.moduleFactory.moduleDefinitions)
|
|
9
|
+
? this.moduleFactory.moduleDefinitions
|
|
10
10
|
: [];
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
this.
|
|
14
|
-
)
|
|
15
|
-
? this.integrationFactory.integrationTypes
|
|
12
|
+
const integrationClasses = Array.isArray(this.integrationClasses)
|
|
13
|
+
? this.integrationClasses
|
|
16
14
|
: [];
|
|
17
15
|
|
|
16
|
+
// Extract module names from definitions
|
|
17
|
+
const moduleTypes = Array.isArray(moduleDefinitions)
|
|
18
|
+
? moduleDefinitions.map(def => def.moduleName || def.name || def.label || 'Unknown')
|
|
19
|
+
: [];
|
|
20
|
+
|
|
21
|
+
// Extract integration names from classes
|
|
22
|
+
const integrationNames = integrationClasses.map(IntegrationClass => {
|
|
23
|
+
try {
|
|
24
|
+
return IntegrationClass.Definition?.name || IntegrationClass.name || 'Unknown';
|
|
25
|
+
} catch {
|
|
26
|
+
return 'Unknown';
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
18
30
|
return {
|
|
19
31
|
status: 'healthy',
|
|
20
32
|
modules: {
|
|
@@ -22,8 +34,8 @@ class CheckIntegrationsHealthUseCase {
|
|
|
22
34
|
available: moduleTypes,
|
|
23
35
|
},
|
|
24
36
|
integrations: {
|
|
25
|
-
count:
|
|
26
|
-
available:
|
|
37
|
+
count: integrationNames.length,
|
|
38
|
+
available: integrationNames,
|
|
27
39
|
},
|
|
28
40
|
};
|
|
29
41
|
}
|