@friggframework/core 2.0.0--canary.522.cbd3d5a.0 → 2.0.0--canary.517.35ee143.0
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/CHANGELOG.md +67 -66
- package/CLAUDE.md +124 -148
- package/README.md +130 -165
- package/admin-scripts/index.js +16 -30
- package/admin-scripts/repositories/{admin-api-key-repository-documentdb.js → admin-process-repository-documentdb.js} +5 -5
- package/admin-scripts/repositories/{admin-api-key-repository-factory.js → admin-process-repository-factory.js} +15 -19
- package/admin-scripts/repositories/admin-process-repository-interface.js +150 -0
- package/admin-scripts/repositories/admin-process-repository-mongo.js +213 -0
- package/admin-scripts/repositories/admin-process-repository-postgres.js +251 -0
- package/admin-scripts/repositories/script-schedule-repository-factory.js +2 -6
- package/admin-scripts/repositories/script-schedule-repository-interface.js +14 -36
- package/admin-scripts/repositories/script-schedule-repository-mongo.js +13 -25
- package/admin-scripts/repositories/script-schedule-repository-postgres.js +13 -25
- package/application/commands/admin-script-commands.js +102 -266
- package/application/commands/integration-commands.js +6 -12
- package/application/index.js +3 -1
- package/assertions/get.js +4 -1
- package/associations/association.js +57 -59
- package/associations/model.js +41 -41
- package/core/CLAUDE.md +156 -222
- package/core/Worker.js +1 -5
- package/credential/repositories/credential-repository-documentdb.js +1 -71
- package/credential/repositories/credential-repository-interface.js +2 -8
- package/credential/repositories/credential-repository-mongo.js +4 -45
- package/credential/repositories/credential-repository-postgres.js +3 -44
- package/credential/repositories/credential-repository.js +4 -6
- package/credential/use-cases/get-credential-for-user.js +3 -21
- package/credential/use-cases/update-authentication-status.js +2 -5
- package/database/MONGODB_TRANSACTION_FIX.md +52 -72
- package/database/adapters/lambda-invoker.js +7 -8
- package/database/config.js +13 -15
- package/database/documentdb-encryption-service.js +13 -29
- package/database/documentdb-utils.js +12 -21
- package/database/encryption/README.md +36 -53
- package/database/encryption/encryption-schema-registry.js +9 -21
- package/database/encryption/field-encryption-service.js +4 -15
- package/database/encryption/logger.js +2 -3
- package/database/encryption/prisma-encryption-extension.js +8 -5
- package/database/index.js +2 -4
- package/database/models/IndividualUser.js +15 -15
- package/database/models/OrganizationUser.js +4 -6
- package/database/models/UserModel.js +2 -2
- package/database/models/WebsocketConnection.js +1 -4
- package/database/mongoose.js +2 -2
- package/database/prisma.js +14 -22
- package/database/repositories/health-check-repository-documentdb.js +7 -22
- package/database/repositories/health-check-repository-factory.js +3 -9
- package/database/repositories/health-check-repository-interface.js +5 -15
- package/database/repositories/health-check-repository-mongodb.js +6 -9
- package/database/repositories/health-check-repository-postgres.js +1 -1
- package/database/repositories/migration-status-repository-s3.js +5 -10
- package/database/use-cases/check-database-health-use-case.js +2 -3
- package/database/use-cases/check-database-state-use-case.js +7 -9
- package/database/use-cases/get-database-state-via-worker-use-case.js +12 -15
- package/database/use-cases/get-migration-status-use-case.js +2 -4
- package/database/use-cases/run-database-migration-use-case.js +9 -41
- package/database/use-cases/test-encryption-use-case.js +5 -4
- package/database/use-cases/trigger-database-migration-use-case.js +8 -9
- package/database/utils/mongodb-collection-utils.js +3 -11
- package/database/utils/mongodb-schema-init.js +4 -10
- package/database/utils/prisma-runner.js +74 -144
- package/database/utils/prisma-schema-parser.js +2 -2
- package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +80 -135
- package/encrypt/Cryptor.js +2 -8
- package/errors/fetch-error.js +1 -1
- package/generated/prisma-mongodb/edge.js +16 -59
- package/generated/prisma-mongodb/index-browser.js +12 -62
- package/generated/prisma-mongodb/index.d.ts +4850 -8136
- package/generated/prisma-mongodb/index.js +16 -59
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +33 -75
- package/generated/prisma-mongodb/wasm.js +16 -59
- package/generated/prisma-postgresql/edge.js +15 -59
- package/generated/prisma-postgresql/index-browser.js +11 -62
- package/generated/prisma-postgresql/index.d.ts +5963 -8930
- package/generated/prisma-postgresql/index.js +15 -59
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +33 -73
- package/generated/prisma-postgresql/wasm.js +15 -59
- package/handlers/WEBHOOKS.md +81 -104
- package/handlers/app-definition-loader.js +1 -1
- package/handlers/app-handler-helpers.js +2 -14
- package/handlers/backend-utils.js +1 -0
- package/handlers/database-migration-handler.js +45 -64
- package/handlers/middleware/admin-auth.js +53 -0
- package/handlers/routers/HEALTHCHECK.md +135 -170
- package/handlers/routers/auth.js +2 -23
- package/handlers/routers/db-migration.handler.js +3 -2
- package/handlers/routers/db-migration.js +33 -69
- package/handlers/routers/health.js +8 -23
- package/handlers/routers/integration-defined-routers.js +4 -4
- package/handlers/routers/integration-webhook-routers.js +7 -17
- package/handlers/routers/websocket.js +3 -9
- package/handlers/use-cases/check-integrations-health-use-case.js +6 -13
- package/handlers/workers/db-migration.js +26 -54
- package/index.js +9 -5
- package/integrations/WEBHOOK-QUICKSTART.md +14 -21
- package/integrations/index.js +0 -4
- package/integrations/integration-base.js +6 -9
- package/integrations/integration-router.js +146 -1817
- package/integrations/options.js +20 -47
- package/integrations/repositories/integration-repository-documentdb.js +24 -53
- package/integrations/repositories/integration-repository-factory.js +2 -6
- package/integrations/repositories/integration-repository-interface.js +9 -27
- package/integrations/repositories/integration-repository-postgres.js +3 -3
- package/integrations/repositories/process-repository-factory.js +1 -0
- package/integrations/repositories/process-repository-interface.js +5 -9
- package/integrations/repositories/process-repository-mongo.js +3 -7
- package/integrations/repositories/process-repository-postgres.js +2 -2
- package/integrations/tests/doubles/config-capturing-integration.js +8 -9
- package/integrations/tests/doubles/dummy-integration-class.js +8 -81
- package/integrations/tests/doubles/test-integration-repository.js +11 -51
- package/integrations/use-cases/create-integration.js +32 -36
- package/integrations/use-cases/create-process.js +9 -20
- package/integrations/use-cases/delete-integration-for-user.js +4 -5
- package/integrations/use-cases/get-integration-for-user.js +10 -25
- package/integrations/use-cases/get-integration-instance-by-definition.js +7 -13
- package/integrations/use-cases/get-integrations-for-user.js +1 -4
- package/integrations/use-cases/get-possible-integrations.js +1 -1
- package/integrations/use-cases/get-process.js +6 -5
- package/integrations/use-cases/index.js +1 -3
- package/integrations/use-cases/load-integration-context.js +5 -1
- package/integrations/use-cases/update-process-state.js +8 -10
- package/integrations/utils/map-integration-dto.js +3 -9
- package/jest-setup.js +1 -1
- package/jest-teardown.js +1 -1
- package/lambda/TimeoutCatcher.js +30 -32
- package/lambda/index.js +1 -1
- package/logs/index.js +3 -3
- package/modules/module.js +1 -3
- package/modules/repositories/module-repository-documentdb.js +48 -114
- package/modules/repositories/module-repository-interface.js +0 -13
- package/modules/repositories/module-repository-mongo.js +6 -46
- package/modules/repositories/module-repository-postgres.js +6 -48
- package/modules/repositories/module-repository.js +1 -34
- package/modules/requester/api-key.js +2 -0
- package/modules/requester/basic.js +1 -0
- package/modules/requester/oauth-2.js +2 -3
- package/modules/test/mock-api/definition.js +10 -15
- package/modules/test/mock-api/mocks/hubspot.js +36 -36
- package/modules/tests/doubles/test-module-factory.js +4 -10
- package/modules/tests/doubles/test-module-repository.js +1 -1
- package/modules/use-cases/get-entities-for-user.js +1 -1
- package/modules/use-cases/get-entity-options-by-id.js +6 -8
- package/modules/use-cases/get-module.js +9 -12
- package/modules/use-cases/process-authorization-callback.js +6 -12
- package/modules/use-cases/refresh-entity-options.js +6 -8
- package/modules/use-cases/test-module-auth.js +6 -8
- package/modules/utils/map-module-dto.js +2 -2
- package/package.json +5 -7
- package/prisma-mongodb/schema.prisma +33 -75
- package/prisma-postgresql/schema.prisma +33 -73
- package/queues/queuer-util.js +1 -5
- package/syncs/model.js +51 -51
- package/syncs/repositories/sync-repository-documentdb.js +19 -39
- package/syncs/repositories/sync-repository-interface.js +2 -6
- package/syncs/repositories/sync-repository-postgres.js +13 -19
- package/syncs/sync.js +100 -104
- package/token/repositories/token-repository-factory.js +3 -1
- package/types/assertions/index.d.ts +72 -72
- package/types/associations/index.d.ts +57 -57
- package/types/core/index.d.ts +53 -59
- package/types/database/index.d.ts +2 -2
- package/types/encrypt/index.d.ts +3 -3
- package/types/errors/index.d.ts +54 -61
- package/types/eslint-config/index.d.ts +40 -40
- package/types/integrations/index.d.ts +183 -185
- package/types/lambda/index.d.ts +26 -26
- package/types/logs/index.d.ts +4 -4
- package/types/module-plugin/index.d.ts +237 -239
- package/types/prettier-config/index.d.ts +5 -5
- package/types/syncs/index.d.ts +108 -102
- package/types/test-environment/index.d.ts +14 -14
- package/types/tsconfig.json +93 -95
- package/user/tests/doubles/test-user-repository.js +2 -5
- package/user/use-cases/authenticate-user.js +4 -2
- package/user/use-cases/authenticate-with-shared-secret.js +1 -1
- package/user/use-cases/create-individual-user.js +7 -8
- package/user/use-cases/create-organization-user.js +1 -1
- package/user/use-cases/create-token-for-user-id.js +1 -1
- package/user/use-cases/get-user-from-adopter-jwt.js +2 -0
- package/user/use-cases/get-user-from-bearer-token.js +3 -7
- package/user/use-cases/get-user-from-x-frigg-headers.js +11 -14
- package/user/use-cases/login-user.js +8 -8
- package/user/user.js +4 -18
- package/utils/backend-path.js +2 -2
- package/utils/index.js +1 -4
- package/websocket/repositories/websocket-connection-repository-documentdb.js +8 -21
- package/websocket/repositories/websocket-connection-repository-mongo.js +4 -8
- package/websocket/repositories/websocket-connection-repository-postgres.js +4 -8
- package/websocket/repositories/websocket-connection-repository.js +4 -8
- package/admin-scripts/repositories/admin-api-key-repository-interface.js +0 -121
- package/admin-scripts/repositories/admin-api-key-repository-mongo.js +0 -155
- package/admin-scripts/repositories/admin-api-key-repository-postgres.js +0 -189
- package/admin-scripts/repositories/script-execution-repository-documentdb.js +0 -21
- package/admin-scripts/repositories/script-execution-repository-factory.js +0 -55
- package/admin-scripts/repositories/script-execution-repository-interface.js +0 -193
- package/admin-scripts/repositories/script-execution-repository-mongo.js +0 -278
- package/admin-scripts/repositories/script-execution-repository-postgres.js +0 -320
- package/credential/credential-router.js +0 -262
- package/credential/use-cases/delete-credential-for-user.js +0 -50
- package/credential/use-cases/list-credentials-for-user.js +0 -31
- package/credential/use-cases/reauthorize-credential.js +0 -103
- package/handlers/routers/admin.js +0 -450
- package/handlers/routers/docs.js +0 -180
- package/handlers/routers/middleware/loadUser.js +0 -39
- package/handlers/routers/middleware/requireAdmin.js +0 -41
- package/handlers/routers/middleware/requireLoggedInUser.js +0 -19
- package/integrations/use-cases/execute-proxy-request.js +0 -564
- package/modules/domain/entities/AuthorizationSession.js +0 -131
- package/modules/domain/entities/index.js +0 -10
- package/modules/repositories/authorization-session-repository-factory.js +0 -55
- package/modules/repositories/authorization-session-repository-interface.js +0 -75
- package/modules/repositories/authorization-session-repository-mongo.js +0 -169
- package/modules/repositories/authorization-session-repository-postgres.js +0 -170
- package/modules/use-cases/delete-module-entity.js +0 -23
- package/modules/use-cases/get-authorization-requirements.js +0 -110
- package/modules/use-cases/get-module-entity-by-id.js +0 -16
- package/modules/use-cases/process-authorization-step.js +0 -160
- package/modules/use-cases/start-authorization-session.js +0 -86
- package/modules/use-cases/update-module-entity.js +0 -27
- package/openapi/openapi-spec-generator.js +0 -370
- package/openapi/openapi-v1.yaml +0 -1360
- package/openapi/openapi-v2.yaml +0 -1535
- package/user/use-cases/delete-user.js +0 -47
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require('dotenv').config();
|
|
2
2
|
const { Api } = require('./api');
|
|
3
3
|
const { get } = require('../../../assertions');
|
|
4
|
-
const config = { name: 'anapi' }
|
|
4
|
+
const config = { name: 'anapi' }
|
|
5
5
|
|
|
6
6
|
const Definition = {
|
|
7
7
|
API: Api,
|
|
@@ -9,9 +9,7 @@ const Definition = {
|
|
|
9
9
|
url: 'http://localhost:3000/redirect/anapi',
|
|
10
10
|
type: 'oauth2',
|
|
11
11
|
}),
|
|
12
|
-
getName: function () {
|
|
13
|
-
return config.name;
|
|
14
|
-
},
|
|
12
|
+
getName: function () { return config.name },
|
|
15
13
|
moduleName: config.name,
|
|
16
14
|
modelName: 'AnApi',
|
|
17
15
|
requiredAuthMethods: {
|
|
@@ -19,31 +17,28 @@ const Definition = {
|
|
|
19
17
|
const code = get(params.data, 'code');
|
|
20
18
|
return api.getTokenFromCode(code);
|
|
21
19
|
},
|
|
22
|
-
getEntityDetails: async function (
|
|
23
|
-
api,
|
|
24
|
-
callbackParams,
|
|
25
|
-
tokenResponse,
|
|
26
|
-
userId
|
|
27
|
-
) {
|
|
20
|
+
getEntityDetails: async function (api, callbackParams, tokenResponse, userId) {
|
|
28
21
|
const userDetails = await api.getUserDetails();
|
|
29
22
|
return {
|
|
30
23
|
identifiers: { externalId: userDetails.portalId, user: userId },
|
|
31
24
|
details: { name: userDetails.hub_domain },
|
|
32
|
-
}
|
|
25
|
+
}
|
|
33
26
|
},
|
|
34
27
|
apiPropertiesToPersist: {
|
|
35
|
-
credential: [
|
|
28
|
+
credential: [
|
|
29
|
+
'access_token', 'refresh_token'
|
|
30
|
+
],
|
|
36
31
|
entity: [],
|
|
37
32
|
},
|
|
38
33
|
getCredentialDetails: async function (api, userId) {
|
|
39
34
|
const userDetails = await api.getUserDetails();
|
|
40
35
|
return {
|
|
41
36
|
identifiers: { externalId: userDetails.portalId, user: userId },
|
|
42
|
-
details: {}
|
|
37
|
+
details: {}
|
|
43
38
|
};
|
|
44
39
|
},
|
|
45
40
|
testAuthRequest: async function (api) {
|
|
46
|
-
return api.getUserDetails()
|
|
41
|
+
return api.getUserDetails()
|
|
47
42
|
},
|
|
48
43
|
},
|
|
49
44
|
env: {
|
|
@@ -51,7 +46,7 @@ const Definition = {
|
|
|
51
46
|
client_secret: 'test',
|
|
52
47
|
scope: 'test',
|
|
53
48
|
redirect_uri: `http://localhost:3000/redirect/anapi`,
|
|
54
|
-
}
|
|
49
|
+
}
|
|
55
50
|
};
|
|
56
51
|
|
|
57
52
|
module.exports = { Definition };
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
const authorizeResponse = {
|
|
2
|
-
base:
|
|
3
|
-
data: {
|
|
4
|
-
code:
|
|
5
|
-
state:
|
|
6
|
-
}
|
|
7
|
-
}
|
|
2
|
+
"base": "/redirect/hubspot",
|
|
3
|
+
"data": {
|
|
4
|
+
"code": "test-code",
|
|
5
|
+
"state": "null"
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
8
|
|
|
9
9
|
const tokenResponse = {
|
|
10
|
-
token_type:
|
|
11
|
-
refresh_token:
|
|
12
|
-
access_token:
|
|
13
|
-
expires_in: 1800
|
|
14
|
-
}
|
|
10
|
+
"token_type": "bearer",
|
|
11
|
+
"refresh_token": "test-refresh-token",
|
|
12
|
+
"access_token": "test-access-token",
|
|
13
|
+
"expires_in": 1800
|
|
14
|
+
}
|
|
15
15
|
|
|
16
16
|
const userDetailsResponse = {
|
|
17
|
-
portalId: 111111111,
|
|
18
|
-
timeZone:
|
|
19
|
-
accountType:
|
|
20
|
-
currency:
|
|
21
|
-
utcOffset:
|
|
22
|
-
utcOffsetMilliseconds: -18000000,
|
|
23
|
-
token:
|
|
24
|
-
user:
|
|
25
|
-
hub_domain:
|
|
26
|
-
scopes: [
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
17
|
+
"portalId": 111111111,
|
|
18
|
+
"timeZone": "US/Eastern",
|
|
19
|
+
"accountType": "DEVELOPER_TEST",
|
|
20
|
+
"currency": "USD",
|
|
21
|
+
"utcOffset": "-05:00",
|
|
22
|
+
"utcOffsetMilliseconds": -18000000,
|
|
23
|
+
"token": "test-token",
|
|
24
|
+
"user": "projectteam@lefthook.co",
|
|
25
|
+
"hub_domain": "Testing Object Things-dev-44613847.com",
|
|
26
|
+
"scopes": [
|
|
27
|
+
"content",
|
|
28
|
+
"oauth",
|
|
29
|
+
"crm.objects.contacts.read",
|
|
30
|
+
"crm.objects.contacts.write",
|
|
31
|
+
"crm.objects.companies.write",
|
|
32
|
+
"crm.objects.companies.read",
|
|
33
|
+
"crm.objects.deals.read",
|
|
34
|
+
"crm.schemas.deals.read"
|
|
35
35
|
],
|
|
36
|
-
hub_id: 111111111,
|
|
37
|
-
app_id: 22222222,
|
|
38
|
-
expires_in: 1704,
|
|
39
|
-
user_id: 33333333,
|
|
40
|
-
token_type:
|
|
41
|
-
}
|
|
36
|
+
"hub_id": 111111111,
|
|
37
|
+
"app_id": 22222222,
|
|
38
|
+
"expires_in": 1704,
|
|
39
|
+
"user_id": 33333333,
|
|
40
|
+
"token_type": "access"
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
module.exports = { authorizeResponse, tokenResponse, userDetailsResponse }
|
|
43
|
+
module.exports = { authorizeResponse, tokenResponse, userDetailsResponse }
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
class TestModuleFactory {
|
|
2
|
-
constructor() {
|
|
3
|
-
this.moduleRepository = {
|
|
4
|
-
findEntity: jest.fn().mockResolvedValue(null),
|
|
5
|
-
findEntitiesBy: jest.fn().mockResolvedValue([]),
|
|
6
|
-
};
|
|
7
|
-
}
|
|
2
|
+
constructor() { }
|
|
8
3
|
|
|
9
4
|
async getModuleInstance(entityId, userId) {
|
|
5
|
+
// return minimal stub module with getName and api property
|
|
10
6
|
return {
|
|
11
|
-
getName() {
|
|
12
|
-
return 'stubModule';
|
|
13
|
-
},
|
|
7
|
+
getName() { return 'stubModule'; },
|
|
14
8
|
api: {},
|
|
15
9
|
entityId,
|
|
16
10
|
userId,
|
|
@@ -19,4 +13,4 @@ class TestModuleFactory {
|
|
|
19
13
|
}
|
|
20
14
|
}
|
|
21
15
|
|
|
22
|
-
module.exports = { TestModuleFactory };
|
|
16
|
+
module.exports = { TestModuleFactory };
|
|
@@ -20,10 +20,9 @@ class GetEntityOptionsById {
|
|
|
20
20
|
*/
|
|
21
21
|
async execute(entityId, userIdOrUser) {
|
|
22
22
|
// Support both userId (backward compatible) and User object (new pattern)
|
|
23
|
-
const userId =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
: userIdOrUser;
|
|
23
|
+
const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
|
|
24
|
+
? userIdOrUser.getId()
|
|
25
|
+
: userIdOrUser;
|
|
27
26
|
|
|
28
27
|
const entity = await this.moduleRepository.findEntityById(
|
|
29
28
|
entityId,
|
|
@@ -35,10 +34,9 @@ class GetEntityOptionsById {
|
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
// Validate entity ownership
|
|
38
|
-
const isOwned =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
: entity.userId?.toString() === userId?.toString();
|
|
37
|
+
const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
|
|
38
|
+
? userIdOrUser.ownsUserId(entity.userId)
|
|
39
|
+
: entity.userId?.toString() === userId?.toString();
|
|
42
40
|
|
|
43
41
|
if (!isOwned) {
|
|
44
42
|
throw new Error(
|
|
@@ -15,10 +15,9 @@ class GetModule {
|
|
|
15
15
|
*/
|
|
16
16
|
async execute(entityId, userIdOrUser) {
|
|
17
17
|
// Support both userId (backward compatible) and User object (new pattern)
|
|
18
|
-
const userId =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
: userIdOrUser;
|
|
18
|
+
const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
|
|
19
|
+
? userIdOrUser.getId()
|
|
20
|
+
: userIdOrUser;
|
|
22
21
|
|
|
23
22
|
const entity = await this.moduleRepository.findEntityById(
|
|
24
23
|
entityId,
|
|
@@ -32,10 +31,9 @@ class GetModule {
|
|
|
32
31
|
// Validate entity ownership
|
|
33
32
|
// If User object provided, use ownsUserId to check linked users
|
|
34
33
|
// Otherwise fall back to simple equality check
|
|
35
|
-
const isOwned =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
: entity.userId?.toString() === userId?.toString();
|
|
34
|
+
const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
|
|
35
|
+
? userIdOrUser.ownsUserId(entity.userId)
|
|
36
|
+
: entity.userId?.toString() === userId?.toString();
|
|
39
37
|
|
|
40
38
|
if (!isOwned) {
|
|
41
39
|
throw new Error(
|
|
@@ -45,8 +43,7 @@ class GetModule {
|
|
|
45
43
|
|
|
46
44
|
const entityType = entity.moduleName;
|
|
47
45
|
const moduleDefinition = this.moduleDefinitions.find((def) => {
|
|
48
|
-
const modelName =
|
|
49
|
-
Module.getEntityModelFromDefinition(def).modelName;
|
|
46
|
+
const modelName = Module.getEntityModelFromDefinition(def).modelName;
|
|
50
47
|
return entityType === modelName;
|
|
51
48
|
});
|
|
52
49
|
|
|
@@ -70,8 +67,8 @@ class GetModule {
|
|
|
70
67
|
credential: module.credential,
|
|
71
68
|
externalId: module.entity.externalId,
|
|
72
69
|
userId: module.entity.user.toString(),
|
|
73
|
-
}
|
|
70
|
+
}
|
|
74
71
|
}
|
|
75
72
|
}
|
|
76
73
|
|
|
77
|
-
module.exports = { GetModule };
|
|
74
|
+
module.exports = { GetModule };
|
|
@@ -14,7 +14,7 @@ class ProcessAuthorizationCallback {
|
|
|
14
14
|
this.moduleDefinitions = moduleDefinitions;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
async execute(userId, entityType, params
|
|
17
|
+
async execute(userId, entityType, params) {
|
|
18
18
|
const moduleDefinition = this.moduleDefinitions.find((def) => {
|
|
19
19
|
return entityType === def.moduleName;
|
|
20
20
|
});
|
|
@@ -70,8 +70,7 @@ class ProcessAuthorizationCallback {
|
|
|
70
70
|
const persistedEntity = await this.findOrCreateEntity(
|
|
71
71
|
entityDetails,
|
|
72
72
|
entityType,
|
|
73
|
-
module.credential.id
|
|
74
|
-
isGlobal
|
|
73
|
+
module.credential.id
|
|
75
74
|
);
|
|
76
75
|
|
|
77
76
|
return {
|
|
@@ -94,22 +93,18 @@ class ProcessAuthorizationCallback {
|
|
|
94
93
|
);
|
|
95
94
|
credentialDetails.details.authIsValid = true;
|
|
96
95
|
|
|
97
|
-
const persisted = await this.credentialRepository.upsertCredential(
|
|
98
|
-
credentialDetails
|
|
99
|
-
);
|
|
96
|
+
const persisted = await this.credentialRepository.upsertCredential(credentialDetails);
|
|
100
97
|
module.credential = persisted;
|
|
101
98
|
}
|
|
102
99
|
|
|
103
|
-
async findOrCreateEntity(entityDetails, moduleName, credentialId
|
|
100
|
+
async findOrCreateEntity(entityDetails, moduleName, credentialId) {
|
|
104
101
|
const { identifiers, details } = entityDetails;
|
|
105
102
|
|
|
106
103
|
// Support both 'user' and 'userId' field names from module definitions
|
|
107
104
|
// Some modules use 'user' (legacy), others use 'userId' (newer pattern)
|
|
108
105
|
const userId = identifiers.user || identifiers.userId;
|
|
109
106
|
|
|
110
|
-
|
|
111
|
-
// For user-specific entities, userId must be provided for security
|
|
112
|
-
if (!isGlobal && !userId) {
|
|
107
|
+
if (!userId) {
|
|
113
108
|
throw new Error(
|
|
114
109
|
`Module definition for ${moduleName} must return 'user' or 'userId' in identifiers from getEntityDetails(). ` +
|
|
115
110
|
`Without userId, entity lookup would match across all users (security issue).`
|
|
@@ -118,7 +113,7 @@ class ProcessAuthorizationCallback {
|
|
|
118
113
|
|
|
119
114
|
const existingEntity = await this.moduleRepository.findEntity({
|
|
120
115
|
externalId: identifiers.externalId,
|
|
121
|
-
user:
|
|
116
|
+
user: userId,
|
|
122
117
|
moduleName: moduleName,
|
|
123
118
|
});
|
|
124
119
|
|
|
@@ -131,7 +126,6 @@ class ProcessAuthorizationCallback {
|
|
|
131
126
|
...details,
|
|
132
127
|
moduleName: moduleName,
|
|
133
128
|
credential: credentialId,
|
|
134
|
-
isGlobal,
|
|
135
129
|
});
|
|
136
130
|
}
|
|
137
131
|
}
|
|
@@ -21,10 +21,9 @@ class RefreshEntityOptions {
|
|
|
21
21
|
*/
|
|
22
22
|
async execute(entityId, userIdOrUser, options) {
|
|
23
23
|
// Support both userId (backward compatible) and User object (new pattern)
|
|
24
|
-
const userId =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
: userIdOrUser;
|
|
24
|
+
const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
|
|
25
|
+
? userIdOrUser.getId()
|
|
26
|
+
: userIdOrUser;
|
|
28
27
|
|
|
29
28
|
const entity = await this.moduleRepository.findEntityById(
|
|
30
29
|
entityId,
|
|
@@ -36,10 +35,9 @@ class RefreshEntityOptions {
|
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
// Validate entity ownership
|
|
39
|
-
const isOwned =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
: entity.userId?.toString() === userId?.toString();
|
|
38
|
+
const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
|
|
39
|
+
? userIdOrUser.ownsUserId(entity.userId)
|
|
40
|
+
: entity.userId?.toString() === userId?.toString();
|
|
43
41
|
|
|
44
42
|
if (!isOwned) {
|
|
45
43
|
throw new Error(
|
|
@@ -20,10 +20,9 @@ class TestModuleAuth {
|
|
|
20
20
|
*/
|
|
21
21
|
async execute(entityId, userIdOrUser) {
|
|
22
22
|
// Support both userId (backward compatible) and User object (new pattern)
|
|
23
|
-
const userId =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
: userIdOrUser;
|
|
23
|
+
const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
|
|
24
|
+
? userIdOrUser.getId()
|
|
25
|
+
: userIdOrUser;
|
|
27
26
|
|
|
28
27
|
const entity = await this.moduleRepository.findEntityById(
|
|
29
28
|
entityId,
|
|
@@ -35,10 +34,9 @@ class TestModuleAuth {
|
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
// Validate entity ownership
|
|
38
|
-
const isOwned =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
: entity.userId?.toString() === userId?.toString();
|
|
37
|
+
const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
|
|
38
|
+
? userIdOrUser.ownsUserId(entity.userId)
|
|
39
|
+
: entity.userId?.toString() === userId?.toString();
|
|
42
40
|
|
|
43
41
|
if (!isOwned) {
|
|
44
42
|
throw new Error(
|
|
@@ -11,8 +11,8 @@ function mapModuleClassToModuleDTO(moduleInstance) {
|
|
|
11
11
|
userId: moduleInstance.userId,
|
|
12
12
|
entity: moduleInstance.entity,
|
|
13
13
|
credentialId: moduleInstance.credential?._id?.toString(),
|
|
14
|
-
type: moduleInstance.getName()
|
|
14
|
+
type: moduleInstance.getName()
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
module.exports = { mapModuleClassToModuleDTO };
|
|
18
|
+
module.exports = { mapModuleClassToModuleDTO };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/core",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.
|
|
4
|
+
"version": "2.0.0--canary.517.35ee143.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
|
|
7
7
|
"@aws-sdk/client-kms": "^3.588.0",
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"express-async-handler": "^1.2.0",
|
|
19
19
|
"form-data": "^4.0.0",
|
|
20
20
|
"fs-extra": "^11.2.0",
|
|
21
|
-
"js-yaml": "^4.1.0",
|
|
22
21
|
"lodash": "4.17.21",
|
|
23
22
|
"lodash.get": "^4.4.2",
|
|
24
23
|
"mongoose": "6.11.6",
|
|
@@ -39,9 +38,9 @@
|
|
|
39
38
|
}
|
|
40
39
|
},
|
|
41
40
|
"devDependencies": {
|
|
42
|
-
"@friggframework/eslint-config": "2.0.0--canary.
|
|
43
|
-
"@friggframework/prettier-config": "2.0.0--canary.
|
|
44
|
-
"@friggframework/test": "2.0.0--canary.
|
|
41
|
+
"@friggframework/eslint-config": "2.0.0--canary.517.35ee143.0",
|
|
42
|
+
"@friggframework/prettier-config": "2.0.0--canary.517.35ee143.0",
|
|
43
|
+
"@friggframework/test": "2.0.0--canary.517.35ee143.0",
|
|
45
44
|
"@prisma/client": "^6.17.0",
|
|
46
45
|
"@types/lodash": "4.17.15",
|
|
47
46
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
@@ -54,7 +53,6 @@
|
|
|
54
53
|
"prettier": "^2.7.1",
|
|
55
54
|
"prisma": "^6.17.0",
|
|
56
55
|
"sinon": "^16.1.1",
|
|
57
|
-
"supertest": "^7.1.4",
|
|
58
56
|
"typescript": "^5.0.2"
|
|
59
57
|
},
|
|
60
58
|
"scripts": {
|
|
@@ -82,5 +80,5 @@
|
|
|
82
80
|
"publishConfig": {
|
|
83
81
|
"access": "public"
|
|
84
82
|
},
|
|
85
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "35ee143ec0654d0935aee59bf62b882f5f27d8b7"
|
|
86
84
|
}
|
|
@@ -80,26 +80,6 @@ model Token {
|
|
|
80
80
|
@@map("Token")
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
/// Multi-step authorization session tracking
|
|
84
|
-
/// Supports OTP flows and multi-stage authentication (e.g., Nagaris)
|
|
85
|
-
model AuthorizationSession {
|
|
86
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
87
|
-
sessionId String @unique
|
|
88
|
-
userId String
|
|
89
|
-
entityType String
|
|
90
|
-
currentStep Int @default(1)
|
|
91
|
-
maxSteps Int
|
|
92
|
-
stepData Json @default("{}")
|
|
93
|
-
expiresAt DateTime
|
|
94
|
-
completed Boolean @default(false)
|
|
95
|
-
createdAt DateTime @default(now())
|
|
96
|
-
updatedAt DateTime @updatedAt
|
|
97
|
-
|
|
98
|
-
@@index([userId, entityType])
|
|
99
|
-
@@index([expiresAt])
|
|
100
|
-
@@map("AuthorizationSession")
|
|
101
|
-
}
|
|
102
|
-
|
|
103
83
|
// ============================================================================
|
|
104
84
|
// CREDENTIAL & ENTITY MODELS
|
|
105
85
|
// ============================================================================
|
|
@@ -138,7 +118,6 @@ model Entity {
|
|
|
138
118
|
name String?
|
|
139
119
|
moduleName String?
|
|
140
120
|
externalId String?
|
|
141
|
-
isGlobal Boolean @default(false)
|
|
142
121
|
|
|
143
122
|
createdAt DateTime @default(now())
|
|
144
123
|
updatedAt DateTime @updatedAt
|
|
@@ -157,8 +136,6 @@ model Entity {
|
|
|
157
136
|
@@index([externalId])
|
|
158
137
|
@@index([moduleName])
|
|
159
138
|
@@index([credentialId])
|
|
160
|
-
@@index([isGlobal])
|
|
161
|
-
@@index([isGlobal, moduleName])
|
|
162
139
|
@@map("Entity")
|
|
163
140
|
}
|
|
164
141
|
|
|
@@ -383,70 +360,51 @@ model WebsocketConnection {
|
|
|
383
360
|
}
|
|
384
361
|
|
|
385
362
|
// ============================================================================
|
|
386
|
-
// ADMIN
|
|
363
|
+
// ADMIN PROCESS MODELS
|
|
387
364
|
// ============================================================================
|
|
388
365
|
|
|
389
|
-
|
|
366
|
+
/// Admin process state machine
|
|
367
|
+
enum AdminProcessState {
|
|
390
368
|
PENDING
|
|
391
369
|
RUNNING
|
|
392
370
|
COMPLETED
|
|
393
371
|
FAILED
|
|
394
|
-
TIMEOUT
|
|
395
|
-
CANCELLED
|
|
396
372
|
}
|
|
397
373
|
|
|
398
|
-
|
|
374
|
+
/// Admin trigger types
|
|
375
|
+
enum AdminTrigger {
|
|
399
376
|
MANUAL
|
|
400
377
|
SCHEDULED
|
|
401
378
|
QUEUE
|
|
402
379
|
WEBHOOK
|
|
403
380
|
}
|
|
404
381
|
|
|
405
|
-
/// Admin
|
|
406
|
-
///
|
|
407
|
-
model
|
|
408
|
-
id
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
name String // Human-readable name
|
|
412
|
-
scopes String[] // ['scripts:execute', 'scripts:read']
|
|
413
|
-
expiresAt DateTime?
|
|
414
|
-
createdBy String? // User/admin who created
|
|
415
|
-
lastUsedAt DateTime?
|
|
416
|
-
isActive Boolean @default(true)
|
|
417
|
-
createdAt DateTime @default(now())
|
|
418
|
-
updatedAt DateTime @updatedAt
|
|
419
|
-
|
|
420
|
-
@@index([isActive])
|
|
421
|
-
@@map("AdminApiKey")
|
|
422
|
-
}
|
|
382
|
+
/// Admin process tracking (like Process but without user/integration FK)
|
|
383
|
+
/// Used for: admin scripts, db migrations, system maintenance tasks
|
|
384
|
+
model AdminProcess {
|
|
385
|
+
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
386
|
+
name String // e.g., "oauth-token-refresh", "db-migration-xyz"
|
|
387
|
+
type String // e.g., "ADMIN_SCRIPT", "DB_MIGRATION"
|
|
423
388
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
auditIpAddress String?
|
|
444
|
-
createdAt DateTime @default(now())
|
|
445
|
-
updatedAt DateTime @updatedAt
|
|
446
|
-
|
|
447
|
-
@@index([scriptName, createdAt(sort: Desc)])
|
|
448
|
-
@@index([status])
|
|
449
|
-
@@map("ScriptExecution")
|
|
389
|
+
// State machine
|
|
390
|
+
state AdminProcessState @default(PENDING)
|
|
391
|
+
|
|
392
|
+
// Flexible storage (mirrors Process model pattern)
|
|
393
|
+
context Json @default("{}") // input, trigger, audit info, script version
|
|
394
|
+
results Json @default("{}") // output, logs, metrics, errors
|
|
395
|
+
|
|
396
|
+
// Hierarchy support
|
|
397
|
+
childProcesses String[] @db.ObjectId
|
|
398
|
+
parentProcessId String? @db.ObjectId
|
|
399
|
+
|
|
400
|
+
// Timestamps
|
|
401
|
+
createdAt DateTime @default(now())
|
|
402
|
+
updatedAt DateTime @updatedAt
|
|
403
|
+
|
|
404
|
+
@@index([name, createdAt(sort: Desc)])
|
|
405
|
+
@@index([state])
|
|
406
|
+
@@index([type])
|
|
407
|
+
@@map("AdminProcess")
|
|
450
408
|
}
|
|
451
409
|
|
|
452
410
|
/// Script scheduling configuration for hybrid scheduling (SQS + EventBridge)
|
|
@@ -459,9 +417,9 @@ model ScriptSchedule {
|
|
|
459
417
|
lastTriggeredAt DateTime?
|
|
460
418
|
nextTriggerAt DateTime?
|
|
461
419
|
|
|
462
|
-
// AWS EventBridge
|
|
463
|
-
|
|
464
|
-
|
|
420
|
+
// External Scheduler (e.g., AWS EventBridge Scheduler)
|
|
421
|
+
externalScheduleId String?
|
|
422
|
+
externalScheduleName String?
|
|
465
423
|
|
|
466
424
|
createdAt DateTime @default(now())
|
|
467
425
|
updatedAt DateTime @updatedAt
|