style changes, and password login fix

This commit is contained in:
Michael Freno
2025-12-28 21:27:28 -05:00
parent 1ba20339a8
commit 4892dff38e
3 changed files with 130 additions and 25 deletions

View File

@@ -331,12 +331,12 @@ export default function LoginPage() {
<Show when={error()}> <Show when={error()}>
<div class="border-maroon bg-red mb-4 w-full max-w-md rounded-lg border px-4 py-3 text-center"> <div class="border-maroon bg-red mb-4 w-full max-w-md rounded-lg border px-4 py-3 text-center">
<Show when={error() === "passwordMismatch"}> <Show when={error() === "passwordMismatch"}>
<div class="text-red text-lg font-semibold"> <div class="text-base text-lg font-semibold">
Passwords did not match! Passwords did not match!
</div> </div>
</Show> </Show>
<Show when={error() === "duplicate"}> <Show when={error() === "duplicate"}>
<div class="text-red text-lg font-semibold"> <div class="text-base text-lg font-semibold">
Email Already Exists! Email Already Exists!
</div> </div>
</Show> </Show>
@@ -347,7 +347,7 @@ export default function LoginPage() {
error() !== "duplicate" error() !== "duplicate"
} }
> >
<div class="text-red text-sm">{error()}</div> <div class="text-base text-sm">{error()}</div>
</Show> </Show>
</div> </div>
</Show> </Show>

View File

@@ -851,19 +851,25 @@ export const authRouter = createTRPCRouter({
// Check all conditions after password verification // Check all conditions after password verification
if (!user || !passwordHash || !passwordMatch) { if (!user || !passwordHash || !passwordMatch) {
// Log failed login attempt // Log failed login attempt (wrap in try-catch to ensure it never blocks auth flow)
const { ipAddress, userAgent } = getAuditContext(ctx.event.nativeEvent); try {
await logAuditEvent({ const { ipAddress, userAgent } = getAuditContext(
eventType: "auth.login.failed", ctx.event.nativeEvent
eventData: { );
email, await logAuditEvent({
method: "password", eventType: "auth.login.failed",
reason: "invalid_credentials" eventData: {
}, email,
ipAddress, method: "password",
userAgent, reason: "invalid_credentials"
success: false },
}); ipAddress,
userAgent,
success: false
});
} catch (auditError) {
console.error("Audit logging failed:", auditError);
}
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -911,15 +917,19 @@ export const authRouter = createTRPCRouter({
// Set CSRF token for authenticated session // Set CSRF token for authenticated session
setCSRFToken(ctx.event.nativeEvent); setCSRFToken(ctx.event.nativeEvent);
// Log successful login // Log successful login (wrap in try-catch to ensure it never blocks auth flow)
await logAuditEvent({ try {
userId: user.id, await logAuditEvent({
eventType: "auth.login.success", userId: user.id,
eventData: { method: "password", rememberMe: rememberMe || false }, eventType: "auth.login.success",
ipAddress: clientIP, eventData: { method: "password", rememberMe: rememberMe || false },
userAgent, ipAddress: clientIP,
success: true userAgent,
}); success: true
});
} catch (auditError) {
console.error("Audit logging failed:", auditError);
}
return { success: true, message: "success" }; return { success: true, message: "success" };
}), }),

View File

@@ -0,0 +1,95 @@
/**
* Database Initialization for Audit Logging
* Run this script to create the AuditLog table in your database
*
* Usage: bun run src/server/init-audit-table.ts
*/
import { ConnectionFactory } from "./database";
async function initAuditTable() {
console.log("🔧 Initializing AuditLog table...");
try {
const conn = ConnectionFactory();
// Create AuditLog table
await conn.execute({
sql: `CREATE TABLE IF NOT EXISTS AuditLog (
id TEXT PRIMARY KEY,
user_id TEXT,
event_type TEXT NOT NULL,
event_data TEXT,
ip_address TEXT,
user_agent TEXT,
success INTEGER NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (user_id) REFERENCES User(id) ON DELETE SET NULL
)`
});
console.log("✅ AuditLog table created (or already exists)");
// Create indexes for performance
console.log("🔧 Creating indexes...");
await conn.execute({
sql: `CREATE INDEX IF NOT EXISTS idx_audit_user_id ON AuditLog(user_id)`
});
await conn.execute({
sql: `CREATE INDEX IF NOT EXISTS idx_audit_event_type ON AuditLog(event_type)`
});
await conn.execute({
sql: `CREATE INDEX IF NOT EXISTS idx_audit_created_at ON AuditLog(created_at)`
});
await conn.execute({
sql: `CREATE INDEX IF NOT EXISTS idx_audit_ip_address ON AuditLog(ip_address)`
});
console.log("✅ Indexes created");
// Verify table exists
const result = await conn.execute({
sql: `SELECT name FROM sqlite_master WHERE type='table' AND name='AuditLog'`
});
if (result.rows.length > 0) {
console.log("✅ AuditLog table verified - ready for use!");
// Check row count
const countResult = await conn.execute({
sql: `SELECT COUNT(*) as count FROM AuditLog`
});
console.log(
`📊 Current audit log entries: ${countResult.rows[0]?.count || 0}`
);
} else {
console.error("❌ AuditLog table was not created properly");
process.exit(1);
}
console.log("\n✅ Audit logging system is ready!");
console.log("💡 You can now use the audit logging features");
console.log("📖 See docs/AUDIT_LOGGING.md for usage examples\n");
} catch (error) {
console.error("❌ Failed to initialize AuditLog table:");
console.error(error);
process.exit(1);
}
}
// Run if executed directly
if (import.meta.main) {
initAuditTable()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
}
export { initAuditTable };