add signup redirect to register
This commit is contained in:
parent
765a9b358a
commit
3498b7d966
1 changed files with 110 additions and 0 deletions
110
src/routes/auth/signup/+server.ts
Normal file
110
src/routes/auth/signup/+server.ts
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
import type { RequestHandler } from '@sveltejs/kit'
|
||||
import { json } from '@sveltejs/kit'
|
||||
import { z } from 'zod'
|
||||
import { PUBLIC_SIERO_API_URL } from '$env/static/public'
|
||||
import { passwordGrantLogin } from '$lib/auth/oauth'
|
||||
import { UserAdapter } from '$lib/api/adapters/user.adapter'
|
||||
import { buildCookies } from '$lib/auth/map'
|
||||
import { setAccountCookie, setUserCookie, setRefreshCookie } from '$lib/auth/cookies'
|
||||
|
||||
const SignupSchema = z
|
||||
.object({
|
||||
username: z
|
||||
.string()
|
||||
.min(3, 'Username must be at least 3 characters')
|
||||
.max(20, 'Username must be less than 20 characters')
|
||||
.regex(
|
||||
/^[a-zA-Z0-9_-]+$/,
|
||||
'Username can only contain letters, numbers, underscores, and hyphens'
|
||||
),
|
||||
email: z.string().email('Invalid email format'),
|
||||
password: z.string().min(8, 'Password must be at least 8 characters'),
|
||||
password_confirmation: z.string()
|
||||
})
|
||||
.refine((data) => data.password === data.password_confirmation, {
|
||||
message: "Passwords don't match",
|
||||
path: ['password_confirmation']
|
||||
})
|
||||
|
||||
export const POST: RequestHandler = async ({ request, cookies, url, fetch }) => {
|
||||
const raw = await request.json().catch(() => ({}))
|
||||
const parsed = SignupSchema.safeParse(raw)
|
||||
|
||||
if (!parsed.success) {
|
||||
const details = parsed.error.flatten((i) => i.message)
|
||||
return json({ error: 'Validation error', details }, { status: 400 })
|
||||
}
|
||||
|
||||
const { username, email, password, password_confirmation } = parsed.data
|
||||
|
||||
try {
|
||||
// 1. Create user account via API
|
||||
const signupRes = await fetch(`${PUBLIC_SIERO_API_URL}/users`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
user: {
|
||||
username,
|
||||
email,
|
||||
password,
|
||||
password_confirmation
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (!signupRes.ok) {
|
||||
const errorData = await signupRes.json().catch(() => ({}))
|
||||
|
||||
// Handle specific API errors (username/email already taken)
|
||||
if (signupRes.status === 409 || signupRes.status === 422) {
|
||||
return json(
|
||||
{ error: errorData.error || 'Username or email already in use' },
|
||||
{ status: 409 }
|
||||
)
|
||||
}
|
||||
|
||||
return json({ error: errorData.error || 'Signup failed' }, { status: signupRes.status })
|
||||
}
|
||||
|
||||
// 2. Auto-login the new user
|
||||
const oauth = await passwordGrantLogin(fetch, {
|
||||
email,
|
||||
password,
|
||||
grant_type: 'password'
|
||||
})
|
||||
|
||||
// 3. Get additional user info
|
||||
const userAdapter = new UserAdapter()
|
||||
const info = await userAdapter.getInfo(oauth.user.username, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${oauth.access_token}`
|
||||
}
|
||||
})
|
||||
|
||||
// 4. Build and set cookies
|
||||
const { account, user, accessTokenExpiresAt, refresh } = buildCookies(oauth, info)
|
||||
|
||||
const secure = url.protocol === 'https:'
|
||||
setAccountCookie(cookies, account, { secure, expires: accessTokenExpiresAt })
|
||||
setUserCookie(cookies, user, { secure, expires: accessTokenExpiresAt })
|
||||
setRefreshCookie(cookies, refresh, { secure, expires: accessTokenExpiresAt })
|
||||
|
||||
// 5. Return success with user data
|
||||
return json({
|
||||
success: true,
|
||||
user: { username: info.username, avatar: info.avatar },
|
||||
access_token: oauth.access_token,
|
||||
expires_in: oauth.expires_in,
|
||||
expires_at: accessTokenExpiresAt.toISOString()
|
||||
})
|
||||
} catch (e: unknown) {
|
||||
console.error('Signup error:', e)
|
||||
|
||||
if (e instanceof Error && e.message === 'unauthorized') {
|
||||
// This shouldn't happen during signup, but handle it
|
||||
return json({ error: 'Failed to authenticate after signup' }, { status: 500 })
|
||||
}
|
||||
|
||||
return json({ error: 'Signup failed' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue