Skip to content

Commit f188ceb

Browse files
thomasballingerConvex, Inc.
authored andcommitted
Disallow root component UDFs that start with betterAuth/ (#42651)
GitOrigin-RevId: 586784652e7e5e75ff3b1c31c492e548f0f17a90
1 parent 601f94c commit f188ceb

File tree

6 files changed

+64
-0
lines changed

6 files changed

+64
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/udf/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ semver = { workspace = true }
4141
serde_json = { workspace = true }
4242
sync_types = { workspace = true }
4343
tokio = { workspace = true }
44+
tracing = { workspace = true }
4445
url = { workspace = true }
4546
value = { workspace = true }
4647

crates/udf/src/validation.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::LazyLock;
2+
13
use anyhow::Context;
24
use common::{
35
components::{
@@ -86,6 +88,10 @@ pub const SUSPENDED_ERROR_MESSAGE: &str = "Cannot run functions while this deplo
8688
suspended. Please contact Convex if you believe this \
8789
is a mistake.";
8890

91+
/// Convex CLI versions before 1.28.2 double-deployed betterAuth/ paths.
92+
static MIN_NPM_VERSION_FOR_BETTER_AUTH: LazyLock<Version> =
93+
LazyLock::new(|| Version::new(1, 28, 2));
94+
8995
/// Fails with an error if the backend is not running. We have to return a
9096
/// result of a result of () and a JSError because we use them to
9197
/// differentiate between system and user errors.
@@ -211,6 +217,15 @@ fn missing_or_internal_error(path: PublicFunctionPath) -> anyhow::Result<String>
211217
))
212218
}
213219

220+
fn should_block_path(path: &ResolvedComponentFunctionPath) -> bool {
221+
if path.component != ComponentId::Root {
222+
return false;
223+
}
224+
225+
let path_str = path.udf_path.to_string();
226+
path_str.starts_with("betterAuth/")
227+
}
228+
214229
#[fastrace::trace]
215230
async fn udf_version<RT: Runtime>(
216231
path: &ResolvedComponentFunctionPath,
@@ -415,6 +430,17 @@ impl ValidatedPathAndArgs {
415430
)?)));
416431
};
417432

433+
if udf_version < *MIN_NPM_VERSION_FOR_BETTER_AUTH && should_block_path(&path) {
434+
tracing::warn!(
435+
"Blocking betterAuth/ path '{}' for SDK version {} (< 1.28.2)",
436+
path.udf_path,
437+
udf_version
438+
);
439+
return Ok(Err(JsError::from_message(missing_or_internal_error(
440+
public_path,
441+
)?)));
442+
}
443+
418444
let returns_validator = if path.udf_path.is_system() {
419445
ReturnsValidator::Unvalidated
420446
} else {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ConvexHttpClient } from "convex/browser";
2+
import { makeFunctionReference } from "convex/server";
3+
import { deploymentUrl } from "./common";
4+
5+
describe("betterAuth path blocking", () => {
6+
let httpClient: ConvexHttpClient;
7+
8+
beforeEach(() => {
9+
httpClient = new ConvexHttpClient(deploymentUrl);
10+
});
11+
12+
test("betterAuth/ paths should be blocked and return 'not found' error", async () => {
13+
// Try to call a function in the betterAuth/ directory
14+
// This should be blocked by the validation logic and return the same error
15+
// as if the function doesn't exist
16+
await expect(
17+
httpClient.query(
18+
makeFunctionReference<"query">("betterAuth/testFunction:default"),
19+
{},
20+
),
21+
).rejects.toThrow(
22+
"Could not find public function for 'betterAuth/testFunction'. Did you forget to run `npx convex dev` or `npx convex deploy`?",
23+
);
24+
});
25+
});

npm-packages/js-integration-tests/convex/_generated/api.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type * as actions_simple from "../actions/simple.js";
1515
import type * as addUser from "../addUser.js";
1616
import type * as auth from "../auth.js";
1717
import type * as basic from "../basic.js";
18+
import type * as betterAuth_testFunction from "../betterAuth/testFunction.js";
1819
import type * as cachebust from "../cachebust.js";
1920
import type * as cleanUp from "../cleanUp.js";
2021
import type * as component from "../component.js";
@@ -67,6 +68,7 @@ declare const fullApi: ApiFromModules<{
6768
addUser: typeof addUser;
6869
auth: typeof auth;
6970
basic: typeof basic;
71+
"betterAuth/testFunction": typeof betterAuth_testFunction;
7072
cachebust: typeof cachebust;
7173
cleanUp: typeof cleanUp;
7274
component: typeof component;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { query } from "../_generated/server";
2+
3+
// This is a test function that should be blocked for SDK versions < 1.28.2
4+
export default query({
5+
args: {},
6+
handler: async () => {
7+
return { message: "betterAuth function executed successfully" };
8+
},
9+
});

0 commit comments

Comments
 (0)