@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,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get Authorization Requirements Use Case
|
|
3
|
-
* Business logic for retrieving authorization requirements for a specific step
|
|
4
|
-
*
|
|
5
|
-
* Responsibilities:
|
|
6
|
-
* - Find module definition for entity type
|
|
7
|
-
* - Determine step count (single vs multi-step)
|
|
8
|
-
* - Retrieve step-specific requirements (jsonSchema, uiSchema, etc.)
|
|
9
|
-
* - Return structured requirements for frontend rendering
|
|
10
|
-
*
|
|
11
|
-
* Supports both single-step and multi-step modules:
|
|
12
|
-
* - Single-step: Uses getAuthorizationRequirements() (legacy)
|
|
13
|
-
* - Multi-step: Uses getAuthRequirementsForStep(step) (new)
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```javascript
|
|
17
|
-
* const useCase = new GetAuthorizationRequirementsUseCase({
|
|
18
|
-
* moduleDefinitions: [{ moduleName: 'nagaris', definition: NagarisDefinition }]
|
|
19
|
-
* });
|
|
20
|
-
*
|
|
21
|
-
* // Get requirements for step 1
|
|
22
|
-
* const reqs = await useCase.execute('nagaris', 1);
|
|
23
|
-
* // Returns: { type: 'email', data: { jsonSchema, uiSchema }, step: 1, totalSteps: 2, isMultiStep: true }
|
|
24
|
-
*
|
|
25
|
-
* // Get requirements for step 2
|
|
26
|
-
* const reqs = await useCase.execute('nagaris', 2);
|
|
27
|
-
* // Returns: { type: 'otp', data: { jsonSchema, uiSchema }, step: 2, totalSteps: 2, isMultiStep: true }
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
class GetAuthorizationRequirementsUseCase {
|
|
31
|
-
/**
|
|
32
|
-
* @param {Object} params - Dependencies
|
|
33
|
-
* @param {Array<Object>} params.moduleDefinitions - Array of module definitions with structure: { moduleName, definition }
|
|
34
|
-
*/
|
|
35
|
-
constructor({ moduleDefinitions }) {
|
|
36
|
-
if (!moduleDefinitions || !Array.isArray(moduleDefinitions)) {
|
|
37
|
-
throw new Error('moduleDefinitions array is required');
|
|
38
|
-
}
|
|
39
|
-
this.moduleDefinitions = moduleDefinitions;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Get authorization requirements for a specific step
|
|
44
|
-
*
|
|
45
|
-
* @param {string} entityType - Entity type (module name)
|
|
46
|
-
* @param {number} [step=1] - Step number (1-indexed)
|
|
47
|
-
* @returns {Promise<Object>} Requirements object with schema and metadata
|
|
48
|
-
* @throws {Error} If module not found or step invalid
|
|
49
|
-
*/
|
|
50
|
-
async execute(entityType, step = 1) {
|
|
51
|
-
// Validate inputs
|
|
52
|
-
if (!entityType) {
|
|
53
|
-
throw new Error('entityType is required');
|
|
54
|
-
}
|
|
55
|
-
if (!step || step < 1) {
|
|
56
|
-
throw new Error('step must be >= 1');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Find module definition
|
|
60
|
-
const moduleDefinition = this.moduleDefinitions.find(
|
|
61
|
-
(def) => def.moduleName === entityType
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
if (!moduleDefinition) {
|
|
65
|
-
throw new Error(`Module definition not found: ${entityType}`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const ModuleDefinition = moduleDefinition.definition;
|
|
69
|
-
|
|
70
|
-
// Determine step count (multi-step vs single-step)
|
|
71
|
-
const stepCount = ModuleDefinition.getAuthStepCount
|
|
72
|
-
? ModuleDefinition.getAuthStepCount()
|
|
73
|
-
: 1;
|
|
74
|
-
|
|
75
|
-
// Validate requested step doesn't exceed max steps
|
|
76
|
-
if (step > stepCount) {
|
|
77
|
-
throw new Error(
|
|
78
|
-
`Step ${step} exceeds maximum steps (${stepCount}) for ${entityType}`
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Get requirements for this specific step
|
|
83
|
-
let requirements;
|
|
84
|
-
|
|
85
|
-
if (ModuleDefinition.getAuthRequirementsForStep) {
|
|
86
|
-
// Multi-step module - use step-specific method
|
|
87
|
-
requirements = await ModuleDefinition.getAuthRequirementsForStep(
|
|
88
|
-
step
|
|
89
|
-
);
|
|
90
|
-
} else if (step === 1) {
|
|
91
|
-
// Single-step module (legacy) - use standard method
|
|
92
|
-
requirements =
|
|
93
|
-
await ModuleDefinition.getAuthorizationRequirements();
|
|
94
|
-
} else {
|
|
95
|
-
throw new Error(
|
|
96
|
-
`Module ${entityType} does not support step ${step}`
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Return enriched requirements with metadata
|
|
101
|
-
return {
|
|
102
|
-
...requirements,
|
|
103
|
-
step,
|
|
104
|
-
totalSteps: stepCount,
|
|
105
|
-
isMultiStep: stepCount > 1,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
module.exports = { GetAuthorizationRequirementsUseCase };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GetModuleEntityById Use Case
|
|
3
|
-
* Retrieves a module entity by its ID
|
|
4
|
-
*/
|
|
5
|
-
class GetModuleEntityById {
|
|
6
|
-
constructor({ moduleRepository }) {
|
|
7
|
-
this.moduleRepository = moduleRepository;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async execute(entityId) {
|
|
11
|
-
const entity = await this.moduleRepository.findEntityById(entityId);
|
|
12
|
-
return entity;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = { GetModuleEntityById };
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Process Authorization Step Use Case
|
|
3
|
-
* Business logic for processing individual steps in multi-step authorization workflows
|
|
4
|
-
*
|
|
5
|
-
* Responsibilities:
|
|
6
|
-
* - Load and validate authorization session
|
|
7
|
-
* - Verify step sequence and user ownership
|
|
8
|
-
* - Delegate to module's step processing logic
|
|
9
|
-
* - Update session state and persist changes
|
|
10
|
-
* - Return next step requirements or completion data
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```javascript
|
|
14
|
-
* const useCase = new ProcessAuthorizationStepUseCase({
|
|
15
|
-
* authSessionRepository: createAuthorizationSessionRepository(),
|
|
16
|
-
* moduleDefinitions: [{ moduleName: 'nagaris', definition: NagarisDefinition, apiClass: NagarisApi }]
|
|
17
|
-
* });
|
|
18
|
-
*
|
|
19
|
-
* // Process step 1 (email submission)
|
|
20
|
-
* const result = await useCase.execute('session-id', 'user123', 1, { email: 'user@example.com' });
|
|
21
|
-
* // Returns: { nextStep: 2, sessionId, requirements: {...}, message: 'OTP sent to email' }
|
|
22
|
-
*
|
|
23
|
-
* // Process step 2 (OTP verification)
|
|
24
|
-
* const result = await useCase.execute('session-id', 'user123', 2, { email: 'user@example.com', otp: '123456' });
|
|
25
|
-
* // Returns: { completed: true, authData: {...}, sessionId }
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
class ProcessAuthorizationStepUseCase {
|
|
29
|
-
/**
|
|
30
|
-
* @param {Object} params - Dependencies
|
|
31
|
-
* @param {import('../repositories/authorization-session-repository-interface').AuthorizationSessionRepositoryInterface} params.authSessionRepository - Session repository
|
|
32
|
-
* @param {Array<Object>} params.moduleDefinitions - Array of module definitions with structure: { moduleName, definition, apiClass }
|
|
33
|
-
*/
|
|
34
|
-
constructor({ authSessionRepository, moduleDefinitions }) {
|
|
35
|
-
if (!authSessionRepository) {
|
|
36
|
-
throw new Error('authSessionRepository is required');
|
|
37
|
-
}
|
|
38
|
-
if (!moduleDefinitions || !Array.isArray(moduleDefinitions)) {
|
|
39
|
-
throw new Error('moduleDefinitions array is required');
|
|
40
|
-
}
|
|
41
|
-
this.authSessionRepository = authSessionRepository;
|
|
42
|
-
this.moduleDefinitions = moduleDefinitions;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Process a single step of multi-step authorization
|
|
47
|
-
*
|
|
48
|
-
* @param {string} sessionId - Unique session identifier
|
|
49
|
-
* @param {string} userId - User ID (for security validation)
|
|
50
|
-
* @param {number} step - Current step number being processed
|
|
51
|
-
* @param {Object} stepData - Data submitted for this step
|
|
52
|
-
* @returns {Promise<Object>} Result object with nextStep info or completion data
|
|
53
|
-
* @throws {Error} If session not found, validation fails, or step processing fails
|
|
54
|
-
*/
|
|
55
|
-
async execute(sessionId, userId, step, stepData) {
|
|
56
|
-
// Validate inputs
|
|
57
|
-
if (!sessionId) {
|
|
58
|
-
throw new Error('sessionId is required');
|
|
59
|
-
}
|
|
60
|
-
if (!userId) {
|
|
61
|
-
throw new Error('userId is required');
|
|
62
|
-
}
|
|
63
|
-
if (!step || step < 1) {
|
|
64
|
-
throw new Error('step must be >= 1');
|
|
65
|
-
}
|
|
66
|
-
if (!stepData || typeof stepData !== 'object') {
|
|
67
|
-
throw new Error('stepData object is required');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Load session from repository
|
|
71
|
-
const session = await this.authSessionRepository.findBySessionId(
|
|
72
|
-
sessionId
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
if (!session) {
|
|
76
|
-
throw new Error('Authorization session not found or expired');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Security: Verify session belongs to this user
|
|
80
|
-
if (session.userId !== userId) {
|
|
81
|
-
throw new Error('Session does not belong to this user');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Verify session hasn't expired (double-check beyond repository filter)
|
|
85
|
-
if (session.isExpired()) {
|
|
86
|
-
throw new Error('Authorization session has expired');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Validate step sequence - prevent skipping steps
|
|
90
|
-
// Allow step 1 to be re-submitted (restart flow), otherwise must be sequential
|
|
91
|
-
if (session.currentStep !== step && step !== 1) {
|
|
92
|
-
throw new Error(
|
|
93
|
-
`Expected step ${session.currentStep}, received step ${step}`
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Find module definition for this entity type
|
|
98
|
-
const moduleDefinition = this.moduleDefinitions.find(
|
|
99
|
-
(def) => def.moduleName === session.entityType
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
if (!moduleDefinition) {
|
|
103
|
-
throw new Error(
|
|
104
|
-
`Module definition not found: ${session.entityType}`
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Get module's Definition class
|
|
109
|
-
const ModuleDefinition = moduleDefinition.definition;
|
|
110
|
-
|
|
111
|
-
// Validate module supports multi-step auth
|
|
112
|
-
if (!ModuleDefinition.processAuthorizationStep) {
|
|
113
|
-
throw new Error(
|
|
114
|
-
`Module ${session.entityType} does not support multi-step authorization`
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Create API instance for this step
|
|
119
|
-
const ApiClass = moduleDefinition.apiClass;
|
|
120
|
-
const api = new ApiClass({ userId });
|
|
121
|
-
|
|
122
|
-
// Delegate to module's step processing logic
|
|
123
|
-
const result = await ModuleDefinition.processAuthorizationStep(
|
|
124
|
-
api,
|
|
125
|
-
step,
|
|
126
|
-
stepData,
|
|
127
|
-
session.stepData // Pass accumulated data from previous steps
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
// Handle final step completion
|
|
131
|
-
if (result.completed) {
|
|
132
|
-
session.markComplete();
|
|
133
|
-
await this.authSessionRepository.update(session);
|
|
134
|
-
|
|
135
|
-
return {
|
|
136
|
-
completed: true,
|
|
137
|
-
authData: result.authData,
|
|
138
|
-
sessionId,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Handle intermediate step - advance session
|
|
143
|
-
session.advanceStep(result.stepData || {});
|
|
144
|
-
await this.authSessionRepository.update(session);
|
|
145
|
-
|
|
146
|
-
// Get requirements for next step
|
|
147
|
-
const nextRequirements =
|
|
148
|
-
await ModuleDefinition.getAuthRequirementsForStep(result.nextStep);
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
nextStep: result.nextStep,
|
|
152
|
-
totalSteps: session.maxSteps,
|
|
153
|
-
sessionId,
|
|
154
|
-
requirements: nextRequirements,
|
|
155
|
-
message: result.message || undefined,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
module.exports = { ProcessAuthorizationStepUseCase };
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
const crypto = require('crypto');
|
|
2
|
-
const {
|
|
3
|
-
AuthorizationSession,
|
|
4
|
-
} = require('../domain/entities/AuthorizationSession');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Start Authorization Session Use Case
|
|
8
|
-
* Business logic for initiating multi-step authorization workflows
|
|
9
|
-
*
|
|
10
|
-
* Responsibilities:
|
|
11
|
-
* - Generate unique session identifiers
|
|
12
|
-
* - Set appropriate session expiration (15 minutes)
|
|
13
|
-
* - Create and persist new authorization session
|
|
14
|
-
* - Validate input parameters
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```javascript
|
|
18
|
-
* const useCase = new StartAuthorizationSessionUseCase({
|
|
19
|
-
* authSessionRepository: createAuthorizationSessionRepository()
|
|
20
|
-
* });
|
|
21
|
-
*
|
|
22
|
-
* const session = await useCase.execute('user123', 'nagaris', 2);
|
|
23
|
-
* // Returns new AuthorizationSession ready for step 1
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
class StartAuthorizationSessionUseCase {
|
|
27
|
-
/**
|
|
28
|
-
* @param {Object} params - Dependencies
|
|
29
|
-
* @param {import('../repositories/authorization-session-repository-interface').AuthorizationSessionRepositoryInterface} params.authSessionRepository - Session repository
|
|
30
|
-
*/
|
|
31
|
-
constructor({ authSessionRepository }) {
|
|
32
|
-
if (!authSessionRepository) {
|
|
33
|
-
throw new Error('authSessionRepository is required');
|
|
34
|
-
}
|
|
35
|
-
this.authSessionRepository = authSessionRepository;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Start a new multi-step authorization session
|
|
40
|
-
*
|
|
41
|
-
* @param {string} userId - User ID initiating the auth flow
|
|
42
|
-
* @param {string} entityType - Type of entity being authorized (module name)
|
|
43
|
-
* @param {number} maxSteps - Total number of steps in the auth flow
|
|
44
|
-
* @returns {Promise<import('../domain/entities/AuthorizationSession').AuthorizationSession>} Created session
|
|
45
|
-
* @throws {Error} If validation fails
|
|
46
|
-
*/
|
|
47
|
-
async execute(userId, entityType, maxSteps) {
|
|
48
|
-
// Validate inputs
|
|
49
|
-
if (!userId) {
|
|
50
|
-
throw new Error('userId is required');
|
|
51
|
-
}
|
|
52
|
-
if (!entityType) {
|
|
53
|
-
throw new Error('entityType is required');
|
|
54
|
-
}
|
|
55
|
-
if (!maxSteps || maxSteps < 1) {
|
|
56
|
-
throw new Error('maxSteps must be >= 1');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Generate cryptographically secure session ID
|
|
60
|
-
const sessionId = crypto.randomUUID();
|
|
61
|
-
|
|
62
|
-
// Set 15 minute expiration (configurable via env in future)
|
|
63
|
-
const expirationMinutes = parseInt(
|
|
64
|
-
process.env.AUTH_SESSION_EXPIRY_MINUTES || '15',
|
|
65
|
-
10
|
|
66
|
-
);
|
|
67
|
-
const expiresAt = new Date(Date.now() + expirationMinutes * 60 * 1000);
|
|
68
|
-
|
|
69
|
-
// Create domain entity
|
|
70
|
-
const session = new AuthorizationSession({
|
|
71
|
-
sessionId,
|
|
72
|
-
userId,
|
|
73
|
-
entityType,
|
|
74
|
-
currentStep: 1,
|
|
75
|
-
maxSteps,
|
|
76
|
-
stepData: {},
|
|
77
|
-
expiresAt,
|
|
78
|
-
completed: false,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// Persist to database
|
|
82
|
-
return await this.authSessionRepository.create(session);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
module.exports = { StartAuthorizationSessionUseCase };
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UpdateModuleEntity Use Case
|
|
3
|
-
* Updates a module entity with new data
|
|
4
|
-
*/
|
|
5
|
-
class UpdateModuleEntity {
|
|
6
|
-
constructor({ moduleRepository }) {
|
|
7
|
-
this.moduleRepository = moduleRepository;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async execute(entityId, updates) {
|
|
11
|
-
const entity = await this.moduleRepository.findEntityById(entityId);
|
|
12
|
-
|
|
13
|
-
if (!entity) {
|
|
14
|
-
throw new Error(`Entity not found: ${entityId}`);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Update the entity using repository method
|
|
18
|
-
const updatedEntity = await this.moduleRepository.updateEntity(
|
|
19
|
-
entityId,
|
|
20
|
-
updates
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
return updatedEntity;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
module.exports = { UpdateModuleEntity };
|