Files
publisher-dashboard/apps/api-server/src/procedures/me/delete.ts
RevIQ 1bf05465c3 Replace void returns with { success: true } across all API endpoints
- Add successResponseSchema to common.ts for explicit success responses
- Update all auth, me, orgs, and admin procedures to return { success: true }
- Update contract.ts to use successResponseSchema instead of z.void()
- Add ast-grep rule to prevent future z.void() usage in contracts
- Add build:packages script to root package.json
- Fix test file lint errors with eslint-disable comments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 16:30:22 +08:00

53 lines
1.6 KiB
TypeScript

/**
* Delete account procedure - permanently deletes user account
*/
import { ORPCError } from "@orpc/server";
import { COOKIE_NAMES, deleteCookie } from "../../utils/cookies.js";
import { verifyPassword } from "../../utils/password.js";
import { authMiddleware, os } from "../base.js";
/**
* Delete account handler
* - Requires authentication
* - Requires password confirmation (passkey-only users must set password first)
* - Deletes user record (cascades to sessions, devices, passkeys, etc.)
* - Clears session cookie
*/
export const meDelete = os.me.delete
.use(authMiddleware)
.handler(async ({ input, context }) => {
const { password } = input;
// Fetch user with password hash
const user = await context.db
.selectFrom("users")
.select(["password_hash"])
.where("id", "=", context.user.id)
.executeTakeFirstOrThrow();
// Verify password (required for account deletion)
if (!user.password_hash) {
throw new ORPCError("BAD_REQUEST", {
message:
"Cannot delete account without a password. Please set a password first.",
});
}
const valid = await verifyPassword(password, user.password_hash);
if (!valid) {
throw new ORPCError("BAD_REQUEST", { message: "Incorrect password" });
}
// Delete user (cascades to sessions, devices, passkeys, etc.)
await context.db
.deleteFrom("users")
.where("id", "=", context.user.id)
.execute();
// Clear session cookie
deleteCookie(context.resHeaders, COOKIE_NAMES.SESSION_TOKEN);
return { success: true };
});