@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,131 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AuthorizationSession Entity
|
|
3
|
-
* Domain entity for multi-step authorization workflows
|
|
4
|
-
*
|
|
5
|
-
* Manages state for authentication flows that require multiple steps,
|
|
6
|
-
* such as OTP verification, multi-factor authentication, or progressive
|
|
7
|
-
* credential collection.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* const session = new AuthorizationSession({
|
|
11
|
-
* sessionId: '550e8400-e29b-41d4-a716-446655440000',
|
|
12
|
-
* userId: 'user123',
|
|
13
|
-
* entityType: 'nagaris',
|
|
14
|
-
* currentStep: 1,
|
|
15
|
-
* maxSteps: 2,
|
|
16
|
-
* stepData: { email: 'user@example.com' },
|
|
17
|
-
* expiresAt: new Date(Date.now() + 15 * 60 * 1000)
|
|
18
|
-
* });
|
|
19
|
-
*/
|
|
20
|
-
class AuthorizationSession {
|
|
21
|
-
/**
|
|
22
|
-
* Create an authorization session
|
|
23
|
-
*
|
|
24
|
-
* @param {Object} params - Session parameters
|
|
25
|
-
* @param {string} params.sessionId - Unique session identifier (UUID)
|
|
26
|
-
* @param {string} params.userId - User ID who initiated the auth flow
|
|
27
|
-
* @param {string} params.entityType - Type of entity being authorized (module name)
|
|
28
|
-
* @param {number} [params.currentStep=1] - Current step in the auth flow
|
|
29
|
-
* @param {number} params.maxSteps - Total number of steps in the flow
|
|
30
|
-
* @param {Object} [params.stepData={}] - Accumulated data from previous steps
|
|
31
|
-
* @param {Date} params.expiresAt - Session expiration timestamp
|
|
32
|
-
* @param {boolean} [params.completed=false] - Whether auth flow is complete
|
|
33
|
-
* @param {Date} [params.createdAt=new Date()] - Session creation timestamp
|
|
34
|
-
* @param {Date} [params.updatedAt=new Date()] - Last update timestamp
|
|
35
|
-
*/
|
|
36
|
-
constructor({
|
|
37
|
-
sessionId,
|
|
38
|
-
userId,
|
|
39
|
-
entityType,
|
|
40
|
-
currentStep = 1,
|
|
41
|
-
maxSteps,
|
|
42
|
-
stepData = {},
|
|
43
|
-
expiresAt,
|
|
44
|
-
completed = false,
|
|
45
|
-
createdAt = new Date(),
|
|
46
|
-
updatedAt = new Date(),
|
|
47
|
-
}) {
|
|
48
|
-
this.sessionId = sessionId;
|
|
49
|
-
this.userId = userId;
|
|
50
|
-
this.entityType = entityType;
|
|
51
|
-
this.currentStep = currentStep;
|
|
52
|
-
this.maxSteps = maxSteps;
|
|
53
|
-
this.stepData = stepData;
|
|
54
|
-
this.expiresAt = expiresAt;
|
|
55
|
-
this.completed = completed;
|
|
56
|
-
this.createdAt = createdAt;
|
|
57
|
-
this.updatedAt = updatedAt;
|
|
58
|
-
|
|
59
|
-
this.validate();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Validate session state
|
|
64
|
-
*
|
|
65
|
-
* @throws {Error} If validation fails
|
|
66
|
-
*/
|
|
67
|
-
validate() {
|
|
68
|
-
if (!this.sessionId) {
|
|
69
|
-
throw new Error('Session ID is required');
|
|
70
|
-
}
|
|
71
|
-
if (!this.userId) {
|
|
72
|
-
throw new Error('User ID is required');
|
|
73
|
-
}
|
|
74
|
-
if (!this.entityType) {
|
|
75
|
-
throw new Error('Entity type is required');
|
|
76
|
-
}
|
|
77
|
-
if (this.currentStep < 1) {
|
|
78
|
-
throw new Error('Step must be >= 1');
|
|
79
|
-
}
|
|
80
|
-
if (this.currentStep > this.maxSteps) {
|
|
81
|
-
throw new Error('Current step cannot exceed max steps');
|
|
82
|
-
}
|
|
83
|
-
if (this.expiresAt < new Date()) {
|
|
84
|
-
throw new Error('Session has expired');
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Advance to next step with new data
|
|
90
|
-
*
|
|
91
|
-
* @param {Object} newStepData - Data collected from current step
|
|
92
|
-
* @throws {Error} If session is already completed
|
|
93
|
-
*/
|
|
94
|
-
advanceStep(newStepData) {
|
|
95
|
-
if (this.completed) {
|
|
96
|
-
throw new Error('Cannot advance completed session');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
this.currentStep += 1;
|
|
100
|
-
this.stepData = { ...this.stepData, ...newStepData };
|
|
101
|
-
this.updatedAt = new Date();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Mark session as complete
|
|
106
|
-
*/
|
|
107
|
-
markComplete() {
|
|
108
|
-
this.completed = true;
|
|
109
|
-
this.updatedAt = new Date();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Check if session has expired
|
|
114
|
-
*
|
|
115
|
-
* @returns {boolean} True if session is expired
|
|
116
|
-
*/
|
|
117
|
-
isExpired() {
|
|
118
|
-
return this.expiresAt < new Date();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Check if session can advance to next step
|
|
123
|
-
*
|
|
124
|
-
* @returns {boolean} True if session can advance
|
|
125
|
-
*/
|
|
126
|
-
canAdvance() {
|
|
127
|
-
return !this.completed && this.currentStep < this.maxSteps;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
module.exports = { AuthorizationSession };
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
const {
|
|
2
|
-
AuthorizationSessionRepositoryMongo,
|
|
3
|
-
} = require('./authorization-session-repository-mongo');
|
|
4
|
-
const {
|
|
5
|
-
AuthorizationSessionRepositoryPostgres,
|
|
6
|
-
} = require('./authorization-session-repository-postgres');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Authorization Session Repository Factory
|
|
10
|
-
* Creates the appropriate repository adapter based on database type
|
|
11
|
-
*
|
|
12
|
-
* Database-specific implementations:
|
|
13
|
-
* - MongoDB: Uses String IDs (ObjectId), TTL index for auto-cleanup
|
|
14
|
-
* - PostgreSQL: Uses Int IDs, manual cleanup via deleteExpired()
|
|
15
|
-
*
|
|
16
|
-
* All repository methods return AuthorizationSession domain entities,
|
|
17
|
-
* ensuring application layer consistency regardless of database type.
|
|
18
|
-
*
|
|
19
|
-
* Environment Configuration:
|
|
20
|
-
* - DB_TYPE=mongodb (default) - Uses MongoDB adapter
|
|
21
|
-
* - DB_TYPE=postgresql - Uses PostgreSQL adapter
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```javascript
|
|
25
|
-
* const repository = createAuthorizationSessionRepository();
|
|
26
|
-
* const session = await repository.findBySessionId(sessionId);
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* @param {Object} [prismaClient] - Optional Prisma client for testing
|
|
30
|
-
* @returns {AuthorizationSessionRepositoryInterface} Configured repository adapter
|
|
31
|
-
* @throws {Error} If DB_TYPE is not supported
|
|
32
|
-
*/
|
|
33
|
-
function createAuthorizationSessionRepository(prismaClient) {
|
|
34
|
-
const dbType = process.env.DB_TYPE || 'mongodb';
|
|
35
|
-
|
|
36
|
-
switch (dbType) {
|
|
37
|
-
case 'mongodb':
|
|
38
|
-
return new AuthorizationSessionRepositoryMongo(prismaClient);
|
|
39
|
-
|
|
40
|
-
case 'postgresql':
|
|
41
|
-
return new AuthorizationSessionRepositoryPostgres(prismaClient);
|
|
42
|
-
|
|
43
|
-
default:
|
|
44
|
-
throw new Error(
|
|
45
|
-
`Unsupported DB_TYPE: ${dbType}. Supported values: 'mongodb', 'postgresql'`
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
module.exports = {
|
|
51
|
-
createAuthorizationSessionRepository,
|
|
52
|
-
// Export adapters for direct testing
|
|
53
|
-
AuthorizationSessionRepositoryMongo,
|
|
54
|
-
AuthorizationSessionRepositoryPostgres,
|
|
55
|
-
};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Authorization Session Repository Interface
|
|
3
|
-
* Abstract base class defining the contract for AuthorizationSession persistence adapters
|
|
4
|
-
*
|
|
5
|
-
* This follows the Port in Hexagonal Architecture:
|
|
6
|
-
* - Domain layer depends on this abstraction
|
|
7
|
-
* - Concrete adapters (MongoDB, PostgreSQL) implement this interface
|
|
8
|
-
* - Use cases receive repositories via dependency injection
|
|
9
|
-
*
|
|
10
|
-
* @abstract
|
|
11
|
-
*/
|
|
12
|
-
class AuthorizationSessionRepositoryInterface {
|
|
13
|
-
/**
|
|
14
|
-
* Create a new authorization session
|
|
15
|
-
*
|
|
16
|
-
* @param {import('../domain/entities/AuthorizationSession').AuthorizationSession} session - Session entity to create
|
|
17
|
-
* @returns {Promise<import('../domain/entities/AuthorizationSession').AuthorizationSession>} Created session
|
|
18
|
-
* @abstract
|
|
19
|
-
*/
|
|
20
|
-
async create(session) {
|
|
21
|
-
throw new Error('Method create must be implemented by subclass');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Find session by session ID
|
|
26
|
-
*
|
|
27
|
-
* @param {string} sessionId - Unique session identifier
|
|
28
|
-
* @returns {Promise<import('../domain/entities/AuthorizationSession').AuthorizationSession|null>} Session entity or null if not found/expired
|
|
29
|
-
* @abstract
|
|
30
|
-
*/
|
|
31
|
-
async findBySessionId(sessionId) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
'Method findBySessionId must be implemented by subclass'
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Find active session for user and entity type
|
|
39
|
-
* Returns the most recent active (non-completed, non-expired) session
|
|
40
|
-
*
|
|
41
|
-
* @param {string} userId - User ID
|
|
42
|
-
* @param {string} entityType - Entity type (module name)
|
|
43
|
-
* @returns {Promise<import('../domain/entities/AuthorizationSession').AuthorizationSession|null>} Session entity or null if not found
|
|
44
|
-
* @abstract
|
|
45
|
-
*/
|
|
46
|
-
async findActiveSession(userId, entityType) {
|
|
47
|
-
throw new Error(
|
|
48
|
-
'Method findActiveSession must be implemented by subclass'
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Update existing session
|
|
54
|
-
*
|
|
55
|
-
* @param {import('../domain/entities/AuthorizationSession').AuthorizationSession} session - Session entity with updated data
|
|
56
|
-
* @returns {Promise<import('../domain/entities/AuthorizationSession').AuthorizationSession>} Updated session
|
|
57
|
-
* @abstract
|
|
58
|
-
*/
|
|
59
|
-
async update(session) {
|
|
60
|
-
throw new Error('Method update must be implemented by subclass');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Delete expired sessions (cleanup operation)
|
|
65
|
-
* Should be called periodically to remove old sessions
|
|
66
|
-
*
|
|
67
|
-
* @returns {Promise<number>} Number of deleted sessions
|
|
68
|
-
* @abstract
|
|
69
|
-
*/
|
|
70
|
-
async deleteExpired() {
|
|
71
|
-
throw new Error('Method deleteExpired must be implemented by subclass');
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
module.exports = { AuthorizationSessionRepositoryInterface };
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
const { prisma } = require('../../database/prisma');
|
|
2
|
-
const {
|
|
3
|
-
AuthorizationSession,
|
|
4
|
-
} = require('../domain/entities/AuthorizationSession');
|
|
5
|
-
const {
|
|
6
|
-
AuthorizationSessionRepositoryInterface,
|
|
7
|
-
} = require('./authorization-session-repository-interface');
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* MongoDB Authorization Session Repository Adapter
|
|
11
|
-
* Handles AuthorizationSession persistence operations for MongoDB via Prisma
|
|
12
|
-
*
|
|
13
|
-
* MongoDB-specific characteristics:
|
|
14
|
-
* - Uses String IDs (Prisma's default for MongoDB)
|
|
15
|
-
* - TTL index on expiresAt for automatic cleanup
|
|
16
|
-
* - No ID conversion needed (IDs are already strings)
|
|
17
|
-
*
|
|
18
|
-
* Schema Requirements (Prisma):
|
|
19
|
-
* ```prisma
|
|
20
|
-
* model AuthorizationSession {
|
|
21
|
-
* id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
22
|
-
* sessionId String @unique
|
|
23
|
-
* userId String
|
|
24
|
-
* entityType String
|
|
25
|
-
* currentStep Int @default(1)
|
|
26
|
-
* maxSteps Int
|
|
27
|
-
* stepData Json @default("{}")
|
|
28
|
-
* expiresAt DateTime
|
|
29
|
-
* completed Boolean @default(false)
|
|
30
|
-
* createdAt DateTime @default(now())
|
|
31
|
-
* updatedAt DateTime @updatedAt
|
|
32
|
-
*
|
|
33
|
-
* @@index([sessionId])
|
|
34
|
-
* @@index([userId, entityType])
|
|
35
|
-
* @@index([expiresAt])
|
|
36
|
-
* @@index([completed])
|
|
37
|
-
* }
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
class AuthorizationSessionRepositoryMongo extends AuthorizationSessionRepositoryInterface {
|
|
41
|
-
constructor(prismaClient = prisma) {
|
|
42
|
-
super();
|
|
43
|
-
this.prisma = prismaClient; // Allow injection for testing
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Create a new authorization session
|
|
48
|
-
*
|
|
49
|
-
* @param {AuthorizationSession} session - Session entity to create
|
|
50
|
-
* @returns {Promise<AuthorizationSession>} Created session entity
|
|
51
|
-
*/
|
|
52
|
-
async create(session) {
|
|
53
|
-
const doc = await this.prisma.authorizationSession.create({
|
|
54
|
-
data: {
|
|
55
|
-
sessionId: session.sessionId,
|
|
56
|
-
userId: session.userId,
|
|
57
|
-
entityType: session.entityType,
|
|
58
|
-
currentStep: session.currentStep,
|
|
59
|
-
maxSteps: session.maxSteps,
|
|
60
|
-
stepData: session.stepData,
|
|
61
|
-
expiresAt: session.expiresAt,
|
|
62
|
-
completed: session.completed,
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
return this._toEntity(doc);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Find session by session ID
|
|
71
|
-
* Excludes expired sessions
|
|
72
|
-
*
|
|
73
|
-
* @param {string} sessionId - Unique session identifier
|
|
74
|
-
* @returns {Promise<AuthorizationSession|null>} Session entity or null
|
|
75
|
-
*/
|
|
76
|
-
async findBySessionId(sessionId) {
|
|
77
|
-
const doc = await this.prisma.authorizationSession.findFirst({
|
|
78
|
-
where: {
|
|
79
|
-
sessionId,
|
|
80
|
-
expiresAt: { gt: new Date() },
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
return doc ? this._toEntity(doc) : null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Find active session for user and entity type
|
|
89
|
-
* Returns most recent active session
|
|
90
|
-
*
|
|
91
|
-
* @param {string} userId - User ID
|
|
92
|
-
* @param {string} entityType - Entity type (module name)
|
|
93
|
-
* @returns {Promise<AuthorizationSession|null>} Session entity or null
|
|
94
|
-
*/
|
|
95
|
-
async findActiveSession(userId, entityType) {
|
|
96
|
-
const doc = await this.prisma.authorizationSession.findFirst({
|
|
97
|
-
where: {
|
|
98
|
-
userId,
|
|
99
|
-
entityType,
|
|
100
|
-
completed: false,
|
|
101
|
-
expiresAt: { gt: new Date() },
|
|
102
|
-
},
|
|
103
|
-
orderBy: { createdAt: 'desc' },
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
return doc ? this._toEntity(doc) : null;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Update existing session
|
|
111
|
-
*
|
|
112
|
-
* @param {AuthorizationSession} session - Session entity with updated data
|
|
113
|
-
* @returns {Promise<AuthorizationSession>} Updated session entity
|
|
114
|
-
*/
|
|
115
|
-
async update(session) {
|
|
116
|
-
const updated = await this.prisma.authorizationSession.update({
|
|
117
|
-
where: { sessionId: session.sessionId },
|
|
118
|
-
data: {
|
|
119
|
-
currentStep: session.currentStep,
|
|
120
|
-
stepData: session.stepData,
|
|
121
|
-
completed: session.completed,
|
|
122
|
-
updatedAt: new Date(),
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
return this._toEntity(updated);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Delete expired sessions (cleanup operation)
|
|
131
|
-
* Note: MongoDB TTL index handles automatic deletion, but this provides
|
|
132
|
-
* manual cleanup capability
|
|
133
|
-
*
|
|
134
|
-
* @returns {Promise<number>} Number of deleted sessions
|
|
135
|
-
*/
|
|
136
|
-
async deleteExpired() {
|
|
137
|
-
const result = await this.prisma.authorizationSession.deleteMany({
|
|
138
|
-
where: {
|
|
139
|
-
expiresAt: { lt: new Date() },
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
return result.count;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Convert Prisma document to domain entity
|
|
148
|
-
*
|
|
149
|
-
* @private
|
|
150
|
-
* @param {Object} doc - Prisma document
|
|
151
|
-
* @returns {AuthorizationSession} Domain entity
|
|
152
|
-
*/
|
|
153
|
-
_toEntity(doc) {
|
|
154
|
-
return new AuthorizationSession({
|
|
155
|
-
sessionId: doc.sessionId,
|
|
156
|
-
userId: doc.userId,
|
|
157
|
-
entityType: doc.entityType,
|
|
158
|
-
currentStep: doc.currentStep,
|
|
159
|
-
maxSteps: doc.maxSteps,
|
|
160
|
-
stepData: doc.stepData,
|
|
161
|
-
expiresAt: doc.expiresAt,
|
|
162
|
-
completed: doc.completed,
|
|
163
|
-
createdAt: doc.createdAt,
|
|
164
|
-
updatedAt: doc.updatedAt,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
module.exports = { AuthorizationSessionRepositoryMongo };
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
const { prisma } = require('../../database/prisma');
|
|
2
|
-
const {
|
|
3
|
-
AuthorizationSession,
|
|
4
|
-
} = require('../domain/entities/AuthorizationSession');
|
|
5
|
-
const {
|
|
6
|
-
AuthorizationSessionRepositoryInterface,
|
|
7
|
-
} = require('./authorization-session-repository-interface');
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* PostgreSQL Authorization Session Repository Adapter
|
|
11
|
-
* Handles AuthorizationSession persistence operations for PostgreSQL via Prisma
|
|
12
|
-
*
|
|
13
|
-
* PostgreSQL-specific characteristics:
|
|
14
|
-
* - Uses Int IDs (auto-incrementing)
|
|
15
|
-
* - Indexes on sessionId, userId+entityType, expiresAt, completed
|
|
16
|
-
* - JSON/JSONB support for stepData
|
|
17
|
-
* - No automatic TTL (manual cleanup via deleteExpired)
|
|
18
|
-
*
|
|
19
|
-
* Schema Requirements (Prisma):
|
|
20
|
-
* ```prisma
|
|
21
|
-
* model AuthorizationSession {
|
|
22
|
-
* id Int @id @default(autoincrement())
|
|
23
|
-
* sessionId String @unique
|
|
24
|
-
* userId String
|
|
25
|
-
* entityType String
|
|
26
|
-
* currentStep Int @default(1)
|
|
27
|
-
* maxSteps Int
|
|
28
|
-
* stepData Json @default("{}")
|
|
29
|
-
* expiresAt DateTime
|
|
30
|
-
* completed Boolean @default(false)
|
|
31
|
-
* createdAt DateTime @default(now())
|
|
32
|
-
* updatedAt DateTime @updatedAt
|
|
33
|
-
*
|
|
34
|
-
* @@index([sessionId])
|
|
35
|
-
* @@index([userId, entityType])
|
|
36
|
-
* @@index([expiresAt])
|
|
37
|
-
* @@index([completed])
|
|
38
|
-
* }
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
class AuthorizationSessionRepositoryPostgres extends AuthorizationSessionRepositoryInterface {
|
|
42
|
-
constructor(prismaClient = prisma) {
|
|
43
|
-
super();
|
|
44
|
-
this.prisma = prismaClient; // Allow injection for testing
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Create a new authorization session
|
|
49
|
-
*
|
|
50
|
-
* @param {AuthorizationSession} session - Session entity to create
|
|
51
|
-
* @returns {Promise<AuthorizationSession>} Created session entity
|
|
52
|
-
*/
|
|
53
|
-
async create(session) {
|
|
54
|
-
const created = await this.prisma.authorizationSession.create({
|
|
55
|
-
data: {
|
|
56
|
-
sessionId: session.sessionId,
|
|
57
|
-
userId: session.userId,
|
|
58
|
-
entityType: session.entityType,
|
|
59
|
-
currentStep: session.currentStep,
|
|
60
|
-
maxSteps: session.maxSteps,
|
|
61
|
-
stepData: session.stepData,
|
|
62
|
-
expiresAt: session.expiresAt,
|
|
63
|
-
completed: session.completed,
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
return this._toEntity(created);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Find session by session ID
|
|
72
|
-
* Excludes expired sessions
|
|
73
|
-
*
|
|
74
|
-
* @param {string} sessionId - Unique session identifier
|
|
75
|
-
* @returns {Promise<AuthorizationSession|null>} Session entity or null
|
|
76
|
-
*/
|
|
77
|
-
async findBySessionId(sessionId) {
|
|
78
|
-
const record = await this.prisma.authorizationSession.findFirst({
|
|
79
|
-
where: {
|
|
80
|
-
sessionId,
|
|
81
|
-
expiresAt: { gt: new Date() },
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
return record ? this._toEntity(record) : null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Find active session for user and entity type
|
|
90
|
-
* Returns most recent active session
|
|
91
|
-
*
|
|
92
|
-
* @param {string} userId - User ID
|
|
93
|
-
* @param {string} entityType - Entity type (module name)
|
|
94
|
-
* @returns {Promise<AuthorizationSession|null>} Session entity or null
|
|
95
|
-
*/
|
|
96
|
-
async findActiveSession(userId, entityType) {
|
|
97
|
-
const record = await this.prisma.authorizationSession.findFirst({
|
|
98
|
-
where: {
|
|
99
|
-
userId,
|
|
100
|
-
entityType,
|
|
101
|
-
completed: false,
|
|
102
|
-
expiresAt: { gt: new Date() },
|
|
103
|
-
},
|
|
104
|
-
orderBy: { createdAt: 'desc' },
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
return record ? this._toEntity(record) : null;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Update existing session
|
|
112
|
-
*
|
|
113
|
-
* @param {AuthorizationSession} session - Session entity with updated data
|
|
114
|
-
* @returns {Promise<AuthorizationSession>} Updated session entity
|
|
115
|
-
*/
|
|
116
|
-
async update(session) {
|
|
117
|
-
const updated = await this.prisma.authorizationSession.update({
|
|
118
|
-
where: { sessionId: session.sessionId },
|
|
119
|
-
data: {
|
|
120
|
-
currentStep: session.currentStep,
|
|
121
|
-
stepData: session.stepData,
|
|
122
|
-
completed: session.completed,
|
|
123
|
-
updatedAt: new Date(),
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
return this._toEntity(updated);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Delete expired sessions (cleanup operation)
|
|
132
|
-
* PostgreSQL doesn't have TTL indexes, so this must be called periodically
|
|
133
|
-
* Recommend running as cron job or scheduled task
|
|
134
|
-
*
|
|
135
|
-
* @returns {Promise<number>} Number of deleted sessions
|
|
136
|
-
*/
|
|
137
|
-
async deleteExpired() {
|
|
138
|
-
const result = await this.prisma.authorizationSession.deleteMany({
|
|
139
|
-
where: {
|
|
140
|
-
expiresAt: { lt: new Date() },
|
|
141
|
-
},
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
return result.count;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Convert Prisma record to domain entity
|
|
149
|
-
*
|
|
150
|
-
* @private
|
|
151
|
-
* @param {Object} record - Prisma record
|
|
152
|
-
* @returns {AuthorizationSession} Domain entity
|
|
153
|
-
*/
|
|
154
|
-
_toEntity(record) {
|
|
155
|
-
return new AuthorizationSession({
|
|
156
|
-
sessionId: record.sessionId,
|
|
157
|
-
userId: record.userId,
|
|
158
|
-
entityType: record.entityType,
|
|
159
|
-
currentStep: record.currentStep,
|
|
160
|
-
maxSteps: record.maxSteps,
|
|
161
|
-
stepData: record.stepData,
|
|
162
|
-
expiresAt: record.expiresAt,
|
|
163
|
-
completed: record.completed,
|
|
164
|
-
createdAt: record.createdAt,
|
|
165
|
-
updatedAt: record.updatedAt,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
module.exports = { AuthorizationSessionRepositoryPostgres };
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DeleteModuleEntity Use Case
|
|
3
|
-
* Deletes a module entity by its ID
|
|
4
|
-
*/
|
|
5
|
-
class DeleteModuleEntity {
|
|
6
|
-
constructor({ moduleRepository }) {
|
|
7
|
-
this.moduleRepository = moduleRepository;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async execute(entityId) {
|
|
11
|
-
const entity = await this.moduleRepository.findEntityById(entityId);
|
|
12
|
-
|
|
13
|
-
if (!entity) {
|
|
14
|
-
throw new Error(`Entity not found: ${entityId}`);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
await this.moduleRepository.deleteEntity(entityId);
|
|
18
|
-
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
module.exports = { DeleteModuleEntity };
|