Add reset-password endpoint
This commit is contained in:
127
src/routes/account/reset-password/post.ts
Normal file
127
src/routes/account/reset-password/post.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { Context } from 'elysia'
|
||||
import {
|
||||
getClientIp,
|
||||
getDatabaseConnection,
|
||||
jsonResponse,
|
||||
validateTurnstile
|
||||
} from '../../../lib/util'
|
||||
import { resetCodes, users } from '../../../lib/tables'
|
||||
import { and, desc, eq, sql } from 'drizzle-orm'
|
||||
import bcrypt from 'bcryptjs'
|
||||
|
||||
type Body = {
|
||||
token: string
|
||||
code: string
|
||||
password: string
|
||||
}
|
||||
|
||||
export async function handler (context: Context) {
|
||||
const dbInfo0 = getDatabaseConnection(0)
|
||||
|
||||
if (!dbInfo0)
|
||||
return jsonResponse(
|
||||
{ success: false, message: 'Failed to connect to database' },
|
||||
500
|
||||
)
|
||||
const { connection: connection0, db: db0 } = dbInfo0
|
||||
|
||||
const body = context.body as Body
|
||||
if (!body.token || !body.code || !body.password) {
|
||||
connection0.end()
|
||||
return jsonResponse(
|
||||
{
|
||||
success: false,
|
||||
message: 'Token, code and password must be in POST data'
|
||||
},
|
||||
400
|
||||
)
|
||||
}
|
||||
if (body.code.length != 64) {
|
||||
connection0.end()
|
||||
return jsonResponse(
|
||||
{
|
||||
success: false,
|
||||
message: 'Invalid verify code (codes can only be used once)'
|
||||
},
|
||||
400
|
||||
)
|
||||
}
|
||||
const ip = getClientIp(context)
|
||||
if (!ip) {
|
||||
connection0.end()
|
||||
return jsonResponse(
|
||||
{
|
||||
success: false,
|
||||
message: 'Failed to get required info'
|
||||
},
|
||||
400
|
||||
)
|
||||
}
|
||||
|
||||
const result = await validateTurnstile(body.token, ip)
|
||||
if (!result.success) {
|
||||
connection0.end()
|
||||
return jsonResponse(
|
||||
{
|
||||
success: false,
|
||||
message: 'Unable to verify captcha key'
|
||||
},
|
||||
400
|
||||
)
|
||||
}
|
||||
|
||||
const time = Math.floor(Date.now() / 1000)
|
||||
const codeExists = await db0
|
||||
.select({ id: resetCodes.id, userId: resetCodes.userId })
|
||||
.from(resetCodes)
|
||||
.where(
|
||||
and(
|
||||
eq(resetCodes.ip, ip),
|
||||
eq(resetCodes.usedTimestamp, 0),
|
||||
eq(resetCodes.code, body.code),
|
||||
sql`${resetCodes.timestamp} >= UNIX_TIMESTAMP() - 600`,
|
||||
eq(resetCodes.type, 0)
|
||||
)
|
||||
)
|
||||
.orderBy(desc(resetCodes.id))
|
||||
.limit(1)
|
||||
.execute()
|
||||
if (codeExists[0]) {
|
||||
await db0
|
||||
.update(resetCodes)
|
||||
.set({ usedTimestamp: time })
|
||||
.where(
|
||||
and(
|
||||
eq(resetCodes.id, codeExists[0].id),
|
||||
eq(resetCodes.ip, ip),
|
||||
eq(resetCodes.usedTimestamp, 0),
|
||||
eq(resetCodes.code, body.code),
|
||||
eq(resetCodes.type, 0)
|
||||
)
|
||||
)
|
||||
.execute()
|
||||
const hashedPassword = await bcrypt.hash(body.password, 10)
|
||||
await db0
|
||||
.update(users)
|
||||
.set({ password: hashedPassword })
|
||||
.where(eq(users.id, codeExists[0].userId))
|
||||
.execute()
|
||||
connection0.end()
|
||||
return jsonResponse(
|
||||
{
|
||||
success: true,
|
||||
message: null
|
||||
},
|
||||
200
|
||||
)
|
||||
} else {
|
||||
connection0.end()
|
||||
return jsonResponse(
|
||||
{
|
||||
success: false,
|
||||
message: 'Invalid reset code (codes can only be used once)'
|
||||
},
|
||||
400
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user