mirror of
https://github.com/Hackdex-App/hackdex-website.git
synced 2026-04-21 22:47:18 -05:00
Add support for static invite codes through edge config
This commit is contained in:
parent
b7220ca057
commit
b5857bda4c
31
package-lock.json
generated
31
package-lock.json
generated
|
|
@ -16,6 +16,7 @@
|
|||
"@supabase/ssr": "^0.7.0",
|
||||
"@supabase/supabase-js": "^2.74.0",
|
||||
"@types/serialize-javascript": "^5.0.4",
|
||||
"@vercel/edge-config": "^1.4.3",
|
||||
"chart.js": "^4.5.1",
|
||||
"embla-carousel-react": "8.6.0",
|
||||
"minio": "^8.0.6",
|
||||
|
|
@ -1483,6 +1484,36 @@
|
|||
"integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@vercel/edge-config": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/edge-config/-/edge-config-1.4.3.tgz",
|
||||
"integrity": "sha512-8vTDATodRrH49wMzKEjZ8/5H2qs1aPkD0uRK585f/Fx4YN2wfHfY/3td9OFrh+gdnCq07z8A5f0hoY6xhBcPkg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@vercel/edge-config-fs": "0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": "^1.7.0",
|
||||
"next": ">=1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@opentelemetry/api": {
|
||||
"optional": true
|
||||
},
|
||||
"next": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vercel/edge-config-fs": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/edge-config-fs/-/edge-config-fs-0.1.0.tgz",
|
||||
"integrity": "sha512-NRIBwfcS0bUoUbRWlNGetqjvLSwgYH/BqKqDN7vK1g32p7dN96k0712COgaz6VFizAm9b0g6IG6hR6+hc0KCPg==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
"@supabase/ssr": "^0.7.0",
|
||||
"@supabase/supabase-js": "^2.74.0",
|
||||
"@types/serialize-javascript": "^5.0.4",
|
||||
"@vercel/edge-config": "^1.4.3",
|
||||
"chart.js": "^4.5.1",
|
||||
"embla-carousel-react": "8.6.0",
|
||||
"minio": "^8.0.6",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { revalidatePath } from 'next/cache'
|
||||
import { redirect } from 'next/navigation'
|
||||
import { AuthError } from '@supabase/supabase-js'
|
||||
import { get } from '@vercel/edge-config'
|
||||
|
||||
import { createClient, createServiceClient } from '@/utils/supabase/server'
|
||||
import { validateEmail, validatePassword } from '@/utils/auth'
|
||||
|
|
@ -54,16 +55,27 @@ export async function signup(state: AuthActionState, payload: FormData) {
|
|||
return { error: 'An invite code is required to sign up.' }
|
||||
}
|
||||
|
||||
// Pre-check: ensure invite exists and is unused before attempting signup
|
||||
const { data: availableInvite, error: inviteCheckError } = await service
|
||||
.from('invite_codes')
|
||||
.select('code')
|
||||
.eq('code', inviteCode)
|
||||
.is('used_by', null)
|
||||
.maybeSingle()
|
||||
// Allow static invite codes via Edge Config to bypass DB checks
|
||||
let isStaticInvite = false
|
||||
try {
|
||||
const staticCodes = (await get<string[] | null>('staticInviteCodes')) || []
|
||||
if (Array.isArray(staticCodes)) {
|
||||
isStaticInvite = staticCodes.includes(inviteCode)
|
||||
}
|
||||
} catch {}
|
||||
|
||||
if (inviteCheckError || !availableInvite) {
|
||||
return { error: 'Invalid or already used invite code.' }
|
||||
if (!isStaticInvite) {
|
||||
// Pre-check: ensure invite exists and is unused before attempting signup
|
||||
const { data: availableInvite, error: inviteCheckError } = await service
|
||||
.from('invite_codes')
|
||||
.select('code')
|
||||
.eq('code', inviteCode)
|
||||
.is('used_by', null)
|
||||
.maybeSingle()
|
||||
|
||||
if (inviteCheckError || !availableInvite) {
|
||||
return { error: 'Invalid or already used invite code.' }
|
||||
}
|
||||
}
|
||||
|
||||
const { data: signUpResult, error } = await supabase.auth.signUp(data)
|
||||
|
|
@ -73,23 +85,27 @@ export async function signup(state: AuthActionState, payload: FormData) {
|
|||
}
|
||||
|
||||
const userId = signUpResult.user?.id || null
|
||||
// Finalize: set used_by to the new user id iff still unused (atomic)
|
||||
const { data: finalized, error: finalizeError } = await service
|
||||
.from('invite_codes')
|
||||
.update({ used_by: userId ?? null })
|
||||
.eq('code', inviteCode)
|
||||
.is('used_by', null)
|
||||
.select('code')
|
||||
.maybeSingle()
|
||||
if (isStaticInvite) {
|
||||
console.log('[signup] Static invite code used:', { inviteCode, userId })
|
||||
} else {
|
||||
// Finalize: set used_by to the new user id iff still unused (atomic)
|
||||
const { data: finalized, error: finalizeError } = await service
|
||||
.from('invite_codes')
|
||||
.update({ used_by: userId ?? null })
|
||||
.eq('code', inviteCode)
|
||||
.is('used_by', null)
|
||||
.select('code')
|
||||
.maybeSingle()
|
||||
|
||||
if (finalizeError || !finalized) {
|
||||
// The code claim could not be finalized (race). Roll back user creation.
|
||||
if (userId) {
|
||||
try {
|
||||
await service.auth.admin.deleteUser(userId)
|
||||
} catch {}
|
||||
if (finalizeError || !finalized) {
|
||||
// The code claim could not be finalized (race). Roll back user creation.
|
||||
if (userId) {
|
||||
try {
|
||||
await service.auth.admin.deleteUser(userId)
|
||||
} catch {}
|
||||
}
|
||||
return { error: 'Invite code is no longer available. Please try again.' }
|
||||
}
|
||||
return { error: 'Invite code is no longer available. Please try again.' }
|
||||
}
|
||||
|
||||
revalidatePath('/', 'layout');
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user