app.js 8.4 KB

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