spb/vquant Public MIT
VibeQuant — AI-powered institutional-grade financial intelligence platform.
TypeScript 84.3%
Python 11.7%
JavaScript 1.6%
CSS 1.5%
HTML 0.7%
1/*2 * =============================================================================3 * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform4 * -----------------------------------------------------------------------------5 * File: server/routes/auth.ts6 *7 * Author: Simon-Pierre Boucher8 * Contact: contact@spboucher.ai9 * Website: https://www.spboucher.ai10 * Demo: https://www.vquant.ai11 * License: MIT (see LICENSE)12 *13 * Copyright © 2026 Simon-Pierre Boucher. All rights reserved.14 * =============================================================================15 */1617import type { Express, Request, Response } from "express";18import { randomBytes } from "crypto";19import { storage } from "../storage";20import { logger } from "../utils/logger";21import { registerBodySchema, loginBodySchema } from "./validation";2223export function registerAuthRoutes(app: Express) {24 // Register25 app.post("/api/auth/register", async (req: Request, res: Response) => {26 try {27 const parsed = registerBodySchema.safeParse(req.body);28 if (!parsed.success) {29 return res.status(400).json({ error: parsed.error.issues[0].message });30 }3132 const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';33 const bytes = randomBytes(7);34 let tokenSuffix = '';35 for (let i = 0; i < 7; i++) {36 tokenSuffix += chars[bytes[i] % chars.length];37 }38 const token = `vquant-${tokenSuffix}`;3940 const user = await storage.createUser({41 displayName: parsed.data.name.trim(),42 token,43 });4445 (req.session as any).userId = user.id;4647 res.json({48 user: { id: user.id, displayName: user.displayName },49 token,50 });51 } catch (error) {52 logger.error(`Register error: ${(error as Error).message}`);53 res.status(500).json({ error: "Failed to create account" });54 }55 });5657 // Login58 app.post("/api/auth/login", async (req: Request, res: Response) => {59 try {60 const parsed = loginBodySchema.safeParse(req.body);61 if (!parsed.success) {62 return res.status(400).json({ error: parsed.error.issues[0].message });63 }6465 const user = await storage.getUserByToken(parsed.data.token.trim());66 if (!user) {67 return res.status(401).json({ error: "Token invalide" });68 }6970 (req.session as any).userId = user.id;7172 res.json({73 user: { id: user.id, displayName: user.displayName },74 });75 } catch (error) {76 logger.error(`Login error: ${(error as Error).message}`);77 res.status(500).json({ error: "Failed to login" });78 }79 });8081 // Logout82 app.post("/api/auth/logout", async (req: Request, res: Response) => {83 req.session.destroy((err) => {84 if (err) {85 logger.error(`Logout error: ${err.message}`);86 return res.status(500).json({ error: "Failed to logout" });87 }88 res.json({ success: true });89 });90 });9192 // Get current user93 app.get("/api/auth/me", async (req: Request, res: Response) => {94 try {95 const userId = (req.session as any).userId;96 if (!userId) return res.json({ user: null });9798 const user = await storage.getUser(userId);99 if (!user) return res.json({ user: null });100101 res.json({102 user: { id: user.id, displayName: user.displayName },103 });104 } catch (error) {105 logger.error(`Get user error: ${(error as Error).message}`);106 res.status(500).json({ error: "Failed to get user" });107 }108 });109}110