@friggframework/core 2.0.0--canary.397.05c9b19.0 → 2.0.0--canary.397.b7e1978.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.
@@ -4,6 +4,39 @@ class CredentialRepository {
4
4
  async findCredentialById(id) {
5
5
  return Credential.findById(id);
6
6
  }
7
+
8
+ async updateAuthenticationStatus(credentialId, authIsValid) {
9
+ return Credential.updateOne({ _id: credentialId }, { $set: { auth_is_valid: authIsValid } });
10
+ }
11
+
12
+ /**
13
+ * Permanently remove a credential document.
14
+ * @param {string} credentialId
15
+ * @returns {Promise<import('mongoose').DeleteResult>}
16
+ */
17
+ async deleteCredentialById(credentialId) {
18
+ return Credential.deleteOne({ _id: credentialId });
19
+ }
20
+
21
+ /**
22
+ * Create a new credential or update an existing one matching the identifiers.
23
+ * `credentialDetails` format: { identifiers: { ... }, details: { ... } }
24
+ * Identifiers are used in the query filter; details are merged into the document.
25
+ * @param {{identifiers: Object, details: Object}} credentialDetails
26
+ * @returns {Promise<Object>} The persisted credential (lean object)
27
+ */
28
+ async upsertCredential(credentialDetails) {
29
+ const { identifiers, details } = credentialDetails;
30
+ if (!identifiers) throw new Error('identifiers required to upsert credential');
31
+
32
+ const query = { ...identifiers };
33
+
34
+ const update = { $set: { ...details } };
35
+
36
+ const options = { upsert: true, new: true, setDefaultsOnInsert: true, lean: true };
37
+
38
+ return Credential.findOneAndUpdate(query, update, options);
39
+ }
7
40
  }
8
41
 
9
42
  module.exports = { CredentialRepository };
@@ -0,0 +1,15 @@
1
+ class UpdateAuthenticationStatus {
2
+ constructor({ credentialRepository }) {
3
+ this.credentialRepository = credentialRepository;
4
+ }
5
+
6
+ /**
7
+ * @param {string} credentialId
8
+ * @param {boolean} authIsValid
9
+ */
10
+ async execute(credentialId, authIsValid) {
11
+ await this.credentialRepository.updateAuthenticationStatus(credentialId, authIsValid);
12
+ }
13
+ }
14
+
15
+ module.exports = { UpdateAuthenticationStatus };
@@ -42,7 +42,7 @@ class ModuleRepository {
42
42
  async findEntitiesByUserId(userId) {
43
43
  const entitiesRecords = await Entity.find(
44
44
  { user: userId },
45
- '-dateCreated -dateUpdated -user -credentials -credential -__t -__v',
45
+ '',
46
46
  { lean: true }
47
47
  ).populate('credential');
48
48
 
@@ -76,6 +76,16 @@ class ModuleRepository {
76
76
  moduleName: e.moduleName,
77
77
  }));
78
78
  }
79
+
80
+ /**
81
+ * Remove the credential reference from an Entity document without loading a full Mongoose instance.
82
+ * Useful when a credential has been revoked/deleted (e.g. via Module.deauthorize).
83
+ * @param {string} entityId
84
+ * @returns {Promise<import('mongoose').UpdateWriteOpResult>}
85
+ */
86
+ async unsetCredential(entityId) {
87
+ return Entity.updateOne({ _id: entityId }, { $unset: { credential: "" } });
88
+ }
79
89
  }
80
90
 
81
91
  module.exports = { ModuleRepository };
package/modules/module.js CHANGED
@@ -3,6 +3,9 @@ const _ = require('lodash');
3
3
  const { flushDebugLog } = require('../logs');
4
4
  const { ModuleConstants } = require('./ModuleConstants');
5
5
 
