-
Notifications
You must be signed in to change notification settings - Fork 0
feat: implement authentication for convex functions and relevant route. #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,8 @@ | ||
| import { createClient, type AuthFunctions } from "@convex-dev/better-auth"; | ||
| import { betterAuth, type BetterAuthOptions } from "better-auth"; | ||
| import { convex, crossDomain } from "@convex-dev/better-auth/plugins"; | ||
| import { admin } from "better-auth/plugins"; | ||
| // import { magicLink } from "better-auth/plugins"; | ||
| import { magicLink, admin } from "better-auth/plugins"; | ||
| import { createAuthMiddleware, APIError } from "better-auth/api"; | ||
| import { components, internal } from "./_generated/api"; | ||
| import { query } from "./_generated/server"; | ||
| import { v } from "convex/values"; | ||
|
|
@@ -64,6 +64,39 @@ export const createAuthOptions = (ctx: GenericCtx<DataModel>): BetterAuthOptions | |
| emailAndPassword: { | ||
| enabled: true, | ||
| }, | ||
| hooks: { | ||
| before: createAuthMiddleware(async (apiCtx) => { | ||
| if (apiCtx.path === "/sign-up/email") { | ||
| const body = apiCtx.body as any; | ||
| const code = body?.code; | ||
| if (!code) { | ||
| throw new APIError("BAD_REQUEST", { | ||
| message: "Invitation code is required.", | ||
| }); | ||
| } | ||
|
|
||
| const invitation = await ctx.db | ||
| .query("invitationCodes") | ||
| .withIndex("by_code", (q) => q.eq("code", code)) | ||
| .unique(); | ||
|
|
||
| if (!invitation || !invitation.isValid || invitation.usesCount >= invitation.quantity) { | ||
| throw new APIError("BAD_REQUEST", { | ||
| message: "Invalid or expired invitation code.", | ||
| }); | ||
| } | ||
|
|
||
| if (invitation.expiryDate) { | ||
| const expiry = new Date(invitation.expiryDate); | ||
| if (!isNaN(expiry.getTime()) && expiry.getTime() < Date.now()) { | ||
| throw new APIError("BAD_REQUEST", { | ||
| message: "Invitation code has expired.", | ||
| }); | ||
| } | ||
| } | ||
|
Comment on lines
+78
to
+96
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift Consume the invitation and create the gated profile after sign-up succeeds. This hook only checks the code. It never increments 🤖 Prompt for AI Agents |
||
| } | ||
| }), | ||
| }, | ||
| plugins: [ | ||
| convex({ authConfig, jwtExpirationSeconds: 60 * 60 * 24 }), | ||
| crossDomain({ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Preserve the internal admin bootstrap path.
web/convex/init.tsstill callsauth.api.signUpEmailwithoutcode, so this hook rejectscreateAdminUserbefore the admin can be created. Add a trusted internal bootstrap path or update admin provisioning so it does not hit the student invitation requirement.🤖 Prompt for AI Agents