|
@@ -5,15 +5,13 @@ const server = require('http').createServer(app);
|
|
|
const mongoose = require('mongoose');
|
|
|
const bcrypt = require('bcrypt');
|
|
|
const User = require('./db/models/User');
|
|
|
+const Message = require('./db/models/Message');
|
|
|
const jwt = require('jsonwebtoken');
|
|
|
|
|
|
|
|
|
-
|
|
|
const PORT = process.env.PORT || 4000;
|
|
|
-const HASH_KEY = process.env.HASH_KEY;
|
|
|
const TOKEN_KEY = process.env.TOKEN_KEY || 'rGH452fdfhdfg06hgj7';
|
|
|
|
|
|
-
|
|
|
const socket = require('socket.io');
|
|
|
const cors = require('cors');
|
|
|
|
|
@@ -21,55 +19,204 @@ app.get('/', (req, res) => {
|
|
|
res.send('Hello from express server!')
|
|
|
})
|
|
|
|
|
|
+
|
|
|
app.use(cors());
|
|
|
app.use(express.json());
|
|
|
|
|
|
const io = socket(server, {
|
|
|
cors: {
|
|
|
- origin: "http://localhost:3000"
|
|
|
+ origin: "http://localhost:3000"
|
|
|
}
|
|
|
});
|
|
|
|
|
|
-const generateToken = (id, userName) => {
|
|
|
+const generateToken = (id, userName, isAdmin) => {
|
|
|
const payload = {
|
|
|
id,
|
|
|
userName,
|
|
|
+ isAdmin
|
|
|
}
|
|
|
return jwt.sign(payload, TOKEN_KEY);
|
|
|
}
|
|
|
|
|
|
const getOneUser = async (userName) => {
|
|
|
+ const userInDb = await User.findOne({userName});
|
|
|
return userInDb;
|
|
|
}
|
|
|
|
|
|
-const user = getOneUser('Sergey');
|
|
|
-
|
|
|
-io.on("connection", async (socket) => {
|
|
|
- console.log(socket.id);
|
|
|
- const userInDb = await User.findOne({userName: 'Sergey'});
|
|
|
- socket.emit('connected', userInDb);
|
|
|
-});
|
|
|
+const isValidUserName = (userName) => {
|
|
|
+ const nameRegex = /[^A-Za-z0-9]/ ;
|
|
|
+ return (!nameRegex.test(userName) && userName.trim().length > 2);
|
|
|
+}
|
|
|
|
|
|
+const getAllDbUsers = async (socket) => {
|
|
|
+ const usersDb = await User.find({})
|
|
|
+ socket.emit('allDbUsers', usersDb)
|
|
|
+}
|
|
|
|
|
|
|
|
|
+app.post('/login', async (req, res) => {
|
|
|
+ try {
|
|
|
+ const {userName,password} = req.body;
|
|
|
+ if (!isValidUserName(userName)){
|
|
|
+ return res.status(400).json({message: 'Invalid username'})
|
|
|
+ }
|
|
|
+ const dbUser = await getOneUser(userName)
|
|
|
+ if (dbUser?.isBanned){
|
|
|
+ return res.status(401).json({message: 'Your account has been banned!!!'})
|
|
|
+ }
|
|
|
+ const salt =await bcrypt.genSalt(2);
|
|
|
+ const hashPassword = await bcrypt.hash(password, salt);
|
|
|
+ if (!dbUser) {
|
|
|
+ const user = new User({
|
|
|
+ userName,
|
|
|
+ hashPassword,
|
|
|
+ isAdmin: !await User.count().exec(),
|
|
|
+ isBanned: false,
|
|
|
+ isMutted: false
|
|
|
+ });
|
|
|
+ await user.save()
|
|
|
+ return res.json({
|
|
|
+ token: generateToken(user.id, user.userName, user.isAdmin)
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dbUser && !bcrypt.compareSync(password, dbUser.hashPassword)){
|
|
|
+ return res.status(400).json({message: 'Invalid credantials'})
|
|
|
+ }
|
|
|
+ res.json({
|
|
|
+ token: generateToken(dbUser.id, dbUser.userName, dbUser.isAdmin)
|
|
|
+ })
|
|
|
+
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+ res.status(500).json({message: `Error ${e}`});
|
|
|
+ }
|
|
|
+})
|
|
|
|
|
|
-const db = async () => {
|
|
|
- try{
|
|
|
- const salt = await bcrypt.genSalt(2);
|
|
|
- const hashPassword = await bcrypt.hash('myPassword', salt);
|
|
|
- const user = new User({
|
|
|
- userName: 'Sergey',
|
|
|
- hashPassword: hashPassword
|
|
|
- })
|
|
|
- user.save();
|
|
|
- }catch(e){
|
|
|
- console.log(e)
|
|
|
+io.use(async (socket, next) => {
|
|
|
+ const token = socket.handshake.auth.token;
|
|
|
+ const sockets = await io.fetchSockets();
|
|
|
+ if(!token) {
|
|
|
+ socket.disconnect();
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
-}
|
|
|
+ const usersOnline = [];
|
|
|
+ sockets.map((sock) => {
|
|
|
+ usersOnline.push(sock.user);
|
|
|
+ })
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ try {
|
|
|
+ const user = jwt.verify(token, TOKEN_KEY);
|
|
|
+ const userName = user.userName;
|
|
|
+ const dbUser = await getOneUser(userName);
|
|
|
+ if(dbUser.isBanned){
|
|
|
+ socket.disconnect();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ socket.user = user;
|
|
|
+ const exist = sockets.find((current) => current.user.userName == socket.user.userName)
|
|
|
+
|
|
|
+ if(exist) {
|
|
|
+ console.log(exist.userName, 'exist twice entering...')
|
|
|
+ exist.disconnect();
|
|
|
+ }
|
|
|
+ } catch(e) {
|
|
|
+ console.log(e);
|
|
|
+ socket.disconnect();
|
|
|
+ }
|
|
|
+ next();
|
|
|
+});
|
|
|
|
|
|
+io.on("connection", async (socket) => {
|
|
|
+ const userName = socket.user.userName;
|
|
|
+ const sockets = await io.fetchSockets();
|
|
|
+ const dbUser = await getOneUser(userName);
|
|
|
+
|
|
|
+ io.emit('usersOnline', sockets.map((sock) => sock.user));
|
|
|
+ socket.emit('connected', dbUser);
|
|
|
+
|
|
|
+ if(socket.user.isAdmin){
|
|
|
+ getAllDbUsers(socket);
|
|
|
+ }
|
|
|
+
|
|
|
+ const messagesToShow = await Message.find({}).sort({ 'createDate': -1 }).limit(20);
|
|
|
+
|
|
|
+ socket.emit('allmessages', messagesToShow.reverse());
|
|
|
+ socket.on("message", async (data) => {
|
|
|
+ const dateNow = Date.now();
|
|
|
+ const post = await Message.findOne({userName}).sort({ 'createDate': -1 })
|
|
|
+ const oneUser = await getOneUser(userName);
|
|
|
+ if(oneUser.isMutted){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(post && ((Date.now() - Date.parse(post?.createDate)) < 5000)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(!oneUser.isMutted && data){
|
|
|
+ const message = new Message({
|
|
|
+ text: data.message,
|
|
|
+ userName: userName,
|
|
|
+ createDate: Date.now()
|
|
|
+ });
|
|
|
+ try {
|
|
|
+ await message.save();
|
|
|
+ console.log('saved to db')
|
|
|
+ } catch (error) {
|
|
|
+ console.log('Message save to db error', error);
|
|
|
+ }
|
|
|
+ io.emit('message', message);
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ try {
|
|
|
+ socket.on("disconnect", async () => {
|
|
|
+ const sockets = await io.fetchSockets();
|
|
|
+ io.emit('usersOnline', sockets.map((sock) => sock.user));
|
|
|
+ console.log(`user :${socket.user.userName} , disconnected to socket`);
|
|
|
+ });
|
|
|
+ console.log(`user :${socket.user.userName} , connected to socket`);
|
|
|
+
|
|
|
+ socket.on("muteUser",async (data) => {
|
|
|
+ if(!socket.user.isAdmin){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const {user, prevStatus} = data;
|
|
|
+ const sockets = await io.fetchSockets();
|
|
|
+ const mute = await User.updateOne({userName : user}, {$set: {isMutted :!prevStatus}});
|
|
|
+ getAllDbUsers(socket);
|
|
|
+ const exist = sockets.find( current => current.user.userName == user)
|
|
|
+ const dbUser = await getOneUser(user);
|
|
|
+
|
|
|
+ if(exist){
|
|
|
+ exist.emit('connected', dbUser);
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("banUser",async (data) => {
|
|
|
+ if(!socket.user.isAdmin){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const {user, prevStatus} = data;
|
|
|
+ const sockets = await io.fetchSockets();
|
|
|
+ const ban = await User.updateOne({userName : user}, {$set: {isBanned:!prevStatus}});
|
|
|
+ getAllDbUsers(socket)
|
|
|
+ const exist = sockets.find( current => current.user.userName == user)
|
|
|
+
|
|
|
+ if(exist){
|
|
|
+ exist.disconnect();
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+ }
|
|
|
+});
|
|
|
const start = async () => {
|
|
|
try {
|
|
|
await mongoose.connect('mongodb://localhost:27017/chat')
|