const passport = require('passport'); const pool = require('../db/pool.js'); const env = process.env.NODE_ENV; const tbProject = env === 'production' ? 'tb_project' : '_test_tb_project'; const tbPermission = env === 'production' ? 'tb_permission' : '_test_tb_permission'; //////// pm-bcmf 연결용 테스트 코드 - pm-bcmf url에 담겨있던 쿼리 정보 저장, 조회 let bcmfId, startPath; exports.setBcmfUrlQuery = async (req,res)=>{ bcmfId = req.body.id; startPath = req.body.startPath; } exports.getBcmfUrlQuery = async (req,res)=>{ res.status(200).json({ bcmfId: bcmfId, startPath: startPath }); } exports.getBcmfId = () => { return bcmfId; } // passport.initialize()와 passport.session()를 추가해야 req.isAuthenticated() 함수를 사용할 수 있음. exports.isLoggedIn = async(req,res,next)=>{ if (req.isAuthenticated()) { // 패스포트를 통해 로그인 했는지를 확인 console.log('🚥 [authController] isLoggedIn? : ture'); next(); } else { // 1) 주소를 요청: http://localhost:3000/zip/status/?url=a.glb&url=b.glb // 2) 로그인 페이지(html)로 이동(쿼리스트링으로 path에 주소 넣음): http://localhost:3000/login?path=/zip/status/?url=a.glb&url=b.glb // 3) 로그인 이후 원래 주소로 이동: http://localhost:3000/zip/status/?url=a.glb&url=b.glb console.log('🚥 [authController] isLoggedIn? : false'); res.redirect('/user/login?path='+req.originalUrl);//=> 로그인X인경우 이동할 페이지 } } exports.isNotLoggedIn = async(req,res,next)=>{ if(!req.isAuthenticated()){ console.log('🚥 [authController] isNotLoggedIn? : true'); next(); }else{ console.log('🚥 [authController] isNotLoggedIn? : false'); // const html = ` // // //

로그인을 이미 했습니다

