From 7862a33a823de4a46719a1e5ad8b30946a23e22b Mon Sep 17 00:00:00 2001 From: KUD <61041800+kimud6003@users.noreply.github.com> Date: Tue, 3 Aug 2021 22:48:26 +0900 Subject: [PATCH 1/4] init template --- .gitignore | 5 + README.md | 184 +++--------------------------- docker-compose.yml | 63 ++++++++++ nginx/Dockerfile | 11 ++ nginx/nginx.conf | 11 ++ node-template/.adminbro/.entry.js | 1 + node-template/.adminbro/bundle.js | 1 + node-template/.config/morgan.js | 22 ++++ node-template/.config/winston.js | 83 ++++++++++++++ node-template/README.md | 13 +++ node-template/app.js | 72 ++++++++++++ node-template/ecosystem.config.js | 34 ++++++ node-template/index-room.html | 38 ++++++ node-template/package.json | 44 +++++++ node-template/passport/index.js | 5 + node-template/passport/local.js | 0 node-template/routes/index.js | 9 ++ node-template/routes/users.js | 9 ++ node-template/socket/socket.js | 26 +++++ node-template/test/app.test.js | 45 ++++++++ node-template/test/testuser.js | 81 +++++++++++++ node-template/test/user.test.js | 49 ++++++++ package.json | 5 + 23 files changed, 646 insertions(+), 165 deletions(-) create mode 100644 .gitignore create mode 100644 docker-compose.yml create mode 100644 nginx/Dockerfile create mode 100644 nginx/nginx.conf create mode 100644 node-template/.adminbro/.entry.js create mode 100644 node-template/.adminbro/bundle.js create mode 100644 node-template/.config/morgan.js create mode 100644 node-template/.config/winston.js create mode 100644 node-template/README.md create mode 100644 node-template/app.js create mode 100644 node-template/ecosystem.config.js create mode 100644 node-template/index-room.html create mode 100644 node-template/package.json create mode 100644 node-template/passport/index.js create mode 100644 node-template/passport/local.js create mode 100644 node-template/routes/index.js create mode 100644 node-template/routes/users.js create mode 100644 node-template/socket/socket.js create mode 100644 node-template/test/app.test.js create mode 100644 node-template/test/testuser.js create mode 100644 node-template/test/user.test.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3998b66 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +mysql/* +node_modules +logs +yarn.lock +package-lock.json \ No newline at end of file diff --git a/README.md b/README.md index bbf0a58..8d3eba9 100644 --- a/README.md +++ b/README.md @@ -3,86 +3,28 @@ ## 추가점 -- redis 추가 (공부차원에서 넣어봄 신경쓰지 말것) -- redis 시험 페이지 index.js에 적용 +- redis 추가 (cluster mode) - redis session 적용가능 - sequelize, seqeulize-auto, express 구동확인 -- 기존의 도커는 호스팅을 중점으로 파일을 만들었다 -- 지금 세팅은 개발에 집중하게 docker-compse.yml 23번째 줄에 command: tail -f /dev/null을 삽입 ## 필독 -- command: tail -f /dev/null 도커 프로세스가 끝나도 종료되지 않게 세팅 -- vscode나 ssh로 연결해서 node 컨테이너로 들어간후 yarn dev || npm run dev를 쳐서 실행할것 +- node 들어간후 yarn dev || npm run dev를 쳐서 실행할것 +- test으 경우 알아서 test 파일을 찾기 때문에 yarn test|| npm test로 확인 가능 - 치고나면 log가 나오지 않을것인데 그것은 pm2 monit쳐서 확인 가능하다 - +- jest를 활용해 모듈이 제대로 작동하는지 서버를 실행전에 확인할수 있다. +> test 폴더의 user.test.js와 testuser.js를 반드시 확인할것 ## docker - docker-compose up -d build를 통해 백그라운드와 빌드를 동시 가능 - docker-compose에서 command를 통해 시작할때 서버와 mysql nginx가 실행되게 하였다. ## node.js - express -- Login : passport 사용 (로그인 사용할때 필수적으로 사용되는 모듈) +- passport: 사용 (로그인 사용할때 필수적으로 사용되는 모듈) passport.js - -```js -패스포트 예시 -./passport/index.js -const passport = require('passport'); -const local = require('./local'); -const { User } = require('../models'); - -module.exports = () => { - passport.serializeUser((user, done) => { - done(null, user.id); - }); - - passport.deserializeUser(async (id, done) => { - try { - const user = await User.findOne({ where: { id }}); - done(null, user); // req.user - } catch (error) { - console.error(error); - done(error); - } - }); - - local(); -}; - -./passport/local.js -const passport = require('passport'); -const { Strategy: LocalStrategy } = require('passport-local'); -const bcrypt = require('bcrypt'); -const { User } = require('../models'); - -module.exports = () => { - passport.use(new LocalStrategy({ - usernameField: 'email', - passwordField: 'password', - }, async (email, password, done) => { - try { - const user = await User.findOne({ - where: { email } - }); - if (!user) { - return done(null, false, { reason: '존재하지 않는 이메일입니다!' }); - } - const result = await bcrypt.compare(password, user.password); - if (result) { - return done(null, user); - } - return done(null, false, { reason: '비밀번호가 틀렸습니다.' }); - } catch (error) { - console.error(error); - return done(error); - } - })); -}; - -``` - helmet : http header의 보안관련 모듈 - morgan : express 내에서 로그 기록 남김 -- express -view=ejs 폴더명 (express를 써서 간단한 필요 모듈을 설치하자) - +- winston : moragn의 추가 로그 API +- jest : 테스트 API +- Adminbro : 어드민 페이지 구축 ## nginx - nginx -g daemon off 명령어로 현재 백그라운드에서 실행 @@ -140,45 +82,9 @@ yarn sequelize-auto -o "./models" -d DB이름 -h mysql -u root -p 3306 -x root - - http://localhost:80/ - mysql : ip: localhost , port 3306 -## 사용 라이브러리 - -- 칼만 필터 - -> 칼만 필터는 과거의 정보와 새로운 측정값을 사용하여 측정값에 포함된 잡음을 제거시켜 값을 최적화 하는 필터 - kalmanjs - -- 사용법 예시 -```js -var KalmanFilter = require('kalmanjs') - -var kf = new KalmanFilter(); -console.log(kf.filter(3)); -console.log(kf.filter(2)); -console.log(kf.filter(1)); - -``` - -```js -//Generate a simple static dataset -var dataConstant = Array.apply(null, {length: dataSetSize}).map(function() { - return 4; -}); -//Add noise to data -var noisyDataConstant = dataConstant.map(function(v) { - return v + randn(0, 3); -}); - -//Apply kalman filter -var kalmanFilter = new KalmanFilter({R: 0.01, Q: 3}); - -var dataConstantKalman = noisyDataConstant.map(function(v) { - return kalmanFilter.filter(v); -}); -``` - ## Admin > sequelize - express를 사용해서 만드는게 적정 -Admin 페이지 + ## JWT >서버에 부담을 적게 주기위해 사용 @@ -187,69 +93,17 @@ var dataConstantKalman = noisyDataConstant.map(function(v) { - 설치 : npm isntall jsonwebtoken rand-token - 우리는 passport와 JWT를 같이 써야한다 -```js -//passport/index.js -const passport = require("passport"); -const passportJWT = require("passport-jwt"); -const bcrypt = require("bcrypt"); - -const JWTStrategy = passportJWT.Strategy; -const { ExtractJwt } = passportJWT; -const LocalStrategy = require("passport-local").Strategy; -``` - -- ID,PWD에 대한 전략 -```js -const LocalStrategyOption = { - username: "UserId", - userpwd: "PWD", -}; -async function idpwVerify(id, pwd, done) { - let user; - try { - user = await userDAO.find(id); - - if (!user) return done(null, false); - const CorrectPassword = await bcrypt.compare(pwd, user.userpwd); - if (!CorrectPassword) return done(null, false); - } catch (e) { - done(e); - } - return done(null, user); -} -``` -- 토큰 전략 생성 -```js -const jwtStrategyOption = { - jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), - secretOrKey: global.config.secret, -}; - -async function jwtVerifty(payload, done) { - let user; - try { - user = await userDAO.find(payload.uid); - if (!user) return done(null, false); - } catch (e) { - return done(e); - } - return done(null, user); -} -``` -## 날씨 정보 -- 기상청 RSS 사용 -- http://www.kma.go.kr/wid/queryDFSRSS.jsp?zone=2714076000 ## 해야할일 -- [x] 백엔드 문서 설계화 -- [x] rest-API 통신 문서 설계화 -- [x] 개발환경 구축 -- [x] 로그인 구현 -- [x] 받아오는 자료에 대한 CRUD -- [x] 앱과의 통신 -- [ ] 로드 밸런싱 -- [ ] AWS나 학교 서버에 배포 +- [] 백엔드 문서 설계화 +- [] rest-API 통신 문서 설계화 +- [] 개발환경 구축 +- [] 로그인 구현 +- [] 받아오는 자료에 대한 CRUD +- [] Socket 채팅 +- [] 앱과의 통신 +- [] 로드 밸런싱 +- [] 서버에 배포 -# Server diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..636acf7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,63 @@ +version: '3' + +services: + nginx: + build: + context: ./nginx + container_name: nginx + entrypoint: dockerize -wait tcp://node:3000 -timeout 5m + command: [ 'nginx', '-g', 'daemon off;' ] + networks: + - node_nginx + depends_on: + - node + ports: + - 80:80 + restart: "unless-stopped" + node: + build: + context: ./node + container_name: node + volumes: + - ./node/:/usr/src/app/ + - /usr/src/app/node_modules/ + entrypoint: dockerize -wait tcp://mysql:3306 -timeout 5m + command: tail -f /dev/null + # command: ["pm2-runtime", "app.js","--watch"] + networks: + - node_nginx + - node_mysql + - node_redis + depends_on: + - mysql + - redis + restart: "unless-stopped" + mysql: + image: mysql:5.7 + command: --innodb-use-native-aio=0 + container_name: mysql + restart: always + volumes: + - ./mysql:/var/lib/mysql + environment: + - MYSQL_DATABASE=nodedb + - MYSQL_ROOT_PASSWORD=root + + ports: + - 3306:3306 + networks: + - node_mysql + redis: + image: redis:alpine + container_name: redis + ports: + - 3307:3307 + networks: + - node_redis +networks: + node_nginx: + driver: bridge + node_mysql: + driver: bridge + node_redis: + driver: bridge diff --git a/nginx/Dockerfile b/nginx/Dockerfile new file mode 100644 index 0000000..edd61ab --- /dev/null +++ b/nginx/Dockerfile @@ -0,0 +1,11 @@ +FROM nginx:1.19.7-alpine + +RUN apk add --no-cache openssl + +ENV DOCKERIZE_VERSION v0.6.1 +RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz + +RUN rm /etc/nginx/conf.d/default.conf +COPY nginx.conf /etc/nginx/conf.d/ diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..b6b2fa9 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,11 @@ +server { + listen 80; + location / { + proxy_pass http://node:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} diff --git a/node-template/.adminbro/.entry.js b/node-template/.adminbro/.entry.js new file mode 100644 index 0000000..7b71a22 --- /dev/null +++ b/node-template/.adminbro/.entry.js @@ -0,0 +1 @@ +AdminBro.UserComponents = {} diff --git a/node-template/.adminbro/bundle.js b/node-template/.adminbro/bundle.js new file mode 100644 index 0000000..a58eb8b --- /dev/null +++ b/node-template/.adminbro/bundle.js @@ -0,0 +1 @@ +!function(){"use strict";AdminBro.UserComponents={}}(); diff --git a/node-template/.config/morgan.js b/node-template/.config/morgan.js new file mode 100644 index 0000000..f8f6bae --- /dev/null +++ b/node-template/.config/morgan.js @@ -0,0 +1,22 @@ +//custom morgan middleware +const morgan = require('morgan') +const Logger = require('./winston') + + +const format = () => { + const result = 'combined' === 'production' ? 'combined' : 'common' + return result +} + +const stream = { write: (message) => Logger.http(message) } + +const skip = (_, res) => { + if (process.env.NODE_ENV === 'production') { + return res.statusCode < 400 + } + return false +} + +const morganMiddleware = morgan(format(), { stream, skip }) + +module.exports = morganMiddleware \ No newline at end of file diff --git a/node-template/.config/winston.js b/node-template/.config/winston.js new file mode 100644 index 0000000..999d386 --- /dev/null +++ b/node-template/.config/winston.js @@ -0,0 +1,83 @@ +const winston = require('winston') +const WinstonDaily = require('winston-daily-rotate-file') +const path = require('path') + +const { combine, timestamp, printf, colorize } = winston.format + +const logDir = '../logs' + +const levels = { + error: 0, + warn: 1, + info: 2, + http: 3, + debug: 4 +} + +const colors = { + error: 'red', + warn: 'yellow', + info: 'green', + http: 'magenta', + debug: 'blue' +} +winston.addColors(colors) + +const level = () => { + const env = process.env.NODE_ENV || 'development' + const isDevelopment = env === 'development' + return isDevelopment ? 'debug' : 'http' +} + +// Log Format +const logFormat = combine( + timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }), + printf((info) => { + if (info.stack) { + return `${info.timestamp} ${info.level}: ${info.message} \n Error Stack: ${info.stack}` + } + return `${info.timestamp} ${info.level}: ${info.message}` + }) +) + +// 콘솔에 찍힐 때는 색깔을 구변해서 로깅해주자. +const consoleOpts = { + handleExceptions: true, + level: process.env.NODE_ENV === 'production' ? 'error' : 'debug', + format: combine( + colorize({ all: true }), + timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }) + ) +} + +const transports = [ + // 콘솔로그찍을 때만 색넣자. + new winston.transports.Console(consoleOpts), + // error 레벨 로그를 저장할 파일 설정 + new WinstonDaily({ + level: 'error', + datePattern: 'YYYY-MM-DD', + dirname: path.join(__dirname, logDir, '/error'), + filename: '%DATE%.error.log', + maxFiles: 30, + zippedArchive: true + }), + // 모든 레벨 로그를 저장할 파일 설정 + new WinstonDaily({ + level: 'debug', + datePattern: 'YYYY-MM-DD', + dirname: path.join(__dirname, logDir, '/all'), + filename: '%DATE%.all.log', + maxFiles: 7, + zippedArchive: true + }) +] + +const Logger = winston.createLogger({ + level: level(), + levels, + format: logFormat, + transports +}) + +module.exports = Logger \ No newline at end of file diff --git a/node-template/README.md b/node-template/README.md new file mode 100644 index 0000000..dc24029 --- /dev/null +++ b/node-template/README.md @@ -0,0 +1,13 @@ +# Sever + +## Redis-Scoket + +- 프로젝트에서 최대한 대규모의 가능성 고려할때 Redis Pub/sub이 필요하다고 생각합니다. + +- socket.io-redis 모듈을 사용한다. + +- Adapting Redis +```js +io.adapter(redis({ host: 'localhost', port: 6379 })); +io.on('connection', (socket) => { /* … */ }); +``` \ No newline at end of file diff --git a/node-template/app.js b/node-template/app.js new file mode 100644 index 0000000..db33ca2 --- /dev/null +++ b/node-template/app.js @@ -0,0 +1,72 @@ +const createError = require('http-errors'); +const helmet = require('helmet'); +const passport = require('passport'); +const express = require('express'); +const cookieParser = require('cookie-parser'); +const morganMiddleware = require('./.config/morgan'); +const session = require('express-session'); +const RedisStore = require('connect-redis')(session) +const logger = require('./.config/winston'); +const redis = require('redis'); +const webSocket = require("./socket/socket"); +const AdminBro = require('admin-bro'); +const AdminBroExpress = require('@admin-bro/express'); +const indexRouter = require('./routes/index'); +const usersRouter = require('./routes/users'); + +const app = express(); + +// admin 사이트 제작 +const adminBro = new AdminBro({ + databases: [] +}) +const router = AdminBroExpress.buildRouter(adminBro) + +app.use(adminBro.options.rootPath, router) +app.use(helmet()); +app.use(morganMiddleware) +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); +app.use(cookieParser()); + +app.use('/', indexRouter); +app.use('/users',usersRouter); + +const redisClient = redis.createClient({ + host: "127.0.0.1", + port:6379, + logErrors: true, + db:0, + }) +// redis 세팅 +app.use(session({ + secret: "secret", + saveUninitialized: true, + resave: false, + store: new RedisStore({ + client : redisClient + }) +})) +app.use(passport.initialize()) +app.use(passport.session()) + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + next(createError(404)); +}); + + +app.use(function(err, req, res, next) { + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; + res.status(err.status || 500); + res.render('error'); +}); + +const server = app.listen(3000, () => { + logger.info(`Server Start Listening on port ${3000}`) +}); + +webSocket(server,app) + +module.exports = app; diff --git a/node-template/ecosystem.config.js b/node-template/ecosystem.config.js new file mode 100644 index 0000000..8261246 --- /dev/null +++ b/node-template/ecosystem.config.js @@ -0,0 +1,34 @@ +module.exports = { + apps : [{ + name : 'SWDevelop', // 프로젝트 이름 + script: 'app.js', // 실행되는 파일 + instances: 4, // 클러스터 모드 사용 시 생성할 인스턴스 수 + exec_mode: 'cluster', // fork, cluster 모드 중 선택 + merge_logs: true, // 클러스터 모드 사용 시 각 클러스터에서 생성되는 로그를 한 파일로 합쳐준다. + autorestart: true, // 프로세스 실패 시 자동으로 재시작할지 선택 + watch:true, + env: { + // 개발 환경설정 + NODE_ENV: 'development', + PROT:3000, + }, + env_production: { + // 운영 환경설정 (--env production 옵션으로 지정할 수 있다.) + NODE_ENV: 'production', + PROT:80 + } + }], + + deploy : { + production : { + user : 'SSH_USERNAME', + host : 'SSH_HOSTMACHINE', + ref : 'origin/master', + repo : 'GIT_REPOSITORY', + path : 'DESTINATION_PATH', + 'pre-deploy-local': '', + 'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production', + 'pre-setup': '' + } + } +}; diff --git a/node-template/index-room.html b/node-template/index-room.html new file mode 100644 index 0000000..99b3680 --- /dev/null +++ b/node-template/index-room.html @@ -0,0 +1,38 @@ + + + + + socket io redis store + + + + + +socketio redis store...
+ + + + + \ No newline at end of file diff --git a/node-template/package.json b/node-template/package.json new file mode 100644 index 0000000..128fd7f --- /dev/null +++ b/node-template/package.json @@ -0,0 +1,44 @@ +{ + "name": "node2", + "version": "0.0.0", + "private": true, + "scripts": { + "api-docs": "swagger-cli bundle ./src/swagger/openapi.yaml --outfile build/swagger.yaml --type yaml", + "start": "pm2 start ecosystem.config.js --env development", + "test": "jest" + }, + "dependencies": { + "@admin-bro/express": "^3.1.0", + "@admin-bro/sequelize": "^1.2.1", + "admin-bro": "^4.0.1", + "connect-redis": "^6.0.0", + "cookie-parser": "~1.4.4", + "debug": "~2.6.9", + "express": "^4.17.1", + "express-formidable": "^1.2.0", + "express-session": "^1.17.2", + "helmet": "^4.6.0", + "http-errors": "~1.6.3", + "install": "^0.13.0", + "jade": "~1.11.0", + "moment-timezone": "^0.5.33", + "morgan": "^1.9.1", + "mysql2": "^2.2.5", + "passport": "^0.4.1", + "pm2": "^5.1.0", + "redis": "^3.1.2", + "sequelize": "^6.6.5", + "sequelize-auto": "^0.8.3", + "socket.io": "^4.1.3", + "socket.io-redis": "^6.1.1", + "swagger-jsdoc": "^6.1.0", + "swagger-ui-express": "^4.1.6", + "tslib": "^2.3.0", + "winston": "^3.3.3", + "winston-daily-rotate-file": "^4.5.5" + }, + "devDependencies": { + "jest": "^27.0.6", + "supertest": "^6.1.4" + } +} diff --git a/node-template/passport/index.js b/node-template/passport/index.js new file mode 100644 index 0000000..32c678b --- /dev/null +++ b/node-template/passport/index.js @@ -0,0 +1,5 @@ +const passport = require('passport'); +const { Strategy: LocalStrategy } = require('passport-local'); +const bcrypt = require('bcrypt'); + +const User = require('../models/user'); // sequelize의 user 모델 \ No newline at end of file diff --git a/node-template/passport/local.js b/node-template/passport/local.js new file mode 100644 index 0000000..e69de29 diff --git a/node-template/routes/index.js b/node-template/routes/index.js new file mode 100644 index 0000000..73818e9 --- /dev/null +++ b/node-template/routes/index.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.send(`${aa}`); +}); + +module.exports = router; diff --git a/node-template/routes/users.js b/node-template/routes/users.js new file mode 100644 index 0000000..a48a625 --- /dev/null +++ b/node-template/routes/users.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +/* GET users listing. */ +router.post('/', function(req, res, next) { + res.send({userId:0}) +}); + +module.exports = router; diff --git a/node-template/socket/socket.js b/node-template/socket/socket.js new file mode 100644 index 0000000..e745da7 --- /dev/null +++ b/node-template/socket/socket.js @@ -0,0 +1,26 @@ +const SocketIO = require("socket.io"); +var redis = require('socket.io-redis'); + +module.exports = (server) => { + + // 이는 클라이언트가 /socket.io 경로 접근시 소켓 연결을 시작함을 의미 + const io = SocketIO(server, { path: "/socket.io"}); + io.adapter(redis({ host: 'localhost', port: 6379 })); + + // 연결시 connection 이벤트 발생한 후 콜백 실행 + io.on("connection", (socket) => { + + // ws에 req가 따로 있었다면 socket에서는 socket.request에 존재합니다 + const req = socket.request; + const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress; + console.log(`✔ ${ip} 클라이언트 접속, socket.id : ${socket.id}, req.ip : ${req.ip}`); + + // 연결 해제 + socket.on("disconnect", () => { + console.log(`${ip} 클라이언트 접속 해제. socket.id : ${socket.id}`); + clearInterval(socket.interval); + }); + // 에러 + socket.on("error", (error) => {}); + }); +}; \ No newline at end of file diff --git a/node-template/test/app.test.js b/node-template/test/app.test.js new file mode 100644 index 0000000..e8961fd --- /dev/null +++ b/node-template/test/app.test.js @@ -0,0 +1,45 @@ +const request = require("supertest"); +const app = require("../app"); + +describe("POST/users",()=>{ + describe("given a username and password", ()=>{ + + test("should respond with a 200 status code", async()=>{ + const response = await request(app).post("/users").send({ + username:"username", + password: "passowrd" + }) + expect(response.statusCode).toBe(200) + }) + // header의 content-type + test("should specify json in the content type header", async () => { + const response = await request(app).post("/users").send({ + username: "username", + password: "password" + }) + expect(response.headers['content-type']).toEqual(expect.stringContaining("json")) + }) + test("response has userId", async () => { + const response = await request(app).post("/users").send({ + username: "username", + password: "password" + }) + expect(response.body.userId).toBeDefined() + }) + }) + + describe("when the username and password is missing", () => { + test("should respond with a status code of 400", async () => { + const bodyData = [ + {username: "username"}, + {password: "password"}, + {} + ] + for (const body of bodyData) { + const response = await request(app).post("/users").send(body) + expect(response.statusCode).toBe(400) + } + }) + }) + +}) \ No newline at end of file diff --git a/node-template/test/testuser.js b/node-template/test/testuser.js new file mode 100644 index 0000000..d22020a --- /dev/null +++ b/node-template/test/testuser.js @@ -0,0 +1,81 @@ +// 이문서는 user.test.js의 테스트용 파일이라 실행 되지 않습니다. +const { User, Item } = require('../models'); +const createUser = async (req, res) => { + try { + const user = await User.create(req.body); + return res.status(201).json({ + user, + }); + } catch (error) { + return res.status(500).json({ error: error.message }) + } +} +const getAllUsers = async (req, res) => { + try { + const users = await User.findAll({ + include: [ + { + model: Item + } + ] + }); + return res.status(200).json({ users }); + } catch (error) { + return res.status(500).send(error.message); + } +} +const getUserById = async (req, res) => { + try { + const { id } = req.params; + const user = await User.findOne({ + where: { id: id }, + include: [ + { + model: Item + } + ] + }); + if (user) { + return res.status(200).json({ user }); + } + return res.status(404).send('User with the specified ID does not exists'); + } catch (error) { + return res.status(500).send(error.message); + } +} +const updateUser = async (req, res) => { + try { + const { id } = req.params; + const [updated] = await User.update(req.body, { + where: { id: id } + }); + if (updated) { + const updatedUser = await User.findOne({ where: { id: id } }); + return res.status(200).json({ user: updatedUser }); + } + throw new Error('User not found'); + } catch (error) { + return res.status(500).send(error.message); + } +}; +const deleteUser = async (req, res) => { + try { + const { id } = req.params; + const deleted = await User.destroy({ + where: { id: id } + }); + if (deleted) { + return res.status(204).send("User deleted"); + } + throw new Error("User not found"); + } catch (error) { + return res.status(500).send(error.message); + } +}; +module.exports = { + createUser, + getAllUsers, + getUserById, + updateUser, + deleteUser +} \ No newline at end of file diff --git a/node-template/test/user.test.js b/node-template/test/user.test.js new file mode 100644 index 0000000..50caea0 --- /dev/null +++ b/node-template/test/user.test.js @@ -0,0 +1,49 @@ +const request = require("supertest") +const app = require("../app.js") +// 이문서는 test 폴더에 있는 testuser.js를 참고해 만든것입니다. + +// describe 에는 테스트 할 내용을 작성한다. +describe('User API 테스트', () => { + // 테스트할 기능을 적는다. + it('유저 등록 테스트', async () => { + const res = await request(app) + .post('/api/users') + .send({ + firstName: 'Bob', + lastName: 'Doe', + email: 'bob@doe.com', + password: '12345678' + }) + // 상태 코드가 201과 같을걸로 예상 + expect(res.statusCode).toEqual(201) + // body안에 user라는 프로터티가 있을걸로 판단 + expect(res.body).toHaveProperty('user') + }), + it('should show a user', async () => { + const res = await request(app).get('/api/users/3') + expect(res.statusCode).toEqual(200) + expect(res.body).toHaveProperty('user') + }), + it('should show all users', async () => { + const res = await request(app).get('/api/users') + expect(res.statusCode).toEqual(200) + expect(res.body).toHaveProperty('users') + }), + it('should update a user', async () => { + const res = await request(app) + .put('/api/users/3') + .send({ + firstName: 'Bob', + lastName: 'Smith', + email: 'bob@doe.com', + password: 'abc123' + }) + expect(res.statusCode).toEqual(200) + expect(res.body).toHaveProperty('user') + }), + it('should delete a user', async () => { + const res = await request(app) + .del('/api/users/3') + expect(res.statusCode).toEqual(204) + }) +}) \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..47ba503 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "bcrypt": "^5.0.1" + } +} From aeda1750d2b6fb4090d2c053add1cf9df0766eb7 Mon Sep 17 00:00:00 2001 From: KUD <61041800+kimud6003@users.noreply.github.com> Date: Tue, 3 Aug 2021 22:56:16 +0900 Subject: [PATCH 2/4] image delete --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 8d3eba9..1534a2f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # nginx,nodejs,mysql 도커 - - ## 추가점 - redis 추가 (cluster mode) - redis session 적용가능 From 83c89f61fdc1e157c2c741e1a41315a739436711 Mon Sep 17 00:00:00 2001 From: KUD <61041800+kimud6003@users.noreply.github.com> Date: Wed, 11 Aug 2021 17:26:41 +0900 Subject: [PATCH 3/4] Express-Setup complete --- README.md | 8 +- node-template/.adminbro/.entry.js | 1 - node-template/.adminbro/bundle.js | 1 - node-template/README.md | 13 --- node/.adminjs/.entry.js | 1 + node/.adminjs/bundle.js | 7 ++ node/.config/config.json | 23 ++++ {node-template => node}/.config/morgan.js | 0 {node-template => node}/.config/winston.js | 0 node/Dockerfile | 25 +++++ {node-template => node}/app.js | 48 ++++++--- {node-template => node}/ecosystem.config.js | 0 {node-template => node}/index-room.html | 0 node/models/chatRoomTB.js | 25 +++++ node/models/cltTB.js | 110 ++++++++++++++++++++ node/models/index.js | 37 +++++++ node/models/init-models.js | 64 ++++++++++++ node/models/joinChatTB.js | 55 ++++++++++ node/models/joinVolActvTB.js | 66 ++++++++++++ node/models/msgTB.js | 64 ++++++++++++ node/models/tokenGetStateTB.js | 57 ++++++++++ node/models/tokenTB.js | 56 ++++++++++ node/models/volActvCatTB.js | 29 ++++++ node/models/volActvTB.js | 97 +++++++++++++++++ node/package.json | 48 +++++++++ {node-template => node}/passport/index.js | 0 {node-template => node}/passport/local.js | 0 {node-template => node}/routes/index.js | 0 {node-template => node}/routes/users.js | 0 {node-template => node}/socket/socket.js | 4 +- {node-template => node}/test/app.test.js | 0 {node-template => node}/test/testuser.js | 0 {node-template => node}/test/user.test.js | 0 33 files changed, 802 insertions(+), 37 deletions(-) delete mode 100644 node-template/.adminbro/.entry.js delete mode 100644 node-template/.adminbro/bundle.js delete mode 100644 node-template/README.md create mode 100644 node/.adminjs/.entry.js create mode 100644 node/.adminjs/bundle.js create mode 100644 node/.config/config.json rename {node-template => node}/.config/morgan.js (100%) rename {node-template => node}/.config/winston.js (100%) create mode 100644 node/Dockerfile rename {node-template => node}/app.js (61%) rename {node-template => node}/ecosystem.config.js (100%) rename {node-template => node}/index-room.html (100%) create mode 100644 node/models/chatRoomTB.js create mode 100644 node/models/cltTB.js create mode 100644 node/models/index.js create mode 100644 node/models/init-models.js create mode 100644 node/models/joinChatTB.js create mode 100644 node/models/joinVolActvTB.js create mode 100644 node/models/msgTB.js create mode 100644 node/models/tokenGetStateTB.js create mode 100644 node/models/tokenTB.js create mode 100644 node/models/volActvCatTB.js create mode 100644 node/models/volActvTB.js create mode 100644 node/package.json rename {node-template => node}/passport/index.js (100%) rename {node-template => node}/passport/local.js (100%) rename {node-template => node}/routes/index.js (100%) rename {node-template => node}/routes/users.js (100%) rename {node-template => node}/socket/socket.js (88%) rename {node-template => node}/test/app.test.js (100%) rename {node-template => node}/test/testuser.js (100%) rename {node-template => node}/test/user.test.js (100%) diff --git a/README.md b/README.md index 1534a2f..d347ddb 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,13 @@ ## 추가점 - redis 추가 (cluster mode) -- redis session 적용가능 +- redis session 적용가능 (session을 적용하지 않으면 passport 불가능) - sequelize, seqeulize-auto, express 구동확인 +- adminjs로 어드민 페이지 구축 +- socket.io 통신확인 ## 필독 -- node 들어간후 yarn dev || npm run dev를 쳐서 실행할것 +- node 들어간후 yarn strat || npm run start를 쳐서 실행할것 - test으 경우 알아서 test 파일을 찾기 때문에 yarn test|| npm test로 확인 가능 - 치고나면 log가 나오지 않을것인데 그것은 pm2 monit쳐서 확인 가능하다 - jest를 활용해 모듈이 제대로 작동하는지 서버를 실행전에 확인할수 있다. @@ -22,7 +24,7 @@ - morgan : express 내에서 로그 기록 남김 - winston : moragn의 추가 로그 API - jest : 테스트 API -- Adminbro : 어드민 페이지 구축 +- Adminjs : 어드민 페이지 구축 ## nginx - nginx -g daemon off 명령어로 현재 백그라운드에서 실행 diff --git a/node-template/.adminbro/.entry.js b/node-template/.adminbro/.entry.js deleted file mode 100644 index 7b71a22..0000000 --- a/node-template/.adminbro/.entry.js +++ /dev/null @@ -1 +0,0 @@ -AdminBro.UserComponents = {} diff --git a/node-template/.adminbro/bundle.js b/node-template/.adminbro/bundle.js deleted file mode 100644 index a58eb8b..0000000 --- a/node-template/.adminbro/bundle.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";AdminBro.UserComponents={}}(); diff --git a/node-template/README.md b/node-template/README.md deleted file mode 100644 index dc24029..0000000 --- a/node-template/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Sever - -## Redis-Scoket - -- 프로젝트에서 최대한 대규모의 가능성 고려할때 Redis Pub/sub이 필요하다고 생각합니다. - -- socket.io-redis 모듈을 사용한다. - -- Adapting Redis -```js -io.adapter(redis({ host: 'localhost', port: 6379 })); -io.on('connection', (socket) => { /* … */ }); -``` \ No newline at end of file diff --git a/node/.adminjs/.entry.js b/node/.adminjs/.entry.js new file mode 100644 index 0000000..c9edeb9 --- /dev/null +++ b/node/.adminjs/.entry.js @@ -0,0 +1 @@ +AdminJS.UserComponents = {} diff --git a/node/.adminjs/bundle.js b/node/.adminjs/bundle.js new file mode 100644 index 0000000..59a3d30 --- /dev/null +++ b/node/.adminjs/bundle.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + AdminJS.UserComponents = {}; + +}()); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVuZGxlLmpzIiwic291cmNlcyI6WyIuZW50cnkuanMiXSwic291cmNlc0NvbnRlbnQiOlsiQWRtaW5KUy5Vc2VyQ29tcG9uZW50cyA9IHt9XG4iXSwibmFtZXMiOlsiQWRtaW5KUyIsIlVzZXJDb21wb25lbnRzIl0sIm1hcHBpbmdzIjoiOzs7Q0FBQUEsT0FBTyxDQUFDQyxjQUFSLEdBQXlCLEVBQXpCOzs7Ozs7In0= diff --git a/node/.config/config.json b/node/.config/config.json new file mode 100644 index 0000000..1fa42c9 --- /dev/null +++ b/node/.config/config.json @@ -0,0 +1,23 @@ +{ + "development": { + "username": "root", + "password": "root", + "database": "mydb", + "host": "mysql", + "dialect": "mysql" + }, + "test": { + "username": "root", + "password": "root", + "database": "mydb", + "host": "mysql", + "dialect": "mysql" + }, + "production": { + "username": "root", + "password": "root", + "database": "mydb", + "host": "mysql", + "dialect": "mysql" + } +} diff --git a/node-template/.config/morgan.js b/node/.config/morgan.js similarity index 100% rename from node-template/.config/morgan.js rename to node/.config/morgan.js diff --git a/node-template/.config/winston.js b/node/.config/winston.js similarity index 100% rename from node-template/.config/winston.js rename to node/.config/winston.js diff --git a/node/Dockerfile b/node/Dockerfile new file mode 100644 index 0000000..d9519be --- /dev/null +++ b/node/Dockerfile @@ -0,0 +1,25 @@ +FROM node:15 + +WORKDIR /usr/src/app + +LABEL "purpose"="webdev" + +RUN apt-get update && apt-get install -y wget + +ENV DOCKERIZE_VERSION v0.6.1 +RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz + +COPY . . +RUN apt-get install -y yarn +RUN npm install -y -g sequelize-auto +RUN npm install -y -g pm2 +ENV PM2_PUBLIC_KEY ghuzel5nkndxo2m +ENV PM2_SECRET_KEY uzc2e7x174an0ld + +RUN npm install + +# EXPOSE 3000 + +CMD tail -f /dev/null \ No newline at end of file diff --git a/node-template/app.js b/node/app.js similarity index 61% rename from node-template/app.js rename to node/app.js index db33ca2..da8be31 100644 --- a/node-template/app.js +++ b/node/app.js @@ -9,20 +9,43 @@ const RedisStore = require('connect-redis')(session) const logger = require('./.config/winston'); const redis = require('redis'); const webSocket = require("./socket/socket"); -const AdminBro = require('admin-bro'); -const AdminBroExpress = require('@admin-bro/express'); +const AdminJS = require ('adminjs'); +const { buildAuthenticatedRouter } = require('@adminjs/express'); +const AdminJSSequelize = require('@adminjs/sequelize'); +const { sequelize }= require('./models'); const indexRouter = require('./routes/index'); const usersRouter = require('./routes/users'); const app = express(); -// admin 사이트 제작 -const adminBro = new AdminBro({ - databases: [] -}) -const router = AdminBroExpress.buildRouter(adminBro) +sequelize.sync({ force: false }).then(() => { + console.log('데이터베이스 연결 성공'); + }).catch((err) => { + console.error(err); + }); + +// // redis 세팅 +const redisClient = redis.createClient({host: "redis", logErrors: true,}) + + +// // admin 사이트 제작 +AdminJS.registerAdapter(AdminJSSequelize) + const admin = new AdminJS({ + databases: [sequelize], + }) +admin.watch() -app.use(adminBro.options.rootPath, router) +const router = buildAuthenticatedRouter(admin,{ + authenticate: async (email, password) => { + if ("admin" === password && "admin" === email) { + return {email:"admin",password:"admin"} + } + return null + }, + cookieName: 'adminBro', + cookiePassword: 'adminBro' +}) +app.use(admin.options.rootPath, router) app.use(helmet()); app.use(morganMiddleware) app.use(express.json()); @@ -32,13 +55,6 @@ app.use(cookieParser()); app.use('/', indexRouter); app.use('/users',usersRouter); -const redisClient = redis.createClient({ - host: "127.0.0.1", - port:6379, - logErrors: true, - db:0, - }) -// redis 세팅 app.use(session({ secret: "secret", saveUninitialized: true, @@ -55,12 +71,10 @@ app.use(function(req, res, next) { next(createError(404)); }); - app.use(function(err, req, res, next) { res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; res.status(err.status || 500); - res.render('error'); }); const server = app.listen(3000, () => { diff --git a/node-template/ecosystem.config.js b/node/ecosystem.config.js similarity index 100% rename from node-template/ecosystem.config.js rename to node/ecosystem.config.js diff --git a/node-template/index-room.html b/node/index-room.html similarity index 100% rename from node-template/index-room.html rename to node/index-room.html diff --git a/node/models/chatRoomTB.js b/node/models/chatRoomTB.js new file mode 100644 index 0000000..61fb6c5 --- /dev/null +++ b/node/models/chatRoomTB.js @@ -0,0 +1,25 @@ +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('chatRoomTB', { + chatRoomID: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + } + }, { + sequelize, + tableName: 'chatRoomTB', + timestamps: false, + indexes: [ + { + name: "PRIMARY", + unique: true, + using: "BTREE", + fields: [ + { name: "chatRoomID" }, + ] + }, + ] + }); +}; diff --git a/node/models/cltTB.js b/node/models/cltTB.js new file mode 100644 index 0000000..2f00903 --- /dev/null +++ b/node/models/cltTB.js @@ -0,0 +1,110 @@ +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('cltTB', { + cltID: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + cltName: { + type: DataTypes.STRING(10), + allowNull: false + }, + cltTel: { + type: DataTypes.CHAR(11), + allowNull: false + }, + cltAddr: { + type: DataTypes.STRING(45), + allowNull: false + }, + cltEmail: { + type: DataTypes.STRING(50), + allowNull: false + }, + cltPW: { + type: DataTypes.STRING(128), + allowNull: false + }, + cltLv: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 1 + }, + lifeVolTime: { + type: DataTypes.TIME, + allowNull: false, + defaultValue: "00:00:00" + }, + facVolTime: { + type: DataTypes.TIME, + allowNull: false, + defaultValue: "00:00:00" + }, + eduVolTime: { + type: DataTypes.TIME, + allowNull: false, + defaultValue: "00:00:00" + }, + osVolTime: { + type: DataTypes.TIME, + allowNull: false, + defaultValue: "00:00:00" + }, + onlVolTime: { + type: DataTypes.TIME, + allowNull: false, + defaultValue: "00:00:00" + }, + totalVolTime: { + type: DataTypes.TIME, + allowNull: false, + defaultValue: "00:00:00" + }, + lifeVolCnt: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + facVolCnt: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + eduVolCnt: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + osVolCnt: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + onlVolCnt: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + totalVolCnt: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + } + }, { + sequelize, + tableName: 'cltTB', + timestamps: false, + indexes: [ + { + name: "PRIMARY", + unique: true, + using: "BTREE", + fields: [ + { name: "cltID" }, + ] + }, + ] + }); +}; diff --git a/node/models/index.js b/node/models/index.js new file mode 100644 index 0000000..0a296cb --- /dev/null +++ b/node/models/index.js @@ -0,0 +1,37 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const Sequelize = require('sequelize'); +const basename = path.basename(__filename); +const env = process.env.NODE_ENV || 'development'; +const config = require(__dirname + '/../.config/config.json')[env]; +const db = {}; + +let sequelize; +if (config.use_env_variable) { + sequelize = new Sequelize(process.env[config.use_env_variable], config); +} else { + sequelize = new Sequelize(config.database, config.username, config.password, config); +} + +fs + .readdirSync(__dirname) + .filter(file => { + return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); + }) + .forEach(file => { + const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); + db[model.name] = model; + }); + +Object.keys(db).forEach(modelName => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/node/models/init-models.js b/node/models/init-models.js new file mode 100644 index 0000000..f7d3326 --- /dev/null +++ b/node/models/init-models.js @@ -0,0 +1,64 @@ +var DataTypes = require("sequelize").DataTypes; +var _chatRoomTB = require("./chatRoomTB"); +var _cltTB = require("./cltTB"); +var _joinChatTB = require("./joinChatTB"); +var _joinVolActvTB = require("./joinVolActvTB"); +var _msgTB = require("./msgTB"); +var _tokenGetStateTB = require("./tokenGetStateTB"); +var _tokenTB = require("./tokenTB"); +var _volActvCatTB = require("./volActvCatTB"); +var _volActvTB = require("./volActvTB"); + +function initModels(sequelize) { + var chatRoomTB = _chatRoomTB(sequelize, DataTypes); + var cltTB = _cltTB(sequelize, DataTypes); + var joinChatTB = _joinChatTB(sequelize, DataTypes); + var joinVolActvTB = _joinVolActvTB(sequelize, DataTypes); + var msgTB = _msgTB(sequelize, DataTypes); + var tokenGetStateTB = _tokenGetStateTB(sequelize, DataTypes); + var tokenTB = _tokenTB(sequelize, DataTypes); + var volActvCatTB = _volActvCatTB(sequelize, DataTypes); + var volActvTB = _volActvTB(sequelize, DataTypes); + + cltTB.belongsToMany(tokenTB, { as: 'tokenID_tokenTBs', through: tokenGetStateTB, foreignKey: "cltID", otherKey: "tokenID" }); + cltTB.belongsToMany(volActvTB, { as: 'volActvID_volActvTBs', through: joinVolActvTB, foreignKey: "cltID", otherKey: "volActvID" }); + tokenTB.belongsToMany(cltTB, { as: 'cltID_cltTB_tokengetstatetbs', through: tokenGetStateTB, foreignKey: "tokenID", otherKey: "cltID" }); + volActvTB.belongsToMany(cltTB, { as: 'cltID_cltTBs', through: joinVolActvTB, foreignKey: "volActvID", otherKey: "cltID" }); + joinChatTB.belongsTo(chatRoomTB, { as: "chatRoom", foreignKey: "chatRoomID"}); + chatRoomTB.hasMany(joinChatTB, { as: "joinchattbs", foreignKey: "chatRoomID"}); + msgTB.belongsTo(chatRoomTB, { as: "chatRoom", foreignKey: "chatRoomID"}); + chatRoomTB.hasMany(msgTB, { as: "msgtbs", foreignKey: "chatRoomID"}); + joinChatTB.belongsTo(cltTB, { as: "clt", foreignKey: "cltID"}); + cltTB.hasMany(joinChatTB, { as: "joinchattbs", foreignKey: "cltID"}); + joinVolActvTB.belongsTo(cltTB, { as: "clt", foreignKey: "cltID"}); + cltTB.hasMany(joinVolActvTB, { as: "joinvolactvtbs", foreignKey: "cltID"}); + msgTB.belongsTo(cltTB, { as: "clt", foreignKey: "cltID"}); + cltTB.hasMany(msgTB, { as: "msgtbs", foreignKey: "cltID"}); + tokenGetStateTB.belongsTo(cltTB, { as: "clt", foreignKey: "cltID"}); + cltTB.hasMany(tokenGetStateTB, { as: "tokengetstatetbs", foreignKey: "cltID"}); + volActvTB.belongsTo(cltTB, { as: "publ", foreignKey: "publID"}); + cltTB.hasMany(volActvTB, { as: "volactvtbs", foreignKey: "publID"}); + tokenGetStateTB.belongsTo(tokenTB, { as: "token", foreignKey: "tokenID"}); + tokenTB.hasMany(tokenGetStateTB, { as: "tokengetstatetbs", foreignKey: "tokenID"}); + tokenTB.belongsTo(volActvCatTB, { as: "volActvCat", foreignKey: "volActvCatID"}); + volActvCatTB.hasMany(tokenTB, { as: "tokentbs", foreignKey: "volActvCatID"}); + volActvTB.belongsTo(volActvCatTB, { as: "volActvCat", foreignKey: "volActvCatID"}); + volActvCatTB.hasMany(volActvTB, { as: "volactvtbs", foreignKey: "volActvCatID"}); + joinVolActvTB.belongsTo(volActvTB, { as: "volActv", foreignKey: "volActvID"}); + volActvTB.hasMany(joinVolActvTB, { as: "joinvolactvtbs", foreignKey: "volActvID"}); + + return { + chatRoomTB, + cltTB, + joinChatTB, + joinVolActvTB, + msgTB, + tokenGetStateTB, + tokenTB, + volActvCatTB, + volActvTB, + }; +} +module.exports = initModels; +module.exports.initModels = initModels; +module.exports.default = initModels; diff --git a/node/models/joinChatTB.js b/node/models/joinChatTB.js new file mode 100644 index 0000000..3ccf495 --- /dev/null +++ b/node/models/joinChatTB.js @@ -0,0 +1,55 @@ +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('joinChatTB', { + joinChatID: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + cltID: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'cltTB', + key: 'cltID' + } + }, + chatRoomID: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'chatRoomTB', + key: 'chatRoomID' + } + } + }, { + sequelize, + tableName: 'joinChatTB', + timestamps: false, + indexes: [ + { + name: "PRIMARY", + unique: true, + using: "BTREE", + fields: [ + { name: "joinChatID" }, + ] + }, + { + name: "fk_joinChatTB_cltTB1_idx", + using: "BTREE", + fields: [ + { name: "cltID" }, + ] + }, + { + name: "fk_joinChatTB_chatRoomTB1_idx", + using: "BTREE", + fields: [ + { name: "chatRoomID" }, + ] + }, + ] + }); +}; diff --git a/node/models/joinVolActvTB.js b/node/models/joinVolActvTB.js new file mode 100644 index 0000000..2b3f9bc --- /dev/null +++ b/node/models/joinVolActvTB.js @@ -0,0 +1,66 @@ +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('joinVolActvTB', { + cltID: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'cltTB', + key: 'cltID' + } + }, + volActvID: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'volActvTB', + key: 'volActvID' + } + }, + cltActvState: { + type: DataTypes.CHAR(1), + allowNull: false + }, + cltBKM: { + type: DataTypes.CHAR(1), + allowNull: false, + defaultValue: "N" + }, + cltReqTime: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { + sequelize, + tableName: 'joinVolActvTB', + timestamps: false, + indexes: [ + { + name: "PRIMARY", + unique: true, + using: "BTREE", + fields: [ + { name: "cltID" }, + { name: "volActvID" }, + ] + }, + { + name: "fk_joinVolActvTB_cltTB1_idx", + using: "BTREE", + fields: [ + { name: "cltID" }, + ] + }, + { + name: "fk_joinVolActvTB_volActvTB1_idx", + using: "BTREE", + fields: [ + { name: "volActvID" }, + ] + }, + ] + }); +}; diff --git a/node/models/msgTB.js b/node/models/msgTB.js new file mode 100644 index 0000000..9ea214f --- /dev/null +++ b/node/models/msgTB.js @@ -0,0 +1,64 @@ +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('msgTB', { + msgID: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + chatRoomID: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'chatRoomTB', + key: 'chatRoomID' + } + }, + cltID: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'cltTB', + key: 'cltID' + } + }, + msgCont: { + type: DataTypes.STRING(100), + allowNull: false + }, + msgTime: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { + sequelize, + tableName: 'msgTB', + timestamps: false, + indexes: [ + { + name: "PRIMARY", + unique: true, + using: "BTREE", + fields: [ + { name: "msgID" }, + ] + }, + { + name: "fk_msgTB_cltTB1_idx", + using: "BTREE", + fields: [ + { name: "cltID" }, + ] + }, + { + name: "fk_msgTB_chatRoomTB1_idx", + using: "BTREE", + fields: [ + { name: "chatRoomID" }, + ] + }, + ] + }); +}; diff --git a/node/models/tokenGetStateTB.js b/node/models/tokenGetStateTB.js new file mode 100644 index 0000000..9e937e2 --- /dev/null +++ b/node/models/tokenGetStateTB.js @@ -0,0 +1,57 @@ +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('tokenGetStateTB', { + tokenID: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'tokenTB', + key: 'tokenID' + } + }, + cltID: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'cltTB', + key: 'cltID' + } + }, + tokenActState: { + type: DataTypes.CHAR(1), + allowNull: false, + defaultValue: "N" + } + }, { + sequelize, + tableName: 'tokenGetStateTB', + timestamps: false, + indexes: [ + { + name: "PRIMARY", + unique: true, + using: "BTREE", + fields: [ + { name: "tokenID" }, + { name: "cltID" }, + ] + }, + { + name: "fk_tokenGetStateTB_tokenTB_idx", + using: "BTREE", + fields: [ + { name: "tokenID" }, + ] + }, + { + name: "fk_tokenGetStateTB_cltTB1_idx", + using: "BTREE", + fields: [ + { name: "cltID" }, + ] + }, + ] + }); +}; diff --git a/node/models/tokenTB.js b/node/models/tokenTB.js new file mode 100644 index 0000000..4e9efb8 --- /dev/null +++ b/node/models/tokenTB.js @@ -0,0 +1,56 @@ +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('tokenTB', { + tokenID: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + volActvCatID: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: 'volActvCatTB', + key: 'volActvCatID' + } + }, + tokenName: { + type: DataTypes.STRING(20), + allowNull: false + }, + tokenCont: { + type: DataTypes.STRING(50), + allowNull: false + }, + tokenActVolCnt: { + type: DataTypes.INTEGER, + allowNull: true + }, + tokenActVolTime: { + type: DataTypes.TIME, + allowNull: true + } + }, { + sequelize, + tableName: 'tokenTB', + timestamps: false, + indexes: [ + { + name: "PRIMARY", + unique: true, + using: "BTREE", + fields: [ + { name: "tokenID" }, + ] + }, + { + name: "fk_tokenTB_volActvCatTB1_idx", + using: "BTREE", + fields: [ + { name: "volActvCatID" }, + ] + }, + ] + }); +}; diff --git a/node/models/volActvCatTB.js b/node/models/volActvCatTB.js new file mode 100644 index 0000000..9786f89 --- /dev/null +++ b/node/models/volActvCatTB.js @@ -0,0 +1,29 @@ +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('volActvCatTB', { + volActvCatID: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + volActCatName: { + type: DataTypes.STRING(10), + allowNull: false + } + }, { + sequelize, + tableName: 'volActvCatTB', + timestamps: false, + indexes: [ + { + name: "PRIMARY", + unique: true, + using: "BTREE", + fields: [ + { name: "volActvCatID" }, + ] + }, + ] + }); +}; diff --git a/node/models/volActvTB.js b/node/models/volActvTB.js new file mode 100644 index 0000000..97ae7af --- /dev/null +++ b/node/models/volActvTB.js @@ -0,0 +1,97 @@ +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('volActvTB', { + volActvID: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + publID: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'cltTB', + key: 'cltID' + } + }, + volActvCatID: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'volActvCatTB', + key: 'volActvCatID' + } + }, + volActvTitle: { + type: DataTypes.STRING(20), + allowNull: false + }, + volActvCont: { + type: DataTypes.STRING(50), + allowNull: false + }, + volActvPer: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + volActvProgTime: { + type: DataTypes.TIME, + allowNull: false + }, + volActvOSD: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP') + }, + volActvOED: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP') + }, + volActvPT: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP') + }, + volActvState: { + type: DataTypes.CHAR(1), + allowNull: false, + defaultValue: "R" + }, + volActvViews: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + } + }, { + sequelize, + tableName: 'volActvTB', + timestamps: false, + indexes: [ + { + name: "PRIMARY", + unique: true, + using: "BTREE", + fields: [ + { name: "volActvID" }, + ] + }, + { + name: "fk_volActTB_cltTB1_idx", + using: "BTREE", + fields: [ + { name: "publID" }, + ] + }, + { + name: "fk_volActvTB_volActvCatTB1_idx", + using: "BTREE", + fields: [ + { name: "volActvCatID" }, + ] + }, + ] + }); +}; diff --git a/node/package.json b/node/package.json new file mode 100644 index 0000000..9bffaef --- /dev/null +++ b/node/package.json @@ -0,0 +1,48 @@ +{ + "name": "node2", + "version": "0.0.0", + "private": true, + "scripts": { + "api-docs": "swagger-cli bundle ./src/swagger/openapi.yaml --outfile build/swagger.yaml --type yaml", + "start": "pm2 start ecosystem.config.js --env development", + "test": "jest" + }, + "dependencies": { + "@admin-bro/express": "^3.1.0", + "@admin-bro/sequelize": "^1.2.1", + "@adminjs/express": "^4.0.0", + "@adminjs/sequelize": "^2.0.0", + "adminjs": "^5.1.0", + "connect-redis": "^6.0.0", + "cookie-parser": "~1.4.4", + "cors": "^2.8.5", + "debug": "~2.6.9", + "dotenv": "^10.0.0", + "express": "^4.17.1", + "express-formidable": "^1.2.0", + "express-session": "^1.17.2", + "helmet": "^4.6.0", + "http-errors": "~1.6.3", + "install": "^0.13.0", + "jade": "~1.11.0", + "moment-timezone": "^0.5.33", + "morgan": "^1.9.1", + "mysql2": "^2.3.0", + "passport": "^0.4.1", + "pm2": "^5.1.0", + "redis": "^3.1.2", + "sequelize": "^6.6.5", + "sequelize-auto": "^0.8.4", + "socket.io": "^4.1.3", + "socket.io-redis": "^6.1.1", + "swagger-jsdoc": "^6.1.0", + "swagger-ui-express": "^4.1.6", + "tslib": "^2.3.0", + "winston": "^3.3.3", + "winston-daily-rotate-file": "^4.5.5" + }, + "devDependencies": { + "jest": "^27.0.6", + "supertest": "^6.1.4" + } +} diff --git a/node-template/passport/index.js b/node/passport/index.js similarity index 100% rename from node-template/passport/index.js rename to node/passport/index.js diff --git a/node-template/passport/local.js b/node/passport/local.js similarity index 100% rename from node-template/passport/local.js rename to node/passport/local.js diff --git a/node-template/routes/index.js b/node/routes/index.js similarity index 100% rename from node-template/routes/index.js rename to node/routes/index.js diff --git a/node-template/routes/users.js b/node/routes/users.js similarity index 100% rename from node-template/routes/users.js rename to node/routes/users.js diff --git a/node-template/socket/socket.js b/node/socket/socket.js similarity index 88% rename from node-template/socket/socket.js rename to node/socket/socket.js index e745da7..cee677f 100644 --- a/node-template/socket/socket.js +++ b/node/socket/socket.js @@ -4,8 +4,8 @@ var redis = require('socket.io-redis'); module.exports = (server) => { // 이는 클라이언트가 /socket.io 경로 접근시 소켓 연결을 시작함을 의미 - const io = SocketIO(server, { path: "/socket.io"}); - io.adapter(redis({ host: 'localhost', port: 6379 })); + const io = SocketIO(server, { path: "/socket.io",cors: { origin: "*" }}); + io.adapter(redis({ host:'redis'})); // 연결시 connection 이벤트 발생한 후 콜백 실행 io.on("connection", (socket) => { diff --git a/node-template/test/app.test.js b/node/test/app.test.js similarity index 100% rename from node-template/test/app.test.js rename to node/test/app.test.js diff --git a/node-template/test/testuser.js b/node/test/testuser.js similarity index 100% rename from node-template/test/testuser.js rename to node/test/testuser.js diff --git a/node-template/test/user.test.js b/node/test/user.test.js similarity index 100% rename from node-template/test/user.test.js rename to node/test/user.test.js From 2537345b4b86f292f56f200c1377367ecacf3834 Mon Sep 17 00:00:00 2001 From: KUD <61041800+kimud6003@users.noreply.github.com> Date: Wed, 11 Aug 2021 17:42:25 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=A5=20=EC=93=B8=EB=AA=A8=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- node-template/package.json | 44 -------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 node-template/package.json diff --git a/node-template/package.json b/node-template/package.json deleted file mode 100644 index 128fd7f..0000000 --- a/node-template/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "node2", - "version": "0.0.0", - "private": true, - "scripts": { - "api-docs": "swagger-cli bundle ./src/swagger/openapi.yaml --outfile build/swagger.yaml --type yaml", - "start": "pm2 start ecosystem.config.js --env development", - "test": "jest" - }, - "dependencies": { - "@admin-bro/express": "^3.1.0", - "@admin-bro/sequelize": "^1.2.1", - "admin-bro": "^4.0.1", - "connect-redis": "^6.0.0", - "cookie-parser": "~1.4.4", - "debug": "~2.6.9", - "express": "^4.17.1", - "express-formidable": "^1.2.0", - "express-session": "^1.17.2", - "helmet": "^4.6.0", - "http-errors": "~1.6.3", - "install": "^0.13.0", - "jade": "~1.11.0", - "moment-timezone": "^0.5.33", - "morgan": "^1.9.1", - "mysql2": "^2.2.5", - "passport": "^0.4.1", - "pm2": "^5.1.0", - "redis": "^3.1.2", - "sequelize": "^6.6.5", - "sequelize-auto": "^0.8.3", - "socket.io": "^4.1.3", - "socket.io-redis": "^6.1.1", - "swagger-jsdoc": "^6.1.0", - "swagger-ui-express": "^4.1.6", - "tslib": "^2.3.0", - "winston": "^3.3.3", - "winston-daily-rotate-file": "^4.5.5" - }, - "devDependencies": { - "jest": "^27.0.6", - "supertest": "^6.1.4" - } -}