11
This commit is contained in:
parent
9de2286eff
commit
bf829f01fe
fems-api/src
fems-app/src
@ -65,10 +65,14 @@ class AuthService {
|
|||||||
|
|
||||||
// 사용자 정보에서 Roles 배열을 제거하고 가공된 권한 정보를 추가
|
// 사용자 정보에서 Roles 배열을 제거하고 가공된 권한 정보를 추가
|
||||||
const userData = user.toJSON();
|
const userData = user.toJSON();
|
||||||
|
const companyData = userData.Company || {};
|
||||||
delete userData.Roles;
|
delete userData.Roles;
|
||||||
|
|
||||||
const userInfo = {
|
const userInfo = {
|
||||||
...userData,
|
...userData,
|
||||||
|
companyName: companyData.name,
|
||||||
|
businessNumber: companyData.businessNumber,
|
||||||
|
contractEndDate: companyData.contractEndDate,
|
||||||
permissions,
|
permissions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ const { logCreatedAccounts } = require("./initialSetup/loggingSetup");
|
|||||||
|
|
||||||
// 상수로 정의하여 일관성 유지
|
// 상수로 정의하여 일관성 유지
|
||||||
const ADMIN_COMPANY = {
|
const ADMIN_COMPANY = {
|
||||||
BUSINESS_NUMBER: 4397802852, // 올바른 번호로 수정
|
BUSINESS_NUMBER: 4398702852, // 올바른 번호로 수정
|
||||||
NAME: "FEMS 관리자",
|
NAME: "(주)웨이스",
|
||||||
ADDRESS: "서울시 강남구",
|
ADDRESS: "서울시 강남구",
|
||||||
TEL: "02-0000-0000",
|
TEL: "02-0000-0000",
|
||||||
EMAIL: "admin@fems.com",
|
EMAIL: "admin@fems.com",
|
||||||
|
@ -27,7 +27,6 @@ import {
|
|||||||
Target,
|
Target,
|
||||||
Brain,
|
Brain,
|
||||||
Sliders,
|
Sliders,
|
||||||
Building2,
|
|
||||||
Users,
|
Users,
|
||||||
HelpCircle,
|
HelpCircle,
|
||||||
MessageSquare,
|
MessageSquare,
|
||||||
@ -35,6 +34,8 @@ import {
|
|||||||
ChevronDown,
|
ChevronDown,
|
||||||
ChevronRight,
|
ChevronRight,
|
||||||
Puzzle,
|
Puzzle,
|
||||||
|
Building2,
|
||||||
|
Calendar,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
@ -288,8 +289,24 @@ export function SideNav() {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 날짜 포맷팅 함수
|
||||||
|
const formatDate = (dateString: string) => {
|
||||||
|
return new Date(dateString).toLocaleDateString("ko-KR", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "long",
|
||||||
|
day: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 사업자번호 포맷팅 함수
|
||||||
|
const formatBusinessNumber = (number: string) => {
|
||||||
|
if (!number) return "";
|
||||||
|
const cleaned = number.replace(/[^0-9]/g, "");
|
||||||
|
return `${cleaned.slice(0, 3)}-${cleaned.slice(3, 5)}-${cleaned.slice(5)}`;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="w-64 bg-white border-r border-gray-200 h-screen overflow-y-auto">
|
<nav className="w-64 bg-white border-r border-gray-200 h-screen flex flex-col">
|
||||||
<div className="sticky top-0 z-10 bg-white p-4 border-b border-gray-200">
|
<div className="sticky top-0 z-10 bg-white p-4 border-b border-gray-200">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Gauge className="h-8 w-6 text-blue-600" />
|
<Gauge className="h-8 w-6 text-blue-600" />
|
||||||
@ -297,7 +314,7 @@ export function SideNav() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-3">
|
<div className="flex-1 overflow-y-auto p-3">
|
||||||
{menuItems.map((item) => (
|
{menuItems.map((item) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={item.title}
|
key={item.title}
|
||||||
@ -308,6 +325,35 @@ export function SideNav() {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 회사 정보 카드 - 항상 하단에 고정 */}
|
||||||
|
<div className="mt-auto border-t border-gray-200 p-4">
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex items-start space-x-3">
|
||||||
|
<Building2 className="h-5 w-5 text-gray-500 mt-0.5" />
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="text-sm font-medium text-gray-900">
|
||||||
|
{user?.companyName}
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-gray-500">
|
||||||
|
사업자번호: {formatBusinessNumber(user?.businessNumber || "")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<Calendar className="h-5 w-5 text-gray-500" />
|
||||||
|
<div className="flex-1">
|
||||||
|
<p className="text-xs text-gray-500">계약 만료일:</p>
|
||||||
|
<p className="text-sm font-medium text-gray-900">
|
||||||
|
{user?.contractEndDate
|
||||||
|
? formatDate(user.contractEndDate)
|
||||||
|
: "정보 없음"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ interface JwtPayload {
|
|||||||
id: string;
|
id: string;
|
||||||
role: UserRole;
|
role: UserRole;
|
||||||
companyId: string;
|
companyId: string;
|
||||||
|
companyName?: string;
|
||||||
|
businessNumber?: string;
|
||||||
|
contractEndDate?: string;
|
||||||
branchId?: string;
|
branchId?: string;
|
||||||
permissions: Permissions; // 권한 정보 추가
|
permissions: Permissions; // 권한 정보 추가
|
||||||
}
|
}
|
||||||
@ -30,6 +33,9 @@ export function decodeToken(token: string): JwtPayload | null {
|
|||||||
id: payload.id,
|
id: payload.id,
|
||||||
role: payload.role,
|
role: payload.role,
|
||||||
companyId: payload.companyId,
|
companyId: payload.companyId,
|
||||||
|
companyName: payload.companyName,
|
||||||
|
businessNumber: payload.businessNumber,
|
||||||
|
contractEndDate: payload.contractEndDate,
|
||||||
branchId: payload.branchId,
|
branchId: payload.branchId,
|
||||||
permissions: payload.permissions,
|
permissions: payload.permissions,
|
||||||
};
|
};
|
||||||
|
@ -4,14 +4,27 @@ 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";
|
import { decodeToken, hasPermission } from "@/lib/jwt";
|
||||||
|
|
||||||
|
// 인증이 필요없는 public 라우트 정의
|
||||||
|
const PUBLIC_ROUTES = ["/", "/login"];
|
||||||
|
|
||||||
export function middleware(request: NextRequest) {
|
export function middleware(request: NextRequest) {
|
||||||
const token = request.cookies.get("token")?.value;
|
const token = request.cookies.get("token")?.value;
|
||||||
|
const { pathname } = request.nextUrl;
|
||||||
|
|
||||||
// Public routes
|
// // Public routes
|
||||||
if (
|
// if (
|
||||||
request.nextUrl.pathname === "/" ||
|
// request.nextUrl.pathname === "/" ||
|
||||||
request.nextUrl.pathname === "/login"
|
// request.nextUrl.pathname === "/login"
|
||||||
) {
|
// ) {
|
||||||
|
// return NextResponse.next();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Public routes 체크
|
||||||
|
if (PUBLIC_ROUTES.includes(pathname)) {
|
||||||
|
// 이미 로그인된 사용자가 렌딩(로그인) 페이지 접근 시 dashboard로 리다이렉트
|
||||||
|
if (token && pathname === "/") {
|
||||||
|
return NextResponse.redirect(new URL("/dashboard/overview", request.url));
|
||||||
|
}
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,9 @@ export interface User {
|
|||||||
email: string;
|
email: string;
|
||||||
role: UserRole;
|
role: UserRole;
|
||||||
companyId: string;
|
companyId: string;
|
||||||
|
companyName: string;
|
||||||
|
businessNumber: string;
|
||||||
|
contractEndDate: string;
|
||||||
branchId?: string;
|
branchId?: string;
|
||||||
permissions: Permissions; // 권한 정보 추가
|
permissions: Permissions; // 권한 정보 추가
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@ export interface User {
|
|||||||
role: string;
|
role: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
companyId?: string;
|
companyId?: string;
|
||||||
|
companyName: string;
|
||||||
|
businessNumber: string;
|
||||||
|
contractEndDate: string;
|
||||||
branchId?: string;
|
branchId?: string;
|
||||||
departmentId?: string;
|
departmentId?: string;
|
||||||
roleId?: string;
|
roleId?: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user