Showing
19 changed files
with
0 additions
and
346 deletions
jaksimsamil-server/.env
deleted
100644 → 0
jaksimsamil-server/.eslintrc.json
deleted
100644 → 0
| 1 | -{ | ||
| 2 | - "parser": "babel-eslint", | ||
| 3 | - "env": { | ||
| 4 | - "commonjs": true, | ||
| 5 | - "es6": true, | ||
| 6 | - "node": true | ||
| 7 | - }, | ||
| 8 | - "extends": "eslint:recommended", | ||
| 9 | - "globals": { | ||
| 10 | - "Atomics": "readonly", | ||
| 11 | - "SharedArrayBuffer": "readonly" | ||
| 12 | - }, | ||
| 13 | - "parserOptions": { | ||
| 14 | - "ecmaVersion": 11 | ||
| 15 | - }, | ||
| 16 | - "rules": {} | ||
| 17 | -} |
jaksimsamil-server/.gitignore
deleted
100644 → 0
jaksimsamil-server/API.md
deleted
100644 → 0
| 1 | -# Jaksimsamil API Documentation | ||
| 2 | - | ||
| 3 | -## Overview | ||
| 4 | - | ||
| 5 | -- TBA | ||
| 6 | - | ||
| 7 | -## URL | ||
| 8 | - | ||
| 9 | -- TBA | ||
| 10 | - | ||
| 11 | -## Usage | ||
| 12 | - | ||
| 13 | -- TBA | ||
| 14 | - | ||
| 15 | -## Example | ||
| 16 | - | ||
| 17 | -- TBA | ||
| 18 | - | ||
| 19 | -## API Table | ||
| 20 | - | ||
| 21 | -| group | description | method | URL | Detail | Auth | | ||
| 22 | -| ------- | ------------------------ | ------ | -------------------------- | -------- | --------- | | ||
| 23 | -| user | 유저 등록 | POST | api/user | 바로가기 | JWT Token | | ||
| 24 | -| user | 유저 삭제 | DELETE | api/user:id | 바로가기 | JWT Token | | ||
| 25 | -| user | 특정 유저 조회 | GET | api/user:id | 바로가기 | None | | ||
| 26 | -| user | 전체 유저 조회 | GET | api/user | 바로가기 | JWT Token | | ||
| 27 | -| friend | 유저 친구 등록 | POST | api/friend | 바로가기 | JWT Token | | ||
| 28 | -| friend | 유저의 친구 조회 | GET | api/friend:id | 바로가기 | None | | ||
| 29 | -| profile | 유저가 푼 문제 조회 | GET | api/profile/solved:id | 바로가기 | None | | ||
| 30 | -| profile | 유저가 푼 문제 개수 조회 | GET | api/profile/solvednum:id | 바로가기 | None | | ||
| 31 | -| profile | 추천 문제 조회 | GET | api/profile/recommendps:id | 바로가기 | None | | ||
| 32 | -| notify | 슬랙 메시지 전송 요청 | POST | api/notify/slack | 바로가기 | Jwt Token | | ||
| 33 | -| auth | 로그인 | POST | api/auth/login | 바로가기 | None | | ||
| 34 | -| auth | 로그아웃 | GET | api/auth/logout | 바로가기 | JWT Token | | ||
| 35 | -| auth | 회원가입 | POST | api/auth/register | 바로가기 | None | | ||
| 36 | -| auth | 로그인 확인 | GET | api/auth/check | 바로가기 | None | |
jaksimsamil-server/index.js
deleted
100644 → 0
| 1 | -const express = require("express"); | ||
| 2 | -const morgan = require("morgan"); | ||
| 3 | -const mongoose = require("mongoose"); | ||
| 4 | -const app = express(); | ||
| 5 | -const bodyParser = require("body-parser"); | ||
| 6 | -const api = require("./src/api"); | ||
| 7 | -const jwtMiddleware = require("./src/lib/jwtMiddleware"); | ||
| 8 | -require("dotenv").config(); | ||
| 9 | -const { SERVER_PORT, MONGO_URL } = process.env; | ||
| 10 | -app.use(morgan("dev")); | ||
| 11 | -app.use(express.json()); | ||
| 12 | -app.use(express.urlencoded({ extended: false })); | ||
| 13 | -app.use(bodyParser()); | ||
| 14 | -app.use(jwtMiddleware); | ||
| 15 | - | ||
| 16 | -app.use("/api", api); | ||
| 17 | -mongoose | ||
| 18 | - .connect(MONGO_URL, { useNewUrlParser: true, useFindAndModify: false }) | ||
| 19 | - .then(() => { | ||
| 20 | - console.log("Connected to MongoDB"); | ||
| 21 | - }) | ||
| 22 | - .catch((e) => { | ||
| 23 | - console.log(e); | ||
| 24 | - }); | ||
| 25 | -app.listen(SERVER_PORT, () => { | ||
| 26 | - console.log("Server is running on port", process.env.SERVER_PORT); | ||
| 27 | -}); |
jaksimsamil-server/package.json
deleted
100644 → 0
| 1 | -{ | ||
| 2 | - "name": "jaksimsamil-server", | ||
| 3 | - "version": "1.0.0", | ||
| 4 | - "main": "index.js", | ||
| 5 | - "license": "MIT", | ||
| 6 | - "dependencies": { | ||
| 7 | - "bcrypt": "^4.0.1", | ||
| 8 | - "body-parser": "^1.19.0", | ||
| 9 | - "dotenv": "^8.2.0", | ||
| 10 | - "eslint-config-prettier": "^6.11.0", | ||
| 11 | - "express": "^4.17.1", | ||
| 12 | - "fs": "^0.0.1-security", | ||
| 13 | - "joi": "^14.3.1", | ||
| 14 | - "jsonwebtoken": "^8.5.1", | ||
| 15 | - "mongoose": "^5.9.17", | ||
| 16 | - "morgan": "^1.10.0", | ||
| 17 | - "path": "^0.12.7" | ||
| 18 | - }, | ||
| 19 | - "devDependencies": { | ||
| 20 | - "babel-eslint": "^10.1.0", | ||
| 21 | - "eslint": "^7.1.0", | ||
| 22 | - "nodemon": "^2.0.4" | ||
| 23 | - }, | ||
| 24 | - "scripts": { | ||
| 25 | - "start": "node src", | ||
| 26 | - "start:dev": "nodemon --watch src/ src/index.js" | ||
| 27 | - } | ||
| 28 | -} |
| 1 | -const Joi = require("joi"); | ||
| 2 | -const User = require("../../models/user"); | ||
| 3 | -/* | ||
| 4 | -POST /api/auth/register | ||
| 5 | -{ | ||
| 6 | - username: 'userid' | ||
| 7 | - password: 'userpassword' | ||
| 8 | -} | ||
| 9 | -*/ | ||
| 10 | -exports.register = async (ctx) => { | ||
| 11 | - const schema = Joi.object().keys({ | ||
| 12 | - username: Joi.string().alphanum().min(3).max(20).required(), | ||
| 13 | - password: Joi.string().required(), | ||
| 14 | - }); | ||
| 15 | - const result = Joi.validate(ctx.request.body, schema); | ||
| 16 | - if (result.error) { | ||
| 17 | - ctx.status = 400; | ||
| 18 | - ctx.body = result.error; | ||
| 19 | - return; | ||
| 20 | - } | ||
| 21 | - | ||
| 22 | - const { username, password } = ctx.request.body; | ||
| 23 | - try { | ||
| 24 | - const isNameExist = await User.findByUsername(username); | ||
| 25 | - if (isNameExist) { | ||
| 26 | - ctx.status = 409; | ||
| 27 | - return; | ||
| 28 | - } | ||
| 29 | - const user = new User({ | ||
| 30 | - username, | ||
| 31 | - }); | ||
| 32 | - await user.setPassword(password); | ||
| 33 | - await user.save(); | ||
| 34 | - ctx.body = user.serialize(); | ||
| 35 | - | ||
| 36 | - const token = user.generateToekn(); | ||
| 37 | - ctx.cookies.set("acces_token", token, { | ||
| 38 | - //3일동안 유효 | ||
| 39 | - maxAge: 1000 * 60 * 60 * 24 * 3, | ||
| 40 | - httpOnly: true, | ||
| 41 | - }); | ||
| 42 | - } catch (e) { | ||
| 43 | - ctx.throw(500, e); | ||
| 44 | - } | ||
| 45 | -}; | ||
| 46 | -/* | ||
| 47 | -POST /api/auth/login | ||
| 48 | -{ | ||
| 49 | - username: 'userid' | ||
| 50 | - password: 'userpassword' | ||
| 51 | -} | ||
| 52 | - */ | ||
| 53 | -exports.login = async (ctx) => { | ||
| 54 | - const { username, password } = ctx.request.body; | ||
| 55 | - if (!username || !password) { | ||
| 56 | - ctx.status = 401; | ||
| 57 | - return; | ||
| 58 | - } | ||
| 59 | - try { | ||
| 60 | - const user = await User.findByUsername(username); | ||
| 61 | - if (!user) { | ||
| 62 | - ctx.status = 401; | ||
| 63 | - return; | ||
| 64 | - } | ||
| 65 | - const isPasswordValid = await user.checkPassword(password); | ||
| 66 | - if (!isPasswordValid) { | ||
| 67 | - ctx.status = 401; | ||
| 68 | - return; | ||
| 69 | - } | ||
| 70 | - ctx.body = user.serialize(); | ||
| 71 | - const token = user.generateToken(); | ||
| 72 | - ctx.cookies.set("acces_token", token, { | ||
| 73 | - //7일동안 유효 | ||
| 74 | - maxAge: 1000 * 60 * 60 * 24 * 7, | ||
| 75 | - httpOnly: true, | ||
| 76 | - }); | ||
| 77 | - } catch (e) { | ||
| 78 | - ctx.throw(500, e); | ||
| 79 | - } | ||
| 80 | -}; | ||
| 81 | -/* | ||
| 82 | -GET api/auth/check | ||
| 83 | -*/ | ||
| 84 | -exports.check = async (ctx) => { | ||
| 85 | - const { user } = ctx.state; | ||
| 86 | - if (!user) { | ||
| 87 | - ctx.status = 401; | ||
| 88 | - return; | ||
| 89 | - } | ||
| 90 | - ctx.body = user; | ||
| 91 | -}; | ||
| 92 | -/* | ||
| 93 | -POST /api/auth/logout | ||
| 94 | -*/ | ||
| 95 | -exports.logout = async (ctx) => { | ||
| 96 | - ctx.cookies.set("access_token"); | ||
| 97 | - ctx.status = 204; | ||
| 98 | -}; |
jaksimsamil-server/src/api/index.js
deleted
100644 → 0
| 1 | -const express = require("express"); | ||
| 2 | -const app = express(); | ||
| 3 | - | ||
| 4 | -const auth = require("./auth"); | ||
| 5 | -const friend = require("./friend"); | ||
| 6 | -const notify = require("./profile"); | ||
| 7 | -const user = require("./user"); | ||
| 8 | -const profile = require("./profile"); | ||
| 9 | - | ||
| 10 | -app.use("/auth", auth); | ||
| 11 | -app.use("/friend", friend); | ||
| 12 | -app.use("/notify", notify); | ||
| 13 | -app.use("/user", user); | ||
| 14 | -app.use("/profile", profile); | ||
| 15 | - | ||
| 16 | -module.exports = app; |
File mode changed
jaksimsamil-server/src/index.js
deleted
100644 → 0
File mode changed
| 1 | -const jwt = require("jsonwebtoken"); | ||
| 2 | -const User = require("../models/user"); | ||
| 3 | -const jwtMiddleware = async (ctx, next) => { | ||
| 4 | - const token = ctx.cookies.get("access_token"); | ||
| 5 | - if (!token) { | ||
| 6 | - //토큰이 없을 때 | ||
| 7 | - return next(); | ||
| 8 | - } | ||
| 9 | - try { | ||
| 10 | - const decoded = jwt.verify(token, process.env.JWT_TOKEN); | ||
| 11 | - ctx.state.user = { | ||
| 12 | - _id: decoded._id, | ||
| 13 | - username: decoded.username, | ||
| 14 | - }; | ||
| 15 | - //토큰의 남은 유효 기간이 2일 이하라면 재발급 | ||
| 16 | - if (decoded.exp - Date.now() / 1000 < 60 * 60 * 24 * 2) { | ||
| 17 | - const user = await User.findById(decoded._id); | ||
| 18 | - const token = user.generateToken(); | ||
| 19 | - ctx.cookies.set("access_token", token, { | ||
| 20 | - maxAge: 1000 * 60 * 60 * 24 * 7, | ||
| 21 | - httpOnly: true, | ||
| 22 | - }); | ||
| 23 | - } | ||
| 24 | - return next(); | ||
| 25 | - } catch (e) { | ||
| 26 | - return next(); | ||
| 27 | - } | ||
| 28 | -}; | ||
| 29 | - | ||
| 30 | -module.exports = jwtMiddleware; |
| 1 | -const mongoose = require("mongoose"); | ||
| 2 | -const bcrypt = require("bcrypt"); | ||
| 3 | -const jwt = require("jsonwebtoken"); | ||
| 4 | -const Schema = mongoose.Schema; | ||
| 5 | - | ||
| 6 | -const UserSchema = new Schema({ | ||
| 7 | - username: String, | ||
| 8 | - hashedPassword: String, | ||
| 9 | -}); | ||
| 10 | - | ||
| 11 | -UserSchema.methods.setPassword = async function (password) { | ||
| 12 | - const hash = await bcrypt.hash(password, 10); | ||
| 13 | - this.hashedPassword = hash; | ||
| 14 | -}; | ||
| 15 | -UserSchema.methodss.checkPassword = async function (password) { | ||
| 16 | - const result = await bcrypt.compare(password, this.hashedPassword); | ||
| 17 | - return result; | ||
| 18 | -}; | ||
| 19 | -UserSchema.statics.findByUsername = function (username) { | ||
| 20 | - return this.findOne({ username }); | ||
| 21 | -}; | ||
| 22 | -UserSchema.methods.serialize = function () { | ||
| 23 | - const data = this.toJSON(); | ||
| 24 | - delete data.hashedPassword; | ||
| 25 | - return data; | ||
| 26 | -}; | ||
| 27 | -UserSchema.methods.generateToken = function () { | ||
| 28 | - const token = jwt.sign( | ||
| 29 | - { | ||
| 30 | - _id: this.id, | ||
| 31 | - username: this.username, | ||
| 32 | - }, | ||
| 33 | - process.env.JWT_SECRET, | ||
| 34 | - { | ||
| 35 | - expiresIn: "7d", | ||
| 36 | - } | ||
| 37 | - ); | ||
| 38 | - return token; | ||
| 39 | -}; | ||
| 40 | -const User = mongoose.model("User", UserSchema); | ||
| 41 | -module.exports = User; |
jaksimsamil-server/yarn-error.log
deleted
100644 → 0
This diff could not be displayed because it is too large.
jaksimsamil-server/yarn.lock
deleted
100644 → 0
This diff could not be displayed because it is too large.
-
Please register or login to post a comment