@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,262 +0,0 @@
|
|
|
1
|
-
const express = require('express');
|
|
2
|
-
const Boom = require('@hapi/boom');
|
|
3
|
-
const catchAsyncError = require('express-async-handler');
|
|
4
|
-
const {
|
|
5
|
-
createCredentialRepository,
|
|
6
|
-
} = require('./repositories/credential-repository-factory');
|
|
7
|
-
const {
|
|
8
|
-
createModuleRepository,
|
|
9
|
-
} = require('../modules/repositories/module-repository-factory');
|
|
10
|
-
const {
|
|
11
|
-
ListCredentialsForUser,
|
|
12
|
-
} = require('./use-cases/list-credentials-for-user');
|
|
13
|
-
const { GetCredentialForUser } = require('./use-cases/get-credential-for-user');
|
|
14
|
-
const {
|
|
15
|
-
DeleteCredentialForUser,
|
|
16
|
-
} = require('./use-cases/delete-credential-for-user');
|
|
17
|
-
const { ReauthorizeCredential } = require('./use-cases/reauthorize-credential');
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Boom Error Handler Middleware
|
|
21
|
-
* Handles Boom errors and converts them to appropriate HTTP responses
|
|
22
|
-
* @param {Error} err - Error object
|
|
23
|
-
* @param {Request} req - Express request
|
|
24
|
-
* @param {Response} res - Express response
|
|
25
|
-
* @param {Function} next - Express next function
|
|
26
|
-
*/
|
|
27
|
-
function boomErrorHandler(err, req, res, next) {
|
|
28
|
-
// Handle Boom errors
|
|
29
|
-
if (err.isBoom) {
|
|
30
|
-
return res.status(err.output.statusCode).json({
|
|
31
|
-
error: err.output.payload.message,
|
|
32
|
-
statusCode: err.output.statusCode,
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Handle generic errors (500)
|
|
37
|
-
console.error('Unexpected error:', err);
|
|
38
|
-
return res.status(500).json({
|
|
39
|
-
error: 'Internal server error',
|
|
40
|
-
statusCode: 500,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Create Credential Router
|
|
46
|
-
* Factory function that creates an Express router with credential management endpoints
|
|
47
|
-
*
|
|
48
|
-
* Endpoints:
|
|
49
|
-
* - GET /api/credentials - List all credentials for authenticated user
|
|
50
|
-
* - GET /api/credentials/:id - Get a single credential
|
|
51
|
-
* - DELETE /api/credentials/:id - Delete a credential
|
|
52
|
-
* - POST /api/credentials/:id/reauthorize - Reauthorize a credential
|
|
53
|
-
*
|
|
54
|
-
* Security:
|
|
55
|
-
* - All endpoints require authentication (via authenticateUser middleware)
|
|
56
|
-
* - Credentials are filtered to only belong to the authenticated user
|
|
57
|
-
* - Sensitive data (tokens) are filtered from responses
|
|
58
|
-
*
|
|
59
|
-
* @returns {express.Router} Configured Express router
|
|
60
|
-
*/
|
|
61
|
-
function createCredentialRouter() {
|
|
62
|
-
const router = express.Router();
|
|
63
|
-
|
|
64
|
-
// Load configuration and create repositories
|
|
65
|
-
const credentialRepository = createCredentialRepository();
|
|
66
|
-
const moduleRepository = createModuleRepository();
|
|
67
|
-
|
|
68
|
-
// Create credential use cases
|
|
69
|
-
const listCredentialsForUser = new ListCredentialsForUser({
|
|
70
|
-
credentialRepository,
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
const getCredentialForUser = new GetCredentialForUser({
|
|
74
|
-
credentialRepository,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const deleteCredentialForUser = new DeleteCredentialForUser({
|
|
78
|
-
credentialRepository,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
const reauthorizeCredential = new ReauthorizeCredential({
|
|
82
|
-
credentialRepository,
|
|
83
|
-
moduleRepository,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Filter sensitive data from credential objects
|
|
88
|
-
* Removes tokens and other sensitive fields from credentials before sending to client
|
|
89
|
-
*
|
|
90
|
-
* @param {Object|Array} credentials - Credential(s) to filter
|
|
91
|
-
* @returns {Object|Array} Filtered credential(s)
|
|
92
|
-
*/
|
|
93
|
-
function filterSensitiveData(credentials) {
|
|
94
|
-
const filter = (cred) => {
|
|
95
|
-
if (!cred) return cred;
|
|
96
|
-
|
|
97
|
-
// Create a copy without sensitive fields
|
|
98
|
-
const {
|
|
99
|
-
data,
|
|
100
|
-
access_token,
|
|
101
|
-
refresh_token,
|
|
102
|
-
id_token,
|
|
103
|
-
domain,
|
|
104
|
-
...safeCredential
|
|
105
|
-
} = cred;
|
|
106
|
-
|
|
107
|
-
// Ensure we have timestamps in ISO format
|
|
108
|
-
if (
|
|
109
|
-
safeCredential.createdAt &&
|
|
110
|
-
!(safeCredential.createdAt instanceof Date)
|
|
111
|
-
) {
|
|
112
|
-
safeCredential.createdAt = new Date(
|
|
113
|
-
safeCredential.createdAt
|
|
114
|
-
).toISOString();
|
|
115
|
-
}
|
|
116
|
-
if (
|
|
117
|
-
safeCredential.updatedAt &&
|
|
118
|
-
!(safeCredential.updatedAt instanceof Date)
|
|
119
|
-
) {
|
|
120
|
-
safeCredential.updatedAt = new Date(
|
|
121
|
-
safeCredential.updatedAt
|
|
122
|
-
).toISOString();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return safeCredential;
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
return Array.isArray(credentials)
|
|
129
|
-
? credentials.map(filter)
|
|
130
|
-
: filter(credentials);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// GET /api/credentials - List all credentials for authenticated user
|
|
134
|
-
router.get(
|
|
135
|
-
'/',
|
|
136
|
-
catchAsyncError(async (req, res) => {
|
|
137
|
-
// Expect authentication middleware to have set req.user
|
|
138
|
-
if (!req.user) {
|
|
139
|
-
throw Boom.unauthorized('Authentication required');
|
|
140
|
-
}
|
|
141
|
-
const userId =
|
|
142
|
-
typeof req.user.getId === 'function'
|
|
143
|
-
? req.user.getId()
|
|
144
|
-
: req.user.id;
|
|
145
|
-
|
|
146
|
-
const credentials = await listCredentialsForUser.execute(userId);
|
|
147
|
-
|
|
148
|
-
// Filter out sensitive data before responding
|
|
149
|
-
const safeCredentials = filterSensitiveData(credentials);
|
|
150
|
-
|
|
151
|
-
res.json({ credentials: safeCredentials });
|
|
152
|
-
})
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
// GET /api/credentials/:id - Get a single credential
|
|
156
|
-
router.get(
|
|
157
|
-
'/:id',
|
|
158
|
-
catchAsyncError(async (req, res) => {
|
|
159
|
-
if (!req.user) {
|
|
160
|
-
throw Boom.unauthorized('Authentication required');
|
|
161
|
-
}
|
|
162
|
-
const userId =
|
|
163
|
-
typeof req.user.getId === 'function'
|
|
164
|
-
? req.user.getId()
|
|
165
|
-
: req.user.id;
|
|
166
|
-
const credentialId = req.params.id;
|
|
167
|
-
|
|
168
|
-
const credential = await getCredentialForUser.execute(
|
|
169
|
-
credentialId,
|
|
170
|
-
userId
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
// Filter out sensitive data before responding
|
|
174
|
-
const safeCredential = filterSensitiveData(credential);
|
|
175
|
-
|
|
176
|
-
res.json(safeCredential);
|
|
177
|
-
})
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
// DELETE /api/credentials/:id - Delete a credential
|
|
181
|
-
router.delete(
|
|
182
|
-
'/:id',
|
|
183
|
-
catchAsyncError(async (req, res) => {
|
|
184
|
-
if (!req.user) {
|
|
185
|
-
throw Boom.unauthorized('Authentication required');
|
|
186
|
-
}
|
|
187
|
-
const userId =
|
|
188
|
-
typeof req.user.getId === 'function'
|
|
189
|
-
? req.user.getId()
|
|
190
|
-
: req.user.id;
|
|
191
|
-
const credentialId = req.params.id;
|
|
192
|
-
|
|
193
|
-
const result = await deleteCredentialForUser.execute(
|
|
194
|
-
credentialId,
|
|
195
|
-
userId
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
// Check if deletion was successful
|
|
199
|
-
if (result.deletedCount === 0) {
|
|
200
|
-
throw Boom.internal('Failed to delete credential');
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
res.json({
|
|
204
|
-
success: true,
|
|
205
|
-
message: `Credential ${credentialId} deleted successfully`,
|
|
206
|
-
});
|
|
207
|
-
})
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
// POST /api/credentials/:id/reauthorize - Reauthorize a credential
|
|
211
|
-
router.post(
|
|
212
|
-
'/:id/reauthorize',
|
|
213
|
-
catchAsyncError(async (req, res) => {
|
|
214
|
-
if (!req.user) {
|
|
215
|
-
throw Boom.unauthorized('Authentication required');
|
|
216
|
-
}
|
|
217
|
-
const userId =
|
|
218
|
-
typeof req.user.getId === 'function'
|
|
219
|
-
? req.user.getId()
|
|
220
|
-
: req.user.id;
|
|
221
|
-
const credentialId = req.params.id;
|
|
222
|
-
|
|
223
|
-
// Validate request body
|
|
224
|
-
if (!req.body.data) {
|
|
225
|
-
throw Boom.badRequest('data is required in request body');
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Get step and sessionId from request
|
|
229
|
-
const step = parseInt(req.body.step || '1', 10);
|
|
230
|
-
const sessionId = req.body.sessionId;
|
|
231
|
-
|
|
232
|
-
// Validate step is a positive integer
|
|
233
|
-
if (step < 1 || !Number.isInteger(step)) {
|
|
234
|
-
throw Boom.badRequest('step must be a positive integer');
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Validate sessionId is present for steps > 1
|
|
238
|
-
if (step > 1 && !sessionId) {
|
|
239
|
-
throw Boom.badRequest('sessionId is required for step > 1');
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Execute the reauthorization
|
|
243
|
-
const result = await reauthorizeCredential.execute(
|
|
244
|
-
credentialId,
|
|
245
|
-
userId,
|
|
246
|
-
req.body.data,
|
|
247
|
-
step,
|
|
248
|
-
sessionId
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
res.json(result);
|
|
252
|
-
})
|
|
253
|
-
);
|
|
254
|
-
|
|
255
|
-
// Boom error handler middleware
|
|
256
|
-
// Must be added after all routes to catch errors from handlers
|
|
257
|
-
router.use(boomErrorHandler);
|
|
258
|
-
|
|
259
|
-
return router;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
module.exports = { createCredentialRouter, boomErrorHandler };
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
const Boom = require('@hapi/boom');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Delete Credential For User Use Case
|
|
5
|
-
* Removes a credential after verifying ownership
|
|
6
|
-
*
|
|
7
|
-
* Business Logic:
|
|
8
|
-
* - Verify credential exists
|
|
9
|
-
* - Verify credential belongs to user (authorization)
|
|
10
|
-
* - Delete the credential
|
|
11
|
-
* - Return success status
|
|
12
|
-
*/
|
|
13
|
-
class DeleteCredentialForUser {
|
|
14
|
-
constructor({ credentialRepository }) {
|
|
15
|
-
this.credentialRepository = credentialRepository;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Execute the use case
|
|
20
|
-
* @param {string} credentialId - Credential ID
|
|
21
|
-
* @param {string} userId - User ID (for ownership verification)
|
|
22
|
-
* @returns {Promise<Object>} Deletion result { deletedCount: number }
|
|
23
|
-
*/
|
|
24
|
-
async execute(credentialId, userId) {
|
|
25
|
-
// Check if credential exists
|
|
26
|
-
const credential = await this.credentialRepository.findCredentialById(
|
|
27
|
-
credentialId
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
if (!credential) {
|
|
31
|
-
throw Boom.notFound(`Credential ${credentialId} not found`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Verify ownership - compare as strings to handle both MongoDB and PostgreSQL
|
|
35
|
-
if (credential.userId.toString() !== userId.toString()) {
|
|
36
|
-
throw Boom.forbidden(
|
|
37
|
-
'You do not have permission to delete this credential'
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Delete the credential
|
|
42
|
-
const result = await this.credentialRepository.deleteCredentialById(
|
|
43
|
-
credentialId
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
module.exports = { DeleteCredentialForUser };
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* List Credentials For User Use Case
|
|
3
|
-
* Retrieves all credentials belonging to a specific user
|
|
4
|
-
*
|
|
5
|
-
* Business Logic:
|
|
6
|
-
* - Fetches credentials for the authenticated user
|
|
7
|
-
* - Returns list of credentials (sensitive data filtered by handler)
|
|
8
|
-
* - Repository returns an array when filtering by userId only
|
|
9
|
-
*/
|
|
10
|
-
class ListCredentialsForUser {
|
|
11
|
-
constructor({ credentialRepository }) {
|
|
12
|
-
this.credentialRepository = credentialRepository;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Execute the use case
|
|
17
|
-
* @param {string} userId - User ID
|
|
18
|
-
* @returns {Promise<Array>} List of credentials (empty array if none found)
|
|
19
|
-
*/
|
|
20
|
-
async execute(userId) {
|
|
21
|
-
const credentials = await this.credentialRepository.findCredential({
|
|
22
|
-
userId,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
// Repository returns array for userId-only queries
|
|
26
|
-
// Ensure we always return an array (defensive programming)
|
|
27
|
-
return Array.isArray(credentials) ? credentials : [];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
module.exports = { ListCredentialsForUser };
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
const Boom = require('@hapi/boom');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Reauthorize Credential Use Case
|
|
5
|
-
* Re-authorizes an existing credential with new authentication data
|
|
6
|
-
* Supports both single-step and multi-step authorization flows
|
|
7
|
-
*
|
|
8
|
-
* Business Logic:
|
|
9
|
-
* - Verify credential exists and belongs to user
|
|
10
|
-
* - Load the appropriate module for the credential type
|
|
11
|
-
* - Process authorization callback (OAuth code, API keys, etc.)
|
|
12
|
-
* - Update credential with new tokens
|
|
13
|
-
* - Return success or next step requirements
|
|
14
|
-
*/
|
|
15
|
-
class ReauthorizeCredential {
|
|
16
|
-
constructor({ credentialRepository, moduleRepository }) {
|
|
17
|
-
this.credentialRepository = credentialRepository;
|
|
18
|
-
this.moduleRepository = moduleRepository;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Execute the use case
|
|
23
|
-
* @param {string} credentialId - Credential ID to reauthorize
|
|
24
|
-
* @param {string} userId - User ID (for ownership verification)
|
|
25
|
-
* @param {Object} authData - Authorization data
|
|
26
|
-
* @param {number} [step=1] - Current step in multi-step flow
|
|
27
|
-
* @param {string} [sessionId] - Session ID for multi-step flows
|
|
28
|
-
* @returns {Promise<Object>} Success response or next step requirements
|
|
29
|
-
*/
|
|
30
|
-
async execute(credentialId, userId, authData, step = 1, sessionId = null) {
|
|
31
|
-
// Check if credential exists
|
|
32
|
-
const credential = await this.credentialRepository.findCredentialById(
|
|
33
|
-
credentialId
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
if (!credential) {
|
|
37
|
-
throw Boom.notFound(`Credential ${credentialId} not found`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Verify ownership - compare as strings to handle both MongoDB and PostgreSQL
|
|
41
|
-
if (credential.userId.toString() !== userId.toString()) {
|
|
42
|
-
throw Boom.forbidden(
|
|
43
|
-
'You do not have permission to reauthorize this credential'
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Load the module for this credential type
|
|
48
|
-
const module = await this.moduleRepository.findModuleById(
|
|
49
|
-
credential.id
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
if (!module) {
|
|
53
|
-
throw Boom.badRequest(
|
|
54
|
-
`Module not found for credential type: ${
|
|
55
|
-
credential.type || 'unknown'
|
|
56
|
-
}`
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Process the authorization callback
|
|
61
|
-
const result = await module.processAuthorizationCallback({
|
|
62
|
-
credentialId,
|
|
63
|
-
userId,
|
|
64
|
-
data: authData,
|
|
65
|
-
step,
|
|
66
|
-
sessionId,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Multi-step flow - return next step requirements
|
|
70
|
-
if (result.step && result.step > 1) {
|
|
71
|
-
return {
|
|
72
|
-
step: result.step,
|
|
73
|
-
totalSteps: result.totalSteps,
|
|
74
|
-
sessionId: result.sessionId,
|
|
75
|
-
requirements: result.requirements,
|
|
76
|
-
message: result.message,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Single-step or final step - update credential and return success
|
|
81
|
-
if (result.success) {
|
|
82
|
-
// Fetch the updated credential to get the new authIsValid status
|
|
83
|
-
const updatedCredential =
|
|
84
|
-
await this.credentialRepository.findCredentialById(
|
|
85
|
-
credentialId
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
success: true,
|
|
90
|
-
credential_id: credentialId,
|
|
91
|
-
authIsValid: updatedCredential?.authIsValid || true,
|
|
92
|
-
...(result.message && { message: result.message }),
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// If we get here, something unexpected happened
|
|
97
|
-
throw new Error(
|
|
98
|
-
'Authorization callback did not return expected result format'
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
module.exports = { ReauthorizeCredential };
|