@friggframework/core 2.0.0-next.81 → 2.0.0-next.83

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.
@@ -531,13 +531,33 @@ function setEntityRoutes(router, authenticateUser, useCases) {
531
531
  'data',
532
532
  ]);
533
533
 
534
- const entityDetails = await processAuthorizationCallback.execute(
535
- userId,
536
- params.entityType,
537
- params.data
534
+ const dataKeys =
535
+ params.data && typeof params.data === 'object'
536
+ ? Object.keys(params.data)
537
+ : [];
538
+ console.log(
539
+ `[Frigg] POST /api/authorize userId=${userId} entityType=${params.entityType} dataKeys=${JSON.stringify(dataKeys)}`
538
540
  );
539
541
 
540
- res.json(entityDetails);
542
+ try {
543
+ const entityDetails =
544
+ await processAuthorizationCallback.execute(
545
+ userId,
546
+ params.entityType,
547
+ params.data
548
+ );
549
+
550
+ console.log(
551
+ `[Frigg] POST /api/authorize success userId=${userId} entityType=${params.entityType} credentialId=${entityDetails?.credential_id} entityId=${entityDetails?.entity_id}`
552
+ );
553
+
554
+ res.json(entityDetails);
555
+ } catch (err) {
556
+ console.error(
557
+ `[Frigg] POST /api/authorize failed userId=${userId} entityType=${params.entityType} error=${err?.message || err}`
558
+ );
559
+ throw err;
560
+ }
541
561
  })
542
562
  );
543
563
 
@@ -28,6 +28,11 @@ class ProcessAuthorizationCallback {
28
28
  }
29
29
 
30
30
  async execute(userId, entityType, params) {
31
+ const hasCode = Boolean(params && params.code);
32
+ console.log(
33
+ `[Frigg] processAuthorizationCallback start userId=${userId} entityType=${entityType} hasCode=${hasCode}`
34
+ );
35
+
31
36
  const moduleDefinition = this.moduleDefinitions.find((def) => {
32
37
  return entityType === def.moduleName;
33
38
  });
@@ -38,12 +43,29 @@ class ProcessAuthorizationCallback {
38
43
  );
39
44
  }
40
45
 
41
- // todo: check if we need to pass entity to Module, right now it's null
42
- let entity = null;
46
+ // Bootstrap the Module with the existing entity (if any) so the API
47
+ // requester is preloaded with prior tokens. This enables a refresh
48
+ // fallback when callers lack a fresh OAuth code, and lets us match a
49
+ // re-auth back to the existing credential record by id.
50
+ const existingEntities =
51
+ await this.moduleRepository.findEntitiesByUserIdAndModuleName(
52
+ userId,
53
+ entityType
54
+ );
55
+ const existingEntity =
56
+ existingEntities && existingEntities.length > 0
57
+ ? existingEntities[0]
58
+ : null;
59
+
60
+ if (existingEntity) {
61
+ console.log(
62
+ `[Frigg] processAuthorizationCallback found existing entity id=${existingEntity.id} credentialId=${existingEntity.credential?.id}`
63
+ );
64
+ }
43
65
 
44
66
  const module = new Module({
45
67
  userId,
46
- entity,
68
+ entity: existingEntity,
47
69
  definition: moduleDefinition,
48
70
  });
49
71
 
@@ -53,6 +75,16 @@ class ProcessAuthorizationCallback {
53
75
  module.api,
54
76
  params
55
77
  );
