Skip to content

Commit 64b5781

Browse files
committed
self-review
1 parent 5f30cae commit 64b5781

File tree

7 files changed

+103
-42
lines changed

7 files changed

+103
-42
lines changed

packages/app-store/_utils/oauth/OAuthManager.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ export class OAuthManager {
355355
}
356356

357357
/**
358-
* currentTokenObject is set in getTokenObjectOrFetch and refreshOAuthToken
358+
* currentTokenObject is set through getTokenObjectOrFetch call
359359
*/
360360
private assertCurrentTokenObjectIsSet(): asserts this is this & {
361361
currentTokenObject: CurrentTokenObject;
@@ -374,6 +374,7 @@ export class OAuthManager {
374374
if (this.autoCheckTokenExpiryOnRequest) {
375375
await this.getTokenObjectOrFetch();
376376
}
377+
// `getTokenObjectOrFetch` has been called or `currentTokenObject` is set through constructor
377378
this.assertCurrentTokenObjectIsSet();
378379
const headers = {
379380
Authorization: `Bearer ${this.currentTokenObject.access_token}`,

packages/app-store/_utils/oauth/getCurrentTokenObject.ts

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logger from "@calcom/lib/logger";
2-
import prisma from "@calcom/prisma";
2+
import { CredentialRepository } from "@calcom/lib/server/repository/credential";
33
import type { CredentialForCalendarService } from "@calcom/types/Credential";
44

55
import { getTokenObjectFromCredential } from "./getTokenObjectFromCredential";
@@ -8,20 +8,10 @@ const log = logger.getSubLogger({
88
prefix: ["getCurrentTokenObject"],
99
});
1010

11-
async function getDelegationUserCredentialInDb({
12-
userId,
13-
delegationCredentialId,
14-
}: {
15-
userId: number;
16-
delegationCredentialId: string;
17-
}) {
18-
const delegationUserCredentialInDb = await prisma.credential.findFirst({
19-
where: {
20-
userId,
21-
delegationCredentialId,
22-
},
23-
});
24-
return delegationUserCredentialInDb;
11+
function buildDummyTokenObjectForDelegationUserCredential() {
12+
return {
13+
access_token: "TOKEN_PLACEHOLDER_FOR_DELEGATION_CREDENTIAL",
14+
};
2515
}
2616

2717
export async function getCurrentTokenObject(
@@ -33,16 +23,17 @@ export async function getCurrentTokenObject(
3323
log.error("DelegationCredential: No user id found for delegation credential");
3424
} else {
3525
log.debug("Getting current token object for delegation credential");
36-
const delegationUserCredentialInDb = await getDelegationUserCredentialInDb({
37-
userId: credential.userId,
38-
delegationCredentialId: credential.delegatedToId,
39-
});
26+
const delegationUserCredentialInDb =
27+
await CredentialRepository.findUniqueByUserIdAndDelegationCredentialId({
28+
userId: credential.userId,
29+
delegationCredentialId: credential.delegatedToId,
30+
});
4031
inDbCredential = delegationUserCredentialInDb;
4132
if (!inDbCredential) {
4233
log.error("getCurrentTokenObject: No delegation user credential found in db");
43-
return {
44-
access_token: "TOKEN_PLACEHOLDER_FOR_DELEGATION_CREDENTIAL",
45-
};
34+
// We return a dummy token object. OAuthManager requires a token object that must have access_token.
35+
// OAuthManager will help fetching new token object and then that would be stored in DB.
36+
return buildDummyTokenObjectForDelegationUserCredential();
4637
}
4738
}
4839
} else {

packages/app-store/_utils/oauth/updateTokenObject.ts

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import type { Prisma } from "@prisma/client";
12
import type z from "zod";
23

34
import logger from "@calcom/lib/logger";
45
import { safeStringify } from "@calcom/lib/safeStringify";
6+
import { CredentialRepository } from "@calcom/lib/server/repository/credential";
57
import prisma from "@calcom/prisma";
68

79
import type { OAuth2UniversalSchemaWithCalcomBackwardCompatibility } from "./universalSchema";
@@ -60,35 +62,30 @@ export const updateTokenObjectInDb = async (
6062
log.error("Cannot update token object in DB for Delegation as delegatedToId is not present");
6163
return;
6264
}
63-
const updated = await prisma.credential.updateMany({
64-
where: {
65-
userId: userId,
66-
delegationCredentialId: delegatedToId,
67-
},
65+
66+
const updated = await CredentialRepository.updateWhereUserIdAndDelegationCredentialId({
67+
userId,
68+
delegationCredentialId: delegatedToId,
6869
data: {
69-
key: tokenObject,
70+
key: tokenObject as Prisma.InputJsonValue,
7071
},
7172
});
7273
// If no delegation-credential is found, create one
7374
if (updated.count === 0) {
7475
log.debug("No delegation-credential found. Creating one");
75-
await prisma.credential.create({
76-
data: {
77-
userId,
78-
delegationCredentialId: delegatedToId,
79-
type: credentialType,
80-
key: tokenObject,
81-
},
76+
await CredentialRepository.createDelegationCredential({
77+
userId,
78+
delegationCredentialId: delegatedToId,
79+
type: credentialType,
80+
key: tokenObject as Prisma.InputJsonValue,
8281
});
8382
}
8483
} else {
8584
const { credentialId } = args;
86-
await prisma.credential.update({
87-
where: {
88-
id: credentialId,
89-
},
85+
await CredentialRepository.updateWhereId({
86+
id: credentialId,
9087
data: {
91-
key: tokenObject,
88+
key: tokenObject as Prisma.InputJsonValue,
9289
},
9390
});
9491
}

packages/app-store/tests/__mocks__/OAuthManager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,5 @@ const defaultMockOAuthManager = vi.fn().mockImplementation(() => {
5151
}),
5252
};
5353
});
54+
5455
export { oAuthManagerMock, defaultMockOAuthManager, setFullMockOAuthManagerRequest };

packages/lib/server/repository/credential.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
import type { Prisma } from "@prisma/client";
2+
3+
import logger from "@calcom/lib/logger";
14
import { prisma } from "@calcom/prisma";
25
import { safeCredentialSelect } from "@calcom/prisma/selects/credential";
36
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
47

58
import { buildNonDelegationCredential } from "../../delegationCredential/server";
69

10+
const log = logger.getSubLogger({ prefix: ["CredentialRepository"] });
11+
712
type CredentialCreateInput = {
813
type: string;
914
key: any;
@@ -142,4 +147,67 @@ export class CredentialRepository {
142147
};
143148
});
144149
}
150+
151+
static async findUniqueByUserIdAndDelegationCredentialId({
152+
userId,
153+
delegationCredentialId,
154+
}: {
155+
userId: number;
156+
delegationCredentialId: string;
157+
}) {
158+
const delegationUserCredentials = await prisma.credential.findMany({
159+
where: {
160+
userId,
161+
delegationCredentialId,
162+
},
163+
});
164+
165+
if (delegationUserCredentials.length > 1) {
166+
// Instead of crashing use the first one and log for observability
167+
log.error(`DelegationCredential: Multiple delegation user credentials found - this should not happen`, {
168+
userId,
169+
delegationCredentialId,
170+
});
171+
}
172+
173+
return delegationUserCredentials[0];
174+
}
175+
176+
static async updateWhereUserIdAndDelegationCredentialId({
177+
userId,
178+
delegationCredentialId,
179+
data,
180+
}: {
181+
userId: number;
182+
delegationCredentialId: string;
183+
data: {
184+
key: Prisma.InputJsonValue;
185+
};
186+
}) {
187+
return prisma.credential.updateMany({
188+
where: {
189+
userId,
190+
delegationCredentialId,
191+
},
192+
data,
193+
});
194+
}
195+
196+
static async createDelegationCredential({
197+
userId,
198+
delegationCredentialId,
199+
type,
200+
key,
201+
}: {
202+
userId: number;
203+
delegationCredentialId: string;
204+
type: string;
205+
key: Prisma.InputJsonValue;
206+
}) {
207+
return prisma.credential.create({ data: { userId, delegationCredentialId, type, key } });
208+
}
209+
210+
static async updateWhereId({ id, data }: { id: number; data: { key: Prisma.InputJsonValue } }) {
211+
return prisma.credential.update({ where: { id }, data });
212+
}
145213
}

scripts/prepare-local-for-delegation-credentials-testing.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ async function main() {
6363
teamId: org.id,
6464
featureId: "delegation-credential",
6565
assignedAt: new Date(),
66+
assignedBy: "prepare-local-script",
6667
},
6768
});
6869
console.log("Created TeamFeatures: delegation-credential");

tests/libs/__mocks__/app-store.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ beforeEach(() => {
1111

1212
const appStoreMock = mockDeep<typeof appStore>({
1313
fallbackMockImplementation: () => {
14-
throw new Error("Unimplemented appStoreMock. You seem to have mocked the app that you are trying to use");
14+
throw new Error(
15+
"Unimplemented appStoreMock. You seem to have not mocked the app that you are trying to use"
16+
);
1517
},
1618
});
1719
export default appStoreMock;

0 commit comments

Comments
 (0)