초기 PM 소스 전체 업로드
This commit is contained in:
198
app.js
Normal file
198
app.js
Normal file
@@ -0,0 +1,198 @@
|
||||
const express = require('express');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const morgan = require('morgan');
|
||||
const path = require('path');
|
||||
const session = require('express-session');
|
||||
const dotenv = require('dotenv');
|
||||
dotenv.config();
|
||||
const bodyParser = require('body-parser');
|
||||
const dbConnect = require('./db/index');
|
||||
const cors = require('cors');
|
||||
const passport = require('passport');
|
||||
// const FileStore = require('session-file-store')(session);
|
||||
|
||||
const helmet = require('helmet');
|
||||
|
||||
const mainRouter = require('./routes/mainRouter');
|
||||
const archiveRouter = require('./routes/archiveRouter');
|
||||
const authRouter = require('./routes/authRouter.js');
|
||||
const passportConfig = require('./passport/index.js');
|
||||
const commonRouter = require('./routes/commonRouter.js');
|
||||
const officialDocRouter = require('./routes/officialDocRouter.js');
|
||||
const overviewRouter = require('./routes/overviewRouter.js');
|
||||
const bullBoardRouter = require('./routes/bullBoardRouter.js');
|
||||
const gsimRouter = require('./routes/gsimRouter.js');
|
||||
|
||||
//test
|
||||
const oauthRouter = require('./oauth/oauthRouter.js');
|
||||
const { isLoggedIn, deserializeUser } = require('./oauth/oauthController');
|
||||
|
||||
const logger = require('./logger');
|
||||
|
||||
const app = express();
|
||||
|
||||
const env = process.env.NODE_ENV;
|
||||
|
||||
dbConnect(); // DB 연결
|
||||
passportConfig(); // passport 설정
|
||||
|
||||
// app.use(
|
||||
// helmet({
|
||||
// contentSecurityPolicy: false, // CSP는 비활성화
|
||||
// crossOriginEmbedderPolicy: false, // 외부 CDN 자원 쓰면 충돌 날 수 있음
|
||||
// })
|
||||
// );
|
||||
|
||||
const ALLOWED_PARENTS = [
|
||||
"http://bcmf.hanmaceng.co.kr",
|
||||
"https://bcmf.hanmaceng.co.kr",
|
||||
"http://*.hanmaceng.co.kr",
|
||||
"https://*.hanmaceng.co.kr",
|
||||
];
|
||||
|
||||
app.use(helmet({
|
||||
frameguard: false, // X-Frame-Options 제거
|
||||
contentSecurityPolicy: false, // CSP는 직접 세팅
|
||||
crossOriginEmbedderPolicy: false,
|
||||
}));
|
||||
|
||||
app.use((req, res, next) => {
|
||||
res.setHeader(
|
||||
"Content-Security-Policy",
|
||||
`frame-ancestors 'self' ${ALLOWED_PARENTS.join(' ')}`
|
||||
);
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
//페이로드 크기 설정 => upload check할때 json 용량때문에 사용
|
||||
app.use(bodyParser.json({limit : '50mb'}));
|
||||
app.use(bodyParser.urlencoded({limit : '50mb', extended:true}));
|
||||
|
||||
app.use(cors());
|
||||
app.use(morgan('dev'));
|
||||
|
||||
app.use('/node_modules', express.static(path.join(__dirname, 'node_modules')));
|
||||
app.use('/libs', express.static(path.join(__dirname, 'libs')));
|
||||
app.use('/', express.static(path.join(__dirname, 'views')));
|
||||
app.use(express.static(__dirname + '/node_modules/socket.io/client-dist'));
|
||||
app.use('/:projectId',express.static(__dirname + '/node_modules/socket.io/client-dist'));
|
||||
// app.use('/PM_ver4', express.static(env != 'production'?'D:\\PM_ver4':'D:\\PM_ver4')); // D드라이브 폴더 사용
|
||||
|
||||
// 동적 API 및 라우트 캐싱 방지 설정 (304 Cache로 인한 이전 에러 응답 물림 및 리다이렉트 캐싱 방지)
|
||||
app.use((req, res, next) => {
|
||||
if (req.method === 'GET' && !req.path.includes('.') && !req.path.startsWith('/node_modules') && !req.path.startsWith('/libs')) {
|
||||
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
|
||||
res.setHeader('Pragma', 'no-cache');
|
||||
res.setHeader('Expires', '0');
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({extended:false}));
|
||||
app.use(cookieParser(process.env.COOKIE_SECRET));
|
||||
|
||||
// const fileStoreOptions = {
|
||||
// path:`C:\\develop\\session`,
|
||||
// ttl:1000*60*60*24,
|
||||
// logFn: function(){},
|
||||
// retries:5
|
||||
// }
|
||||
// app.use(session({
|
||||
// store: new FileStore(fileStoreOptions), // FileStore를 사용하도록 설정
|
||||
// secret: 'testkey', // 세션 ID를 서명하는 데 사용되는 비밀 키 (필수)
|
||||
// resave: false, // 세션 데이터가 변경되지 않아도 세션을 다시 저장할지 여부
|
||||
// saveUninitialized: false, // 초기화되지 않은 세션을 저장소에 저장할지 여부
|
||||
// cookie: {
|
||||
// maxAge: 1000 * 60 * 60 * 24 // 24시간 후 쿠키 만료
|
||||
// }
|
||||
// }));
|
||||
|
||||
|
||||
app.use(session({
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
secret: process.env.COOKIE_SECRET,
|
||||
cookie: {
|
||||
httpOnly: true,
|
||||
secure: false,
|
||||
// maxAge: (24 * 60 * 60 * 1000) + (9 * 3600 * 1000)
|
||||
}
|
||||
}));
|
||||
|
||||
//passport 초기화
|
||||
app.use(passport.initialize()); // passport 설정을 심음
|
||||
app.use(passport.session()); // req.session에 passport 정보를 저장
|
||||
|
||||
app.post('/log-client-error', express.json(), (req, res) => {
|
||||
const { message, source, lineno, colno, stack } = req.body;
|
||||
console.error('🚨 [CLIENT ERROR]:', message);
|
||||
console.error(` at ${source}:${lineno}:${colno}`);
|
||||
if (stack) console.error(stack);
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
// 라우터
|
||||
app.use(`/oauth`, oauthRouter);
|
||||
app.use('/login', (req, res) => {
|
||||
res.redirect('/user/login');
|
||||
});
|
||||
app.use('/user/login', (req, res, next) =>{res.sendFile(path.join(process.cwd()+`/views/login/login.html`))});
|
||||
// app.use('/popup' ,(req,res,next)=>{res.sendFile(path.join(process.cwd()+`/views/main/popup.html`))})
|
||||
|
||||
// 글로벌 사용자 세션 역직렬화 (로그인 상태 복원)
|
||||
app.use(deserializeUser);
|
||||
|
||||
// 공공 라우트 및 인증 API
|
||||
app.use('/auth', authRouter);
|
||||
|
||||
// 어드민 화면 서빙 및 권한 통제
|
||||
const isAdminLocal = (req, res, next) => {
|
||||
const userGroup = req.user?.group;
|
||||
if (req.user && (userGroup === 'USER_GROUP_super' || userGroup === 'dev' || userGroup === 'super')) {
|
||||
return next();
|
||||
}
|
||||
return res.status(403).send("어드민(super) 권한이 필요합니다.");
|
||||
};
|
||||
app.get('/admin', isLoggedIn, isAdminLocal, (req, res) => {
|
||||
res.sendFile(path.join(process.cwd(), 'views/admin/dashboard.html'));
|
||||
});
|
||||
|
||||
// 로그인 보호 장벽 적용 (이하 라우트는 로그인 세션 필수)
|
||||
app.use(isLoggedIn);
|
||||
|
||||
app.use('/', mainRouter);
|
||||
app.use('/:projectId/archive', archiveRouter);
|
||||
app.use('/:projectId/overview', overviewRouter);
|
||||
app.use('/:projectId/officialDoc', officialDocRouter);
|
||||
app.use('/common', commonRouter);
|
||||
|
||||
app.use('/gsim', gsimRouter);
|
||||
|
||||
// 어드민 전용 REST API
|
||||
app.use('/api/admin', require('./routes/admin/adminRouter'));
|
||||
|
||||
// BullMQ 모니터링 대시보드
|
||||
app.use('/admin/queues', bullBoardRouter);
|
||||
|
||||
// 404응답 미들웨어
|
||||
app.use((req, res, next) => {
|
||||
const error = new Error(`${req.method} ${req.url} 라우터가 없어요`);
|
||||
error.status = 404;
|
||||
logger.error(error.message);
|
||||
next(error);
|
||||
});
|
||||
|
||||
// 에러 처리 미들웨어
|
||||
app.use((err, req, res, next) => {
|
||||
console.error(err.stack);
|
||||
logger.error(err.message);
|
||||
res.status(err.status || 500).send(`status code: ${err.status || 500} 에러가 났어요`)
|
||||
});
|
||||
|
||||
// 자동 보관 및 자동 삭제 스케줄러 가동
|
||||
const scheduler = require('./libs/scheduler');
|
||||
scheduler.start();
|
||||
|
||||
module.exports = app;
|
||||
Reference in New Issue
Block a user