feat: 구매/안전 시스템 전면 개편 — tkpurchase 개편 + tksafety 신규 + 권한 보강
Phase 1: tkuser 협력업체 CRUD 이관 (읽기전용 → 전체 CRUD) Phase 2: tkpurchase 개편 — 일용공 신청/확정, 작업일정, 업무현황, 계정관리, 협력업체 포털 Phase 3: tksafety 신규 시스템 — 방문관리 + 안전교육 신고 Phase 4: SSO 인증 보강 (partner_company_id JWT, 만료일 체크), 권한 테이블 기반 접근 제어 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,7 @@ function createTokenPayload(user) {
|
||||
role: user.role,
|
||||
access_level: user.role,
|
||||
sub: user.username,
|
||||
partner_company_id: user.partner_company_id || null,
|
||||
system_access: {
|
||||
system1: user.system1_access,
|
||||
system2: user.system2_access,
|
||||
@@ -65,6 +66,11 @@ async function login(req, res, next) {
|
||||
return res.status(401).json({ success: false, error: '사용자명 또는 비밀번호가 올바르지 않습니다' });
|
||||
}
|
||||
|
||||
// 협력업체 계정 만료일 체크
|
||||
if (user.account_expires_at && new Date(user.account_expires_at) < new Date()) {
|
||||
return res.status(401).json({ success: false, error: '계정이 만료되었습니다. 관리자에게 문의하세요.' });
|
||||
}
|
||||
|
||||
const valid = await userModel.verifyPassword(password, user.password_hash);
|
||||
if (!valid) {
|
||||
await redis.incr(attemptKey);
|
||||
@@ -126,6 +132,11 @@ async function loginForm(req, res, next) {
|
||||
return res.status(401).json({ detail: 'Incorrect username or password' });
|
||||
}
|
||||
|
||||
// 협력업체 계정 만료일 체크
|
||||
if (user.account_expires_at && new Date(user.account_expires_at) < new Date()) {
|
||||
return res.status(401).json({ detail: '계정이 만료되었습니다' });
|
||||
}
|
||||
|
||||
const valid = await userModel.verifyPassword(password, user.password_hash);
|
||||
if (!valid) {
|
||||
return res.status(401).json({ detail: 'Incorrect username or password' });
|
||||
|
||||
Reference in New Issue
Block a user