@friggframework/core 2.0.0-next.5 → 2.0.0-next.51
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 +959 -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 +179 -0
- package/application/commands/user-commands.js +213 -0
- package/application/index.js +69 -0
- package/core/CLAUDE.md +690 -0
- package/core/Worker.js +8 -21
- package/core/create-handler.js +2 -7
- 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 +307 -0
- package/credential/repositories/credential-repository-postgres.js +313 -0
- package/credential/repositories/credential-repository.js +302 -0
- package/credential/use-cases/get-credential-for-user.js +21 -0
- package/credential/use-cases/update-authentication-status.js +15 -0
- package/database/MONGODB_TRANSACTION_FIX.md +198 -0
- package/database/adapters/lambda-invoker.js +97 -0
- package/database/config.js +154 -0
- package/database/encryption/README.md +684 -0
- package/database/encryption/encryption-schema-registry.js +141 -0
- package/database/encryption/field-encryption-service.js +226 -0
- package/database/encryption/logger.js +79 -0
- package/database/encryption/prisma-encryption-extension.js +222 -0
- package/database/index.js +25 -12
- package/database/models/WebsocketConnection.js +16 -10
- package/database/models/readme.md +1 -0
- package/database/prisma.js +222 -0
- package/database/repositories/health-check-repository-factory.js +43 -0
- package/database/repositories/health-check-repository-interface.js +87 -0
- package/database/repositories/health-check-repository-mongodb.js +91 -0
- package/database/repositories/health-check-repository-postgres.js +82 -0
- package/database/repositories/health-check-repository.js +108 -0
- package/database/repositories/migration-status-repository-s3.js +137 -0
- package/database/use-cases/check-database-health-use-case.js +29 -0
- package/database/use-cases/check-database-state-use-case.js +81 -0
- package/database/use-cases/check-encryption-health-use-case.js +83 -0
- package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
- package/database/use-cases/get-migration-status-use-case.js +93 -0
- package/database/use-cases/run-database-migration-use-case.js +137 -0
- package/database/use-cases/test-encryption-use-case.js +253 -0
- package/database/use-cases/trigger-database-migration-use-case.js +157 -0
- package/database/utils/mongodb-collection-utils.js +91 -0
- package/database/utils/mongodb-schema-init.js +106 -0
- package/database/utils/prisma-runner.js +400 -0
- package/database/utils/prisma-schema-parser.js +182 -0
- package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
- package/encrypt/Cryptor.js +34 -168
- package/encrypt/index.js +1 -2
- package/encrypt/test-encrypt.js +0 -2
- package/generated/prisma-mongodb/client.d.ts +1 -0
- package/generated/prisma-mongodb/client.js +4 -0
- package/generated/prisma-mongodb/default.d.ts +1 -0
- package/generated/prisma-mongodb/default.js +4 -0
- package/generated/prisma-mongodb/edge.d.ts +1 -0
- package/generated/prisma-mongodb/edge.js +334 -0
- package/generated/prisma-mongodb/index-browser.js +316 -0
- package/generated/prisma-mongodb/index.d.ts +22898 -0
- package/generated/prisma-mongodb/index.js +359 -0
- package/generated/prisma-mongodb/package.json +183 -0
- package/generated/prisma-mongodb/query-engine-debian-openssl-3.0.x +0 -0
- package/generated/prisma-mongodb/query-engine-rhel-openssl-3.0.x +0 -0
- package/generated/prisma-mongodb/runtime/binary.d.ts +1 -0
- package/generated/prisma-mongodb/runtime/binary.js +289 -0
- package/generated/prisma-mongodb/runtime/edge-esm.js +34 -0
- package/generated/prisma-mongodb/runtime/edge.js +34 -0
- package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-mongodb/runtime/index-browser.js +16 -0
- package/generated/prisma-mongodb/runtime/library.d.ts +3982 -0
- package/generated/prisma-mongodb/runtime/react-native.js +83 -0
- package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +84 -0
- package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +36 -0
- package/generated/prisma-mongodb/schema.prisma +362 -0
- package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +4 -0
- package/generated/prisma-mongodb/wasm-worker-loader.mjs +4 -0
- package/generated/prisma-mongodb/wasm.d.ts +1 -0
- package/generated/prisma-mongodb/wasm.js +341 -0
- package/generated/prisma-postgresql/client.d.ts +1 -0
- package/generated/prisma-postgresql/client.js +4 -0
- package/generated/prisma-postgresql/default.d.ts +1 -0
- package/generated/prisma-postgresql/default.js +4 -0
- package/generated/prisma-postgresql/edge.d.ts +1 -0
- package/generated/prisma-postgresql/edge.js +356 -0
- package/generated/prisma-postgresql/index-browser.js +338 -0
- package/generated/prisma-postgresql/index.d.ts +25072 -0
- package/generated/prisma-postgresql/index.js +381 -0
- package/generated/prisma-postgresql/package.json +183 -0
- package/generated/prisma-postgresql/query-engine-debian-openssl-3.0.x +0 -0
- package/generated/prisma-postgresql/query-engine-rhel-openssl-3.0.x +0 -0
- package/generated/prisma-postgresql/query_engine_bg.js +2 -0
- package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
- package/generated/prisma-postgresql/runtime/binary.d.ts +1 -0
- package/generated/prisma-postgresql/runtime/binary.js +289 -0
- package/generated/prisma-postgresql/runtime/edge-esm.js +34 -0
- package/generated/prisma-postgresql/runtime/edge.js +34 -0
- package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-postgresql/runtime/index-browser.js +16 -0
- package/generated/prisma-postgresql/runtime/library.d.ts +3982 -0
- package/generated/prisma-postgresql/runtime/react-native.js +83 -0
- package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +84 -0
- package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +36 -0
- package/generated/prisma-postgresql/schema.prisma +345 -0
- package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +4 -0
- package/generated/prisma-postgresql/wasm-worker-loader.mjs +4 -0
- package/generated/prisma-postgresql/wasm.d.ts +1 -0
- package/generated/prisma-postgresql/wasm.js +363 -0
- package/handlers/WEBHOOKS.md +653 -0
- package/handlers/app-definition-loader.js +38 -0
- package/handlers/app-handler-helpers.js +56 -0
- package/handlers/backend-utils.js +180 -0
- package/handlers/database-migration-handler.js +227 -0
- package/handlers/integration-event-dispatcher.js +54 -0
- package/handlers/routers/HEALTHCHECK.md +342 -0
- package/handlers/routers/auth.js +15 -0
- package/handlers/routers/db-migration.handler.js +29 -0
- package/handlers/routers/db-migration.js +256 -0
- package/handlers/routers/health.js +519 -0
- package/handlers/routers/integration-defined-routers.js +45 -0
- package/handlers/routers/integration-webhook-routers.js +67 -0
- package/handlers/routers/user.js +63 -0
- package/handlers/routers/websocket.js +57 -0
- package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
- package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
- package/handlers/workers/db-migration.js +352 -0
- package/handlers/workers/integration-defined-workers.js +27 -0
- package/index.js +77 -22
- package/integrations/WEBHOOK-QUICKSTART.md +151 -0
- package/integrations/index.js +12 -10
- package/integrations/integration-base.js +296 -54
- package/integrations/integration-router.js +381 -182
- 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 +127 -0
- package/integrations/repositories/integration-repository-mongo.js +303 -0
- package/integrations/repositories/integration-repository-postgres.js +352 -0
- package/integrations/repositories/process-repository-factory.js +46 -0
- package/integrations/repositories/process-repository-interface.js +90 -0
- package/integrations/repositories/process-repository-mongo.js +190 -0
- package/integrations/repositories/process-repository-postgres.js +217 -0
- package/integrations/tests/doubles/dummy-integration-class.js +83 -0
- package/integrations/tests/doubles/test-integration-repository.js +99 -0
- package/integrations/use-cases/create-integration.js +83 -0
- package/integrations/use-cases/create-process.js +128 -0
- package/integrations/use-cases/delete-integration-for-user.js +101 -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 +88 -0
- package/integrations/use-cases/get-possible-integrations.js +27 -0
- package/integrations/use-cases/get-process.js +87 -0
- package/integrations/use-cases/index.js +19 -0
- package/integrations/use-cases/load-integration-context.js +71 -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/use-cases/update-process-metrics.js +201 -0
- package/integrations/use-cases/update-process-state.js +119 -0
- package/integrations/utils/map-integration-dto.js +37 -0
- package/jest-global-setup-noop.js +3 -0
- package/jest-global-teardown-noop.js +3 -0
- package/logs/logger.js +0 -4
- package/{module-plugin → modules}/entity.js +1 -1
- package/{module-plugin → modules}/index.js +0 -8
- package/modules/module-factory.js +56 -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 +377 -0
- package/modules/repositories/module-repository-postgres.js +426 -0
- package/modules/repositories/module-repository.js +316 -0
- package/{module-plugin → modules}/requester/requester.js +1 -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 +55 -0
- package/modules/use-cases/process-authorization-callback.js +122 -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 +82 -50
- package/prisma-mongodb/schema.prisma +362 -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/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
- package/prisma-postgresql/migrations/migration_lock.toml +3 -0
- package/prisma-postgresql/schema.prisma +345 -0
- package/queues/queuer-util.js +28 -15
- 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/core/index.d.ts +2 -2
- package/types/integrations/index.d.ts +2 -6
- package/types/module-plugin/index.d.ts +5 -59
- 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 +291 -0
- package/user/repositories/user-repository-postgres.js +350 -0
- package/user/tests/doubles/test-user-repository.js +72 -0
- package/user/use-cases/authenticate-user.js +127 -0
- package/user/use-cases/authenticate-with-shared-secret.js +48 -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-adopter-jwt.js +149 -0
- package/user/use-cases/get-user-from-bearer-token.js +77 -0
- package/user/use-cases/get-user-from-x-frigg-headers.js +106 -0
- package/user/use-cases/login-user.js +122 -0
- package/user/user.js +93 -0
- package/utils/backend-path.js +38 -0
- package/utils/index.js +6 -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 +156 -0
- package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
- package/websocket/repositories/websocket-connection-repository.js +161 -0
- package/database/models/State.js +0 -9
- package/database/models/Token.js +0 -70
- package/database/mongo.js +0 -45
- package/encrypt/Cryptor.test.js +0 -32
- package/encrypt/encrypt.js +0 -132
- package/encrypt/encrypt.test.js +0 -1069
- package/errors/base-error.test.js +0 -32
- package/errors/fetch-error.test.js +0 -79
- package/errors/halt-error.test.js +0 -11
- package/errors/validation-errors.test.js +0 -120
- 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/lambda/TimeoutCatcher.test.js +0 -68
- package/logs/logger.test.js +0 -76
- 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/requester/requester.test.js +0 -28
- 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}/test/mock-api/mocks/hubspot.js +0 -0
package/module-plugin/auther.js
DELETED
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
// Manages authorization and credential persistence
|
|
2
|
-
// Instantiation of an API Class
|
|
3
|
-
// Expects input object like this:
|
|
4
|
-
// const authDef = {
|
|
5
|
-
// API: class anAPI{},
|
|
6
|
-
// moduleName: 'anAPI', //maybe not required
|
|
7
|
-
// requiredAuthMethods: {
|
|
8
|
-
// // oauth methods, how to handle these being required/not?
|
|
9
|
-
// getToken: async function(params, callbackParams, tokenResponse) {},
|
|
10
|
-
// // required for all Auth methods
|
|
11
|
-
// getEntityDetails: async function(params) {}, //probably calls api method
|
|
12
|
-
// getCredentialDetails: async function(params) {}, // might be same as above
|
|
13
|
-
// apiParamsFromCredential: function(params) {},
|
|
14
|
-
// testAuth: async function() {}, // basic request to testAuth
|
|
15
|
-
// },
|
|
16
|
-
// env: {
|
|
17
|
-
// client_id: process.env.HUBSPOT_CLIENT_ID,
|
|
18
|
-
// client_secret: process.env.HUBSPOT_CLIENT_SECRET,
|
|
19
|
-
// scope: process.env.HUBSPOT_SCOPE,
|
|
20
|
-
// redirect_uri: `${process.env.REDIRECT_URI}/an-api`,
|
|
21
|
-
// }
|
|
22
|
-
// };
|
|
23
|
-
|
|
24
|
-
//TODO:
|
|
25
|
-
// 1. Add definition of expected params to API Class (or could just be credential?)
|
|
26
|
-
// 2.
|
|
27
|
-
|
|
28
|
-
const { Delegate } = require('../core');
|
|
29
|
-
const { get } = require('../assertions');
|
|
30
|
-
const _ = require('lodash');
|
|
31
|
-
const { flushDebugLog } = require('../logs');
|
|
32
|
-
const { Credential } = require('./credential');
|
|
33
|
-
const { Entity } = require('./entity');
|
|
34
|
-
const { mongoose } = require('../database/mongoose');
|
|
35
|
-
const { ModuleConstants } = require('./ModuleConstants');
|
|
36
|
-
|
|
37
|
-
class Auther extends Delegate {
|
|
38
|
-
static validateDefinition(definition) {
|
|
39
|
-
if (!definition) {
|
|
40
|
-
throw new Error('Auther definition is required');
|
|
41
|
-
}
|
|
42
|
-
if (!definition.moduleName) {
|
|
43
|
-
throw new Error('Auther definition requires moduleName');
|
|
44
|
-
}
|
|
45
|
-
if (!definition.API) {
|
|
46
|
-
throw new Error('Auther definition requires API class');
|
|
47
|
-
}
|
|
48
|
-
// if (!definition.Credential) {
|
|
49
|
-
// throw new Error('Auther definition requires Credential class');
|
|
50
|
-
// }
|
|
51
|
-
// if (!definition.Entity) {
|
|
52
|
-
// throw new Error('Auther definition requires Entity class');
|
|
53
|
-
// }
|
|
54
|
-
if (!definition.requiredAuthMethods) {
|
|
55
|
-
throw new Error('Auther definition requires requiredAuthMethods');
|
|
56
|
-
} else {
|
|
57
|
-
if (
|
|
58
|
-
definition.API.requesterType ===
|
|
59
|
-
ModuleConstants.authType.oauth2 &&
|
|
60
|
-
!definition.requiredAuthMethods.getToken
|
|
61
|
-
) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
'Auther definition requires requiredAuthMethods.getToken'
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
if (!definition.requiredAuthMethods.getEntityDetails) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
'Auther definition requires requiredAuthMethods.getEntityDetails'
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
if (!definition.requiredAuthMethods.getCredentialDetails) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
'Auther definition requires requiredAuthMethods.getCredentialDetails'
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
if (!definition.requiredAuthMethods.apiPropertiesToPersist) {
|
|
77
|
-
throw new Error(
|
|
78
|
-
'Auther definition requires requiredAuthMethods.apiPropertiesToPersist'
|
|
79
|
-
);
|
|
80
|
-
} else if (definition.Credential) {
|
|
81
|
-
for (const prop of definition.requiredAuthMethods
|
|
82
|
-
.apiPropertiesToPersist?.credential) {
|
|
83
|
-
if (
|
|
84
|
-
!definition.Credential.schema.paths.hasOwnProperty(prop)
|
|
85
|
-
) {
|
|
86
|
-
throw new Error(
|
|
87
|
-
`Auther definition requires Credential schema to have property ${prop}`
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (!definition.requiredAuthMethods.testAuthRequest) {
|
|
93
|
-
throw new Error(
|
|
94
|
-
'Auther definition requires requiredAuthMethods.testAuth'
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
constructor(params) {
|
|
101
|
-
super(params);
|
|
102
|
-
this.userId = get(params, 'userId', null); // Making this non-required
|
|
103
|
-
const definition = get(params, 'definition');
|
|
104
|
-
Auther.validateDefinition(definition);
|
|
105
|
-
Object.assign(this, definition.requiredAuthMethods);
|
|
106
|
-
if (definition.getEntityOptions) {
|
|
107
|
-
this.getEntityOptions = definition.getEntityOptions;
|
|
108
|
-
}
|
|
109
|
-
if (definition.refreshEntityOptions) {
|
|
110
|
-
this.refreshEntityOptions = definition.refreshEntityOptions;
|
|
111
|
-
}
|
|
112
|
-
this.name = definition.moduleName;
|
|
113
|
-
this.modelName = definition.modelName;
|
|
114
|
-
this.apiClass = definition.API;
|
|
115
|
-
this.CredentialModel =
|
|
116
|
-
definition.Credential || this.getCredentialModel();
|
|
117
|
-
this.EntityModel = definition.Entity || this.getEntityModel();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
static async getInstance(params) {
|
|
121
|
-
const instance = new this(params);
|
|
122
|
-
if (params.entityId) {
|
|
123
|
-
instance.entity = await instance.EntityModel.findById(
|
|
124
|
-
params.entityId
|
|
125
|
-
);
|
|
126
|
-
instance.credential = await instance.CredentialModel.findById(
|
|
127
|
-
instance.entity.credential
|
|
128
|
-
);
|
|
129
|
-
} else if (params.credentialId) {
|
|
130
|
-
instance.credential = await instance.CredentialModel.findById(
|
|
131
|
-
params.credentialId
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
let credential = {};
|
|
135
|
-
let entity = {};
|
|
136
|
-
if (instance.credential) {
|
|
137
|
-
credential = instance.credential.toObject();
|
|
138
|
-
}
|
|
139
|
-
if (instance.entity) {
|
|
140
|
-
entity = instance.entity.toObject();
|
|
141
|
-
}
|
|
142
|
-
const apiParams = {
|
|
143
|
-
...params.definition.env,
|
|
144
|
-
delegate: instance,
|
|
145
|
-
...instance.apiParamsFromCredential(credential),
|
|
146
|
-
...instance.apiParamsFromEntity(entity),
|
|
147
|
-
};
|
|
148
|
-
instance.api = new instance.apiClass(apiParams);
|
|
149
|
-
return instance;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
static getEntityModelFromDefinition(definition) {
|
|
153
|
-
const partialModule = new this({ definition });
|
|
154
|
-
return partialModule.getEntityModel();
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
getName() {
|
|
158
|
-
return this.name;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
apiParamsFromCredential(credential) {
|
|
162
|
-
return _.pick(credential, ...this.apiPropertiesToPersist?.credential);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
apiParamsFromEntity(entity) {
|
|
166
|
-
return _.pick(entity, ...this.apiPropertiesToPersist?.entity);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
getEntityModel() {
|
|
170
|
-
if (!this.EntityModel) {
|
|
171
|
-
const prefix = this.modelName ?? _.upperFirst(this.getName());
|
|
172
|
-
const arrayToDefaultObject = (array, defaultValue) =>
|
|
173
|
-
_.mapValues(_.keyBy(array), () => defaultValue);
|
|
174
|
-
const schema = new mongoose.Schema(
|
|
175
|
-
arrayToDefaultObject(this.apiPropertiesToPersist.entity, {
|
|
176
|
-
type: mongoose.Schema.Types.Mixed,
|
|
177
|
-
trim: true,
|
|
178
|
-
})
|
|
179
|
-
);
|
|
180
|
-
const name = `${prefix}Entity`;
|
|
181
|
-
this.EntityModel =
|
|
182
|
-
Entity.discriminators?.[name] ||
|
|
183
|
-
Entity.discriminator(name, schema);
|
|
184
|
-
}
|
|
185
|
-
return this.EntityModel;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
getCredentialModel() {
|
|
189
|
-
if (!this.CredentialModel) {
|
|
190
|
-
const arrayToDefaultObject = (array, defaultValue) =>
|
|
191
|
-
_.mapValues(_.keyBy(array), () => defaultValue);
|
|
192
|
-
const schema = new mongoose.Schema(
|
|
193
|
-
arrayToDefaultObject(this.apiPropertiesToPersist.credential, {
|
|
194
|
-
type: mongoose.Schema.Types.Mixed,
|
|
195
|
-
trim: true,
|
|
196
|
-
lhEncrypt: true,
|
|
197
|
-
})
|
|
198
|
-
);
|
|
199
|
-
const prefix = this.modelName ?? _.upperFirst(this.getName());
|
|
200
|
-
const name = `${prefix}Credential`;
|
|
201
|
-
this.CredentialModel =
|
|
202
|
-
Credential.discriminators?.[name] ||
|
|
203
|
-
Credential.discriminator(name, schema);
|
|
204
|
-
}
|
|
205
|
-
return this.CredentialModel;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
async getEntitiesForUserId(userId) {
|
|
209
|
-
// Only return non-internal fields. Leverages "select" and "options" to non-excepted fields and a pure object.
|
|
210
|
-
const list = await this.EntityModel.find(
|
|
211
|
-
{ user: userId },
|
|
212
|
-
'-dateCreated -dateUpdated -user -credentials -credential -__t -__v',
|
|
213
|
-
{ lean: true }
|
|
214
|
-
);
|
|
215
|
-
console.log('getEntitiesForUserId list', list, userId);
|
|
216
|
-
return list.map((entity) => ({
|
|
217
|
-
id: entity._id,
|
|
218
|
-
type: this.getName(),
|
|
219
|
-
...entity,
|
|
220
|
-
}));
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
async validateAuthorizationRequirements() {
|
|
224
|
-
const requirements = await this.getAuthorizationRequirements();
|
|
225
|
-
let valid = true;
|
|
226
|
-
if (
|
|
227
|
-
['oauth1', 'oauth2'].includes(requirements.type) &&
|
|
228
|
-
!requirements.url
|
|
229
|
-
) {
|
|
230
|
-
valid = false;
|
|
231
|
-
}
|
|
232
|
-
return valid;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
async getAuthorizationRequirements(params) {
|
|
236
|
-
// TODO: How can this be more helpful both to implement and consume
|
|
237
|
-
// this function must return a dictionary with the following format
|
|
238
|
-
// node only url key is required. Data would be used for Base Authentication
|
|
239
|
-
// let returnData = {
|
|
240
|
-
// url: "callback url for the data or teh redirect url for login",
|
|
241
|
-
// type: one of the types defined in modules/Constants.js
|
|
242
|
-
// data: ["required", "fields", "we", "may", "need"]
|
|
243
|
-
// }
|
|
244
|
-
return this.api.getAuthorizationRequirements();
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
async testAuth(params) {
|
|
248
|
-
let validAuth = false;
|
|
249
|
-
try {
|
|
250
|
-
if (await this.testAuthRequest(this.api)) validAuth = true;
|
|
251
|
-
} catch (e) {
|
|
252
|
-
flushDebugLog(e);
|
|
253
|
-
}
|
|
254
|
-
return validAuth;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
async processAuthorizationCallback(params) {
|
|
258
|
-
let tokenResponse;
|
|
259
|
-
if (this.apiClass.requesterType === ModuleConstants.authType.oauth2) {
|
|
260
|
-
tokenResponse = await this.getToken(this.api, params);
|
|
261
|
-
} else {
|
|
262
|
-
tokenResponse = await this.setAuthParams(this.api, params);
|
|
263
|
-
await this.onTokenUpdate();
|
|
264
|
-
}
|
|
265
|
-
const authRes = await this.testAuth();
|
|
266
|
-
if (!authRes) {
|
|
267
|
-
throw new Error('Authorization failed');
|
|
268
|
-
}
|
|
269
|
-
const entityDetails = await this.getEntityDetails(
|
|
270
|
-
this.api,
|
|
271
|
-
params,
|
|
272
|
-
tokenResponse,
|
|
273
|
-
this.userId
|
|
274
|
-
);
|
|
275
|
-
Object.assign(
|
|
276
|
-
entityDetails.details,
|
|
277
|
-
this.apiParamsFromEntity(this.api)
|
|
278
|
-
);
|
|
279
|
-
await this.findOrCreateEntity(entityDetails);
|
|
280
|
-
return {
|
|
281
|
-
credential_id: this.credential.id,
|
|
282
|
-
entity_id: this.entity.id,
|
|
283
|
-
type: this.getName(),
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
async onTokenUpdate() {
|
|
288
|
-
const credentialDetails = await this.getCredentialDetails(
|
|
289
|
-
this.api,
|
|
290
|
-
this.userId
|
|
291
|
-
);
|
|
292
|
-
Object.assign(
|
|
293
|
-
credentialDetails.details,
|
|
294
|
-
this.apiParamsFromCredential(this.api)
|
|
295
|
-
);
|
|
296
|
-
credentialDetails.details.auth_is_valid = true;
|
|
297
|
-
await this.updateOrCreateCredential(credentialDetails);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
async receiveNotification(notifier, delegateString, object = null) {
|
|
301
|
-
if (delegateString === this.api.DLGT_TOKEN_UPDATE) {
|
|
302
|
-
await this.onTokenUpdate();
|
|
303
|
-
} else if (delegateString === this.api.DLGT_TOKEN_DEAUTHORIZED) {
|
|
304
|
-
await this.deauthorize();
|
|
305
|
-
} else if (delegateString === this.api.DLGT_INVALID_AUTH) {
|
|
306
|
-
await this.markCredentialsInvalid();
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
async getEntityOptions() {
|
|
311
|
-
throw new Error(
|
|
312
|
-
'Method getEntityOptions() is not defined in the class'
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
async refreshEntityOptions() {
|
|
317
|
-
throw new Error(
|
|
318
|
-
'Method refreshEntityOptions() is not defined in the class'
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
async findOrCreateEntity(entityDetails) {
|
|
323
|
-
const identifiers = get(entityDetails, 'identifiers');
|
|
324
|
-
const details = get(entityDetails, 'details');
|
|
325
|
-
const search = await this.EntityModel.find(identifiers);
|
|
326
|
-
if (search.length > 1) {
|
|
327
|
-
throw new Error(
|
|
328
|
-
'Multiple entities found with the same identifiers: ' +
|
|
329
|
-
JSON.stringify(identifiers)
|
|
330
|
-
);
|
|
331
|
-
} else if (search.length === 0) {
|
|
332
|
-
this.entity = await this.EntityModel.create({
|
|
333
|
-
credential: this.credential.id,
|
|
334
|
-
...details,
|
|
335
|
-
...identifiers,
|
|
336
|
-
});
|
|
337
|
-
} else if (search.length === 1) {
|
|
338
|
-
this.entity = search[0];
|
|
339
|
-
}
|
|
340
|
-
if (this.entity.credential === undefined) {
|
|
341
|
-
this.entity.credential = this.credential.id;
|
|
342
|
-
await this.entity.save();
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
async updateOrCreateCredential(credentialDetails) {
|
|
347
|
-
const identifiers = get(credentialDetails, 'identifiers');
|
|
348
|
-
const details = get(credentialDetails, 'details');
|
|
349
|
-
|
|
350
|
-
if (!this.credential) {
|
|
351
|
-
const credentialSearch = await this.CredentialModel.find(
|
|
352
|
-
identifiers
|
|
353
|
-
);
|
|
354
|
-
if (credentialSearch.length > 1) {
|
|
355
|
-
throw new Error(
|
|
356
|
-
`Multiple credentials found with same identifiers: ${identifiers}`
|
|
357
|
-
);
|
|
358
|
-
} else if (credentialSearch.length === 1) {
|
|
359
|
-
// found exactly one credential with these identifiers
|
|
360
|
-
this.credential = credentialSearch[0];
|
|
361
|
-
} else {
|
|
362
|
-
// found no credential with these identifiers (match none for insert)
|
|
363
|
-
this.credential = { $exists: false };
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
// update credential or create if none was found
|
|
367
|
-
this.credential = await this.CredentialModel.findOneAndUpdate(
|
|
368
|
-
{ _id: this.credential },
|
|
369
|
-
{ $set: { ...identifiers, ...details } },
|
|
370
|
-
{ useFindAndModify: true, new: true, upsert: true }
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
async markCredentialsInvalid() {
|
|
375
|
-
if (this.credential) {
|
|
376
|
-
this.credential.auth_is_valid = false;
|
|
377
|
-
await this.credential.save();
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
async deauthorize() {
|
|
382
|
-
this.api = new this.apiClass();
|
|
383
|
-
if (this.entity?.credential) {
|
|
384
|
-
await this.CredentialModel.deleteOne({
|
|
385
|
-
_id: this.entity.credential,
|
|
386
|
-
});
|
|
387
|
-
this.entity.credential = undefined;
|
|
388
|
-
await this.entity.save();
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
module.exports = { Auther };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
const { mongoose } = require('../database/mongoose');
|
|
2
|
-
const { Encrypt } = require('../encrypt');
|
|
3
|
-
|
|
4
|
-
const schema = new mongoose.Schema(
|
|
5
|
-
{
|
|
6
|
-
user: {
|
|
7
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
8
|
-
ref: 'User',
|
|
9
|
-
required: false,
|
|
10
|
-
},
|
|
11
|
-
subType: { type: String },
|
|
12
|
-
auth_is_valid: { type: Boolean },
|
|
13
|
-
externalId: { type: String }, // Used for lookups, identifying the owner of the credential
|
|
14
|
-
},
|
|
15
|
-
{ timestamps: true }
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
schema.plugin(Encrypt);
|
|
19
|
-
|
|
20
|
-
const Credential =
|
|
21
|
-
mongoose.models.Credential || mongoose.model('Credential', schema);
|
|
22
|
-
module.exports = { Credential };
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
const { loadInstalledModules, Delegate } = require('../core');
|
|
2
|
-
|
|
3
|
-
const { Entity } = require('./entity');
|
|
4
|
-
const { ModuleManager } = require('./manager');
|
|
5
|
-
|
|
6
|
-
class EntityManager {
|
|
7
|
-
static primaryEntityClass = null; //primaryEntity;
|
|
8
|
-
|
|
9
|
-
static entityManagerClasses = loadInstalledModules().map(
|
|
10
|
-
(m) => m.EntityManager
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
static entityTypes = EntityManager.entityManagerClasses.map(
|
|
14
|
-
(ManagerClass) => ManagerClass.getName()
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
static async getEntitiesForUser(userId) {
|
|
18
|
-
const results = [];
|
|
19
|
-
for (const Manager of this.entityManagerClasses) {
|
|
20
|
-
results.push(...(await Manager.getEntitiesForUserId(userId)));
|
|
21
|
-
}
|
|
22
|
-
return results;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
static checkIsValidType(entityType) {
|
|
26
|
-
const indexOfEntity = EntityManager.entityTypes.indexOf(entityType);
|
|
27
|
-
return indexOfEntity >= 0;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
static getEntityManagerClass(entityType = '') {
|
|
31
|
-
const normalizedType = entityType.toLowerCase();
|
|
32
|
-
|
|
33
|
-
const indexOfEntityType =
|
|
34
|
-
EntityManager.entityTypes.indexOf(normalizedType);
|
|
35
|
-
if (!EntityManager.checkIsValidType(normalizedType)) {
|
|
36
|
-
throw new Error(
|
|
37
|
-
`Error: Invalid entity type of ${normalizedType}, options are ${EntityManager.entityTypes.join(
|
|
38
|
-
', '
|
|
39
|
-
)}`
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const managerClass =
|
|
44
|
-
EntityManager.entityManagerClasses[indexOfEntityType];
|
|
45
|
-
|
|
46
|
-
if (!(managerClass.prototype instanceof ModuleManager)) {
|
|
47
|
-
throw new Error('The Entity is not an instance of ModuleManager');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return managerClass;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static async getEntityManagerInstanceFromEntityId(entityId, userId) {
|
|
54
|
-
const entityMO = new Entity();
|
|
55
|
-
const entity = await entityMO.get(entityId);
|
|
56
|
-
let entityManagerClass;
|
|
57
|
-
for (const Manager of this.entityManagerClasses) {
|
|
58
|
-
if (entity instanceof Manager.Entity.Model) {
|
|
59
|
-
entityManagerClass = Manager;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
const instance = await entityManagerClass.getInstance({
|
|
63
|
-
userId,
|
|
64
|
-
entityId,
|
|
65
|
-
});
|
|
66
|
-
return instance;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
module.exports = { EntityManager };
|
package/module-plugin/manager.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
const { Delegate } = require('../core');
|
|
2
|
-
const { Credential } = require('./credential');
|
|
3
|
-
const { Entity } = require('./entity');
|
|
4
|
-
const { get } = require('../assertions');
|
|
5
|
-
|
|
6
|
-
class ModuleManager extends Delegate {
|
|
7
|
-
static Entity = Entity;
|
|
8
|
-
static Credential = Credential;
|
|
9
|
-
|
|
10
|
-
constructor(params) {
|
|
11
|
-
super(params);
|
|
12
|
-
this.userId = get(params, 'userId', null); // Making this non-required
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
static getName() {
|
|
16
|
-
throw new Error('Module name is not defined');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
static async getInstance(params) {
|
|
20
|
-
throw new Error(
|
|
21
|
-
'getInstance is not implemented. It is required for ModuleManager. '
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
static async getEntitiesForUserId(userId) {
|
|
26
|
-
// Only return non-internal fields. Leverages "select" and "options" to non-excepted fields and a pure object.
|
|
27
|
-
const list = await this.Entity.find(
|
|
28
|
-
{ user: userId },
|
|
29
|
-
'-dateCreated -dateUpdated -user -credentials -credential -__t -__v',
|
|
30
|
-
{ lean: true }
|
|
31
|
-
);
|
|
32
|
-
return list.map((entity) => ({
|
|
33
|
-
id: entity._id,
|
|
34
|
-
type: this.getName(),
|
|
35
|
-
...entity,
|
|
36
|
-
}));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async getEntityId() {
|
|
40
|
-
const list = await Entity.find({ user: this.userId });
|
|
41
|
-
if (list.length > 1) {
|
|
42
|
-
throw new Error(
|
|
43
|
-
'There should not be more than one entity associated with a user for this specific class type'
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
if (list.length == 0) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
return list[0].id;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async validateAuthorizationRequirements() {
|
|
53
|
-
const requirements = await this.getAuthorizationRequirements();
|
|
54
|
-
let valid = true;
|
|
55
|
-
if (['oauth1', 'oauth2'].includes(requirements.type) && !requirements.url) {
|
|
56
|
-
valid = false;
|
|
57
|
-
}
|
|
58
|
-
return valid;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async getAuthorizationRequirements(params) {
|
|
62
|
-
// this function must return a dictionary with the following format
|
|
63
|
-
// node only url key is required. Data would be used for Base Authentication
|
|
64
|
-
// let returnData = {
|
|
65
|
-
// url: "callback url for the data or teh redirect url for login",
|
|
66
|
-
// type: one of the types defined in modules/Constants.js
|
|
67
|
-
// data: ["required", "fields", "we", "may", "need"]
|
|
68
|
-
// }
|
|
69
|
-
throw new Error(
|
|
70
|
-
'Authorization requirements method getAuthorizationRequirements() is not defined in the class'
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async testAuth(params) {
|
|
75
|
-
// this function must invoke a method on the API using authentication
|
|
76
|
-
// if it fails, an exception should be thrown
|
|
77
|
-
throw new Error(
|
|
78
|
-
'Authentication test method testAuth() is not defined in the class'
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async processAuthorizationCallback(params) {
|
|
83
|
-
// this function takes in a dictionary of callback information along with
|
|
84
|
-
// a unique user id to associate with the entity in the form of
|
|
85
|
-
// {
|
|
86
|
-
// userId: "some id",
|
|
87
|
-
// data: {}
|
|
88
|
-
// }
|
|
89
|
-
|
|
90
|
-
throw new Error(
|
|
91
|
-
'Authorization requirements method processAuthorizationCallback() is not defined in the class'
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
//----------------------------------------------------------------------------------------------------
|
|
96
|
-
// optional
|
|
97
|
-
|
|
98
|
-
async getEntityOptions() {
|
|
99
|
-
// May not be needed if the callback already creates the entity, such as in situations
|
|
100
|
-
// like HubSpot where the account is determined in the authorization flow.
|
|
101
|
-
// This should only be used in situations such as FreshBooks where the user needs to make
|
|
102
|
-
// an account decision on the front end.
|
|
103
|
-
throw new Error(
|
|
104
|
-
'Entity requirement method getEntityOptions() is not defined in the class'
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
async findOrCreateEntity(params) {
|
|
109
|
-
// May not be needed if the callback already creates the entity, such as in situations
|
|
110
|
-
// like HubSpot where the account is determined in the authorization flow.
|
|
111
|
-
// This should only be used in situations such as FreshBooks where the user needs to make
|
|
112
|
-
// an account decision on the front end.
|
|
113
|
-
throw new Error(
|
|
114
|
-
'Entity requirement method findOrCreateEntity() is not defined in the class'
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async getAllSyncObjects(SyncClass) {
|
|
119
|
-
// takes in a Sync class and will return all objects associated with the SyncClass in an array
|
|
120
|
-
// in the form of
|
|
121
|
-
// [
|
|
122
|
-
// {...object1},{...object2}...
|
|
123
|
-
// ]
|
|
124
|
-
|
|
125
|
-
throw new Error(
|
|
126
|
-
'The method "getAllSyncObjects()" is not defined in the class'
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async batchCreateSyncObjects(syncObjects, syncManager) {
|
|
131
|
-
// takes in an array of Sync objects that has two pieces of data that
|
|
132
|
-
// are important to the updating module:
|
|
133
|
-
// 1. obj.data -> The data mapped to the obj.keys data
|
|
134
|
-
// 2. obj.syncId -> the id of the newly created sync object in our database. You will need to update
|
|
135
|
-
// the sync object in the database with the your id associated with this data. You
|
|
136
|
-
// can do this by calling the SyncManager function updateSyncObject.
|
|
137
|
-
// [
|
|
138
|
-
// syncObject1,syncObject2, ...
|
|
139
|
-
// ]
|
|
140
|
-
|
|
141
|
-
throw new Error(
|
|
142
|
-
'The method "batchUpdateSyncObjects()" is not defined in the class'
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async batchUpdateSyncObjects(syncObjects, syncManager) {
|
|
147
|
-
// takes in an array of Sync objects that has two pieces of data that
|
|
148
|
-
// are important to the updating module:
|
|
149
|
-
// 1. obj.data -> The data mapped to the obj.keys data
|
|
150
|
-
// 2. obj.moduleObjectIds[this.constructor.getName()] -> Indexed from the point of view of the module manager
|
|
151
|
-
// it will return a json object holding all of the keys
|
|
152
|
-
// required update this datapoint. an example would be:
|
|
153
|
-
// {companyId:12, email:"test@test.com"}
|
|
154
|
-
// [
|
|
155
|
-
// syncObject1,syncObject2, ...
|
|
156
|
-
// ]
|
|
157
|
-
|
|
158
|
-
throw new Error(
|
|
159
|
-
'The method "batchUpdateSyncObjects()" is not defined in the class'
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async markCredentialsInvalid() {
|
|
164
|
-
this.credential.auth_is_valid = false;
|
|
165
|
-
return await this.credential.save();
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
module.exports = { ModuleManager };
|