Showing
19 changed files
with
438 additions
and
0 deletions
actions/chatroomActions.js
0 → 100644
1 | +const asyncHandler = require("express-async-handler"); | ||
2 | + | ||
3 | +// @desc Create chatroom | ||
4 | +// @route POST /api/chats | ||
5 | +// @access Private | ||
6 | +const createChatroom = asyncHandler(async (req, res) => { | ||
7 | + return; | ||
8 | +}); | ||
9 | + | ||
10 | +// @desc Delete chatroom | ||
11 | +// @route DELETE /api/chats | ||
12 | +// @access Private | ||
13 | +const delChatroom = asyncHandler(async (req, res) => { | ||
14 | + return; | ||
15 | +}); | ||
16 | + | ||
17 | +module.exports = { | ||
18 | + createChatroom, | ||
19 | + delChatroom, | ||
20 | +}; |
models/chatroomModel.js
0 → 100644
1 | +const mongoose = require("mongoose"); | ||
2 | + | ||
3 | +const chatroomSchema = mongoose.Schema( | ||
4 | + { | ||
5 | + roomName: { | ||
6 | + type: String, | ||
7 | + required: [true, "Please add chatroom name"], | ||
8 | + }, | ||
9 | + participants: [ | ||
10 | + { | ||
11 | + user: { | ||
12 | + type: String, | ||
13 | + required: [true, "Please add participants"], | ||
14 | + }, | ||
15 | + }, | ||
16 | + ], | ||
17 | + messages: [], | ||
18 | + }, | ||
19 | + { | ||
20 | + timestamps: true, | ||
21 | + } | ||
22 | +); | ||
23 | + | ||
24 | +module.exports = mongoose.model("Chatroom", chatroomSchema); |
routes/chatroomRoutes.js
0 → 100644
1 | +const express = require("express"); | ||
2 | +const router = express.Router(); | ||
3 | +const { createChatroom, delChatroom } = require("../actions/chatroomActions"); | ||
4 | +const { authHandler } = require("../middleware/authMiddleware"); | ||
5 | + | ||
6 | +router.post("/", authHandler, createChatroom); | ||
7 | +router.delete("/", authHandler, delChatroom); | ||
8 | +// router.post("/message", authHandler, sendMessage); | ||
9 | + | ||
10 | +module.exports = router; |
... | @@ -11,6 +11,7 @@ app.use(express.json()); | ... | @@ -11,6 +11,7 @@ app.use(express.json()); |
11 | app.use(express.urlencoded({ extended: false })); | 11 | app.use(express.urlencoded({ extended: false })); |
12 | 12 | ||
13 | app.use("/api/users", require("./routes/userRoutes")); | 13 | app.use("/api/users", require("./routes/userRoutes")); |
14 | +app.use("/api/chats", require("./routes/chatroomRoutes")); | ||
14 | 15 | ||
15 | app.use(errorHandler); | 16 | app.use(errorHandler); |
16 | 17 | ... | ... |
server/LICENSE
0 → 100644
1 | +MIT License | ||
2 | + | ||
3 | +Copyright (c) 2022 HWANG SUN HYUK | ||
4 | + | ||
5 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | +of this software and associated documentation files (the "Software"), to deal | ||
7 | +in the Software without restriction, including without limitation the rights | ||
8 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | +copies of the Software, and to permit persons to whom the Software is | ||
10 | +furnished to do so, subject to the following conditions: | ||
11 | + | ||
12 | +The above copyright notice and this permission notice shall be included in all | ||
13 | +copies or substantial portions of the Software. | ||
14 | + | ||
15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | +FITNESSFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
21 | +SOFTWARE. |
server/actions/chatroomActions.js
0 → 100644
1 | +const asyncHandler = require("express-async-handler"); | ||
2 | + | ||
3 | +// @desc Create chatroom | ||
4 | +// @route POST /api/chats | ||
5 | +// @access Private | ||
6 | +const createChatroom = asyncHandler(async (req, res) => { | ||
7 | + return; | ||
8 | +}); | ||
9 | + | ||
10 | +// @desc Delete chatroom | ||
11 | +// @route DELETE /api/chats | ||
12 | +// @access Private | ||
13 | +const delChatroom = asyncHandler(async (req, res) => { | ||
14 | + return; | ||
15 | +}); | ||
16 | + | ||
17 | +module.exports = { | ||
18 | + createChatroom, | ||
19 | + delChatroom, | ||
20 | +}; |
server/actions/userActions.js
0 → 100644
1 | +const bcrypt = require("bcryptjs"); | ||
2 | +// handles "exception" inside of async express routes | ||
3 | +const asyncHandler = require("express-async-handler"); | ||
4 | +const User = require("../models/userModel"); | ||
5 | +const { jwtGenerator } = require("../config/jwt"); | ||
6 | + | ||
7 | +// @desc Signup new user | ||
8 | +// @route POST /api/users | ||
9 | +// @access Public | ||
10 | +const signupUser = asyncHandler(async (req, res) => { | ||
11 | + const { username, email, password } = req.body; | ||
12 | + if (!username || !email || !password) { | ||
13 | + res.status(400); | ||
14 | + throw new Error("Please fill in all fields"); | ||
15 | + } | ||
16 | + | ||
17 | + // Check if user already exists | ||
18 | + const userExists = await User.findOne({ email }); | ||
19 | + if (userExists) { | ||
20 | + res.status(400); | ||
21 | + throw new Error("User with the email already exists"); | ||
22 | + } | ||
23 | + | ||
24 | + // Hash password (bcrypt) | ||
25 | + const salt = await bcrypt.genSalt(10); | ||
26 | + const hashedPassword = await bcrypt.hash(password, salt); | ||
27 | + | ||
28 | + // Create/Build user | ||
29 | + const user = await User.create({ | ||
30 | + username, | ||
31 | + email, | ||
32 | + password: hashedPassword, | ||
33 | + }); | ||
34 | + | ||
35 | + // Send response | ||
36 | + if (user) { | ||
37 | + // 201: Resource successfully created | ||
38 | + res.status(201).json({ | ||
39 | + _id: user.id, | ||
40 | + username: user.username, | ||
41 | + email: user.email, | ||
42 | + token: jwtGenerator(user._id), | ||
43 | + }); | ||
44 | + } else { | ||
45 | + res.status(400); | ||
46 | + throw new Error("Invalid user data"); | ||
47 | + } | ||
48 | +}); | ||
49 | + | ||
50 | +// @desc Login user | ||
51 | +// @route POST /api/users/login | ||
52 | +// @access Public | ||
53 | +const loginUser = asyncHandler(async (req, res) => { | ||
54 | + const { email, password } = req.body; | ||
55 | + | ||
56 | + // Check email & password | ||
57 | + const userInDB = await User.findOne({ email }); | ||
58 | + const validPassword = await bcrypt.compare(password, userInDB.password); | ||
59 | + if (userInDB && validPassword) { | ||
60 | + res.status(200).json({ | ||
61 | + _id: userInDB.id, | ||
62 | + username: userInDB.username, | ||
63 | + email: userInDB.email, | ||
64 | + token: jwtGenerator(userInDB._id), | ||
65 | + }); | ||
66 | + } else { | ||
67 | + res.status(400); | ||
68 | + throw new Error("Invalid credentials"); | ||
69 | + } | ||
70 | +}); | ||
71 | + | ||
72 | +// @desc Get all users | ||
73 | +// @route GET /api/users/all | ||
74 | +// @access Public | ||
75 | +const getAllusers = asyncHandler(async (req, res) => { | ||
76 | + const users = await User.find() | ||
77 | + .select("-password") | ||
78 | + .select("-updatedAt") | ||
79 | + .select("-createdAt") | ||
80 | + .select("-email"); | ||
81 | + | ||
82 | + res.status(200).json(users); | ||
83 | +}); | ||
84 | + | ||
85 | +// @desc Get user | ||
86 | +// @route GET /api/users/self | ||
87 | +// @access Private | ||
88 | +const getSelf = asyncHandler(async (req, res) => { | ||
89 | + res.status(200).json(req.user); | ||
90 | +}); | ||
91 | + | ||
92 | +module.exports = { | ||
93 | + signupUser, | ||
94 | + loginUser, | ||
95 | + getAllusers, | ||
96 | + getSelf, | ||
97 | +}; |
server/config/db.js
0 → 100644
1 | +const mongoose = require("mongoose"); | ||
2 | +const colors = require("colors"); | ||
3 | + | ||
4 | +const connectDB = async () => { | ||
5 | + try { | ||
6 | + const conn = await mongoose.connect(process.env.MONGO_URI); | ||
7 | + console.log(`MongoDB Connected: ${conn.connection.host}`.cyan.underline); | ||
8 | + } catch (error) { | ||
9 | + console.log( | ||
10 | + `Error occured while connecting to the mongoDB`.magenta.underline | ||
11 | + ); | ||
12 | + console.log(error); | ||
13 | + process.exit(1); | ||
14 | + } | ||
15 | +}; | ||
16 | + | ||
17 | +module.exports = connectDB; |
server/config/jwt.js
0 → 100644
server/middleware/authMiddleware.js
0 → 100644
1 | +const jwt = require("jsonwebtoken"); | ||
2 | +const asyncHandler = require("express-async-handler"); | ||
3 | +const User = require("../models/userModel"); | ||
4 | + | ||
5 | +const authHandler = asyncHandler(async (req, res, next) => { | ||
6 | + // Check if token exists | ||
7 | + if (!req.headers.authorization) { | ||
8 | + res.status(401); | ||
9 | + throw new Error("Not authorized"); | ||
10 | + } | ||
11 | + | ||
12 | + // Evaluate the token | ||
13 | + const token = req.headers.authorization.split(" ")[1]; | ||
14 | + const decoded = jwt.verify( | ||
15 | + token, | ||
16 | + process.env.JWT_SECRET, | ||
17 | + function (err, decoded) { | ||
18 | + if (err) { | ||
19 | + res.status(401); | ||
20 | + throw new Error("Not authorized"); | ||
21 | + } | ||
22 | + return decoded; | ||
23 | + } | ||
24 | + ); | ||
25 | + | ||
26 | + const user = await User.findById(decoded.id).select("-password"); | ||
27 | + req.user = user; | ||
28 | + return next(); | ||
29 | +}); | ||
30 | + | ||
31 | +module.exports = { authHandler }; |
server/middleware/errorMiddleware.js
0 → 100644
1 | +const errorHandler = (err, req, res, next) => { | ||
2 | + const statusCode = res.statusCode ? res.statusCode : 500; | ||
3 | + | ||
4 | + res.status(statusCode); | ||
5 | + res.json({ | ||
6 | + message: err.message, | ||
7 | + // stack from mongoDB TODO: Check it! | ||
8 | + stack: process.env.NODE_ENV === "production" ? null : err.stack, | ||
9 | + }); | ||
10 | +}; | ||
11 | + | ||
12 | +module.exports = { | ||
13 | + errorHandler, | ||
14 | +}; |
server/models/chatModel.js
0 → 100644
1 | +const mongoose = require("mongoose"); | ||
2 | + | ||
3 | +const chatSchema = mongoose.Schema({ | ||
4 | + room: { | ||
5 | + type: mongoose.Schema.Types.ObjectId, | ||
6 | + require: true, | ||
7 | + ref: "Chatroom", | ||
8 | + }, | ||
9 | + conversation: [ | ||
10 | + { | ||
11 | + message: { | ||
12 | + type: String, | ||
13 | + required: true, | ||
14 | + }, | ||
15 | + }, | ||
16 | + ], | ||
17 | +}); | ||
18 | + | ||
19 | +module.exports = mongoose.model("Chat", chatSchema); |
server/models/chatroomModel.js
0 → 100644
1 | +const mongoose = require("mongoose"); | ||
2 | + | ||
3 | +const chatroomSchema = mongoose.Schema( | ||
4 | + { | ||
5 | + roomName: { | ||
6 | + type: String, | ||
7 | + required: [true, "Please add chatroom name"], | ||
8 | + }, | ||
9 | + participants: [ | ||
10 | + { | ||
11 | + user: { | ||
12 | + type: mongoose.Schema.Types.ObjectId, | ||
13 | + required: true, | ||
14 | + ref: "User", | ||
15 | + }, | ||
16 | + }, | ||
17 | + ], | ||
18 | + }, | ||
19 | + { | ||
20 | + timestamps: true, | ||
21 | + } | ||
22 | +); | ||
23 | + | ||
24 | +module.exports = mongoose.model("Chatroom", chatroomSchema); |
server/models/userModel.js
0 → 100644
1 | +const mongoose = require("mongoose"); | ||
2 | + | ||
3 | +const userSchema = mongoose.Schema( | ||
4 | + { | ||
5 | + username: { | ||
6 | + type: String, | ||
7 | + required: [true, "Please add a username"], | ||
8 | + }, | ||
9 | + email: { | ||
10 | + type: String, | ||
11 | + required: [true, "Please add a email"], | ||
12 | + }, | ||
13 | + password: { | ||
14 | + type: String, | ||
15 | + required: [true, "Please add a password"], | ||
16 | + }, | ||
17 | + }, | ||
18 | + { | ||
19 | + timestamps: true, | ||
20 | + } | ||
21 | +); | ||
22 | + | ||
23 | +module.exports = mongoose.model("User", userSchema); |
server/package-lock.json
0 → 100644
This diff could not be displayed because it is too large.
server/package.json
0 → 100644
1 | +{ | ||
2 | + "name": "weather_chatbot", | ||
3 | + "version": "1.0.0", | ||
4 | + "description": "web-app weather chatbot", | ||
5 | + "main": "server.js", | ||
6 | + "scripts": { | ||
7 | + "start": "node server/server.js", | ||
8 | + "server": "nodemon server/server.js", | ||
9 | + "client": "npm start --prefix ../client", | ||
10 | + "dev": "concurrently \"npm run client\" \"npm run server\"" | ||
11 | + }, | ||
12 | + "repository": { | ||
13 | + "type": "git", | ||
14 | + "url": "http://khuhub.khu.ac.kr/2019102244/weather_chatbot.git" | ||
15 | + }, | ||
16 | + "author": "황선혁", | ||
17 | + "license": "MIT", | ||
18 | + "dependencies": { | ||
19 | + "bcryptjs": "^2.4.3", | ||
20 | + "colors": "^1.4.0", | ||
21 | + "cors": "^2.8.5", | ||
22 | + "dotenv": "^16.0.1", | ||
23 | + "express": "^4.18.1", | ||
24 | + "express-async-handler": "^1.2.0", | ||
25 | + "jsonwebtoken": "^8.5.1", | ||
26 | + "mongoose": "^6.3.4", | ||
27 | + "socket.io": "^4.5.1" | ||
28 | + }, | ||
29 | + "devDependencies": { | ||
30 | + "concurrently": "^7.2.1", | ||
31 | + "nodemon": "^2.0.16" | ||
32 | + } | ||
33 | +} |
server/routes/chatroomRoutes.js
0 → 100644
1 | +const express = require("express"); | ||
2 | +const router = express.Router(); | ||
3 | +const { createChatroom, delChatroom } = require("../actions/chatroomActions"); | ||
4 | +const { authHandler } = require("../middleware/authMiddleware"); | ||
5 | + | ||
6 | +// "/api/rooms/" | ||
7 | +router.post("/", authHandler, createChatroom); | ||
8 | +router.delete("/", authHandler, delChatroom); | ||
9 | +// router.post("/message", authHandler, sendMessage); | ||
10 | + | ||
11 | +module.exports = router; |
server/routes/userRoutes.js
0 → 100644
1 | +const express = require("express"); | ||
2 | +const router = express.Router(); | ||
3 | +const { | ||
4 | + signupUser, | ||
5 | + loginUser, | ||
6 | + getAllusers, | ||
7 | + getSelf, | ||
8 | +} = require("../actions/userActions"); | ||
9 | +const { authHandler } = require("../middleware/authMiddleware"); | ||
10 | + | ||
11 | +// "/api/users/" | ||
12 | +router.post("/", signupUser); | ||
13 | +router.post("/login", loginUser); | ||
14 | +router.get("/all", getAllusers); | ||
15 | +router.get("/self", authHandler, getSelf); | ||
16 | + | ||
17 | +module.exports = router; |
server/server.js
0 → 100644
1 | +const express = require("express"); | ||
2 | +const dotenv = require("dotenv").config(); | ||
3 | +const { errorHandler } = require("./middleware/errorMiddleware"); | ||
4 | +const { createServer } = require("http"); | ||
5 | +const { Server } = require("socket.io"); | ||
6 | +const cors = require("cors"); | ||
7 | +const connectDB = require("./config/db"); | ||
8 | +const port = process.env.PORT || 8080; | ||
9 | + | ||
10 | +connectDB(); | ||
11 | +const app = express(); | ||
12 | + | ||
13 | +app.use(express.json()); | ||
14 | +app.use(express.urlencoded({ extended: false })); | ||
15 | + | ||
16 | +app.use("/api/users", require("./routes/userRoutes")); | ||
17 | +app.use("/api/rooms", require("./routes/chatroomRoutes")); | ||
18 | + | ||
19 | +// chatbot | ||
20 | +app.use(cors()); | ||
21 | +const httpServer = createServer(app); | ||
22 | +const io = new Server(httpServer, { | ||
23 | + cors: { | ||
24 | + origin: "http://localhost:3000/", | ||
25 | + methods: ["GET", "POST"], | ||
26 | + }, | ||
27 | +}); | ||
28 | + | ||
29 | +io.on("connection", (socket) => { | ||
30 | + console.log(`User Connected: ${socket.id}`); | ||
31 | + | ||
32 | + socket.on("join_room", (data) => { | ||
33 | + socket.join(data); | ||
34 | + }); | ||
35 | + | ||
36 | + socket.on("send_message", (data) => { | ||
37 | + socket.to(data.room).emit("receive_message", data); | ||
38 | + }); | ||
39 | +}); | ||
40 | + | ||
41 | +app.use(errorHandler); | ||
42 | + | ||
43 | +app.listen(port, () => { | ||
44 | + console.log(`Server started on port ${port}`); | ||
45 | +}); |
-
Please register or login to post a comment