6
+ // todo: this class should be a Domain class, and the Delegate function is preventing us from
7
+ // doing that, we probably have to get rid of the Delegate class as well as the event based
8
+ // calls since they go against the Domain Driven Design principles (eg. a domain class should not call repository methods or use cases)
6
9
  class Module extends Delegate {
7
10
 
8
11
  //todo: entity should be replaced with actual entity properties
@@ -26,6 +29,13 @@ class Module extends Delegate {
26
29
  this.modelName = this.definition.modelName;
27
30
  this.apiClass = this.definition.API;
28
31
 
32
+ // Repository used for persistence operations related to credentials.
33
+ const { CredentialRepository } = require('../credential/credential-repository');
34
+ this.credentialRepository = new CredentialRepository();
35
+
36
+ // Repository responsible for entity persistence actions
37
+ const { ModuleRepository } = require('./module-repository');
38
+ this.moduleRepository = new ModuleRepository();
29
39
 
30
40
  Object.assign(this, this.definition.requiredAuthMethods);
31
41
 
@@ -125,7 +135,9 @@ class Module extends Delegate {
125
135
  this.apiParamsFromCredential(this.api)
126
136
  );
127
137
  credentialDetails.details.auth_is_valid = true;
128
- await this.updateOrCreateCredential(credentialDetails);
138
+
139
+ const persisted = await this.credentialRepository.upsertCredential(credentialDetails);
140
+ this.credential = persisted;
129
141
  }
130
142
 
131
143
  async receiveNotification(notifier, delegateString, object = null) {
@@ -139,20 +151,42 @@ class Module extends Delegate {
139
151
  }
140
152
 
141
153
  async markCredentialsInvalid() {
142
- if (this.credential) {
143
- this.credential.auth_is_valid = false;
144
- await this.credential.save();
145
- }
154
+ if (!this.credential) return;
155
+
156
+ // Persist flag change through repository – works even when the
157
+ // credential object is a plain JavaScript object (lean query).
158
+ const credentialId = this.credential._id || this.credential.id;
159
+ if (!credentialId) return;
160
+
161
+ await this.credentialRepository.updateAuthenticationStatus(
162
+ credentialId,
163
+ false
164
+ );
165
+
166
+ // Keep the in-memory snapshot consistent so that callers can read the
167
+ // updated state without another fetch.
168
+ this.credential.auth_is_valid = false;
146
169
  }
147
170
 
148
171
  async deauthorize() {
149
172
  this.api = new this.apiClass();
173
+
174
+ // Remove persisted credential (if any)
150
175
  if (this.entity?.credential) {
151
- await this.CredentialModel.deleteOne({
152
- _id: this.entity.credential,
153
- });
176
+ const credentialId =
177
+ this.entity.credential._id || this.entity.credential.id || this.entity.credential;
178
+
179
+ // Delete credential via repository
180
+ await this.credentialRepository.deleteCredentialById(credentialId);
181
+
182
+ // Unset credential reference on the Entity document
183
+ const entityId = this.entity._id || this.entity.id;
184
+ if (entityId) {
185
+ await this.moduleRepository.unsetCredential(entityId);
186
+ }
187
+
188
+ // Keep in-memory snapshot consistent
154
189
  this.entity.credential = undefined;
155
- await this.entity.save();
156
190
  }
157
191
  }
158
192
 
@@ -6,7 +6,7 @@ function mapModuleClassToModuleDTO(moduleInstance) {
6
6
  if (!moduleInstance) return null;
7
7
 
8
8
  return {
9
- id: moduleInstance.entity._id.toString(),
9
+ id: moduleInstance.entity.id,
10
10
  name: moduleInstance.name,
11
11
  userId: moduleInstance.userId,
12
12
  entity: moduleInstance.entity,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/core",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.397.05c9b19.0",
4
+ "version": "2.0.0--canary.397.b7e1978.0",
5
5
  "dependencies": {
6
6
  "@hapi/boom": "^10.0.1",
7
7
  "aws-sdk": "^2.1200.0",
@@ -22,9 +22,9 @@
22
22
  "uuid": "^9.0.1"
23
23
  },
24
24
  "devDependencies": {
25
- "@friggframework/eslint-config": "2.0.0--canary.397.05c9b19.0",
26
- "@friggframework/prettier-config": "2.0.0--canary.397.05c9b19.0",
27
- "@friggframework/test": "2.0.0--canary.397.05c9b19.0",
25
+ "@friggframework/eslint-config": "2.0.0--canary.397.b7e1978.0",
26
+ "@friggframework/prettier-config": "2.0.0--canary.397.b7e1978.0",
27
+ "@friggframework/test": "2.0.0--canary.397.b7e1978.0",
28
28
  "@types/lodash": "4.17.15",
29
29
  "@typescript-eslint/eslint-plugin": "^8.0.0",
30
30
  "chai": "^4.3.6",
@@ -53,5 +53,5 @@
53
53
  },
54
54
  "homepage": "https://github.com/friggframework/frigg#readme",
55
55
  "description": "",
56
- "gitHead": "05c9b19a8f1f2d8e7ef49983786c1fd622fa376a"
56
+ "gitHead": "b7e197879d90d5bd782c5299aa55f312eb7d4b63"
57
57
  }