auto commit
This commit is contained in:
parent
35e2a31442
commit
f03a9209ea
@ -34,4 +34,33 @@ router.post("/logout", authMiddleware, async (req, res, next) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.post(
|
||||
"/edge-login",
|
||||
[
|
||||
body("username").notEmpty().withMessage("Username is required"),
|
||||
body("password").notEmpty().withMessage("Password is required"),
|
||||
body("businessNumber")
|
||||
.notEmpty()
|
||||
.withMessage("Business number is required")
|
||||
.matches(/^[0-9-]{10,20}$/)
|
||||
.withMessage("Invalid business number format"),
|
||||
validate,
|
||||
],
|
||||
async (req, res, next) => {
|
||||
try {
|
||||
const { username, password, businessNumber } = req.body;
|
||||
const result = await authService.edgeLogin(
|
||||
username,
|
||||
password,
|
||||
businessNumber,
|
||||
req.ip,
|
||||
req.headers["user-agent"]
|
||||
);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = router;
|
||||
|
@ -79,6 +79,111 @@ class AuthService {
|
||||
};
|
||||
}
|
||||
|
||||
async edgeLogin(username, password, businessNumber, ipAddress, userAgent) {
|
||||
// 1. 먼저 회사 검증
|
||||
const company = await Company.findOne({
|
||||
where: {
|
||||
businessNumber,
|
||||
isActive: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!company) {
|
||||
throw new Error("Invalid business number or company not found");
|
||||
}
|
||||
|
||||
// 2. 사용자 검증
|
||||
const userWithPassword = await User.findOne({
|
||||
where: {
|
||||
username,
|
||||
companyId: company.id,
|
||||
isActive: true,
|
||||
},
|
||||
attributes: ["id", "password", "isActive"],
|
||||
});
|
||||
|
||||
if (!userWithPassword) {
|
||||
await this._logAuthAttempt(
|
||||
null,
|
||||
"edge_failed_login",
|
||||
ipAddress,
|
||||
userAgent,
|
||||
businessNumber
|
||||
);
|
||||
throw new Error("Invalid credentials");
|
||||
}
|
||||
|
||||
// 3. 비밀번호 검증
|
||||
const isValidPassword = await userWithPassword.validatePassword(password);
|
||||
if (!isValidPassword) {
|
||||
await this._logAuthAttempt(
|
||||
userWithPassword.id,
|
||||
"edge_failed_login",
|
||||
ipAddress,
|
||||
userAgent,
|
||||
businessNumber
|
||||
);
|
||||
throw new Error("Invalid credentials");
|
||||
}
|
||||
|
||||
// 4. 사용자 정보 조회 (상세 정보)
|
||||
const user = await User.findOne({
|
||||
where: { id: userWithPassword.id },
|
||||
include: [
|
||||
{
|
||||
model: Company,
|
||||
attributes: ["id", "name", "businessNumber"],
|
||||
where: { isActive: true }, // 활성화된 회사만
|
||||
},
|
||||
{
|
||||
model: Branch,
|
||||
attributes: ["id", "name"],
|
||||
},
|
||||
{
|
||||
model: Role,
|
||||
through: { attributes: [] },
|
||||
attributes: ["id", "name", "permissions"],
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
attributes: {
|
||||
exclude: ["password"],
|
||||
},
|
||||
});
|
||||
|
||||
// 5. 마지막 로그인 시간 업데이트
|
||||
await User.update({ lastLoginAt: new Date() }, { where: { id: user.id } });
|
||||
|
||||
// 6. 로그인 기록
|
||||
await this._logAuthAttempt(
|
||||
user.id,
|
||||
"edge_login",
|
||||
ipAddress,
|
||||
userAgent,
|
||||
businessNumber
|
||||
);
|
||||
|
||||
// 7. 권한 정보 처리
|
||||
const permissions = this._processPermissions(user.Roles || []);
|
||||
|
||||
// 8. 응답 데이터 구성
|
||||
const userData = user.toJSON();
|
||||
delete userData.Roles;
|
||||
|
||||
const userInfo = {
|
||||
...userData,
|
||||
permissions,
|
||||
isEdgeLogin: true, // Edge 로그인 여부 표시
|
||||
};
|
||||
|
||||
const token = this._generateToken(userInfo);
|
||||
|
||||
return {
|
||||
token,
|
||||
user: userInfo,
|
||||
};
|
||||
}
|
||||
|
||||
_processPermissions(roles) {
|
||||
// 기본 권한 설정 (모든 사용자가 가져야 할 기본 권한)
|
||||
const permissions = {
|
||||
@ -101,7 +206,13 @@ class AuthService {
|
||||
return true;
|
||||
}
|
||||
|
||||
async _logAuthAttempt(userId, action, ipAddress, userAgent) {
|
||||
async _logAuthAttempt(
|
||||
userId,
|
||||
action,
|
||||
ipAddress,
|
||||
userAgent,
|
||||
businessNumber = null
|
||||
) {
|
||||
if (userId) {
|
||||
// userId가 있을 때만 로그 생성
|
||||
await AuthLog.create({
|
||||
@ -109,6 +220,7 @@ class AuthService {
|
||||
action,
|
||||
ipAddress,
|
||||
userAgent,
|
||||
metadata: businessNumber ? { businessNumber } : null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ const AdminLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<AdminGuard>
|
||||
<div className="h-screen flex">
|
||||
{/* 왼쪽 사이드바 */}
|
||||
<aside className="w-64 h-screen flex-shrink-0 bg-gray-800">
|
||||
<SideNav />
|
||||
</aside>
|
||||
|
@ -1,7 +1,8 @@
|
||||
// src/middleware.ts
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { decodeToken, hasPermission, hasAnyPermission } from "@/lib/jwt";
|
||||
// import { decodeToken, hasPermission, hasAnyPermission } from "@/lib/jwt";
|
||||
import { decodeToken, hasPermission } from "@/lib/jwt";
|
||||
|
||||
export function middleware(request: NextRequest) {
|
||||
const token = request.cookies.get("token")?.value;
|
||||
@ -37,29 +38,29 @@ export function middleware(request: NextRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
// 사용자 관리 페이지
|
||||
if (request.nextUrl.pathname.startsWith("/users")) {
|
||||
const hasUserManageAccess = hasAnyPermission(tokenData, [
|
||||
"users:manage",
|
||||
"users:view",
|
||||
]);
|
||||
// // 사용자 관리 페이지
|
||||
// if (request.nextUrl.pathname.startsWith("/users")) {
|
||||
// const hasUserManageAccess = hasAnyPermission(tokenData, [
|
||||
// "users:manage",
|
||||
// "users:view",
|
||||
// ]);
|
||||
|
||||
if (!hasUserManageAccess) {
|
||||
return NextResponse.redirect(new URL("/dashboard/overview", request.url));
|
||||
}
|
||||
}
|
||||
// if (!hasUserManageAccess) {
|
||||
// return NextResponse.redirect(new URL("/dashboard/overview", request.url));
|
||||
// }
|
||||
// }
|
||||
|
||||
// 부서 관리 페이지
|
||||
if (request.nextUrl.pathname.startsWith("/departments")) {
|
||||
const hasDepartmentAccess = hasAnyPermission(tokenData, [
|
||||
"departments:manage",
|
||||
"departments:view",
|
||||
]);
|
||||
// // 부서 관리 페이지
|
||||
// if (request.nextUrl.pathname.startsWith("/departments")) {
|
||||
// const hasDepartmentAccess = hasAnyPermission(tokenData, [
|
||||
// "departments:manage",
|
||||
// "departments:view",
|
||||
// ]);
|
||||
|
||||
if (!hasDepartmentAccess) {
|
||||
return NextResponse.redirect(new URL("/dashboard/overview", request.url));
|
||||
}
|
||||
}
|
||||
// if (!hasDepartmentAccess) {
|
||||
// return NextResponse.redirect(new URL("/dashboard/overview", request.url));
|
||||
// }
|
||||
// }
|
||||
|
||||
// 응답 헤더에 사용자 권한 정보 추가 (옵션)
|
||||
const response = NextResponse.next();
|
||||
|
Loading…
Reference in New Issue
Block a user