114 lines
2.5 KiB
TypeScript
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"],
|
|
},
|
|
}
|
|
);
|