78
+ console.log(
79
+ `[Frigg] processAuthorizationCallback OAuth getToken complete userId=${userId} entityType=${entityType}`
80
+ );
81
+ // Belt-and-suspenders: persist tokens explicitly here rather than
82
+ // relying solely on the DLGT_TOKEN_UPDATE notification chain
83
+ // inside setTokens. The notification path remains in place but
84
+ // has been observed to no-op silently in some prod paths,
85
+ // leaving newly-issued tokens unsaved while the user-visible
86
+ // OAuth flow appears to succeed.
87
+ await this.onTokenUpdate(module, moduleDefinition, userId);
56
88
  } else {
57
89
  tokenResponse =
58
90
  await moduleDefinition.requiredAuthMethods.setAuthParams(
@@ -62,6 +94,10 @@ class ProcessAuthorizationCallback {
62
94
  await this.onTokenUpdate(module, moduleDefinition, userId);
63
95
  }
64
96
 
97
+ console.log(
98
+ `[Frigg] processAuthorizationCallback credential persisted credentialId=${module.credential?.id} authIsValid=${module.credential?.authIsValid}`
99
+ );
100
+
65
101
  const authRes = await module.testAuth();
66
102
  if (!authRes) {
67
103
  throw new Error('Authorization failed');
@@ -90,7 +126,12 @@ class ProcessAuthorizationCallback {
90
126
  // credential + entity are already persisted. Operators can recover
91
127
  // stuck integrations manually.
92
128
  try {
93
- await this.restoreIntegrationsForEntity(persistedEntity.id);
129
+ const restoredCount = await this.restoreIntegrationsForEntity(
130
+ persistedEntity.id
131
+ );
132
+ console.log(
133
+ `[Frigg] processAuthorizationCallback restored ${restoredCount} integration(s) for entityId=${persistedEntity.id}`
134
+ );
94
135
  } catch (err) {
95
136
  console.error(
96
137
  `[Frigg] Failed to restore integrations for entity ${persistedEntity.id} after successful re-auth — manual intervention may be needed`,
@@ -106,11 +147,12 @@ class ProcessAuthorizationCallback {
106
147
  }
107
148
 
108
149
  async restoreIntegrationsForEntity(entityId) {
109
- if (!this.integrationRepository) return;
150
+ if (!this.integrationRepository) return 0;
110
151
  const integrations =
111
152
  await this.integrationRepository.findIntegrationsByEntityId(
112
153
  entityId
113
154
  );
155
+ let restored = 0;
114
156
  for (const integration of integrations) {
115
157
  if (STATUSES_RESET_ON_REAUTH.includes(integration.status)) {
116
158
  console.log(
@@ -120,8 +162,10 @@ class ProcessAuthorizationCallback {
120
162
  integration.id,
121
163
  'ENABLED'
122
164
  );
165
+ restored++;
123
166
  }
124
167
  }
168
+ return restored;
125
169
  }
126
170
 
127
171
  async onTokenUpdate(module, moduleDefinition, userId) {
@@ -162,6 +206,28 @@ class ProcessAuthorizationCallback {
162
206
  });
163
207
 
164
208
  if (existingEntity) {
209
+ // Repoint the entity's credentialId when re-auth produced a
210
+ // different credential than the one currently linked. This
211
+ // happens when the user re-authenticates against a different
212
+ // workspace/account of the same provider — `upsertCredential`
213
+ // matches/creates a credential keyed by externalId, but
214
+ // findEntity matches the entity by its own externalId, leaving
215
+ // the entity still linked to the prior workspace's credential
216
+ // unless we explicitly update the link.
217
+ const existingCredentialId = existingEntity.credential?.id;
218
+ if (
219
+ credentialId &&
220
+ String(existingCredentialId) !== String(credentialId)
221
+ ) {
222
+ console.log(
223
+ `[Frigg] Repointing entity ${existingEntity.id} credentialId ${existingCredentialId} -> ${credentialId} after re-auth`
224
+ );
225
+ const updated = await this.moduleRepository.updateEntity(
226
+ existingEntity.id,
227
+ { credential: credentialId }
228
+ );
229
+ if (updated) return updated;
230
+ }
165
231
  return existingEntity;
166
232
  }
167
233
 
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-next.81",
4
+ "version": "2.0.0-next.83",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
7
7
  "@aws-sdk/client-kms": "^3.588.0",
@@ -38,9 +38,9 @@
38
38
  }
39
39
  },
40
40
  "devDependencies": {
41
- "@friggframework/eslint-config": "2.0.0-next.81",
42
- "@friggframework/prettier-config": "2.0.0-next.81",
43
- "@friggframework/test": "2.0.0-next.81",
41
+ "@friggframework/eslint-config": "2.0.0-next.83",
42
+ "@friggframework/prettier-config": "2.0.0-next.83",
43
+ "@friggframework/test": "2.0.0-next.83",
44
44
  "@prisma/client": "^6.17.0",
45
45
  "@types/lodash": "4.17.15",
46
46
  "@typescript-eslint/eslint-plugin": "^8.0.0",
@@ -80,5 +80,5 @@
80
80
  "publishConfig": {
81
81
  "access": "public"
82
82
  },
83
- "gitHead": "f928679326fe06cc56ac46e97cf268fe8f8e823e"
83
+ "gitHead": "e01d96a234ebb71582e5f1f2e6d53bfe8bf8ce33"
84
84
  }