Browse Source

done logic to send messages

unknown 2 years ago
parent
commit
b90a8e70b0

+ 2 - 0
app.js

@@ -6,6 +6,7 @@ const helmet = require('helmet');
 const apiLimiter = require('./helpers/apiLimiter');
 
 const chatsRouter = require('./routes/chats');
+const messagesRouter = require('./routes/messages');
 const contactsRouter = require('./routes/contacts');
 const userRoute = require('./routes/user');
 const app = express();
@@ -22,6 +23,7 @@ app.use(cors());
 app.use(express.json());
 
 app.use('/api/chats', apiLimiter, chatsRouter);
+app.use('/api/messages', apiLimiter, messagesRouter);
 app.use('/api/contacts', apiLimiter, contactsRouter);
 app.use('/api', apiLimiter, userRoute);
 

+ 5 - 4
controllers/chats.js

@@ -32,7 +32,7 @@ const startChat = async (req, res, next) => {
 			avatarUrl: AvatarUrl,
 			color: Color,
 		} = user;
-		if ((companion && isUser) || isCompanion) {
+		if (companion && (isUser || isCompanion)) {
 			await ChatModel.update(isUser._id, { name, lastName, avatarUrl, color });
 			await ChatModel.update(isCompanion._id, {
 				name: Name,
@@ -40,15 +40,16 @@ const startChat = async (req, res, next) => {
 				avatarUrl: AvatarUrl,
 				color: Color,
 			});
+			const updatedUser = await ChatModel.getByField(id, userId);
 			return res.status(200).json({
 				status: 'success',
 				code: 200,
-				data: companion,
+				data: updatedUser,
 			});
 		}
 
 		if (companion && !isUser && !isCompanion) {
-			await ChatModel.add({
+			const updatedUser = await ChatModel.add({
 				name,
 				lastName,
 				avatarUrl,
@@ -67,7 +68,7 @@ const startChat = async (req, res, next) => {
 			return res.status(201).json({
 				status: 'success',
 				code: 201,
-				data: companion,
+				data: updatedUser,
 			});
 		}
 	} catch (e) {

+ 86 - 0
controllers/messages.js

@@ -0,0 +1,86 @@
+const MessageModel = require('../model/message');
+const UserModel = require('../model/user');
+const ChatModel = require('../model/chat');
+
+const listMessages = async (req, res, next) => {
+	try {
+		const userId = req.user.id;
+		const chats = await MessageModel.getList(userId, req.query);
+		return res.json({
+			status: 'success',
+			code: 200,
+			data: {
+				...chats,
+			},
+		});
+	} catch (e) {
+		next(e);
+	}
+};
+
+const listMessagesById = async (req, res, next) => {
+	try {
+		const userId = req.user.id;
+		const companionId = req.params.companionId;
+		const chats = await MessageModel.getListById(companionId, userId);
+
+		return res.json({
+			status: 'success',
+			code: 200,
+			data: [...chats],
+		});
+	} catch (e) {
+		next(e);
+	}
+};
+
+const sentMessage = async (req, res, next) => {
+	try {
+		const { id, message } = req.body;
+		const user = req.user;
+		const userId = user.id;
+		const companion = await UserModel.findById(id);
+		const isUser = await ChatModel.getByField(id, userId);
+		const isCompanion = await ChatModel.getByField(userId, id);
+		const { name, lastName, avatarUrl, color } = companion;
+		const {
+			name: Name,
+			lastName: LastName,
+			avatarUrl: AvatarUrl,
+			color: Color,
+		} = user;
+		if (companion && isUser && isCompanion) {
+			const newMessage = await MessageModel.add({
+				message,
+				name,
+				lastName,
+				avatarUrl,
+				color,
+				companionId: id,
+				owner: userId,
+			});
+			await MessageModel.add({
+				message,
+				name: Name,
+				lastName: LastName,
+				avatarUrl: AvatarUrl,
+				color: Color,
+				companionId: userId,
+				owner: id,
+			});
+			return res.status(201).json({
+				status: 'success',
+				code: 201,
+				data: newMessage,
+			});
+		}
+	} catch (e) {
+		next(e);
+	}
+};
+
+module.exports = {
+	listMessages,
+	sentMessage,
+	listMessagesById,
+};

+ 0 - 43
model/__mocks__/contact.js

@@ -1,43 +0,0 @@
-const { contacts } = require("./data");
-
-const getList = jest.fn(
-  (
-    _userId,
-    { _sortBy, _sortByDesc, _filter, limit = "5", page = "1", _sub }
-  ) => {
-    return { contacts, total: contacts.length, limit, page };
-  }
-);
-
-const getById = jest.fn((id, _userId) => {
-  const [contact] = contacts.filter((el) => el._id === id);
-
-  return contact;
-});
-
-const add = jest.fn((newContact) => {
-  const contact = { ...newContact, _id: "604cec3345d8c632bc1fake3" };
-  contacts.push(contact);
-  return contact;
-});
-
-const update = jest.fn((id, body, _userId) => {
-  let [contact] = contacts.filter((el) => el._id === id);
-  if (contact) return (contact = { ...contact, ...body });
-});
-
-const remove = jest.fn((id, _userId) => {
-  const index = contacts.findIndex((el) => String(el._id) === String(id));
-  if (index === -1) return null;
-
-  const [contact] = contacts.splice(index, 1);
-  return contact;
-});
-
-module.exports = {
-  getList,
-  getById,
-  add,
-  remove,
-  update,
-};

+ 0 - 43
model/__mocks__/data.js

@@ -1,43 +0,0 @@
-const contacts = [
-  {
-    _id: "604cec2a45d8c632bc1fake1",
-    name: "FAKE-ONE",
-    phone: "0915088491",
-    subscription: "free",
-  },
-  {
-    _id: "604cec3345d8c632bc1fake2",
-    name: "FAKE-SECOND",
-    phone: "0914088491",
-    subscription: "free",
-  },
-  {
-    _id: "604cec3345d8c632bc1fake3",
-    name: "FAKE-SECOND",
-    phone: "0914088491",
-    subscription: "free",
-  },
-];
-const newContact = {
-  name: "newUser",
-  phone: "9810088491",
-  subscription: "free",
-};
-
-const User = {
-  subscription: "free",
-  token:
-    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYwNGUzMTY4YTA1ZDNkMzQzMDBjMDA0ZiIsImlhdCI6MTYxNTczNzIyNSwiZXhwIjoxNjE1NzQ0NDI1fQ.8byA4KylqGkp9j9AV1eqL1EogAA0VDxr2GbBB7YIkoA",
-  _id: "604cec3345d8c632bc1fake2",
-  email: "12345678@gmail.com",
-  password: "$2a$08$7Ri2ggA1VXgal7.MUrnRa.rS1lja0y6j0VRQMu495ssO5PFyQ1hQO",
-  avatarUrl:
-    "https://s.gravatar.com/avatar/0ffd40d14c2320ab59aa28ff91e8d813?s=250",
-};
-
-const users = [];
-users[0] = User;
-
-const newUser = { email: "newuser@gmail.com", password: "newUser" };
-
-module.exports = { contacts, newContact, users, User, newUser };

+ 0 - 36
model/__mocks__/user.js

@@ -1,36 +0,0 @@
-const { users } = require("./data");
-
-const findByEmail = jest.fn((email) => {
-  const [user] = users.filter((el) => String(el.email) === String(email));
-  return user;
-});
-
-const findById = jest.fn((id) => {
-  const [user] = users.filter((el) => String(el._id) === String(id));
-  return user;
-});
-
-const createUser = jest.fn(({ name, email, password }) => {
-  return {};
-});
-
-const updateName = jest.fn((id, body) => {
-  return {};
-});
-
-const updateToken = jest.fn((id, token) => {
-  return {};
-});
-
-const updateAvatar = jest.fn((id, avatarUrl) => {
-  return {};
-});
-
-module.exports = {
-  findByEmail,
-  createUser,
-  updateToken,
-  updateName,
-  updateAvatar,
-  findById,
-};

+ 3 - 2
model/chat.js

@@ -2,7 +2,7 @@ const Chat = require('./schemas/chat');
 
 const getList = async (
 	userId,
-	{ sortBy, sortByDesc, filter, limit = '5', page = '1', sub }
+	{ sortBy, sortByDesc, filter, limit = '500', page = '1', sub }
 ) => {
 	const options = { owner: userId };
 	if (sub) options.subscription = { $all: [sub] };
@@ -37,7 +37,8 @@ const add = async (obj) => {
 };
 
 const update = async (id, obj) => {
-	return await Chat.updateOne({ _id: id }, { ...obj });
+	const chat = await Chat.updateOne({ _id: id }, { ...obj });
+	return chat;
 };
 
 module.exports = {

+ 1 - 1
model/contact.js

@@ -2,7 +2,7 @@ const Contact = require('./schemas/contact');
 
 const getList = async (
 	userId,
-	{ sortBy, sortByDesc, filter, limit = '5', page = '1', sub }
+	{ sortBy, sortByDesc, filter, limit = '500', page = '1', sub }
 ) => {
 	const options = { owner: userId };
 	if (sub) options.subscription = { $all: [sub] };

+ 70 - 0
model/message.js

@@ -0,0 +1,70 @@
+const Message = require('./schemas/message');
+
+const getList = async (
+	userId,
+	{ sortBy, sortByDesc, filter, limit = '500', page = '1', sub }
+) => {
+	const options = { owner: userId };
+	if (sub) options.subscription = { $all: [sub] };
+	const results = await Message.paginate(options, {
+		limit,
+		page,
+		sort: {
+			...(sortBy ? { [`${sortBy}`]: 1 } : {}),
+			...(sortByDesc ? { [`${sortByDesc}`]: -1 } : {}),
+		},
+		select: filter ? filter.split('|').join(' ') : '',
+		populate: {
+			path: 'owner',
+			select: '_id',
+		},
+	});
+	const { docs: messages, totalDocs: total } = results;
+	return { total: total.toString(), limit, page, messages };
+};
+
+const getListById = async (companionId, userId) => {
+	const messages = await Message.find({
+		companionId,
+		owner: userId,
+	});
+	return messages;
+};
+
+const getById = async (id, userId) => {
+	const foundContact = await Message.findById({
+		_id: id,
+		owner: userId,
+	});
+	return foundContact;
+};
+
+const getByField = async (number, userId) => {
+	const contact = await Message.findOne({
+		number,
+		owner: userId,
+	});
+	return contact;
+};
+
+const add = async (obj) => {
+	const contact = await Message.create(obj);
+	return contact;
+};
+
+const remove = async (id, userId) => {
+	const removedContact = await Message.findByIdAndRemove({
+		_id: id,
+		owner: userId,
+	});
+	return removedContact;
+};
+
+module.exports = {
+	getList,
+	getListById,
+	getByField,
+	getById,
+	add,
+	remove,
+};

+ 1 - 0
model/schemas/contact.js

@@ -8,6 +8,7 @@ const contactSchema = new Schema(
 	{
 		companionId: {
 			type: String,
+			default: null,
 		},
 		name: {
 			type: String,

+ 44 - 0
model/schemas/message.js

@@ -0,0 +1,44 @@
+const mongoose = require('mongoose');
+const { Schema, model, SchemaTypes } = mongoose;
+const mongoosePaginate = require('mongoose-paginate-v2');
+
+mongoose.Types.ObjectId.isValid();
+
+const messageSchema = new Schema(
+	{
+		message: {
+			type: String,
+			default: null,
+		},
+		companionId: {
+			type: String,
+			default: null,
+		},
+		name: {
+			type: String,
+			default: null,
+		},
+		lastName: {
+			type: String,
+			default: null,
+		},
+		avatarUrl: {
+			type: String,
+			default: null,
+		},
+		color: {
+			type: String,
+			default: null,
+		},
+		owner: {
+			type: SchemaTypes.ObjectId,
+			ref: 'user',
+		},
+	},
+
+	{ timestamps: true }
+);
+messageSchema.plugin(mongoosePaginate);
+const Message = model('message', messageSchema);
+
+module.exports = Message;

File diff suppressed because it is too large
+ 20936 - 20750
package-lock.json


+ 50 - 49
package.json

@@ -1,51 +1,52 @@
 {
-  "name": "template",
-  "version": "0.0.0",
-  "private": true,
-  "scripts": {
-    "start": "cross-env NODE_ENV=production node ./bin/server.js",
-    "start:dev": "cross-env NODE_ENV=development nodemon ./bin/server.js",
-    "lint": "eslint **/*.{js,json}",
-    "lint:fix": "eslint --fix **/*.{js,json}",
-    "dev:debug": "node --inspect ./bin/server.js",
-    "test": "cross-env NODE_ENV=test jest --no-cache --verbose",
-    "test:coverage": "jest --coverage",
-    "test:watch": "jest --watchAll"
-  },
-  "dependencies": {
-    "bcryptjs": "2.4.3",
-    "chalk": "^3.0.0",
-    "cloudinary": "1.25.0",
-    "cors": "2.8.5",
-    "cross-env": "7.0.3",
-    "dotenv": "8.2.0",
-    "express": "4.17.1",
-    "express-rate-limit": "5.2.6",
-    "generate-sms-verification-code": "^1.0.5",
-    "gravatar": "1.8.1",
-    "helmet": "4.4.1",
-    "jimp": "0.16.1",
-    "joi": "17.4.0",
-    "jsonwebtoken": "8.5.1",
-    "mongoose": "5.11.18",
-    "mongoose-paginate-v2": "1.3.16",
-    "morgan": "1.10.0",
-    "multer": "^1.4.2",
-    "passport": "0.4.1",
-    "passport-jwt": "4.0.0",
-    "shortid": "^2.2.16",
-    "twilio": "^3.73.1"
-  },
-  "devDependencies": {
-    "eslint": "^7.19.0",
-    "eslint-config-prettier": "7.2.0",
-    "eslint-config-standard": "^16.0.2",
-    "eslint-plugin-import": "^2.22.1",
-    "eslint-plugin-json": "2.1.2",
-    "eslint-plugin-node": "^11.1.0",
-    "eslint-plugin-promise": "^4.2.1",
-    "jest": "26.6.3",
-    "nodemon": "2.0.7",
-    "supertest": "^6.1.3"
-  }
+	"name": "template",
+	"version": "0.0.0",
+	"private": true,
+	"scripts": {
+		"start": "cross-env NODE_ENV=production node ./bin/server.js",
+		"start:dev": "cross-env NODE_ENV=development nodemon ./bin/server.js",
+		"lint": "eslint **/*.{js,json}",
+		"lint:fix": "eslint --fix **/*.{js,json}",
+		"dev:debug": "node --inspect ./bin/server.js",
+		"test": "cross-env NODE_ENV=test jest --no-cache --verbose",
+		"test:coverage": "jest --coverage",
+		"test:watch": "jest --watchAll"
+	},
+	"dependencies": {
+		"bcryptjs": "2.4.3",
+		"chalk": "^3.0.0",
+		"cloudinary": "1.25.0",
+		"cors": "2.8.5",
+		"cross-env": "7.0.3",
+		"dotenv": "8.2.0",
+		"express": "4.17.1",
+		"express-rate-limit": "5.2.6",
+		"generate-sms-verification-code": "^1.0.5",
+		"gravatar": "1.8.1",
+		"helmet": "4.4.1",
+		"jimp": "0.16.1",
+		"joi": "17.4.0",
+		"jsonwebtoken": "8.5.1",
+		"mongoose": "5.11.18",
+		"mongoose-paginate-v2": "1.3.16",
+		"morgan": "1.10.0",
+		"multer": "^1.4.2",
+		"passport": "0.4.1",
+		"passport-jwt": "4.0.0",
+		"shortid": "^2.2.16",
+		"socket.io": "4.0.0",
+		"twilio": "^3.73.1"
+	},
+	"devDependencies": {
+		"eslint": "^7.19.0",
+		"eslint-config-prettier": "7.2.0",
+		"eslint-config-standard": "^16.0.2",
+		"eslint-plugin-import": "^2.22.1",
+		"eslint-plugin-json": "2.1.2",
+		"eslint-plugin-node": "^11.1.0",
+		"eslint-plugin-promise": "^4.2.1",
+		"jest": "26.6.3",
+		"nodemon": "2.0.7",
+		"supertest": "^6.1.3"
+	}
 }

+ 1 - 1
routes/chats.js

@@ -2,7 +2,7 @@ const express = require('express');
 const router = express.Router();
 const guard = require('../helpers/guard');
 const controllers = require('../controllers/chats');
-const validation = require('../validation/chats');
+const validation = require('../validation/chat');
 
 router
 	.get('/', guard, controllers.listChats)

+ 13 - 0
routes/messages.js

@@ -0,0 +1,13 @@
+const express = require('express');
+const router = express.Router();
+const guard = require('../helpers/guard');
+const controllers = require('../controllers/messages');
+const validation = require('../validation/message');
+
+router
+	.get('/', guard, controllers.listMessages)
+	.post('/', guard, validation.sentMessage, controllers.sentMessage);
+
+router.get('/:companionId', guard, controllers.listMessagesById);
+
+module.exports = router;

+ 0 - 176
test/contacts.e2.test.js

@@ -1,176 +0,0 @@
-const jwt = require("jsonwebtoken");
-require("dotenv").config();
-const request = require("supertest");
-const { User, contacts, newContact } = require("../model/__mocks__/data");
-const app = require("../app");
-
-const SECRET_KEY = process.env.JWT_SECRET;
-const issueToken = (payload, secret) => jwt.sign(payload, secret);
-const token = issueToken({ id: User._id }, SECRET_KEY);
-User.token = token;
-const wrongId = "lol";
-const wrongToken = "lol";
-const contact = contacts[0];
-
-jest.mock("../model/contact.js");
-jest.mock("../model/user.js");
-
-describe("Test for route /api/contacts", () => {
-  let idNewContact;
-  describe("should handle request PATCH contact by id ", () => {
-    it("should return 200 on request PATCH contact", async (done) => {
-      const res = await request(app)
-        .patch(`/api/contacts/${contact._id}`)
-        .set("Authorization", `Bearer ${token}`)
-        .send({ phone: "0995688412" })
-        .set("Accept", "application/json");
-      expect(res.status).toEqual(200);
-      done();
-    });
-    it("should return 404 on request PATCH  contacts by id", async (done) => {
-      const res = await request(app)
-        .patch(`/api/contacts/${wrongId}`)
-        .set("Authorization", `Bearer ${token}`)
-        .send({ name: "Grigore" });
-      expect(res.status).toEqual(404);
-      expect(res.body).toBeDefined();
-      done();
-    });
-    it("should return 403 on request on request PATCH  contacts by id without token", async (done) => {
-      const res = await request(app)
-        .patch(`/api/contacts/${contact._id}`)
-        .set("Authorization", `Bearer ${wrongToken}`)
-        .send({ name: "Grigore" })
-        .set("Accept", "application/json");
-      expect(res.status).toEqual(403);
-      expect(res.body).toBeDefined();
-      done();
-    });
-    it("should return 500 on request on request PATCH  with wrong filed", async (done) => {
-      const res = await request(app)
-        .patch(`/api/contacts/${contact._id}`)
-        .set("Authorization", `Bearer ${token}`)
-        .send({ WrongField: "Grigore" })
-        .set("Accept", "application/json");
-      expect(res.status).toEqual(500);
-      expect(res.body).toBeDefined();
-      done();
-    });
-  });
-  describe("should handle GET request", () => {
-    it("should return 200 on GET request All contacts", async (done) => {
-      const res = await request(app)
-        .get(`/api/contacts`)
-        .set("Authorization", `Bearer ${token}`);
-      expect(res.status).toEqual(200);
-      expect(res.body).toBeDefined();
-      expect(res.body.data.contacts).toBeInstanceOf(Array);
-      done();
-    });
-    it("should return 403 on GET request All contacts by wrong  token", async (done) => {
-      const res = await request(app)
-        .get(`/api/contacts`)
-        .set("Authorization", `Bearer ${wrongToken}`);
-      expect(res.status).toEqual(403);
-      expect(res.body).toBeDefined();
-      done();
-    });
-    it("should return 200 on request GET  contact by ID", async (done) => {
-      const res = await request(app)
-        .get(`/api/contacts/${contact._id}`)
-        .set("Authorization", `Bearer ${token}`);
-      expect(res.status).toEqual(200);
-      expect(res.body).toBeDefined();
-      expect(res.body.data.contact).toHaveProperty("_id");
-      expect(res.body.data.contact._id).toBe(contact._id);
-      done();
-    });
-    it("should return 403 on GET request GET  contact by ID by wrong  token", async (done) => {
-      const res = await request(app)
-        .get(`/api/contacts/${contact._id}`)
-        .set("Authorization", `Bearer ${wrongToken}`);
-      expect(res.status).toEqual(403);
-      expect(res.body).toBeDefined();
-      done();
-    });
-
-    it("should return 404 on request GET  contact by wrong ID", async (done) => {
-      const res = await request(app)
-        .get(`/api/contacts/${wrongId}`)
-        .set("Authorization", `Bearer ${token}`);
-      expect(res.status).toEqual(404);
-      expect(res.body).toBeDefined();
-      done();
-    });
-  });
-  describe("should handle POST request", () => {
-    it("should return 201 on request POST  create new contact", async (done) => {
-      const res = await request(app)
-        .post(`/api/contacts`)
-        .set("Authorization", `Bearer ${token}`)
-        .send(newContact)
-        .set("Accept", "application/json");
-      expect(res.status).toEqual(201);
-      expect(res.body).toBeDefined();
-      idNewContact = res.body.data.contact._id;
-      done();
-    });
-    it("should return 500 on request POST  with wrong field or fields", async (done) => {
-      const res = await request(app)
-        .post(`/api/contacts`)
-        .set("Authorization", `Bearer ${token}`)
-        .send({ ...newContact, wrongFiled: "axe" })
-        .set("Accept", "application/json");
-      expect(res.status).toEqual(500);
-      expect(res.body).toBeDefined();
-      done();
-    });
-    it("should return 500 on request POST without required fields like : name,email,phone,password,subscription", async (done) => {
-      const res = await request(app)
-        .post(`/api/contacts`)
-        .set("Authorization", `Bearer ${token}`)
-        .send({ name: "Simon" })
-        .set("Accept", "application/json");
-      expect(res.status).toEqual(500);
-      expect(res.body).toBeDefined();
-      done();
-    });
-    it("should return 403 on request POST without token", async (done) => {
-      const res = await request(app)
-        .post(`/api/contacts`)
-        .set("Authorization", `Bearer ${wrongToken}`)
-        .send(newContact)
-        .set("Accept", "application/json");
-      expect(res.status).toEqual(403);
-      expect(res.body).toBeDefined();
-      done();
-    });
-  });
-  describe("should handle request DELETE contact by id ", () => {
-    it("should return 201 on request DELETE  contact", async (done) => {
-      const res = await request(app)
-        .delete(`/api/contacts/${contact._id}`)
-        .set("Authorization", `Bearer ${token}`);
-      expect(res.status).toEqual(200);
-      expect(res.body).toBeDefined();
-      contacts.pop(contact);
-      done();
-    });
-    it("should return 404 on request DELETE  contacts by id", async (done) => {
-      const res = await request(app)
-        .delete(`/api/contacts/${wrongId}`)
-        .set("Authorization", `Bearer ${token}`);
-      expect(res.status).toEqual(404);
-      expect(res.body).toBeDefined();
-      done();
-    });
-    it("should return 403 on request on request DELETE  contacts by id without token", async (done) => {
-      const res = await request(app)
-        .delete(`/api/contacts/${contact._id}`)
-        .set("Authorization", `Bearer ${wrongToken}`);
-      expect(res.status).toEqual(403);
-      expect(res.body).toBeDefined();
-      done();
-    });
-  });
-});

validation/chats.js → validation/chat.js


+ 11 - 0
validation/message.js

@@ -0,0 +1,11 @@
+const Joi = require('joi');
+
+const validate = require('./validate');
+
+const schemaSentMessage = Joi.object({
+	id: Joi.string().required(),
+	message: Joi.string().min(1).max(1400).required(),
+});
+module.exports.sentMessage = (req, _res, next) => {
+	return validate(schemaSentMessage, req.body, next);
+};