@friggframework/core 2.0.0-next.40 → 2.0.0-next.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +693 -0
- package/README.md +931 -50
- package/application/commands/README.md +421 -0
- package/application/commands/credential-commands.js +224 -0
- package/application/commands/entity-commands.js +315 -0
- package/application/commands/integration-commands.js +160 -0
- package/application/commands/integration-commands.test.js +123 -0
- package/application/commands/user-commands.js +213 -0
- package/application/index.js +69 -0
- package/core/CLAUDE.md +690 -0
- package/core/create-handler.js +0 -6
- package/credential/repositories/credential-repository-factory.js +47 -0
- package/credential/repositories/credential-repository-interface.js +98 -0
- package/credential/repositories/credential-repository-mongo.js +301 -0
- package/credential/repositories/credential-repository-postgres.js +307 -0
- package/credential/repositories/credential-repository.js +307 -0
- package/credential/use-cases/get-credential-for-user.js +21 -0
- package/credential/use-cases/update-authentication-status.js +15 -0
- package/database/config.js +117 -0
- package/database/encryption/README.md +683 -0
- package/database/encryption/encryption-integration.test.js +553 -0
- package/database/encryption/encryption-schema-registry.js +141 -0
- package/database/encryption/encryption-schema-registry.test.js +392 -0
- package/database/encryption/field-encryption-service.js +226 -0
- package/database/encryption/field-encryption-service.test.js +525 -0
- package/database/encryption/logger.js +79 -0
- package/database/encryption/mongo-decryption-fix-verification.test.js +348 -0
- package/database/encryption/postgres-decryption-fix-verification.test.js +371 -0
- package/database/encryption/postgres-relation-decryption.test.js +245 -0
- package/database/encryption/prisma-encryption-extension.js +222 -0
- package/database/encryption/prisma-encryption-extension.test.js +439 -0
- package/database/index.js +25 -12
- package/database/models/readme.md +1 -0
- package/database/prisma.js +162 -0
- package/database/repositories/health-check-repository-factory.js +38 -0
- package/database/repositories/health-check-repository-interface.js +86 -0
- package/database/repositories/health-check-repository-mongodb.js +72 -0
- package/database/repositories/health-check-repository-postgres.js +75 -0
- package/database/repositories/health-check-repository.js +108 -0
- package/database/use-cases/check-database-health-use-case.js +34 -0
- package/database/use-cases/check-encryption-health-use-case.js +82 -0
- package/database/use-cases/test-encryption-use-case.js +252 -0
- package/encrypt/Cryptor.js +20 -152
- package/encrypt/index.js +1 -2
- package/encrypt/test-encrypt.js +0 -2
- package/handlers/app-definition-loader.js +38 -0
- package/handlers/app-handler-helpers.js +0 -3
- package/handlers/auth-flow.integration.test.js +147 -0
- package/handlers/backend-utils.js +25 -45
- package/handlers/integration-event-dispatcher.js +54 -0
- package/handlers/integration-event-dispatcher.test.js +141 -0
- package/handlers/routers/HEALTHCHECK.md +103 -1
- package/handlers/routers/auth.js +3 -14
- package/handlers/routers/health.js +63 -424
- package/handlers/routers/health.test.js +7 -0
- package/handlers/routers/integration-defined-routers.js +8 -5
- package/handlers/routers/user.js +25 -5
- package/handlers/routers/websocket.js +5 -3
- package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
- package/handlers/use-cases/check-integrations-health-use-case.js +32 -0
- package/handlers/workers/integration-defined-workers.js +6 -3
- package/index.js +45 -22
- package/integrations/index.js +12 -10
- package/integrations/integration-base.js +224 -53
- package/integrations/integration-router.js +386 -178
- package/integrations/options.js +1 -1
- package/integrations/repositories/integration-mapping-repository-factory.js +50 -0
- package/integrations/repositories/integration-mapping-repository-interface.js +106 -0
- package/integrations/repositories/integration-mapping-repository-mongo.js +161 -0
- package/integrations/repositories/integration-mapping-repository-postgres.js +227 -0
- package/integrations/repositories/integration-mapping-repository.js +156 -0
- package/integrations/repositories/integration-repository-factory.js +44 -0
- package/integrations/repositories/integration-repository-interface.js +115 -0
- package/integrations/repositories/integration-repository-mongo.js +271 -0
- package/integrations/repositories/integration-repository-postgres.js +319 -0
- package/integrations/tests/doubles/dummy-integration-class.js +90 -0
- package/integrations/tests/doubles/test-integration-repository.js +99 -0
- package/integrations/tests/use-cases/create-integration.test.js +131 -0
- package/integrations/tests/use-cases/delete-integration-for-user.test.js +150 -0
- package/integrations/tests/use-cases/find-integration-context-by-external-entity-id.test.js +92 -0
- package/integrations/tests/use-cases/get-integration-for-user.test.js +150 -0
- package/integrations/tests/use-cases/get-integration-instance.test.js +176 -0
- package/integrations/tests/use-cases/get-integrations-for-user.test.js +176 -0
- package/integrations/tests/use-cases/get-possible-integrations.test.js +188 -0
- package/integrations/tests/use-cases/update-integration-messages.test.js +142 -0
- package/integrations/tests/use-cases/update-integration-status.test.js +103 -0
- package/integrations/tests/use-cases/update-integration.test.js +141 -0
- package/integrations/use-cases/create-integration.js +83 -0
- package/integrations/use-cases/delete-integration-for-user.js +73 -0
- package/integrations/use-cases/find-integration-context-by-external-entity-id.js +72 -0
- package/integrations/use-cases/get-integration-for-user.js +78 -0
- package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
- package/integrations/use-cases/get-integration-instance.js +83 -0
- package/integrations/use-cases/get-integrations-for-user.js +87 -0
- package/integrations/use-cases/get-possible-integrations.js +27 -0
- package/integrations/use-cases/index.js +11 -0
- package/integrations/use-cases/load-integration-context-full.test.js +329 -0
- package/integrations/use-cases/load-integration-context.js +71 -0
- package/integrations/use-cases/load-integration-context.test.js +114 -0
- package/integrations/use-cases/update-integration-messages.js +44 -0
- package/integrations/use-cases/update-integration-status.js +32 -0
- package/integrations/use-cases/update-integration.js +93 -0
- package/integrations/utils/map-integration-dto.js +36 -0
- package/jest-global-setup-noop.js +3 -0
- package/jest-global-teardown-noop.js +3 -0
- package/{module-plugin → modules}/entity.js +1 -0
- package/{module-plugin → modules}/index.js +0 -8
- package/modules/module-factory.js +56 -0
- package/modules/module-hydration.test.js +205 -0
- package/modules/module.js +221 -0
- package/modules/repositories/module-repository-factory.js +33 -0
- package/modules/repositories/module-repository-interface.js +129 -0
- package/modules/repositories/module-repository-mongo.js +386 -0
- package/modules/repositories/module-repository-postgres.js +437 -0
- package/modules/repositories/module-repository.js +327 -0
- package/{module-plugin → modules}/test/mock-api/api.js +8 -3
- package/{module-plugin → modules}/test/mock-api/definition.js +12 -8
- package/modules/tests/doubles/test-module-factory.js +16 -0
- package/modules/tests/doubles/test-module-repository.js +39 -0
- package/modules/use-cases/get-entities-for-user.js +32 -0
- package/modules/use-cases/get-entity-options-by-id.js +59 -0
- package/modules/use-cases/get-entity-options-by-type.js +34 -0
- package/modules/use-cases/get-module-instance-from-type.js +31 -0
- package/modules/use-cases/get-module.js +56 -0
- package/modules/use-cases/process-authorization-callback.js +121 -0
- package/modules/use-cases/refresh-entity-options.js +59 -0
- package/modules/use-cases/test-module-auth.js +55 -0
- package/modules/utils/map-module-dto.js +18 -0
- package/package.json +14 -6
- package/prisma-mongodb/schema.prisma +321 -0
- package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
- package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
- package/prisma-postgresql/migrations/migration_lock.toml +3 -0
- package/prisma-postgresql/schema.prisma +303 -0
- package/syncs/manager.js +468 -443
- package/syncs/repositories/sync-repository-factory.js +38 -0
- package/syncs/repositories/sync-repository-interface.js +109 -0
- package/syncs/repositories/sync-repository-mongo.js +239 -0
- package/syncs/repositories/sync-repository-postgres.js +319 -0
- package/syncs/sync.js +0 -1
- package/token/repositories/token-repository-factory.js +33 -0
- package/token/repositories/token-repository-interface.js +131 -0
- package/token/repositories/token-repository-mongo.js +212 -0
- package/token/repositories/token-repository-postgres.js +257 -0
- package/token/repositories/token-repository.js +219 -0
- package/types/integrations/index.d.ts +2 -6
- package/types/module-plugin/index.d.ts +5 -57
- package/types/syncs/index.d.ts +0 -2
- package/user/repositories/user-repository-factory.js +46 -0
- package/user/repositories/user-repository-interface.js +198 -0
- package/user/repositories/user-repository-mongo.js +250 -0
- package/user/repositories/user-repository-postgres.js +311 -0
- package/user/tests/doubles/test-user-repository.js +72 -0
- package/user/tests/use-cases/create-individual-user.test.js +24 -0
- package/user/tests/use-cases/create-organization-user.test.js +28 -0
- package/user/tests/use-cases/create-token-for-user-id.test.js +19 -0
- package/user/tests/use-cases/get-user-from-bearer-token.test.js +64 -0
- package/user/tests/use-cases/login-user.test.js +140 -0
- package/user/use-cases/create-individual-user.js +61 -0
- package/user/use-cases/create-organization-user.js +47 -0
- package/user/use-cases/create-token-for-user-id.js +30 -0
- package/user/use-cases/get-user-from-bearer-token.js +77 -0
- package/user/use-cases/login-user.js +122 -0
- package/user/user.js +77 -0
- package/websocket/repositories/websocket-connection-repository-factory.js +37 -0
- package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
- package/websocket/repositories/websocket-connection-repository-mongo.js +155 -0
- package/websocket/repositories/websocket-connection-repository-postgres.js +195 -0
- package/websocket/repositories/websocket-connection-repository.js +160 -0
- package/database/models/State.js +0 -9
- package/database/models/Token.js +0 -70
- package/database/mongo.js +0 -171
- package/encrypt/Cryptor.test.js +0 -32
- package/encrypt/encrypt.js +0 -104
- package/encrypt/encrypt.test.js +0 -1069
- package/handlers/routers/middleware/loadUser.js +0 -15
- package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
- package/integrations/create-frigg-backend.js +0 -31
- package/integrations/integration-factory.js +0 -251
- package/integrations/integration-mapping.js +0 -43
- package/integrations/integration-model.js +0 -46
- package/integrations/integration-user.js +0 -144
- package/integrations/test/integration-base.test.js +0 -144
- package/module-plugin/auther.js +0 -393
- package/module-plugin/credential.js +0 -22
- package/module-plugin/entity-manager.js +0 -70
- package/module-plugin/manager.js +0 -169
- package/module-plugin/module-factory.js +0 -61
- package/module-plugin/test/auther.test.js +0 -97
- /package/{module-plugin → modules}/ModuleConstants.js +0 -0
- /package/{module-plugin → modules}/requester/api-key.js +0 -0
- /package/{module-plugin → modules}/requester/basic.js +0 -0
- /package/{module-plugin → modules}/requester/oauth-2.js +0 -0
- /package/{module-plugin → modules}/requester/requester.js +0 -0
- /package/{module-plugin → modules}/requester/requester.test.js +0 -0
- /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const bcrypt = require('bcryptjs');
|
|
3
|
+
const { TokenRepositoryInterface } = require('./token-repository-interface');
|
|
4
|
+
|
|
5
|
+
const BCRYPT_ROUNDS = 10;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Prisma-based Token Repository
|
|
9
|
+
* Handles persistence of authentication tokens with bcrypt hashing
|
|
10
|
+
*
|
|
11
|
+
* Works identically for both MongoDB and PostgreSQL:
|
|
12
|
+
* - MongoDB: String IDs with @db.ObjectId
|
|
13
|
+
* - PostgreSQL: Integer IDs with auto-increment
|
|
14
|
+
* - Both use same query patterns (no many-to-many differences)
|
|
15
|
+
*
|
|
16
|
+
* Migration from Mongoose:
|
|
17
|
+
* - Constructor injection of Prisma client
|
|
18
|
+
* - Static methods → Instance methods
|
|
19
|
+
* - Token.createTokenWithExpire() → createTokenWithExpire()
|
|
20
|
+
* - Token.validateAndGetTokenFromJSONToken() → validateAndGetToken()
|
|
21
|
+
* - Bcrypt hashing handled in repository layer
|
|
22
|
+
*/
|
|
23
|
+
class TokenRepository extends TokenRepositoryInterface {
|
|
24
|
+
constructor(prismaClient = prisma) {
|
|
25
|
+
super();
|
|
26
|
+
this.prisma = prismaClient; // Allow injection for testing
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create a token with expiration
|
|
31
|
+
* Replaces: Token.createTokenWithExpire(userId, rawToken, minutes)
|
|
32
|
+
*
|
|
33
|
+
* @param {string} userId - The user ID
|
|
34
|
+
* @param {string} rawToken - The raw (unhashed) token string
|
|
35
|
+
* @param {number} minutes - Minutes until expiration
|
|
36
|
+
* @returns {Promise<Object>} The created token record
|
|
37
|
+
*/
|
|
38
|
+
async createTokenWithExpire(userId, rawToken, minutes) {
|
|
39
|
+
// Hash the token with bcrypt
|
|
40
|
+
const tokenHash = await bcrypt.hash(rawToken, BCRYPT_ROUNDS);
|
|
41
|
+
|
|
42
|
+
// Calculate expiration time
|
|
43
|
+
const expires = new Date(Date.now() + minutes * 60000);
|
|
44
|
+
|
|
45
|
+
return await this.prisma.token.create({
|
|
46
|
+
data: {
|
|
47
|
+
token: tokenHash,
|
|
48
|
+
expires,
|
|
49
|
+
userId,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Validate and retrieve token from JSON token object
|
|
56
|
+
* Replaces: Token.validateAndGetTokenFromJSONToken(tokenObj)
|
|
57
|
+
*
|
|
58
|
+
* @param {Object} tokenObj - Object with id and token properties
|
|
59
|
+
* @returns {Promise<Object>} The validated token record
|
|
60
|
+
* @throws {Error} If token is invalid, expired, or doesn't exist
|
|
61
|
+
*/
|
|
62
|
+
async validateAndGetToken(tokenObj) {
|
|
63
|
+
const sessionToken = await this.prisma.token.findUnique({
|
|
64
|
+
where: { id: tokenObj.id },
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (!sessionToken) {
|
|
68
|
+
throw new Error('Invalid Token: Token does not exist');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Verify token hash matches
|
|
72
|
+
const isValid = await bcrypt.compare(
|
|
73
|
+
tokenObj.token,
|
|
74
|
+
sessionToken.token
|
|
75
|
+
);
|
|
76
|
+
if (!isValid) {
|
|
77
|
+
throw new Error('Invalid Token: Token does not match');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check if token is expired
|
|
81
|
+
if (
|
|
82
|
+
sessionToken.expires &&
|
|
83
|
+
new Date(sessionToken.expires) < new Date()
|
|
84
|
+
) {
|
|
85
|
+
throw new Error('Invalid Token: Token is expired');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return sessionToken;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Find a token by ID
|
|
93
|
+
* Replaces: Token.findById(tokenId)
|
|
94
|
+
*
|
|
95
|
+
* @param {string} tokenId - The token ID
|
|
96
|
+
* @returns {Promise<Object|null>} The token record or null
|
|
97
|
+
*/
|
|
98
|
+
async findTokenById(tokenId) {
|
|
99
|
+
return await this.prisma.token.findUnique({
|
|
100
|
+
where: { id: tokenId },
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Find tokens by user ID
|
|
106
|
+
* Replaces: Token.find({ user: userId })
|
|
107
|
+
*
|
|
108
|
+
* @param {string} userId - The user ID
|
|
109
|
+
* @returns {Promise<Array>} Array of token records
|
|
110
|
+
*/
|
|
111
|
+
async findTokensByUserId(userId) {
|
|
112
|
+
return await this.prisma.token.findMany({
|
|
113
|
+
where: { userId },
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Delete a token by ID
|
|
119
|
+
* Replaces: Token.deleteOne({ _id: tokenId })
|
|
120
|
+
*
|
|
121
|
+
* @param {string} tokenId - The token ID
|
|
122
|
+
* @returns {Promise<Object>} The deletion result
|
|
123
|
+
*/
|
|
124
|
+
async deleteToken(tokenId) {
|
|
125
|
+
try {
|
|
126
|
+
await this.prisma.token.delete({
|
|
127
|
+
where: { id: tokenId },
|
|
128
|
+
});
|
|
129
|
+
return { acknowledged: true, deletedCount: 1 };
|
|
130
|
+
} catch (error) {
|
|
131
|
+
if (error.code === 'P2025') {
|
|
132
|
+
// Record not found
|
|
133
|
+
return { acknowledged: true, deletedCount: 0 };
|
|
134
|
+
}
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Delete expired tokens
|
|
141
|
+
* Replaces: Token.deleteMany({ expires: { $lt: new Date() } })
|
|
142
|
+
*
|
|
143
|
+
* @returns {Promise<Object>} The deletion result with count
|
|
144
|
+
*/
|
|
145
|
+
async deleteExpiredTokens() {
|
|
146
|
+
const result = await this.prisma.token.deleteMany({
|
|
147
|
+
where: {
|
|
148
|
+
expires: {
|
|
149
|
+
lt: new Date(),
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
acknowledged: true,
|
|
156
|
+
deletedCount: result.count,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Delete all tokens for a user
|
|
162
|
+
* Replaces: Token.deleteMany({ user: userId })
|
|
163
|
+
*
|
|
164
|
+
* @param {string} userId - The user ID
|
|
165
|
+
* @returns {Promise<Object>} The deletion result
|
|
166
|
+
*/
|
|
167
|
+
async deleteTokensByUserId(userId) {
|
|
168
|
+
const result = await this.prisma.token.deleteMany({
|
|
169
|
+
where: { userId },
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
acknowledged: true,
|
|
174
|
+
deletedCount: result.count,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Create JSON token string from token object and raw token
|
|
180
|
+
* Replaces: Token.createJSONToken(token, rawToken)
|
|
181
|
+
*
|
|
182
|
+
* @param {Object} token - The token record
|
|
183
|
+
* @param {string} rawToken - The raw token string
|
|
184
|
+
* @returns {string} JSON string with id and token
|
|
185
|
+
*/
|
|
186
|
+
createJSONToken(token, rawToken) {
|
|
187
|
+
return JSON.stringify({
|
|
188
|
+
id: token.id,
|
|
189
|
+
token: rawToken,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Create base64 encoded buffer token
|
|
195
|
+
* Replaces: Token.createBase64BufferToken(token, rawToken)
|
|
196
|
+
*
|
|
197
|
+
* @param {Object} token - The token record
|
|
198
|
+
* @param {string} rawToken - The raw token string
|
|
199
|
+
* @returns {string} Base64 encoded token
|
|
200
|
+
*/
|
|
201
|
+
createBase64BufferToken(token, rawToken) {
|
|
202
|
+
const jsonVal = this.createJSONToken(token, rawToken);
|
|
203
|
+
return Buffer.from(jsonVal).toString('base64');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Parse JSON token from base64 buffer
|
|
208
|
+
* Replaces: Token.getJSONTokenFromBase64BufferToken(buffer)
|
|
209
|
+
*
|
|
210
|
+
* @param {string} buffer - Base64 encoded token string
|
|
211
|
+
* @returns {Object} Parsed token object with id and token
|
|
212
|
+
*/
|
|
213
|
+
getJSONTokenFromBase64BufferToken(buffer) {
|
|
214
|
+
const tokenStr = Buffer.from(buffer.trim(), 'base64').toString('ascii');
|
|
215
|
+
return JSON.parse(tokenStr);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
module.exports = { TokenRepository };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
declare module "@friggframework/integrations" {
|
|
2
2
|
import { Delegate, IFriggDelegate } from "@friggframework/core";
|
|
3
3
|
import { Model } from "mongoose";
|
|
4
|
-
import { EntityManager } from "@friggframework/module-plugin";
|
|
5
4
|
|
|
6
5
|
export class Integration extends Model {
|
|
7
6
|
entities: any[];
|
|
@@ -19,8 +18,7 @@ declare module "@friggframework/integrations" {
|
|
|
19
18
|
|
|
20
19
|
export class IntegrationManager
|
|
21
20
|
extends Delegate
|
|
22
|
-
implements IFriggIntegrationManager
|
|
23
|
-
{
|
|
21
|
+
implements IFriggIntegrationManager {
|
|
24
22
|
integration: Integration;
|
|
25
23
|
primaryInstance: any;
|
|
26
24
|
targetInstance: any;
|
|
@@ -56,7 +54,6 @@ declare module "@friggframework/integrations" {
|
|
|
56
54
|
entities: { id: string; user: any },
|
|
57
55
|
userId: string,
|
|
58
56
|
config: any,
|
|
59
|
-
EntityManager: EntityManager
|
|
60
57
|
): Promise<any>;
|
|
61
58
|
|
|
62
59
|
static getFormattedIntegration(
|
|
@@ -116,8 +113,7 @@ declare module "@friggframework/integrations" {
|
|
|
116
113
|
}
|
|
117
114
|
|
|
118
115
|
export class IntegrationConfigManager
|
|
119
|
-
implements IFriggIntegrationConfigManager
|
|
120
|
-
{
|
|
116
|
+
implements IFriggIntegrationConfigManager {
|
|
121
117
|
options: IntegrationOptions[];
|
|
122
118
|
primary: any;
|
|
123
119
|
|
|
@@ -4,26 +4,12 @@ declare module "@friggframework/module-plugin" {
|
|
|
4
4
|
|
|
5
5
|
export class Credential extends Model {
|
|
6
6
|
userId: string;
|
|
7
|
-
|
|
7
|
+
authIsValid: boolean;
|
|
8
8
|
subType: string;
|
|
9
9
|
externalId: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
static primaryEntityClass: any;
|
|
14
|
-
static entityManagerClasses: any[];
|
|
15
|
-
static entityTypes: string[];
|
|
16
|
-
static getEntitiesForUser(userId: string): Promise<any[]>;
|
|
17
|
-
static checkIsValidType(entityType: string): boolean;
|
|
18
|
-
static getEntityManagerClass(entityType?: string): any;
|
|
19
|
-
|
|
20
|
-
static getEntityManagerInstanceFromEntityId(
|
|
21
|
-
entityId: string,
|
|
22
|
-
userId: string
|
|
23
|
-
): Promise<any>;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
interface IFriggEntityManager {}
|
|
12
|
+
interface IFriggEntityManager { }
|
|
27
13
|
|
|
28
14
|
export class Entity extends Model {
|
|
29
15
|
credentialId: string;
|
|
@@ -34,42 +20,7 @@ declare module "@friggframework/module-plugin" {
|
|
|
34
20
|
}
|
|
35
21
|
|
|
36
22
|
export type MappedEntity = Entity & { id: string; type: any };
|
|
37
|
-
export class ModuleManager extends Delegate implements IFriggModuleManager {
|
|
38
|
-
static Entity: Entity;
|
|
39
|
-
static Credential: Credential;
|
|
40
|
-
|
|
41
|
-
constructor(params: { userId: string });
|
|
42
23
|
|
|
43
|
-
static getName(): any;
|
|
44
|
-
static getInstance(params: any): Promise<any>;
|
|
45
|
-
static getEntitiesForUserId(userId: string): Promise<MappedEntity[]>;
|
|
46
|
-
|
|
47
|
-
batchCreateSyncObjects(syncObjects: any, syncManager: any): Promise<any>;
|
|
48
|
-
batchUpdateSyncObjects(syncObjects: any, syncManager: any): Promise<any>;
|
|
49
|
-
findOrCreateEntity(params: any): Promise<any>;
|
|
50
|
-
getAllSyncObjects(SyncClass: any): Promise<any>;
|
|
51
|
-
getAuthorizationRequirements(params: any): Promise<any>;
|
|
52
|
-
getEntityId(): Promise<string>;
|
|
53
|
-
getEntityOptions(): Promise<any>;
|
|
54
|
-
markCredentialsInvalid(): Promise<Credential>;
|
|
55
|
-
processAuthorizationCallback(params: any): Promise<any>;
|
|
56
|
-
testAuth(params: any): Promise<any>;
|
|
57
|
-
validateAuthorizationRequirements(): Promise<boolean>;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
interface IFriggModuleManager extends IFriggDelegate {
|
|
61
|
-
getEntityId(): Promise<string>;
|
|
62
|
-
validateAuthorizationRequirements(): Promise<boolean>;
|
|
63
|
-
getAuthorizationRequirements(params: any): Promise<any>;
|
|
64
|
-
testAuth(params: any): Promise<any>;
|
|
65
|
-
processAuthorizationCallback(params: any): Promise<any>;
|
|
66
|
-
getEntityOptions(): Promise<any>;
|
|
67
|
-
findOrCreateEntity(params: any): Promise<any>;
|
|
68
|
-
getAllSyncObjects(SyncClass: any): Promise<any>;
|
|
69
|
-
batchCreateSyncObjects(syncObjects: any, syncManager: any): Promise<any>;
|
|
70
|
-
batchUpdateSyncObjects(syncObjects: any, syncManager: any): Promise<any>;
|
|
71
|
-
markCredentialsInvalid(): Promise<Credential>;
|
|
72
|
-
}
|
|
73
24
|
|
|
74
25
|
export class Requester implements IFriggRequester {
|
|
75
26
|
DLGT_INVALID_AUTH: string;
|
|
@@ -138,8 +89,7 @@ declare module "@friggframework/module-plugin" {
|
|
|
138
89
|
|
|
139
90
|
export class ApiKeyRequester
|
|
140
91
|
extends Requester
|
|
141
|
-
implements IFriggApiKeyRequester
|
|
142
|
-
{
|
|
92
|
+
implements IFriggApiKeyRequester {
|
|
143
93
|
API_KEY_NAME: string;
|
|
144
94
|
API_KEY_VALUE: any;
|
|
145
95
|
|
|
@@ -160,8 +110,7 @@ declare module "@friggframework/module-plugin" {
|
|
|
160
110
|
|
|
161
111
|
export class BasicAuthRequester
|
|
162
112
|
extends Requester
|
|
163
|
-
implements IFriggBasicAuthRequester
|
|
164
|
-
{
|
|
113
|
+
implements IFriggBasicAuthRequester {
|
|
165
114
|
password: string;
|
|
166
115
|
username: string;
|
|
167
116
|
|
|
@@ -189,8 +138,7 @@ declare module "@friggframework/module-plugin" {
|
|
|
189
138
|
|
|
190
139
|
export class OAuth2Requester
|
|
191
140
|
extends Requester
|
|
192
|
-
implements IFriggOAuth2Requester
|
|
193
|
-
{
|
|
141
|
+
implements IFriggOAuth2Requester {
|
|
194
142
|
DLGT_TOKEN_DEAUTHORIZED: string;
|
|
195
143
|
DLGT_TOKEN_UPDATE: string;
|
|
196
144
|
accessTokenExpire: any;
|
package/types/syncs/index.d.ts
CHANGED
|
@@ -28,7 +28,6 @@ declare module "@friggframework/syncs/manager" {
|
|
|
28
28
|
confirmCreate(
|
|
29
29
|
syncObj: Sync,
|
|
30
30
|
createdId: string,
|
|
31
|
-
moduleManager: any
|
|
32
31
|
): Promise<any>;
|
|
33
32
|
confirmUpdate(syncObj: Sync): Promise<any>;
|
|
34
33
|
createSyncDBObject(objArr: any[], entities: any[]): Promise<any>;
|
|
@@ -50,7 +49,6 @@ declare module "@friggframework/syncs/manager" {
|
|
|
50
49
|
confirmCreate(
|
|
51
50
|
syncObj: Sync,
|
|
52
51
|
createdId: string,
|
|
53
|
-
moduleManager: any
|
|
54
52
|
): Promise<any>;
|
|
55
53
|
confirmUpdate(syncObj: Sync): Promise<any>;
|
|
56
54
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const { UserRepositoryMongo } = require('./user-repository-mongo');
|
|
2
|
+
const { UserRepositoryPostgres } = require('./user-repository-postgres');
|
|
3
|
+
const databaseConfig = require('../../database/config');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* User Repository Factory
|
|
7
|
+
* Creates the appropriate repository adapter based on database type
|
|
8
|
+
*
|
|
9
|
+
* Database-specific implementations:
|
|
10
|
+
* - MongoDB: Uses String IDs (ObjectId), no conversion needed
|
|
11
|
+
* - PostgreSQL: Uses Int IDs, converts String ↔ Int
|
|
12
|
+
*
|
|
13
|
+
* All repository methods return String IDs regardless of database type,
|
|
14
|
+
* ensuring application layer consistency.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* ```javascript
|
|
18
|
+
* const repository = createUserRepository();
|
|
19
|
+
* const user = await repository.findUserById(id); // ID is string
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @returns {UserRepositoryInterface} Configured repository adapter
|
|
23
|
+
*/
|
|
24
|
+
function createUserRepository() {
|
|
25
|
+
const dbType = databaseConfig.DB_TYPE;
|
|
26
|
+
|
|
27
|
+
switch (dbType) {
|
|
28
|
+
case 'mongodb':
|
|
29
|
+
return new UserRepositoryMongo();
|
|
30
|
+
|
|
31
|
+
case 'postgresql':
|
|
32
|
+
return new UserRepositoryPostgres();
|
|
33
|
+
|
|
34
|
+
default:
|
|
35
|
+
throw new Error(
|
|
36
|
+
`Unsupported DB_TYPE: ${dbType}. Supported values: 'mongodb', 'postgresql'`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = {
|
|
42
|
+
createUserRepository,
|
|
43
|
+
// Export adapters for direct testing
|
|
44
|
+
UserRepositoryMongo,
|
|
45
|
+
UserRepositoryPostgres,
|
|
46
|
+
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Repository Interface
|
|
3
|
+
* Abstract base class defining the contract for user persistence adapters
|
|
4
|
+
*
|
|
5
|
+
* This follows the Port in Hexagonal Architecture:
|
|
6
|
+
* - Domain layer depends on this abstraction
|
|
7
|
+
* - Concrete adapters implement this interface
|
|
8
|
+
* - Use cases receive repositories via dependency injection
|
|
9
|
+
*
|
|
10
|
+
* Note: Currently, User model has identical structure across MongoDB and PostgreSQL,
|
|
11
|
+
* so UserRepository serves both. This interface exists for consistency and
|
|
12
|
+
* future-proofing if database-specific implementations become needed.
|
|
13
|
+
*
|
|
14
|
+
* @abstract
|
|
15
|
+
*/
|
|
16
|
+
class UserRepositoryInterface {
|
|
17
|
+
/**
|
|
18
|
+
* Get session token from base64 buffer token
|
|
19
|
+
*
|
|
20
|
+
* @param {string} token - Base64 buffer token
|
|
21
|
+
* @returns {Promise<Object>} Session token object
|
|
22
|
+
* @abstract
|
|
23
|
+
*/
|
|
24
|
+
async getSessionToken(token) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
'Method getSessionToken must be implemented by subclass'
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Find organization user by ID
|
|
32
|
+
*
|
|
33
|
+
* @param {string|number} userId - User ID
|
|
34
|
+
* @returns {Promise<Object|null>} User object or null
|
|
35
|
+
* @abstract
|
|
36
|
+
*/
|
|
37
|
+
async findOrganizationUserById(userId) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
'Method findOrganizationUserById must be implemented by subclass'
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Find individual user by ID
|
|
45
|
+
*
|
|
46
|
+
* @param {string|number} userId - User ID
|
|
47
|
+
* @returns {Promise<Object|null>} User object or null
|
|
48
|
+
* @abstract
|
|
49
|
+
*/
|
|
50
|
+
async findIndividualUserById(userId) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
'Method findIndividualUserById must be implemented by subclass'
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Create token with expiration
|
|
58
|
+
*
|
|
59
|
+
* @param {string|number} userId - User ID
|
|
60
|
+
* @param {string} rawToken - Raw unhashed token
|
|
61
|
+
* @param {number} minutes - Minutes until expiration (default 120)
|
|
62
|
+
* @returns {Promise<string>} Base64 buffer token
|
|
63
|
+
* @abstract
|
|
64
|
+
*/
|
|
65
|
+
async createToken(userId, rawToken, minutes = 120) {
|
|
66
|
+
throw new Error('Method createToken must be implemented by subclass');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Create individual user
|
|
71
|
+
*
|
|
72
|
+
* @param {Object} params - User creation parameters
|
|
73
|
+
* @returns {Promise<Object>} Created user object
|
|
74
|
+
* @abstract
|
|
75
|
+
*/
|
|
76
|
+
async createIndividualUser(params) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
'Method createIndividualUser must be implemented by subclass'
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Create organization user
|
|
84
|
+
*
|
|
85
|
+
* @param {Object} params - Organization creation parameters
|
|
86
|
+
* @returns {Promise<Object>} Created organization object
|
|
87
|
+
* @abstract
|
|
88
|
+
*/
|
|
89
|
+
async createOrganizationUser(params) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
'Method createOrganizationUser must be implemented by subclass'
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Find individual user by username
|
|
97
|
+
*
|
|
98
|
+
* @param {string} username - Username to search for
|
|
99
|
+
* @returns {Promise<Object|null>} User object or null
|
|
100
|
+
* @abstract
|
|
101
|
+
*/
|
|
102
|
+
async findIndividualUserByUsername(username) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
'Method findIndividualUserByUsername must be implemented by subclass'
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Find individual user by app user ID
|
|
110
|
+
*
|
|
111
|
+
* @param {string} appUserId - App user ID to search for
|
|
112
|
+
* @returns {Promise<Object|null>} User object or null
|
|
113
|
+
* @abstract
|
|
114
|
+
*/
|
|
115
|
+
async findIndividualUserByAppUserId(appUserId) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
'Method findIndividualUserByAppUserId must be implemented by subclass'
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Find organization user by app org ID
|
|
123
|
+
*
|
|
124
|
+
* @param {string} appOrgId - App organization ID to search for
|
|
125
|
+
* @returns {Promise<Object|null>} User object or null
|
|
126
|
+
* @abstract
|
|
127
|
+
*/
|
|
128
|
+
async findOrganizationUserByAppOrgId(appOrgId) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
'Method findOrganizationUserByAppOrgId must be implemented by subclass'
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Find user by ID (any type)
|
|
136
|
+
*
|
|
137
|
+
* @param {string|number} userId - User ID
|
|
138
|
+
* @returns {Promise<Object|null>} User object or null
|
|
139
|
+
* @abstract
|
|
140
|
+
*/
|
|
141
|
+
async findUserById(userId) {
|
|
142
|
+
throw new Error('Method findUserById must be implemented by subclass');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Find individual user by email
|
|
147
|
+
*
|
|
148
|
+
* @param {string} email - Email to search for
|
|
149
|
+
* @returns {Promise<Object|null>} User object or null
|
|
150
|
+
* @abstract
|
|
151
|
+
*/
|
|
152
|
+
async findIndividualUserByEmail(email) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
'Method findIndividualUserByEmail must be implemented by subclass'
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Update individual user
|
|
160
|
+
*
|
|
161
|
+
* @param {string|number} userId - User ID
|
|
162
|
+
* @param {Object} updates - Fields to update
|
|
163
|
+
* @returns {Promise<Object>} Updated user object
|
|
164
|
+
* @abstract
|
|
165
|
+
*/
|
|
166
|
+
async updateIndividualUser(userId, updates) {
|
|
167
|
+
throw new Error(
|
|
168
|
+
'Method updateIndividualUser must be implemented by subclass'
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Update organization user
|
|
174
|
+
*
|
|
175
|
+
* @param {string|number} userId - User ID
|
|
176
|
+
* @param {Object} updates - Fields to update
|
|
177
|
+
* @returns {Promise<Object>} Updated user object
|
|
178
|
+
* @abstract
|
|
179
|
+
*/
|
|
180
|
+
async updateOrganizationUser(userId, updates) {
|
|
181
|
+
throw new Error(
|
|
182
|
+
'Method updateOrganizationUser must be implemented by subclass'
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Delete user by ID
|
|
188
|
+
*
|
|
189
|
+
* @param {string|number} userId - User ID to delete
|
|
190
|
+
* @returns {Promise<boolean>} True if deleted successfully
|
|
191
|
+
* @abstract
|
|
192
|
+
*/
|
|
193
|
+
async deleteUser(userId) {
|
|
194
|
+
throw new Error('Method deleteUser must be implemented by subclass');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
module.exports = { UserRepositoryInterface };
|