// 로그아웃 //
// index 화면으로 이동 // // // `; // res.send(html); // res.status(200).json({redirect : req.}) next();//로그인 상태에서 로그인 요청 시 그냥 로그인 절차 밟도록 수정 } } exports.login =async(req,res,next)=>{ //진입 시도페이지로 다시 보내기위한 쿼리 const newQuery = req.query.path ? decodeURIComponent(req.query.path) : '/'; console.log('🌏 [authController.js] newQuery :', newQuery); //서비스 이름 넣기 // req.body.service = 'PM_ver4'; req.body.service = process.env.SERVICE_NAME +' - ' + req.headers['origin']; // 접근 아이피 넣기 /** * cf-connecting-ip: Cloudflare가 원본 클라이언트 IP를 전달하는 헤더 * x-forwarded-for: 일반적인 프록시 체인 헤더 * req.ip: Express가 계산한 IP (trust proxy 설정 시 의미 있음) * remoteAddress: 실제 TCP 연결의 IP */ req.body.user_ip = req.headers['cf-connecting-ip'] || req.ip || req.headers['x-forwarded-for'] || req.connection.remoteAddress; if (req.body.startPath) req.session.startPath = req.body.startPath; passport.authenticate('local', (authError, user, info)=>{ if(authError){ console.error(authError); return next(authError); } if(!user){ return res.json({error:info.message}); } return req.login(user, async (loginError)=>{ //로그인 후 행위등록 - ex log추가... if(loginError){ console.error(loginError); return next(loginError); } return res.json({redirect:newQuery, user:user}); }); }) (req,res,next); } exports.logout = async (req,res,next)=>{ //////// pm-bcmf 연결용 테스트 코드 - 로그아웃할 때 bcmfId, startPath 초기화 bcmfId = undefined; startPath = undefined; req.logout(()=>{ //기본페이지로 redirect // res.redirect('/user/login'); res.redirect('/user/login?path=/'); }) } //로그인 상태 확인 exports.status = async(req,res,next)=>{ if(req.user){ const client = await pool.connect(); try{ if(!req.user.permission || req.user.permission ==null){ let {project_id} = req.query; if (project_id && project_id !== 'undefined' && project_id !== 'null') { let queryString = ` select case when exists (select 1 from ver4.${tbProject} where project_id = '${project_id}' and user_id = '${req.user.user_id}') then 255 else ( select lev from ver4.${tbPermission} where project_id = '${project_id}' and user_id = '${req.user.user_id}' ) end as lev `; let {rows} = await client.query(queryString); req.user.permission = rows[0]?.lev || null; } else { req.user.permission = null; } } let queryString2 = `select bookmark from ver4.tb_user where user_id = '${req.user.user_id}'`; let bookmarkRes = await client.query(queryString2); req.user.bookmark = bookmarkRes.rows[0]?.bookmark || ''; req.user.user_pw = undefined; res.json({loggedIn : true, user : req.user}); }catch(err){ console.error('🚨 [authController.status] Error:', err); res.status(500).json({loggedIn : false, error: err.message}); }finally{ client.release(); } }else{ res.json({loggedIn : false}); } } //권한 설정 관련 // 권한 부여용 멤버 가져오기 exports.getMemberList = async (req,res,next)=>{ let {project_id} = req.query; const client = await pool.connect(); try{ let queryString = `select user_id, user_nm, company, dept, position from ver4.tb_user where ("group" is null or "group" = '') and is_resigned = false order by user_nm asc`; let {rows} = await client.query(queryString); let permissionQuery = `select user_id, CASE lev WHEN 191 THEN 'sub-master' WHEN 15 THEN 'security-worker' WHEN 7 THEN 'worker' WHEN 3 THEN 'uploader' WHEN 1 THEN 'viewer' END as lev from ver4.${tbPermission} where project_id = $1`; let permissionRes = await client.query(permissionQuery, [project_id]); res.status(200).json({all : rows, permission : permissionRes.rows}); }catch(err){ console.error(err); }finally{ client.release(); } } //권한 수정(json Array 로 받아서 parse후 처리) /* project_id : 단일, a_per, target_id, target_name : 배열 */ exports.upsertPermission = async(req, res, next)=>{ let {project_id , targetArr, userInfoString } = req.body; // let actor_user_id = req.user.user_id; // let user_nm = req.user.user_nm; // let activity_id = 'addUserPermission'; // let dateNow = makePostgresTimestamp(Date.now()); let userIp = req.ip; const client = await pool.connect(); try{ let queryString = `insert into ver4.${tbPermission} (user_id, project_id, lev) values `; for(let i = 0; i < targetArr.length; i++){ queryString += ` ('${targetArr[i].user_id}','${project_id}',${getPermissionLev(targetArr[i].lev)})${(i==targetArr.length-1)?'':','} `; } queryString += `on conflict (user_id, project_id) do update set lev = EXCLUDED.lev RETURNING *`; let upsertRes = await client.query(queryString); if(upsertRes.rows.length == targetArr.length){// 권한 부여 성공 // 유저권한 renderlog code let group = {}; for (const user of targetArr){ if(!group[user.lev]) group[user.lev] = {lev: user.lev, before: user.before , userIds: [], names : []} group[user.lev].userIds.push(user.user_id); group[user.lev].names.push(user.user_nm); } const permissionArr = Object.values(group); const levMap = { 'sub-master' : 'addPermission_subMaster', 'security-worker' : 'addPermission_securityWorker'}; // 로그를 담기 위한 배열 const logs = []; for (const p of permissionArr){ let activity = levMap[p.lev] || `addPermission_${p.lev}` let params = { projectId : project_id, activity, userInfoString, userIp, resourcePathArr: p.names, dataIdArr: p.userIds} logs.push(params) }; // upsert success와 함께 logs 배열 res res.status(200).json({message : 'upsert success', logs}); }else{ res.status(500).json({message : 'upsert error'}); } }catch(err){ console.error(err); res.status(500).json({message : 'upsert error'}); }finally{ client.release(); } } //권한 삭제 exports.deletePermission = async(req, res, next)=>{ let {project_id, targetArr, userInfoString} = req.body; let userIp = req.ip; const client = await pool.connect(); try{ const conditions = targetArr.map((item, index) => { return `(project_id = $1 AND user_id = $${index + 2})`; }).join(' OR '); let queryString = `DELETE FROM ver4.${tbPermission} WHERE ${conditions} RETURNING *`; const params = [project_id, ...targetArr.map(item => item.user_id)]; let deleteRes = await client.query(queryString, params); if(deleteRes.rows.length == targetArr.length){ //delete 성공 // 유저권한 renderlog code let group = {}; for(const user of targetArr){ // 권한 삭제 경우 기존 권한 before를 바탕으로 로그에 넣어준다. if(!group[user.before]) group[user.before] = {lev: user.before, before: user.lev, userIds: [], names: []}; group[user.before].userIds.push(user.user_id); group[user.before].names.push(user.user_nm); } const permissionArr = Object.values(group); const levMap = { 'sub-master' : 'deletePermission_subMaster', 'security-worker' : 'deletePermission_securityWorker'} // 로그를 담기 위한 배열 const logs = []; for (const p of permissionArr){ let activity = levMap[p.lev] || `deletePermission_${p.lev}` let params = {projectId : project_id , activity, userInfoString, userIp, resourcePathArr : p.names, dataIdArr : p.userIds} logs.push(params); }; // delete success와 함께 logs 배열 res res.status(200).json({message : 'delete success', logs}); }else{//delete 실패 res.status(500).json({message : 'delete error'}); } }catch(err){ console.error(err); }finally{ client.release(); } } // 회사-부서 목록 exports.getDeptList = async (req, res, next) => { const company = req.query.company; const client = await pool.connect(); try { let queryString = 'SELECT DISTINCT dept FROM ver4.tb_user WHERE company = $1 AND is_resigned = false'; let queryResult = await client.query(queryString, [company]); res.status(200).json({message : '200', result : queryResult.rows}) } catch(err) { console.error('getCompanyList Error : ', err); } finally { client.release(); } } // 회사-부서-유저 목록 exports.getUserList = async (req, res, next) => { const company = req.query.company; const dept = req.query.dept; const client = await pool.connect(); try { let queryString = `SELECT user_id, user_nm, company, dept, position, is_resigned FROM ver4.tb_user WHERE company = $1 AND dept = $2 AND is_resigned = false ORDER BY CASE WHEN position = '회장' THEN 1 WHEN position = '부회장' THEN 2 WHEN position = '사장' THEN 3 WHEN position = '상임고문' THEN 4 WHEN position = '기술위원' THEN 5 WHEN position = '부사장' THEN 6 WHEN position = '고문' THEN 7 WHEN position = '전무이사' THEN 8 WHEN position = '수석연구원' THEN 9 WHEN position = '상무이사' THEN 10 WHEN position = '이사' THEN 11 WHEN position = '책임연구원' THEN 12 WHEN position = '부장' THEN 13 WHEN position = '차장' THEN 14 WHEN position = '선임연구원' THEN 15 WHEN position = '과장' THEN 16 WHEN position = '연구원' THEN 17 WHEN position = '대리' THEN 18 WHEN position = '사원' THEN 19 ELSE 99 END, user_nm ASC`; let queryResult = await client.query(queryString, [company, dept]); res.status(200).json({message : '200', result : queryResult.rows}); } catch(err) { console.error('getUserList Error : ', err); } finally { client.release(); } } exports.getPermissionUserInfo = async (req, res, next) => { const permission = req.body.permission; const userIds = permission.map(p => p.user_id).filter(user_id => !user_id.includes('dev')).filter(user_id => !user_id.includes('SAVANNAH')).filter(user_id => !user_id.includes('ECHO')).filter(user_id => !user_id.includes('VOID')).filter(user_id => !user_id.includes('STRIKE')).filter(user_id => !user_id.includes('CHILL')).filter(user_id => !user_id.includes('NOIR')).filter(user_id => !user_id.includes('LESSER')); const client = await pool.connect(); try{ let queryString = `SELECT user_id, user_nm, company, dept, position, is_resigned FROM ver4.tb_user WHERE user_id = ANY($1::text[]) AND is_resigned = false ORDER BY CASE WHEN position = '회장' THEN 1 WHEN position = '부회장' THEN 2 WHEN position = '사장' THEN 3 WHEN position = '상임고문' THEN 4 WHEN position = '기술위원' THEN 5 WHEN position = '부사장' THEN 6 WHEN position = '고문' THEN 7 WHEN position = '전무이사' THEN 8 WHEN position = '수석연구원' THEN 9 WHEN position = '상무이사' THEN 10 WHEN position = '이사' THEN 11 WHEN position = '책임연구원' THEN 12 WHEN position = '부장' THEN 13 WHEN position = '차장' THEN 14 WHEN position = '선임연구원' THEN 15 WHEN position = '과장' THEN 16 WHEN position = '연구원' THEN 17 WHEN position = '대리' THEN 18 WHEN position = '사원' THEN 19 ELSE 99 END, user_nm ASC`; let queryResult = await client.query(queryString, [userIds]); res.status(200).json({message : '200', result : queryResult.rows}); } catch(err) { console.error('getPermissionUserInfo Error : ') } finally { client.release(); } } //내부용 함수 // 날짜 formatter function formatDate(date){ const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); return `${year}. ${month}. ${day}. ${hours}:${minutes}:${seconds}`; } // 권한 lev string=>number function getPermissionLev(lev){ let result; switch(lev){ case 'sub-master': result = 191; break; case 'security-worker': result = 15; break; case 'worker': result = 7; break; // case 'uploader': // result = 3; // break; case 'viewer': result = 1; break; } return result; } // 권한 lev number => string (우선 select에서 case when then으로 처리) function getPermissionName(lev){ let result; switch(lev){ case 191: result = 'sub-master'; break; case 15: result = 'security-worker'; break; case 7: result = 'worker'; break; // case 3: // result = 'uploader'; // break; case 1: result = 'viewer'; break; } return result; }