diff --git a/app/config.js b/app/config.js
index f734ed3..6ad35b0 100644
--- a/app/config.js
+++ b/app/config.js
@@ -6,5 +6,4 @@ export const config = {
jwt: process.env.JWT_SECRET || "asdasdawe",
email: process.env.EMAIL,
password: process.env.EMAIL_PASSWORD,
- domain: ""
};
diff --git a/app/controllers/announcementsController.js b/app/controllers/announcementsController.js
index 8e81578..1fced31 100644
--- a/app/controllers/announcementsController.js
+++ b/app/controllers/announcementsController.js
@@ -24,16 +24,17 @@ export const getAnnouncements = async (req, res, next) => {
};
export const addAnnouncement = async (req, res, next) => {
- const { title, description, price, category, animal, city, user } = req.body;
+ const { title, description, price, category, animal, city } = req.body;
let creator;
try {
- creator = await User.findById(user);
+ creator = await User.findById(req.user.id);
} catch (e) {
res.status(422).json({ message: "Couldn't find user" });
return next();
}
+
const announcement = new Announcement({
title: title,
description: description,
@@ -43,6 +44,7 @@ export const addAnnouncement = async (req, res, next) => {
city: city,
user: creator,
});
+
try {
await announcement.save();
res.status(201).json(announcement);
diff --git a/app/controllers/opinionController.js b/app/controllers/opinionController.js
index 9c1ff97..aa6a602 100644
--- a/app/controllers/opinionController.js
+++ b/app/controllers/opinionController.js
@@ -2,10 +2,10 @@ import { Opinion } from "../db/models/OpinionSchema.js";
import { User } from "../db/models/UserSchema.js";
export const addOpinion = async (req, res, next) => {
- const { rate, opinion, user } = req.body;
+ const { rate, opinion } = req.body;
let creator;
try {
- creator = await User.findById(user);
+ creator = await User.findById(req.user.id);
} catch (error) {
res.status(422).json({ message: "Couldn't find user" });
return next();
diff --git a/app/controllers/userController.js b/app/controllers/userController.js
index 15c6366..2e0a996 100644
--- a/app/controllers/userController.js
+++ b/app/controllers/userController.js
@@ -33,8 +33,12 @@ export const login = async (req, res, next) => {
}
}
const isValidPassword = user.comparePassword(req.body.password);
+ const { _id, email, username, city, phone } = user;
if (isValidPassword) {
- const token = jsonwebtoken.sign({ id: user.id }, config.jwt);
+ const token = jsonwebtoken.sign(
+ { id: _id, email, username, city, phone },
+ config.jwt,
+ );
return res.header("auth-token", token).send(token);
}
return res.json({ error: "Invalid password" });
@@ -43,7 +47,7 @@ export const login = async (req, res, next) => {
}
};
-export const reset = async (req, res) => {
+export const forgot = async (req, res) => {
const email = req.body.email;
User.findOne({email: email}, (err, user) =>{
@@ -53,9 +57,7 @@ export const reset = async (req, res) => {
const token = jsonwebtoken.sign({ id: user.id }, config.jwt, {expiresIn: "20m"});
const transporter = nodemailer.createTransport({
- host: 'smtp.gmail.com',
- port: 465,
- secure: true,
+ service: "Gmail",
auth: {
user: config.email,
pass: config.password
@@ -66,7 +68,7 @@ export const reset = async (req, res) => {
from: config.email,
to: email,
subject: "Reset password",
- html: `
To reset your password click here
`
+ html: ` To reset your password click here
`
}
transporter.sendMail(mailOptions, (err, data) =>{
if(err){
@@ -82,6 +84,25 @@ export const reset = async (req, res) => {
})
})
}
+
+export const reset = async (req, res) => {
+ const token = req.params.token;
+ let newPassword = req.body.password;
+ let user;
+
+ let decoded = jsonwebtoken.decode(token);
+ user = await User.findById(decoded.id);
+ user.password = newPassword;
+
+try {
+ await user.save();
+ return res.status(200).json({message: "Password has been changed!"})
+
+} catch (error) {
+ res.status(400).json({error: error})
+}
+}
+
export const getUserData = async (req, res, next) => {
const id = req.params.uid;
let user;
@@ -93,6 +114,11 @@ export const getUserData = async (req, res, next) => {
city: user.city,
phone: user.phone,
announcements: user.announcements,
+ business: user.business,
+ description: user.description,
+ NIP: user.NIP,
+ openHour: user.openHour,
+ closeHour: user.closeHour,
});
} catch (error) {
res.status(422).json({ error: "User not found" });
@@ -107,23 +133,32 @@ export const updateUser = async (req, res, next) => {
} catch (error) {
res.status(400).json({ error: "User not found" });
}
- if(user.comparePassword(req.body.password)){
- const { city, phone, business, description, NIP, openHour, closeHour, password} = req.body;
- if(city) user.city = city;
- if(phone) user.phone = phone;
- if(business) user.business = business;
- if(description) user.description = description;
- if(NIP) user.NIP = NIP;
- if(openHour) user.openHour = openHour;
- if(closeHour) user.closeHour = closeHour;
- if(password) user.password = password;
+ if (user.comparePassword(req.body.password)) {
+ const {
+ city,
+ phone,
+ business,
+ description,
+ NIP,
+ openHour,
+ closeHour,
+ password,
+ } = req.body;
+ if (city) user.city = city;
+ if (phone) user.phone = phone;
+ if (business) user.business = business;
+ if (description) user.description = description;
+ if (NIP) user.NIP = NIP;
+ if (openHour) user.openHour = openHour;
+ if (closeHour) user.closeHour = closeHour;
+ if (password) user.password = password;
try {
await user.save();
- res.json({message: "Succesfully data changed!"})
+ res.json({ message: "Succesfully data changed!" });
} catch (error) {
- res.json({error: "Couldn't get data"});
+ res.json({ error: error });
}
- }else{
- return res.status(422).json({error: "invalid Password"})
+ } else {
+ return res.status(422).json({ error: "invalid Password" });
}
-};
+};
\ No newline at end of file
diff --git a/app/db/models/UserSchema.js b/app/db/models/UserSchema.js
index c62c55b..4176ce3 100644
--- a/app/db/models/UserSchema.js
+++ b/app/db/models/UserSchema.js
@@ -17,7 +17,6 @@ const UserSchema = new mongoose.Schema({
type: String,
required: true,
minLength: [4, "At least 4 characters"],
- maxlength: [30, "Max length is 30 characters"],
},
username: {
type: String,
diff --git a/app/index.js b/app/index.js
index 6d36127..1636183 100644
--- a/app/index.js
+++ b/app/index.js
@@ -5,6 +5,8 @@ import { opinionsRouter } from "./routes/opinionsRoutes.js";
import { userRouter } from "./routes/userRouter.js";
import "./db/mongoose.js";
import { config } from "./config.js";
+import swaggerUi from "swagger-ui-express";
+import swaggerFile from "./swagger-output.json" assert { type: "json" };
const app = express();
@@ -12,7 +14,10 @@ app.use(express.json());
app.use(function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
- res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH");
+ res.setHeader(
+ "Access-Control-Allow-Methods",
+ "GET, POST, DELETE, PUT, PATCH",
+ );
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
next();
});
@@ -21,6 +26,7 @@ app.use("/auth", authRouter);
app.use("/announcements", announcementRouter);
app.use("/opinions", opinionsRouter);
app.use("/user", userRouter);
+app.use("/doc", swaggerUi.serve, swaggerUi.setup(swaggerFile));
app
.listen(config.port, () => {
diff --git a/app/middleware/verifyToken.js b/app/middleware/verifyToken.js
index 868703b..38154f5 100644
--- a/app/middleware/verifyToken.js
+++ b/app/middleware/verifyToken.js
@@ -8,6 +8,7 @@ export function auth(req, res, next) {
try {
const verified = jwt.verify(token, config.jwt);
req.user = verified;
+ return next();
} catch (error) {
res.status(400).send("Invalid Token");
}
diff --git a/app/routes/authRoutes.js b/app/routes/authRoutes.js
index 353f4ad..3b9d4c3 100644
--- a/app/routes/authRoutes.js
+++ b/app/routes/authRoutes.js
@@ -1,16 +1,12 @@
import express from "express";
-import { login, register, reset } from "../controllers/userController.js";
+import { login, register, forgot, reset } from "../controllers/userController.js";
export const authRouter = express.Router();
authRouter.post("/login", login);
-authRouter.post("/forgot", (req, res) => {
- res.status(200).json({
- message: "Handling POST requests to /auth/forgot",
- });
-});
+authRouter.post("/forgot", forgot);
-authRouter.post("/reset", reset);
+authRouter.post("/reset/:token", reset);
authRouter.post("/register", register);
diff --git a/app/swagger-output.json b/app/swagger-output.json
new file mode 100644
index 0000000..d278f08
--- /dev/null
+++ b/app/swagger-output.json
@@ -0,0 +1,325 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "REST API",
+ "description": ""
+ },
+ "host": "localhost:3000",
+ "basePath": "/",
+ "schemes": [
+ "http"
+ ],
+ "paths": {
+ "/auth/login": {
+ "post": {
+ "description": "",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "example": "any"
+ },
+ "password": {
+ "example": "any"
+ }
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK"
+ }
+ }
+ }
+ },
+ "/auth/forgot": {
+ "post": {
+ "description": "",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "OK"
+ }
+ }
+ }
+ },
+ "/auth/reset": {
+ "post": {
+ "description": "",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "example": "any"
+ }
+ }
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Created"
+ },
+ "400": {
+ "description": "Bad Request"
+ }
+ }
+ }
+ },
+ "/auth/register": {
+ "post": {
+ "description": "",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "example": "any"
+ },
+ "password": {
+ "example": "any"
+ },
+ "username": {
+ "example": "any"
+ },
+ "city": {
+ "example": "any"
+ },
+ "phone": {
+ "example": "any"
+ }
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK"
+ },
+ "422": {
+ "description": "Unprocessable Entity"
+ }
+ }
+ }
+ },
+ "/announcements/{aid}": {
+ "get": {
+ "description": "",
+ "parameters": [
+ {
+ "name": "aid",
+ "in": "path",
+ "required": true,
+ "type": "string"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK"
+ }
+ }
+ }
+ },
+ "/announcements/": {
+ "get": {
+ "description": "",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "OK"
+ }
+ }
+ },
+ "post": {
+ "description": "",
+ "parameters": [
+ {
+ "name": "auth-token",
+ "in": "header",
+ "type": "string"
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "example": "any"
+ },
+ "description": {
+ "example": "any"
+ },
+ "price": {
+ "example": "any"
+ },
+ "category": {
+ "example": "any"
+ },
+ "animal": {
+ "example": "any"
+ },
+ "city": {
+ "example": "any"
+ }
+ }
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Created"
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "422": {
+ "description": "Unprocessable Entity"
+ }
+ }
+ }
+ },
+ "/opinions/": {
+ "get": {
+ "description": "",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "OK"
+ }
+ }
+ },
+ "post": {
+ "description": "",
+ "parameters": [
+ {
+ "name": "auth-token",
+ "in": "header",
+ "type": "string"
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "rate": {
+ "example": "any"
+ },
+ "opinion": {
+ "example": "any"
+ }
+ }
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Created"
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "422": {
+ "description": "Unprocessable Entity"
+ }
+ }
+ }
+ },
+ "/user/{uid}": {
+ "get": {
+ "description": "",
+ "parameters": [
+ {
+ "name": "uid",
+ "in": "path",
+ "required": true,
+ "type": "string"
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Created"
+ },
+ "422": {
+ "description": "Unprocessable Entity"
+ }
+ }
+ },
+ "patch": {
+ "description": "",
+ "parameters": [
+ {
+ "name": "uid",
+ "in": "path",
+ "required": true,
+ "type": "string"
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "password": {
+ "example": "any"
+ },
+ "city": {
+ "example": "any"
+ },
+ "phone": {
+ "example": "any"
+ },
+ "business": {
+ "example": "any"
+ },
+ "description": {
+ "example": "any"
+ },
+ "NIP": {
+ "example": "any"
+ },
+ "openHour": {
+ "example": "any"
+ },
+ "closeHour": {
+ "example": "any"
+ }
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK"
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "422": {
+ "description": "Unprocessable Entity"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/swagger.js b/app/swagger.js
new file mode 100644
index 0000000..b2bfc7b
--- /dev/null
+++ b/app/swagger.js
@@ -0,0 +1,6 @@
+import swaggerAutogen from "swagger-autogen";
+
+const outputFile = "app/swagger-output.json";
+const endpointsFiles = ["app/index.js"];
+
+swaggerAutogen()(outputFile, endpointsFiles);
diff --git a/package-lock.json b/package-lock.json
index 4eecc46..b620f40 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,11 +15,13 @@
"jsonwebtoken": "^8.5.1",
"mongodb": "^4.4.0",
"mongoose": "^6.2.2",
- "nodemailer": "^6.7.2"
+ "nodemailer": "^6.7.2",
+ "swagger-ui-express": "^4.3.0"
},
"devDependencies": {
"nodemon": "^2.0.15",
- "prettier": "^2.5.1"
+ "prettier": "^2.5.1",
+ "swagger-autogen": "^2.20.5"
}
},
"node_modules/@mapbox/node-pre-gyp": {
@@ -98,6 +100,18 @@
"node": ">= 0.6"
}
},
+ "node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -629,6 +643,15 @@
"node": ">=4.0.0"
}
},
+ "node_modules/deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/defer-to-connect": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
@@ -1268,6 +1291,18 @@
"integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
"dev": true
},
+ "node_modules/json5": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
@@ -2323,6 +2358,37 @@
"node": ">=4"
}
},
+ "node_modules/swagger-autogen": {
+ "version": "2.20.5",
+ "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.20.5.tgz",
+ "integrity": "sha512-VqgZhlZr/SCBA1jDICKunlPoDhxqq1+AcAAStvI4HuWveLYzHim2CVEbV/kvIqjlkBg0AxWba6NqoCCbFKdL6g==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^7.4.1",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.7",
+ "json5": "^2.2.1"
+ }
+ },
+ "node_modules/swagger-ui-dist": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.6.2.tgz",
+ "integrity": "sha512-BSt+ukOGkGZ2uHV4jyyCAzt60ysyQpGZAAhtIh7AMHT4MH1xXGkoXm2tfr1oRqO1N4IEY6qqNAlmcfMo/dAYuw=="
+ },
+ "node_modules/swagger-ui-express": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.3.0.tgz",
+ "integrity": "sha512-jN46SEEe9EoXa3ZgZoKgnSF6z0w3tnM1yqhO4Y+Q4iZVc8JOQB960EZpIAz6rNROrDApVDwcMHR0mhlnc/5Omw==",
+ "dependencies": {
+ "swagger-ui-dist": ">=4.1.3"
+ },
+ "engines": {
+ "node": ">= v0.10.32"
+ },
+ "peerDependencies": {
+ "express": ">=4.0.0"
+ }
+ },
"node_modules/tar": {
"version": "6.1.11",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
@@ -2680,6 +2746,12 @@
"negotiator": "0.6.3"
}
},
+ "acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true
+ },
"agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -3061,6 +3133,12 @@
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"dev": true
},
+ "deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "dev": true
+ },
"defer-to-connect": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
@@ -3541,6 +3619,12 @@
"integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
"dev": true
},
+ "json5": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "dev": true
+ },
"jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
@@ -4345,6 +4429,31 @@
"has-flag": "^3.0.0"
}
},
+ "swagger-autogen": {
+ "version": "2.20.5",
+ "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.20.5.tgz",
+ "integrity": "sha512-VqgZhlZr/SCBA1jDICKunlPoDhxqq1+AcAAStvI4HuWveLYzHim2CVEbV/kvIqjlkBg0AxWba6NqoCCbFKdL6g==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.4.1",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.7",
+ "json5": "^2.2.1"
+ }
+ },
+ "swagger-ui-dist": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.6.2.tgz",
+ "integrity": "sha512-BSt+ukOGkGZ2uHV4jyyCAzt60ysyQpGZAAhtIh7AMHT4MH1xXGkoXm2tfr1oRqO1N4IEY6qqNAlmcfMo/dAYuw=="
+ },
+ "swagger-ui-express": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.3.0.tgz",
+ "integrity": "sha512-jN46SEEe9EoXa3ZgZoKgnSF6z0w3tnM1yqhO4Y+Q4iZVc8JOQB960EZpIAz6rNROrDApVDwcMHR0mhlnc/5Omw==",
+ "requires": {
+ "swagger-ui-dist": ">=4.1.3"
+ }
+ },
"tar": {
"version": "6.1.11",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
diff --git a/package.json b/package.json
index 65f5b35..89676bd 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,8 @@
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
- "watch": "nodemon app/index.js -e js,json"
+ "watch": "nodemon --experimental-json-modules app/index.js -e js,json",
+ "swagger": "node app/swagger.js"
},
"repository": {
"type": "git",
@@ -25,10 +26,12 @@
"jsonwebtoken": "^8.5.1",
"mongodb": "^4.4.0",
"mongoose": "^6.2.2",
- "nodemailer": "^6.7.2"
+ "nodemailer": "^6.7.2",
+ "swagger-ui-express": "^4.3.0"
},
"devDependencies": {
"nodemon": "^2.0.15",
- "prettier": "^2.5.1"
+ "prettier": "^2.5.1",
+ "swagger-autogen": "^2.20.5"
}
}