Eric Whale

Re-Organize folder structure (server)

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 +};
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);
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
......
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.
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 +};
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 +};
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;
1 +const jwt = require("jsonwebtoken");
2 +
3 +const jwtGenerator = (id) => {
4 + // https://github.com/auth0/node-jsonwebtoken
5 + const token = jwt.sign({ id }, process.env.JWT_SECRET, {
6 + expiresIn: "2 days",
7 + });
8 + return token;
9 +};
10 +
11 +module.exports = { jwtGenerator };
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 };
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 +};
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);
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);
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);
This diff could not be displayed because it is too large.
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 +}
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;
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;
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 +});