Files
Xu_BrowserBookmark/apps/server/src/routes/auth.routes.js

61 lines
2.0 KiB
JavaScript
Raw Normal View History

2026-01-18 10:35:27 +08:00
import { hashPassword, verifyPassword } from "../lib/auth.js";
import { httpError } from "../lib/httpErrors.js";
import { userRowToDto } from "../lib/rows.js";
export async function authRoutes(app) {
app.post("/auth/register", async (req) => {
const { email, password } = req.body || {};
if (!email || !password) throw httpError(400, "email and password required");
if (String(password).length < 8) throw httpError(400, "password too short");
const passwordHash = await hashPassword(password);
try {
const res = await app.pg.query(
"insert into users (email, password_hash) values ($1, $2) returning id, email, role, created_at, updated_at",
[email, passwordHash]
);
const user = userRowToDto(res.rows[0]);
const token = await app.jwt.sign({ sub: user.id, role: user.role });
return { token, user };
} catch (err) {
if (String(err?.code) === "23505") throw httpError(409, "email already exists");
throw err;
}
});
app.post("/auth/login", async (req) => {
const { email, password } = req.body || {};
if (!email || !password) throw httpError(400, "email and password required");
const res = await app.pg.query(
"select id, email, role, password_hash, created_at, updated_at from users where email=$1",
[email]
);
const row = res.rows[0];
if (!row) throw httpError(401, "invalid credentials");
const ok = await verifyPassword(password, row.password_hash);
if (!ok) throw httpError(401, "invalid credentials");
const user = userRowToDto(row);
const token = await app.jwt.sign({ sub: user.id, role: user.role });
return { token, user };
});
app.get(
"/auth/me",
{ preHandler: [app.authenticate] },
async (req) => {
const userId = req.user.sub;
const res = await app.pg.query(
"select id, email, role, created_at, updated_at from users where id=$1",
[userId]
);
const row = res.rows[0];
if (!row) throw httpError(404, "user not found");
return userRowToDto(row);
}
);
}