feat(auth): block protected account deletion in auth endpoints
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import {
|
||||
auth,
|
||||
authRouteHandlers,
|
||||
canDeleteUserAccount,
|
||||
canUserSelfRegister,
|
||||
ensureSupportUserBootstrap,
|
||||
ensureUserUsername,
|
||||
@@ -40,6 +42,51 @@ function buildJsonRequest(request: Request, body: Record<string, unknown>): Requ
|
||||
})
|
||||
}
|
||||
|
||||
function isDeleteUserAuthPath(pathname: string): boolean {
|
||||
const actionPrefix = "/api/auth/"
|
||||
const actionIndex = pathname.indexOf(actionPrefix)
|
||||
|
||||
if (actionIndex === -1) {
|
||||
return false
|
||||
}
|
||||
|
||||
const actionPath = pathname.slice(actionIndex + actionPrefix.length)
|
||||
return actionPath === "delete-user" || actionPath.startsWith("delete-user/")
|
||||
}
|
||||
|
||||
async function guardProtectedAccountDeletion(request: Request): Promise<Response | null> {
|
||||
const pathname = new URL(request.url).pathname
|
||||
|
||||
if (!isDeleteUserAuthPath(pathname)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const session = await auth.api
|
||||
.getSession({
|
||||
headers: request.headers,
|
||||
})
|
||||
.catch(() => null)
|
||||
|
||||
const userId = session?.user?.id
|
||||
|
||||
if (!userId) {
|
||||
return null
|
||||
}
|
||||
|
||||
const allowed = await canDeleteUserAccount(userId)
|
||||
|
||||
if (allowed) {
|
||||
return null
|
||||
}
|
||||
|
||||
return jsonResponse(
|
||||
{
|
||||
message: "This account is protected and cannot be deleted.",
|
||||
},
|
||||
403,
|
||||
)
|
||||
}
|
||||
|
||||
async function handleSignInPost(request: Request): Promise<Response> {
|
||||
await ensureSupportUserBootstrap()
|
||||
|
||||
@@ -136,6 +183,13 @@ async function handleSignUpPost(request: Request): Promise<Response> {
|
||||
|
||||
export async function GET(request: Request): Promise<Response> {
|
||||
await ensureSupportUserBootstrap()
|
||||
|
||||
const deletionGuardResponse = await guardProtectedAccountDeletion(request)
|
||||
|
||||
if (deletionGuardResponse) {
|
||||
return deletionGuardResponse
|
||||
}
|
||||
|
||||
return authRouteHandlers.GET(request)
|
||||
}
|
||||
|
||||
@@ -151,20 +205,48 @@ export async function POST(request: Request): Promise<Response> {
|
||||
}
|
||||
|
||||
await ensureSupportUserBootstrap()
|
||||
|
||||
const deletionGuardResponse = await guardProtectedAccountDeletion(request)
|
||||
|
||||
if (deletionGuardResponse) {
|
||||
return deletionGuardResponse
|
||||
}
|
||||
|
||||
return authRouteHandlers.POST(request)
|
||||
}
|
||||
|
||||
export async function PATCH(request: Request): Promise<Response> {
|
||||
await ensureSupportUserBootstrap()
|
||||
|
||||
const deletionGuardResponse = await guardProtectedAccountDeletion(request)
|
||||
|
||||
if (deletionGuardResponse) {
|
||||
return deletionGuardResponse
|
||||
}
|
||||
|
||||
return authRouteHandlers.PATCH(request)
|
||||
}
|
||||
|
||||
export async function PUT(request: Request): Promise<Response> {
|
||||
await ensureSupportUserBootstrap()
|
||||
|
||||
const deletionGuardResponse = await guardProtectedAccountDeletion(request)
|
||||
|
||||
if (deletionGuardResponse) {
|
||||
return deletionGuardResponse
|
||||
}
|
||||
|
||||
return authRouteHandlers.PUT(request)
|
||||
}
|
||||
|
||||
export async function DELETE(request: Request): Promise<Response> {
|
||||
await ensureSupportUserBootstrap()
|
||||
|
||||
const deletionGuardResponse = await guardProtectedAccountDeletion(request)
|
||||
|
||||
if (deletionGuardResponse) {
|
||||
return deletionGuardResponse
|
||||
}
|
||||
|
||||
return authRouteHandlers.DELETE(request)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user