Skip to content

Commit 9fbe8cc

Browse files
sshaderConvex, Inc.
authored and
Convex, Inc.
committed
Fix issues with project keys (#35726)
The previous code was mistakenly always returning "does not have access to project" instead of "cannot determine if has access" for project keys. Additionally, we'd prompt for opt ins with preview or project keys, which wouldn't work. Also we'd try and check usage which would fail with the project key. GitOrigin-RevId: 5079ce3b28d4d6686de351722b1e27789ac5cfb4
1 parent 571a9b2 commit 9fbe8cc

File tree

6 files changed

+94
-38
lines changed

6 files changed

+94
-38
lines changed

npm-packages/convex/src/cli/configure.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ export async function deploymentCredentialsOrConfigure(
108108
deploymentFields: {
109109
deploymentName: DeploymentName;
110110
deploymentType: string;
111-
projectSlug: string;
112-
teamSlug: string;
111+
projectSlug: string | null;
112+
teamSlug: string | null;
113113
} | null;
114114
}
115115
> {
@@ -174,11 +174,11 @@ export async function deploymentCredentialsOrConfigure(
174174
overrideAuthUsername: cmdOptions.overrideAuthUsername,
175175
overrideAuthPassword: cmdOptions.overrideAuthPassword,
176176
});
177-
const projectSlugs = await checkAccessToSelectedProject(
177+
const accessResult = await checkAccessToSelectedProject(
178178
ctx,
179179
deploymentSelection.targetProject,
180180
);
181-
if (projectSlugs === null) {
181+
if (accessResult.kind === "noAccess") {
182182
logMessage(ctx, "You don't have access to the selected project.");
183183
const result = await handleChooseProject(
184184
ctx,
@@ -614,8 +614,8 @@ async function updateEnvAndConfigForDeploymentSelection(
614614
options: {
615615
url: string;
616616
deploymentName: string;
617-
teamSlug: string;
618-
projectSlug: string;
617+
teamSlug: string | null;
618+
projectSlug: string | null;
619619
deploymentType: DeploymentType;
620620
},
621621
existingValue: string | null,

npm-packages/convex/src/cli/lib/api.ts

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -208,31 +208,43 @@ async function hasAccessToProject(
208208
export async function checkAccessToSelectedProject(
209209
ctx: Context,
210210
projectSelection: ProjectSelection,
211-
): Promise<{ teamSlug: string; projectSlug: string } | null> {
211+
): Promise<
212+
| { kind: "hasAccess"; teamSlug: string; projectSlug: string }
213+
| { kind: "noAccess" }
214+
| { kind: "unknown" }
215+
> {
212216
switch (projectSelection.kind) {
213217
case "deploymentName": {
214218
const result = await getTeamAndProjectSlugForDeployment(ctx, {
215219
deploymentName: projectSelection.deploymentName,
216220
});
217-
return result;
221+
if (result === null) {
222+
return { kind: "noAccess" };
223+
}
224+
return {
225+
kind: "hasAccess",
226+
teamSlug: result.teamSlug,
227+
projectSlug: result.projectSlug,
228+
};
218229
}
219230
case "teamAndProjectSlugs": {
220231
const hasAccess = await hasAccessToProject(ctx, {
221232
teamSlug: projectSelection.teamSlug,
222233
projectSlug: projectSelection.projectSlug,
223234
});
224235
if (!hasAccess) {
225-
return null;
236+
return { kind: "noAccess" };
226237
}
227238
return {
239+
kind: "hasAccess",
228240
teamSlug: projectSelection.teamSlug,
229241
projectSlug: projectSelection.projectSlug,
230242
};
231243
}
232244
case "projectDeployKey":
233245
// Ideally we would be able to do an explicit check here, but if the key is invalid,
234246
// it will instead fail as soon as we try to use the key.
235-
return null;
247+
return { kind: "unknown" };
236248
default: {
237249
const _exhaustivenessCheck: never = projectSelection;
238250
return await ctx.crash({
@@ -603,12 +615,12 @@ async function _loadExistingDeploymentCredentialsForProject(
603615
deploymentFields: {
604616
deploymentName: string;
605617
deploymentType: string;
606-
projectSlug: string;
607-
teamSlug: string;
618+
projectSlug: string | null;
619+
teamSlug: string | null;
608620
} | null;
609621
}> {
610-
const projectSlugs = await checkAccessToSelectedProject(ctx, targetProject);
611-
if (projectSlugs === null) {
622+
const accessResult = await checkAccessToSelectedProject(ctx, targetProject);
623+
if (accessResult.kind === "noAccess") {
612624
return await ctx.crash({
613625
exitCode: 1,
614626
errorType: "fatal",
@@ -636,8 +648,11 @@ async function _loadExistingDeploymentCredentialsForProject(
636648
deploymentFields: {
637649
deploymentName: result.deploymentName,
638650
deploymentType: result.deploymentType,
639-
projectSlug: projectSlugs.projectSlug,
640-
teamSlug: projectSlugs.teamSlug,
651+
652+
projectSlug:
653+
accessResult.kind === "hasAccess" ? accessResult.projectSlug : null,
654+
teamSlug:
655+
accessResult.kind === "hasAccess" ? accessResult.teamSlug : null,
641656
},
642657
};
643658
}
@@ -655,8 +670,8 @@ export async function loadSelectedDeploymentCredentials(
655670
deploymentFields: {
656671
deploymentName: string;
657672
deploymentType: string;
658-
projectSlug: string;
659-
teamSlug: string;
673+
projectSlug: string | null;
674+
teamSlug: string | null;
660675
} | null;
661676
}> {
662677
switch (deploymentSelection.kind) {

npm-packages/convex/src/cli/lib/deployment.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ export function getDeploymentTypeFromConfiguredDeployment(raw: string) {
3131
export async function writeDeploymentEnvVar(
3232
ctx: Context,
3333
deploymentType: DeploymentType,
34-
deployment: { team: string; project: string; deploymentName: string },
34+
deployment: {
35+
team: string | null;
36+
project: string | null;
37+
deploymentName: string;
38+
},
3539
existingValue: string | null,
3640
): Promise<{ wroteToGitIgnore: boolean; changedDeploymentEnvVar: boolean }> {
3741
const existingFile = ctx.fs.exists(ENV_VAR_FILE_PATH)
@@ -101,18 +105,21 @@ export function changesToEnvVarFile(
101105
team,
102106
project,
103107
deploymentName,
104-
}: { team: string; project: string; deploymentName: string },
108+
}: { team: string | null; project: string | null; deploymentName: string },
105109
): string | null {
106110
const deploymentValue = deploymentType + ":" + deploymentName;
107111
const commentOnPreviousLine = "# Deployment used by `npx convex dev`";
108-
const commentAfterValue = `team: ${team}, project: ${project}`;
109-
return changedEnvVarFile(
110-
existingFile,
111-
CONVEX_DEPLOYMENT_ENV_VAR_NAME,
112-
deploymentValue,
112+
const commentAfterValue =
113+
team !== null && project !== null
114+
? `team: ${team}, project: ${project}`
115+
: null;
116+
return changedEnvVarFile({
117+
existingFileContent: existingFile,
118+
envVarName: CONVEX_DEPLOYMENT_ENV_VAR_NAME,
119+
envVarValue: deploymentValue,
113120
commentAfterValue,
114121
commentOnPreviousLine,
115-
);
122+
});
116123
}
117124

118125
// exported for tests

npm-packages/convex/src/cli/lib/envvars.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,35 @@ export async function writeConvexUrlToEnvFile(
3535
}
3636

3737
const { envFile, envVar, existingFileContent } = writeConfig;
38-
const modified = changedEnvVarFile(existingFileContent, envVar, value)!;
38+
const modified = changedEnvVarFile({
39+
existingFileContent,
40+
envVarName: envVar,
41+
envVarValue: value,
42+
commentAfterValue: null,
43+
commentOnPreviousLine: null,
44+
})!;
3945
ctx.fs.writeUtf8File(envFile, modified);
4046
return writeConfig;
4147
}
4248

43-
export function changedEnvVarFile(
44-
existingFileContent: string | null,
45-
envVarName: string,
46-
envVarValue: string,
47-
commentAfterValue?: string,
48-
commentOnPreviousLine?: string,
49-
): string | null {
49+
export function changedEnvVarFile({
50+
existingFileContent,
51+
envVarName,
52+
envVarValue,
53+
commentAfterValue,
54+
commentOnPreviousLine,
55+
}: {
56+
existingFileContent: string | null;
57+
envVarName: string;
58+
envVarValue: string;
59+
commentAfterValue: string | null;
60+
commentOnPreviousLine: string | null;
61+
}): string | null {
5062
const varAssignment = `${envVarName}=${envVarValue}${
51-
commentAfterValue === undefined ? "" : ` # ${commentAfterValue}`
63+
commentAfterValue === null ? "" : ` # ${commentAfterValue}`
5264
}`;
5365
const commentOnPreviousLineWithLineBreak =
54-
commentOnPreviousLine === undefined ? "" : `${commentOnPreviousLine}\n`;
66+
commentOnPreviousLine === null ? "" : `${commentOnPreviousLine}\n`;
5567
if (existingFileContent === null) {
5668
return `${commentOnPreviousLineWithLineBreak}${varAssignment}\n`;
5769
}

npm-packages/convex/src/cli/lib/login.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,28 @@ type AcceptOptInsArgs = {
446446

447447
// Returns whether we can proceed or not.
448448
async function optins(ctx: Context, acceptOptIns: boolean): Promise<boolean> {
449+
const bbAuth = ctx.bigBrainAuth();
450+
if (bbAuth === null) {
451+
// This should never happen, but if we're not even logged in, we can't proceed.
452+
return false;
453+
}
454+
switch (bbAuth.kind) {
455+
case "accessToken":
456+
break;
457+
case "projectKey":
458+
case "previewDeployKey":
459+
// If we have a key configured as auth, we do not need to check opt ins.
460+
return true;
461+
default: {
462+
const _exhaustivenessCheck: never = bbAuth;
463+
return await ctx.crash({
464+
exitCode: 1,
465+
errorType: "fatal",
466+
errForSentry: `Unexpected auth kind ${(bbAuth as any).kind}`,
467+
printedMessage: "Hit an unexpected error while logging in.",
468+
});
469+
}
470+
}
449471
const data = await bigBrainAPI({
450472
ctx,
451473
method: "POST",

npm-packages/convex/src/cli/lib/usage.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ export async function usageStateWarning(
4848
) {
4949
// Skip the warning if the user doesn’t have an auth token
5050
// (which can happen for instance when using a deploy key)
51-
const auth = ctx.bigBrainAuth()?.header ?? null;
52-
if (auth === null) {
51+
const auth = ctx.bigBrainAuth();
52+
if (auth === null || auth.kind === "projectKey") {
5353
return;
5454
}
5555
const { teamId, team } = await fetchTeamAndProject(ctx, targetDeployment);

0 commit comments

Comments
 (0)