@friggframework/core 2.0.0-next.6 → 2.0.0-next.60
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/CLAUDE.md +694 -0
- package/README.md +959 -50
- package/application/commands/README.md +451 -0
- package/application/commands/credential-commands.js +245 -0
- package/application/commands/entity-commands.js +336 -0
- package/application/commands/integration-commands.js +210 -0
- package/application/commands/user-commands.js +283 -0
- package/application/index.js +69 -0
- package/core/CLAUDE.md +690 -0
- package/core/Worker.js +8 -21
- package/core/create-handler.js +14 -7
- package/credential/repositories/credential-repository-documentdb.js +304 -0
- package/credential/repositories/credential-repository-factory.js +54 -0
- package/credential/repositories/credential-repository-interface.js +98 -0
- package/credential/repositories/credential-repository-mongo.js +269 -0
- package/credential/repositories/credential-repository-postgres.js +291 -0
- package/credential/repositories/credential-repository.js +302 -0
- package/credential/use-cases/get-credential-for-user.js +25 -0
- package/credential/use-cases/update-authentication-status.js +15 -0
- package/database/MONGODB_TRANSACTION_FIX.md +198 -0
- package/database/adapters/lambda-invoker.js +97 -0
- package/database/config.js +154 -0
- package/database/documentdb-encryption-service.js +330 -0
- package/database/documentdb-utils.js +136 -0
- package/database/encryption/README.md +839 -0
- package/database/encryption/documentdb-encryption-service.md +3575 -0
- package/database/encryption/encryption-schema-registry.js +268 -0
- package/database/encryption/field-encryption-service.js +226 -0
- package/database/encryption/logger.js +79 -0
- package/database/encryption/prisma-encryption-extension.js +222 -0
- package/database/index.js +61 -21
- package/database/models/WebsocketConnection.js +16 -10
- package/database/models/readme.md +1 -0
- package/database/prisma.js +182 -0
- package/database/repositories/health-check-repository-documentdb.js +134 -0
- package/database/repositories/health-check-repository-factory.js +48 -0
- package/database/repositories/health-check-repository-interface.js +82 -0
- package/database/repositories/health-check-repository-mongodb.js +89 -0
- package/database/repositories/health-check-repository-postgres.js +82 -0
- package/database/repositories/health-check-repository.js +108 -0
- package/database/repositories/migration-status-repository-s3.js +137 -0
- package/database/use-cases/check-database-health-use-case.js +29 -0
- package/database/use-cases/check-database-state-use-case.js +81 -0
- package/database/use-cases/check-encryption-health-use-case.js +83 -0
- 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 +139 -0
- package/database/use-cases/test-encryption-use-case.js +253 -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 +477 -0
- package/database/utils/prisma-schema-parser.js +182 -0
- package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
- package/encrypt/Cryptor.js +34 -168
- package/encrypt/index.js +1 -2
- package/encrypt/test-encrypt.js +0 -2
- package/errors/client-safe-error.js +26 -0
- package/errors/fetch-error.js +2 -1
- package/errors/index.js +2 -0
- 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 +22903 -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 +360 -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 +25077 -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 +343 -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/WEBHOOKS.md +653 -0
- package/handlers/app-definition-loader.js +38 -0
- package/handlers/app-handler-helpers.js +56 -0
- package/handlers/backend-utils.js +186 -0
- package/handlers/database-migration-handler.js +227 -0
- package/handlers/integration-event-dispatcher.js +54 -0
- package/handlers/routers/HEALTHCHECK.md +342 -0
- package/handlers/routers/auth.js +15 -0
- package/handlers/routers/db-migration.handler.js +29 -0
- package/handlers/routers/db-migration.js +326 -0
- package/handlers/routers/health.js +516 -0
- package/handlers/routers/integration-defined-routers.js +45 -0
- package/handlers/routers/integration-webhook-routers.js +67 -0
- package/handlers/routers/user.js +63 -0
- package/handlers/routers/websocket.js +57 -0
- package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
- package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
- package/handlers/workers/db-migration.js +352 -0
- package/handlers/workers/integration-defined-workers.js +27 -0
- package/index.js +77 -22
- package/integrations/WEBHOOK-QUICKSTART.md +151 -0
- package/integrations/index.js +12 -10
- package/integrations/integration-base.js +326 -55
- package/integrations/integration-router.js +374 -179
- package/integrations/options.js +1 -1
- package/integrations/repositories/integration-mapping-repository-documentdb.js +280 -0
- package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
- package/integrations/repositories/integration-mapping-repository-interface.js +106 -0
- package/integrations/repositories/integration-mapping-repository-mongo.js +161 -0
- package/integrations/repositories/integration-mapping-repository-postgres.js +227 -0
- package/integrations/repositories/integration-mapping-repository.js +156 -0
- package/integrations/repositories/integration-repository-documentdb.js +210 -0
- package/integrations/repositories/integration-repository-factory.js +51 -0
- package/integrations/repositories/integration-repository-interface.js +127 -0
- package/integrations/repositories/integration-repository-mongo.js +303 -0
- package/integrations/repositories/integration-repository-postgres.js +352 -0
- package/integrations/repositories/process-repository-documentdb.js +243 -0
- package/integrations/repositories/process-repository-factory.js +53 -0
- package/integrations/repositories/process-repository-interface.js +90 -0
- package/integrations/repositories/process-repository-mongo.js +190 -0
- package/integrations/repositories/process-repository-postgres.js +217 -0
- package/integrations/tests/doubles/dummy-integration-class.js +83 -0
- package/integrations/tests/doubles/test-integration-repository.js +99 -0
- package/integrations/use-cases/create-integration.js +83 -0
- package/integrations/use-cases/create-process.js +128 -0
- package/integrations/use-cases/delete-integration-for-user.js +101 -0
- package/integrations/use-cases/find-integration-context-by-external-entity-id.js +72 -0
- package/integrations/use-cases/get-integration-for-user.js +78 -0
- package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
- package/integrations/use-cases/get-integration-instance.js +83 -0
- package/integrations/use-cases/get-integrations-for-user.js +88 -0
- package/integrations/use-cases/get-possible-integrations.js +27 -0
- package/integrations/use-cases/get-process.js +87 -0
- package/integrations/use-cases/index.js +19 -0
- package/integrations/use-cases/load-integration-context.js +71 -0
- package/integrations/use-cases/update-integration-messages.js +44 -0
- package/integrations/use-cases/update-integration-status.js +32 -0
- package/integrations/use-cases/update-integration.js +93 -0
- package/integrations/use-cases/update-process-metrics.js +201 -0
- package/integrations/use-cases/update-process-state.js +119 -0
- package/integrations/utils/map-integration-dto.js +37 -0
- package/jest-global-setup-noop.js +3 -0
- package/jest-global-teardown-noop.js +3 -0
- package/logs/logger.js +0 -4
- package/{module-plugin → modules}/entity.js +1 -1
- package/{module-plugin → modules}/index.js +0 -8
- package/modules/module-factory.js +56 -0
- package/modules/module.js +221 -0
- package/modules/repositories/module-repository-documentdb.js +307 -0
- package/modules/repositories/module-repository-factory.js +40 -0
- package/modules/repositories/module-repository-interface.js +129 -0
- package/modules/repositories/module-repository-mongo.js +377 -0
- package/modules/repositories/module-repository-postgres.js +426 -0
- package/modules/repositories/module-repository.js +316 -0
- package/modules/requester/api-key.js +52 -0
- package/{module-plugin → modules}/requester/requester.js +1 -0
- package/{module-plugin → modules}/test/mock-api/api.js +8 -3
- package/{module-plugin → modules}/test/mock-api/definition.js +12 -8
- package/modules/tests/doubles/test-module-factory.js +16 -0
- package/modules/tests/doubles/test-module-repository.js +39 -0
- package/modules/use-cases/get-entities-for-user.js +32 -0
- package/modules/use-cases/get-entity-options-by-id.js +71 -0
- package/modules/use-cases/get-entity-options-by-type.js +34 -0
- package/modules/use-cases/get-module-instance-from-type.js +31 -0
- package/modules/use-cases/get-module.js +74 -0
- package/modules/use-cases/process-authorization-callback.js +133 -0
- package/modules/use-cases/refresh-entity-options.js +72 -0
- package/modules/use-cases/test-module-auth.js +72 -0
- package/modules/utils/map-module-dto.js +18 -0
- package/package.json +82 -50
- package/prisma-mongodb/schema.prisma +360 -0
- package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
- package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
- package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
- package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
- package/prisma-postgresql/migrations/migration_lock.toml +3 -0
- package/prisma-postgresql/schema.prisma +343 -0
- package/queues/queuer-util.js +27 -22
- package/syncs/manager.js +468 -443
- package/syncs/repositories/sync-repository-documentdb.js +240 -0
- package/syncs/repositories/sync-repository-factory.js +43 -0
- package/syncs/repositories/sync-repository-interface.js +109 -0
- package/syncs/repositories/sync-repository-mongo.js +239 -0
- package/syncs/repositories/sync-repository-postgres.js +319 -0
- package/syncs/sync.js +0 -1
- package/token/repositories/token-repository-documentdb.js +137 -0
- package/token/repositories/token-repository-factory.js +40 -0
- package/token/repositories/token-repository-interface.js +131 -0
- package/token/repositories/token-repository-mongo.js +219 -0
- package/token/repositories/token-repository-postgres.js +264 -0
- package/token/repositories/token-repository.js +219 -0
- package/types/core/index.d.ts +2 -2
- package/types/integrations/index.d.ts +2 -6
- package/types/module-plugin/index.d.ts +5 -59
- package/types/syncs/index.d.ts +0 -2
- package/user/repositories/user-repository-documentdb.js +441 -0
- package/user/repositories/user-repository-factory.js +52 -0
- package/user/repositories/user-repository-interface.js +201 -0
- package/user/repositories/user-repository-mongo.js +308 -0
- package/user/repositories/user-repository-postgres.js +360 -0
- package/user/tests/doubles/test-user-repository.js +72 -0
- package/user/use-cases/authenticate-user.js +127 -0
- package/user/use-cases/authenticate-with-shared-secret.js +48 -0
- package/user/use-cases/create-individual-user.js +61 -0
- package/user/use-cases/create-organization-user.js +47 -0
- package/user/use-cases/create-token-for-user-id.js +30 -0
- package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
- package/user/use-cases/get-user-from-bearer-token.js +77 -0
- package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
- package/user/use-cases/login-user.js +122 -0
- package/user/user.js +125 -0
- package/utils/backend-path.js +38 -0
- package/utils/index.js +6 -0
- package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
- package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
- package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
- package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
- package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
- package/websocket/repositories/websocket-connection-repository.js +161 -0
- package/database/models/State.js +0 -9
- package/database/models/Token.js +0 -70
- package/database/mongo.js +0 -45
- package/encrypt/Cryptor.test.js +0 -32
- package/encrypt/encrypt.js +0 -132
- package/encrypt/encrypt.test.js +0 -1069
- 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/integrations/create-frigg-backend.js +0 -31
- package/integrations/integration-factory.js +0 -251
- package/integrations/integration-mapping.js +0 -43
- package/integrations/integration-model.js +0 -46
- package/integrations/integration-user.js +0 -144
- package/integrations/test/integration-base.test.js +0 -144
- package/lambda/TimeoutCatcher.test.js +0 -68
- package/logs/logger.test.js +0 -76
- package/module-plugin/auther.js +0 -393
- package/module-plugin/credential.js +0 -22
- package/module-plugin/entity-manager.js +0 -70
- package/module-plugin/manager.js +0 -169
- package/module-plugin/module-factory.js +0 -61
- package/module-plugin/requester/api-key.js +0 -36
- package/module-plugin/requester/requester.test.js +0 -28
- package/module-plugin/test/auther.test.js +0 -97
- /package/{module-plugin → modules}/ModuleConstants.js +0 -0
- /package/{module-plugin → modules}/requester/basic.js +0 -0
- /package/{module-plugin → modules}/requester/oauth-2.js +0 -0
- /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const { Module } = require('../module');
|
|
2
|
+
|
|
3
|
+
class GetModule {
|
|
4
|
+
constructor({ moduleRepository, moduleDefinitions }) {
|
|
5
|
+
this.moduleRepository = moduleRepository;
|
|
6
|
+
this.moduleDefinitions = moduleDefinitions;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get module instance for an entity
|
|
11
|
+
*
|
|
12
|
+
* @param {string|number} entityId - Entity ID to retrieve
|
|
13
|
+
* @param {string|number|import('../../user/user').User} userIdOrUser - User ID or User object for validation
|
|
14
|
+
* @returns {Promise<Object>} Module details
|
|
15
|
+
*/
|
|
16
|
+
async execute(entityId, userIdOrUser) {
|
|
17
|
+
// Support both userId (backward compatible) and User object (new pattern)
|
|
18
|
+
const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
|
|
19
|
+
? userIdOrUser.getId()
|
|
20
|
+
: userIdOrUser;
|
|
21
|
+
|
|
22
|
+
const entity = await this.moduleRepository.findEntityById(
|
|
23
|
+
entityId,
|
|
24
|
+
userId
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (!entity) {
|
|
28
|
+
throw new Error(`Entity ${entityId} not found`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Validate entity ownership
|
|
32
|
+
// If User object provided, use ownsUserId to check linked users
|
|
33
|
+
// Otherwise fall back to simple equality check
|
|
34
|
+
const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
|
|
35
|
+
? userIdOrUser.ownsUserId(entity.userId)
|
|
36
|
+
: entity.userId?.toString() === userId?.toString();
|
|
37
|
+
|
|
38
|
+
if (!isOwned) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Entity ${entityId} does not belong to user ${userId}`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const entityType = entity.moduleName;
|
|
45
|
+
const moduleDefinition = this.moduleDefinitions.find((def) => {
|
|
46
|
+
const modelName = Module.getEntityModelFromDefinition(def).modelName;
|
|
47
|
+
return entityType === modelName;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (!moduleDefinition) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Module definition not found for entity type: ${entityType}`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const module = new Module({
|
|
57
|
+
userId,
|
|
58
|
+
entity,
|
|
59
|
+
definition: moduleDefinition,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// todo: this properties should be methods in the Module class
|
|
63
|
+
return {
|
|
64
|
+
id: module.entity.id,
|
|
65
|
+
name: module.entity.name,
|
|
66
|
+
moduleName: module.entity.moduleName,
|
|
67
|
+
credential: module.credential,
|
|
68
|
+
externalId: module.entity.externalId,
|
|
69
|
+
userId: module.entity.user.toString(),
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = { GetModule };
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const { Module } = require('../module');
|
|
2
|
+
const { ModuleConstants } = require('../ModuleConstants');
|
|
3
|
+
|
|
4
|
+
class ProcessAuthorizationCallback {
|
|
5
|
+
/**
|
|
6
|
+
* @param {Object} params - Configuration parameters.
|
|
7
|
+
* @param {import('../repositories/module-repository-factory').ModuleRepositoryInterface} params.moduleRepository - Repository for module data operations.
|
|
8
|
+
* @param {import('../../credential/repositories/credential-repository-factory').CredentialRepositoryInterface} params.credentialRepository - Repository for credential data operations.
|
|
9
|
+
* @param {Array<Object>} params.moduleDefinitions - Array of module definitions.
|
|
10
|
+
*/
|
|
11
|
+
constructor({ moduleRepository, credentialRepository, moduleDefinitions }) {
|
|
12
|
+
this.moduleRepository = moduleRepository;
|
|
13
|
+
this.credentialRepository = credentialRepository;
|
|
14
|
+
this.moduleDefinitions = moduleDefinitions;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async execute(userId, entityType, params) {
|
|
18
|
+
const moduleDefinition = this.moduleDefinitions.find((def) => {
|
|
19
|
+
return entityType === def.moduleName;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (!moduleDefinition) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
`Module definition not found for entity type: ${entityType}`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// todo: check if we need to pass entity to Module, right now it's null
|
|
29
|
+
let entity = null;
|
|
30
|
+
|
|
31
|
+
const module = new Module({
|
|
32
|
+
userId,
|
|
33
|
+
entity,
|
|
34
|
+
definition: moduleDefinition,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
let tokenResponse;
|
|
38
|
+
if (module.apiClass.requesterType === ModuleConstants.authType.oauth2) {
|
|
39
|
+
tokenResponse = await moduleDefinition.requiredAuthMethods.getToken(
|
|
40
|
+
module.api,
|
|
41
|
+
params
|
|
42
|
+
);
|
|
43
|
+
} else {
|
|
44
|
+
tokenResponse =
|
|
45
|
+
await moduleDefinition.requiredAuthMethods.setAuthParams(
|
|
46
|
+
module.api,
|
|
47
|
+
params
|
|
48
|
+
);
|
|
49
|
+
await this.onTokenUpdate(module, moduleDefinition, userId);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const authRes = await module.testAuth();
|
|
53
|
+
if (!authRes) {
|
|
54
|
+
throw new Error('Authorization failed');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const entityDetails =
|
|
58
|
+
await moduleDefinition.requiredAuthMethods.getEntityDetails(
|
|
59
|
+
module.api,
|
|
60
|
+
params,
|
|
61
|
+
tokenResponse,
|
|
62
|
+
userId
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
Object.assign(
|
|
66
|
+
entityDetails.details,
|
|
67
|
+
module.apiParamsFromEntity(module.api)
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const persistedEntity = await this.findOrCreateEntity(
|
|
71
|
+
entityDetails,
|
|
72
|
+
entityType,
|
|
73
|
+
module.credential.id
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
credential_id: module.credential.id,
|
|
78
|
+
entity_id: persistedEntity.id,
|
|
79
|
+
type: module.getName(),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async onTokenUpdate(module, moduleDefinition, userId) {
|
|
84
|
+
const credentialDetails =
|
|
85
|
+
await moduleDefinition.requiredAuthMethods.getCredentialDetails(
|
|
86
|
+
module.api,
|
|
87
|
+
userId
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
Object.assign(
|
|
91
|
+
credentialDetails.details,
|
|
92
|
+
module.apiParamsFromCredential(module.api)
|
|
93
|
+
);
|
|
94
|
+
credentialDetails.details.authIsValid = true;
|
|
95
|
+
|
|
96
|
+
const persisted = await this.credentialRepository.upsertCredential(credentialDetails);
|
|
97
|
+
module.credential = persisted;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async findOrCreateEntity(entityDetails, moduleName, credentialId) {
|
|
101
|
+
const { identifiers, details } = entityDetails;
|
|
102
|
+
|
|
103
|
+
// Support both 'user' and 'userId' field names from module definitions
|
|
104
|
+
// Some modules use 'user' (legacy), others use 'userId' (newer pattern)
|
|
105
|
+
const userId = identifiers.user || identifiers.userId;
|
|
106
|
+
|
|
107
|
+
if (!userId) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`Module definition for ${moduleName} must return 'user' or 'userId' in identifiers from getEntityDetails(). ` +
|
|
110
|
+
`Without userId, entity lookup would match across all users (security issue).`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const existingEntity = await this.moduleRepository.findEntity({
|
|
115
|
+
externalId: identifiers.externalId,
|
|
116
|
+
user: userId,
|
|
117
|
+
moduleName: moduleName,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (existingEntity) {
|
|
121
|
+
return existingEntity;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return await this.moduleRepository.createEntity({
|
|
125
|
+
...identifiers,
|
|
126
|
+
...details,
|
|
127
|
+
moduleName: moduleName,
|
|
128
|
+
credential: credentialId,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
module.exports = { ProcessAuthorizationCallback };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const { Module } = require('../module');
|
|
2
|
+
|
|
3
|
+
class RefreshEntityOptions {
|
|
4
|
+
/**
|
|
5
|
+
* @param {Object} params
|
|
6
|
+
* @param {import('../repositories/module-repository-interface').ModuleRepositoryInterface} params.moduleRepository
|
|
7
|
+
* @param {} params.moduleDefinitions
|
|
8
|
+
*/
|
|
9
|
+
constructor({ moduleRepository, moduleDefinitions }) {
|
|
10
|
+
this.moduleRepository = moduleRepository;
|
|
11
|
+
this.moduleDefinitions = moduleDefinitions;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Refresh entity options for a given entity
|
|
16
|
+
*
|
|
17
|
+
* @param {string|number} entityId - Entity ID to refresh
|
|
18
|
+
* @param {string|number|import('../../user/user').User} userIdOrUser - User ID or User object for validation
|
|
19
|
+
* @param {Object} options - Refresh options
|
|
20
|
+
* @returns {Promise<Object>} Updated entity options
|
|
21
|
+
*/
|
|
22
|
+
async execute(entityId, userIdOrUser, options) {
|
|
23
|
+
// Support both userId (backward compatible) and User object (new pattern)
|
|
24
|
+
const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
|
|
25
|
+
? userIdOrUser.getId()
|
|
26
|
+
: userIdOrUser;
|
|
27
|
+
|
|
28
|
+
const entity = await this.moduleRepository.findEntityById(
|
|
29
|
+
entityId,
|
|
30
|
+
userId
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (!entity) {
|
|
34
|
+
throw new Error(`Entity ${entityId} not found`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Validate entity ownership
|
|
38
|
+
const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
|
|
39
|
+
? userIdOrUser.ownsUserId(entity.userId)
|
|
40
|
+
: entity.userId?.toString() === userId?.toString();
|
|
41
|
+
|
|
42
|
+
if (!isOwned) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`Entity ${entityId} does not belong to user ${userId}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const entityType = entity.moduleName;
|
|
49
|
+
const moduleDefinition = this.moduleDefinitions.find((def) => {
|
|
50
|
+
const modelName =
|
|
51
|
+
Module.getEntityModelFromDefinition(def).modelName;
|
|
52
|
+
return entityType === modelName;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (!moduleDefinition) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Module definition not found for entity type: ${entityType}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const module = new Module({
|
|
62
|
+
userId,
|
|
63
|
+
entity,
|
|
64
|
+
definition: moduleDefinition,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await module.refreshEntityOptions(options);
|
|
68
|
+
return module.getEntityOptions();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = { RefreshEntityOptions };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const { Module } = require('../module');
|
|
2
|
+
|
|
3
|
+
class TestModuleAuth {
|
|
4
|
+
/**
|
|
5
|
+
* @param {Object} params - Configuration parameters.
|
|
6
|
+
* @param {import('../repositories/module-repository-interface').ModuleRepositoryInterface} params.moduleRepository - Repository for module data operations.
|
|
7
|
+
* @param {Array<Object>} params.moduleDefinitions - Array of module definitions.
|
|
8
|
+
*/
|
|
9
|
+
constructor({ moduleRepository, moduleDefinitions }) {
|
|
10
|
+
this.moduleRepository = moduleRepository;
|
|
11
|
+
this.moduleDefinitions = moduleDefinitions;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Test authentication for a module entity
|
|
16
|
+
*
|
|
17
|
+
* @param {string|number} entityId - Entity ID to test
|
|
18
|
+
* @param {string|number|import('../../user/user').User} userIdOrUser - User ID or User object for validation
|
|
19
|
+
* @returns {Promise<boolean>} Authentication test result
|
|
20
|
+
*/
|
|
21
|
+
async execute(entityId, userIdOrUser) {
|
|
22
|
+
// Support both userId (backward compatible) and User object (new pattern)
|
|
23
|
+
const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
|
|
24
|
+
? userIdOrUser.getId()
|
|
25
|
+
: userIdOrUser;
|
|
26
|
+
|
|
27
|
+
const entity = await this.moduleRepository.findEntityById(
|
|
28
|
+
entityId,
|
|
29
|
+
userId
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if (!entity) {
|
|
33
|
+
throw new Error(`Entity ${entityId} not found`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Validate entity ownership
|
|
37
|
+
const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
|
|
38
|
+
? userIdOrUser.ownsUserId(entity.userId)
|
|
39
|
+
: entity.userId?.toString() === userId?.toString();
|
|
40
|
+
|
|
41
|
+
if (!isOwned) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Entity ${entityId} does not belong to user ${userId}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const entityType = entity.moduleName;
|
|
48
|
+
const moduleDefinition = this.moduleDefinitions.find((def) => {
|
|
49
|
+
const modelName =
|
|
50
|
+
Module.getEntityModelFromDefinition(def).modelName;
|
|
51
|
+
return entityType === modelName;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (!moduleDefinition) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`Module definition not found for entity type: ${entityType}`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const module = new Module({
|
|
61
|
+
userId,
|
|
62
|
+
entity,
|
|
63
|
+
definition: moduleDefinition,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const testAuthResponse = await module.testAuth();
|
|
67
|
+
|
|
68
|
+
return testAuthResponse;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = { TestModuleAuth };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {import('../module').Module} moduleInstance
|
|
3
|
+
* Convert a Module domain instance to a plain DTO suitable for JSON responses.
|
|
4
|
+
*/
|
|
5
|
+
function mapModuleClassToModuleDTO(moduleInstance) {
|
|
6
|
+
if (!moduleInstance) return null;
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
id: moduleInstance.entity.id,
|
|
10
|
+
name: moduleInstance.name,
|
|
11
|
+
userId: moduleInstance.userId,
|
|
12
|
+
entity: moduleInstance.entity,
|
|
13
|
+
credentialId: moduleInstance.credential?._id?.toString(),
|
|
14
|
+
type: moduleInstance.getName()
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = { mapModuleClassToModuleDTO };
|
package/package.json
CHANGED
|
@@ -1,52 +1,84 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
2
|
+
"name": "@friggframework/core",
|
|
3
|
+
"prettier": "@friggframework/prettier-config",
|
|
4
|
+
"version": "2.0.0-next.60",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
|
|
7
|
+
"@aws-sdk/client-kms": "^3.588.0",
|
|
8
|
+
"@aws-sdk/client-lambda": "^3.714.0",
|
|
9
|
+
"@aws-sdk/client-sqs": "^3.588.0",
|
|
10
|
+
"@hapi/boom": "^10.0.1",
|
|
11
|
+
"bcryptjs": "^2.4.3",
|
|
12
|
+
"body-parser": "^1.20.2",
|
|
13
|
+
"chalk": "^4.1.2",
|
|
14
|
+
"common-tags": "^1.8.2",
|
|
15
|
+
"cors": "^2.8.5",
|
|
16
|
+
"dotenv": "^16.4.7",
|
|
17
|
+
"express": "^4.19.2",
|
|
18
|
+
"express-async-handler": "^1.2.0",
|
|
19
|
+
"form-data": "^4.0.0",
|
|
20
|
+
"fs-extra": "^11.2.0",
|
|
21
|
+
"lodash": "4.17.21",
|
|
22
|
+
"lodash.get": "^4.4.2",
|
|
23
|
+
"mongoose": "6.11.6",
|
|
24
|
+
"node-fetch": "^2.6.7",
|
|
25
|
+
"serverless-http": "^2.7.0",
|
|
26
|
+
"uuid": "^9.0.1"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@prisma/client": "^6.16.3",
|
|
30
|
+
"prisma": "^6.16.3"
|
|
31
|
+
},
|
|
32
|
+
"peerDependenciesMeta": {
|
|
33
|
+
"@prisma/client": {
|
|
34
|
+
"optional": true
|
|
35
|
+
},
|
|
36
|
+
"prisma": {
|
|
37
|
+
"optional": true
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@friggframework/eslint-config": "2.0.0-next.60",
|
|
42
|
+
"@friggframework/prettier-config": "2.0.0-next.60",
|
|
43
|
+
"@friggframework/test": "2.0.0-next.60",
|
|
44
|
+
"@prisma/client": "^6.17.0",
|
|
45
|
+
"@types/lodash": "4.17.15",
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
47
|
+
"chai": "^4.3.6",
|
|
48
|
+
"eslint": "^8.22.0",
|
|
49
|
+
"eslint-plugin-import": "^2.29.1",
|
|
50
|
+
"eslint-plugin-n": "^17.10.2",
|
|
51
|
+
"eslint-plugin-promise": "^7.0.0",
|
|
52
|
+
"jest": "^29.7.0",
|
|
53
|
+
"prettier": "^2.7.1",
|
|
54
|
+
"prisma": "^6.17.0",
|
|
55
|
+
"sinon": "^16.1.1",
|
|
56
|
+
"typescript": "^5.0.2"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"lint:fix": "prettier --write --loglevel error . && eslint . --fix",
|
|
60
|
+
"test": "jest --passWithNoTests # TODO",
|
|
61
|
+
"prisma:generate:mongo": "npx prisma generate --schema ./prisma-mongodb/schema.prisma",
|
|
62
|
+
"prisma:generate:postgres": "npx prisma generate --schema ./prisma-postgresql/schema.prisma",
|
|
63
|
+
"prisma:generate": "npm run prisma:generate:mongo && npm run prisma:generate:postgres",
|
|
64
|
+
"prisma:push:mongo": "npx prisma db push --schema ./prisma-mongodb/schema.prisma",
|
|
65
|
+
"prisma:migrate:postgres": "npx prisma migrate dev --schema ./prisma-postgresql/schema.prisma",
|
|
66
|
+
"prepublishOnly": "npm run prisma:generate"
|
|
67
|
+
},
|
|
68
|
+
"author": "",
|
|
69
|
+
"license": "MIT",
|
|
70
|
+
"main": "index.js",
|
|
71
|
+
"repository": {
|
|
72
|
+
"type": "git",
|
|
73
|
+
"url": "git+https://github.com/friggframework/frigg.git"
|
|
74
|
+
},
|
|
75
|
+
"bugs": {
|
|
76
|
+
"url": "https://github.com/friggframework/frigg/issues"
|
|
77
|
+
},
|
|
78
|
+
"homepage": "https://github.com/friggframework/frigg#readme",
|
|
79
|
+
"description": "",
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public"
|
|
82
|
+
},
|
|
83
|
+
"gitHead": "8fc85a629bedc7b17a9415ef8952dddb1daee1b5"
|
|
52
84
|
}
|