Fix Session.id type and restore nested passkey routes
- Change Session.id from number to string to match DB bigint type
- Restore me.passkeys.{list,rename,delete} nested route structure
- Remove unnecessary String() conversion in logout procedure
- Auto-formatted procedure files
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -110,7 +110,11 @@ export const loginPassword = os.auth.loginPassword.handler(
|
||||
// Password is valid - check if device is trusted
|
||||
// If no device fingerprint, treat as untrusted
|
||||
const deviceTrusted = result.device_fingerprint
|
||||
? await isDeviceTrusted(context.db, result.user_id, result.device_fingerprint)
|
||||
? await isDeviceTrusted(
|
||||
context.db,
|
||||
result.user_id,
|
||||
result.device_fingerprint,
|
||||
)
|
||||
: false;
|
||||
|
||||
if (deviceTrusted) {
|
||||
|
||||
@@ -14,13 +14,13 @@ import { authMiddleware, os } from "../base.js";
|
||||
export const logout = os.auth.logout
|
||||
.use(authMiddleware)
|
||||
.handler(async ({ context }) => {
|
||||
// Revoke the current session
|
||||
await context.db
|
||||
.updateTable("sessions")
|
||||
.set({ revoked_at: new Date() })
|
||||
.where("id", "=", String(context.session.id))
|
||||
.execute();
|
||||
// Revoke the current session
|
||||
await context.db
|
||||
.updateTable("sessions")
|
||||
.set({ revoked_at: new Date() })
|
||||
.where("id", "=", context.session.id)
|
||||
.execute();
|
||||
|
||||
// Clear the session cookie
|
||||
deleteCookie(context.resHeaders, COOKIE_NAMES.SESSION_TOKEN);
|
||||
});
|
||||
// Clear the session cookie
|
||||
deleteCookie(context.resHeaders, COOKIE_NAMES.SESSION_TOKEN);
|
||||
});
|
||||
|
||||
@@ -18,32 +18,32 @@ import { authMiddleware, os } from "../base.js";
|
||||
export const resendVerificationEmail = os.auth.resendVerificationEmail
|
||||
.use(authMiddleware)
|
||||
.handler(async ({ context }) => {
|
||||
// Check if email is already verified
|
||||
if (context.user.emailVerifiedAt !== null) {
|
||||
// Email already verified, return early
|
||||
return;
|
||||
}
|
||||
// Check if email is already verified
|
||||
if (context.user.emailVerifiedAt !== null) {
|
||||
// Email already verified, return early
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete any existing verification tokens for this user
|
||||
await context.db
|
||||
.deleteFrom("email_verifications")
|
||||
.where("user_id", "=", context.user.id)
|
||||
.execute();
|
||||
// Delete any existing verification tokens for this user
|
||||
await context.db
|
||||
.deleteFrom("email_verifications")
|
||||
.where("user_id", "=", context.user.id)
|
||||
.execute();
|
||||
|
||||
// Generate new secure token
|
||||
const token = generateSecureToken();
|
||||
const expiresAt = generateExpiry(TOKEN_DURATIONS.EMAIL_VERIFICATION);
|
||||
// Generate new secure token
|
||||
const token = generateSecureToken();
|
||||
const expiresAt = generateExpiry(TOKEN_DURATIONS.EMAIL_VERIFICATION);
|
||||
|
||||
// Create new verification record
|
||||
await context.db
|
||||
.insertInto("email_verifications")
|
||||
.values({
|
||||
user_id: context.user.id,
|
||||
token,
|
||||
expires_at: expiresAt,
|
||||
})
|
||||
.execute();
|
||||
// Create new verification record
|
||||
await context.db
|
||||
.insertInto("email_verifications")
|
||||
.values({
|
||||
user_id: context.user.id,
|
||||
token,
|
||||
expires_at: expiresAt,
|
||||
})
|
||||
.execute();
|
||||
|
||||
// Send verification email (stubbed)
|
||||
await sendVerificationEmail(context.user.email, token);
|
||||
});
|
||||
// Send verification email (stubbed)
|
||||
await sendVerificationEmail(context.user.email, token);
|
||||
});
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
* Signup procedure - creates a new user account with email + password or passkey
|
||||
*/
|
||||
|
||||
import type { DB } from "@reviq/db-schema";
|
||||
import type {
|
||||
PublicKeyCredentialCreationOptionsJSON,
|
||||
RegistrationResponseJSON,
|
||||
} from "@simplewebauthn/types";
|
||||
import type { Kysely } from "kysely";
|
||||
import type { DB } from "@reviq/db-schema";
|
||||
import type { RPInfo } from "../../utils/webauthn.js";
|
||||
import { ORPCError } from "@orpc/server";
|
||||
import { verifyRegistrationResponse } from "@simplewebauthn/server";
|
||||
import { os } from "../base.js";
|
||||
import {
|
||||
COOKIE_NAMES,
|
||||
COOKIE_OPTIONS,
|
||||
@@ -24,6 +23,7 @@ import { getGeoInfo, getUserAgent } from "../../utils/geo.js";
|
||||
import { hashPassword, validatePassword } from "../../utils/password.js";
|
||||
import { createSession } from "../../utils/session.js";
|
||||
import { getRPInfo, KNOWN_AAGUIDS } from "../../utils/webauthn.js";
|
||||
import { os } from "../base.js";
|
||||
|
||||
/**
|
||||
* Create user with password authentication
|
||||
@@ -231,7 +231,11 @@ export const signup = os.auth.signup.handler(async ({ input, context }) => {
|
||||
if (password) {
|
||||
userId = await signupWithPassword(context.db, email, password);
|
||||
} else if (passkeyInfo) {
|
||||
const rpInfo = getRPInfo(context.origin, context.allowedOrigins, context.rpName);
|
||||
const rpInfo = getRPInfo(
|
||||
context.origin,
|
||||
context.allowedOrigins,
|
||||
context.rpName,
|
||||
);
|
||||
userId = await signupWithPasskey(context.db, email, passkeyInfo, rpInfo);
|
||||
} else {
|
||||
// Should never reach here due to schema validation
|
||||
|
||||
Reference in New Issue
Block a user