Files
homaroma/apps/backend/src/routes/auth.ts
T

114 lines
2.5 KiB
TypeScript

import { Elysia, t } from "elysia";
import { jwt } from "@elysiajs/jwt";
import bcrypt from "bcryptjs";
import prisma from "../lib/prisma";
export const authRoute = new Elysia({ prefix: "/auth" })
.use(
jwt({
name: "jwt",
secret: process.env.JWT_SECRET || "homaroma_secret_2026_scent",
exp: "24h",
})
)
.post(
"/login",
async ({ body, jwt, set }) => {
const { username, password } = body;
// 1. Find user
const user = await prisma.user.findUnique({
where: { username },
});
if (!user) {
set.status = 401;
return { success: false, message: "Invalid credentials" };
}
// 2. Check password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
set.status = 401;
return { success: false, message: "Invalid credentials" };
}
// 3. Generate Token
const token = await jwt.sign({
id: user.id,
username: user.username,
role: user.role,
});
return {
success: true,
token,
user: {
id: user.id,
username: user.username,
role: user.role,
},
};
},
{
body: t.Object({
username: t.String(),
password: t.String(),
}),
detail: {
summary: "Admin Login",
tags: ["auth"],
},
}
)
.post(
"/line",
async ({ body, jwt, set }) => {
const { lineUserId, displayName, pictureUrl, email, phone } = body;
// Upsert Customer
const customer = await prisma.customer.upsert({
where: { lineUserId },
update: {
displayName,
pictureUrl,
...(email && { email }),
...(phone && { phone }),
},
create: {
lineUserId,
displayName,
pictureUrl,
email,
phone,
},
});
// Generate Token
const token = await jwt.sign({
id: customer.id,
lineUserId: customer.lineUserId,
role: "CUSTOMER",
});
return {
success: true,
token,
customer,
};
},
{
body: t.Object({
lineUserId: t.String(),
displayName: t.Optional(t.String()),
pictureUrl: t.Optional(t.String()),
email: t.Optional(t.String()),
phone: t.Optional(t.String()),
}),
detail: {
summary: "LINE Login for Customers",
tags: ["auth"],
},
}
);