app.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. const express = require('express');
  2. const app = express()
  3. const cors = require("cors");
  4. const http = require('http'); //create new http
  5. const mongoose = require('mongoose');
  6. const socket = require("socket.io");
  7. const User = require('./db/models/User');
  8. const Message = require('./db/models/Message');
  9. const jwt = require('jsonwebtoken');
  10. const bcrypt = require('bcrypt');
  11. require('dotenv').config(); // add dotnv for config
  12. const server = http.createServer(app);
  13. const jsonParser = express.json();
  14. app.use(cors());
  15. const io = require("socket.io")(server, {
  16. cors: {
  17. origin: "http://localhost:3000" //client endpoint and port
  18. }
  19. });
  20. const randomColor = require('randomcolor');
  21. const PORT = process.env.PORT || 5000;
  22. const TOKEN_KEY = process.env.TOKEN_KEY || 'rGH4r@3DKOg06hgj';
  23. const HASH_KEY = 7;
  24. //main test page
  25. app.get('/', (req, res) => {
  26. res.send('here will be login page')
  27. })
  28. const generateToken = (id, userName, isAdmin) => {
  29. const payload = {
  30. id,
  31. userName,
  32. isAdmin
  33. }
  34. return jwt.sign(payload, TOKEN_KEY);
  35. }
  36. const isValidUserName = (userName) => {
  37. const nameRegex = /[^A-Za-z0-9]/ ;
  38. return (!nameRegex.test(userName) && userName.trim());
  39. }
  40. const getAllDbUsers = async (socket) => {
  41. const usersDb = await User.find({})
  42. socket.emit('allDbUsers', usersDb)
  43. }
  44. app.post('/login', jsonParser, async (req, res) => {
  45. try {
  46. const {userName,password} = req.body;
  47. const dbUser = await User.findOne({userName})
  48. if (!isValidUserName(userName)){
  49. return res.status(400).json({message: 'Invalid username'})
  50. }
  51. if (dbUser && dbUser.isBanned){
  52. return res.status(401).json({message: 'Your account has been banned!!!'})
  53. }
  54. const hashPassword = await bcrypt.hash(password, HASH_KEY);
  55. const usersCount = await User.count().exec();
  56. const isFirst = !usersCount;
  57. let user;
  58. if (isFirst) { // if first create as admin
  59. user = new User({
  60. userName,
  61. hashPassword,
  62. isAdmin: true,
  63. isBanned: false,
  64. isMutted: false
  65. });
  66. await user.save();
  67. }
  68. user = await User.findOne({userName})
  69. if (!user) {
  70. user = new User({
  71. userName,
  72. hashPassword,
  73. isAdmin: false,
  74. isBanned: false,
  75. isMutted: false
  76. });
  77. await user.save()
  78. }
  79. if (!bcrypt.compareSync(password, user.hashPassword)){
  80. return res.status(400).json({message: 'Invalid credantials'})
  81. }
  82. const token = generateToken(user._id, userName, user.isAdmin);
  83. res.json({token})
  84. } catch (e) {
  85. console.log(e)
  86. res.status(500).json({message: `Error ${e}`})
  87. }
  88. })
  89. //use auth token
  90. io.use( async (socket, next) => {
  91. const token = socket.handshake.auth.token;
  92. const sockets = await io.fetchSockets();
  93. const usersOnline = [];
  94. sockets.map((sock) => {
  95. usersOnline.push(sock.user);
  96. })
  97. if(!token) {
  98. socket.disconnect();
  99. return
  100. }
  101. try {
  102. const user = jwt.verify(token, TOKEN_KEY)
  103. socket.user = user;
  104. socket.user.color = randomColor();
  105. const exist = sockets.find(current => current.user.userName == socket.user.userName)
  106. if(exist) { //&& !user.isAdmin - add for two or more admins
  107. console.log('exist twice entering...')
  108. exist.disconnect();
  109. return // ?
  110. }
  111. } catch(e) {
  112. console.log(e)
  113. socket.disconnect();
  114. return
  115. }
  116. next();
  117. });
  118. io.on("connection", async (socket) => {
  119. const userName = socket.user.userName;
  120. const sockets = await io.fetchSockets();
  121. let dbUser = await User.findOne({userName})
  122. let results = [];
  123. sockets.map((sock) => {
  124. results.push(sock.user);
  125. })
  126. io.emit('usersOnline', results) // send array online users
  127. socket.emit('connected', dbUser) //socket.user
  128. if(socket.user.isAdmin) getAllDbUsers(socket); //sent all users from db to admin
  129. const messagesToShow = await Message.find({}).sort({ 'createDate': -1 }).limit(20)
  130. socket.emit('allmessages', messagesToShow.reverse())
  131. socket.on("message", async (data) => {
  132. const userName = socket.user.userName;
  133. const dateNow = Date.now();
  134. const post = await Message.findOne({userName}).sort({ 'createDate': -1 })
  135. if(post){
  136. if(((Date.now() - Date.parse(post.createDate)) > 15000)){//change later 15000
  137. const message = new Message({
  138. text: data.message,
  139. userName: userName,
  140. createDate: Date.now()
  141. });
  142. try {
  143. await message.save()
  144. } catch (error) {
  145. console.log(error)
  146. }
  147. io.emit('message', message)
  148. }
  149. } else {
  150. const message = new Message({
  151. text: data.message,
  152. userName: userName,
  153. createDate: Date.now()
  154. });
  155. try {
  156. await message.save()
  157. } catch (error) {
  158. console.log(error)
  159. }
  160. io.emit('message', message)
  161. }
  162. });
  163. try {
  164. socket.on("disconnect", async () => {
  165. const sockets = await io.fetchSockets();
  166. const results = [];
  167. sockets.map((sock) => {
  168. results.push(sock.user);
  169. })
  170. io.emit('usersOnline', results)
  171. console.log(`user :${socket.user.userName} , disconnected to socket`);
  172. });
  173. console.log(`user :${socket.user.userName} , connected to socket`);
  174. } catch (e) {
  175. console.log(e)
  176. }
  177. try {
  178. socket.on("muteUser",async (data) => {
  179. const {user, prevStatus} = data;
  180. const sockets = await io.fetchSockets();
  181. const mute = await User.updateOne({userName : user}, {$set: {isMutted :!prevStatus}});
  182. getAllDbUsers(socket)
  183. const exist = sockets.find( current => current.user.userName == user)
  184. const dbUser = await User.findOne({userName : user})
  185. if(exist){
  186. exist.emit('connected', dbUser)
  187. }
  188. });
  189. } catch (e) {
  190. console.log(e)
  191. }
  192. try {
  193. socket.on("banUser",async (data) => {
  194. if(socket.user.isAdmin) {
  195. const {user, prevStatus} = data;
  196. const sockets = await io.fetchSockets();
  197. const ban = await User.updateOne({userName : user}, {$set: {isBanned:!prevStatus}});
  198. getAllDbUsers(socket)
  199. const exist = sockets.find( current => current.user.userName == user)
  200. const dbUser = await User.findOne({userName : user})
  201. if(exist){
  202. exist.disconnect();
  203. }}
  204. });
  205. } catch (e) {
  206. console.log(e)
  207. }
  208. });
  209. //server and database start
  210. const start = async () => {
  211. try {
  212. await mongoose.connect('mongodb://localhost:27017/chat')
  213. .then(() => console.log(`DB started`))
  214. server.listen(PORT, () => {
  215. console.log(`Server started. Port: ${PORT}`)
  216. })
  217. } catch (e) {
  218. console.log(e)
  219. }
  220. }
  221. start();