diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..de625be --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +node_modules +npm-debug.log \ No newline at end of file diff --git a/.env b/.env index 4c24d8d..a5b5ed0 100644 --- a/.env +++ b/.env @@ -1,4 +1,5 @@ -PORT=2000 +PORT=3000 JWT_SECRET=askfeed1234 - +USER=santanrathore75209@gmail.com +PASS=*Saheb13* \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3c3629e..1dcef2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +.env \ No newline at end of file diff --git a/.scannerwork/.sonar_lock b/.scannerwork/.sonar_lock new file mode 100644 index 0000000..e69de29 diff --git a/.scannerwork/report-task.txt b/.scannerwork/report-task.txt new file mode 100644 index 0000000..b851003 --- /dev/null +++ b/.scannerwork/report-task.txt @@ -0,0 +1,6 @@ +projectKey=token +serverUrl=http://dev-sonarqube.springrole.com:9000 +serverVersion=8.9.1.44547 +dashboardUrl=http://dev-sonarqube.springrole.com:9000/dashboard?id=token +ceTaskId=AXoaL8nL8zulQfXeM_9Q +ceTaskUrl=http://dev-sonarqube.springrole.com:9000/api/ce/task?id=AXoaL8nL8zulQfXeM_9Q diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c519607 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + "configurations": [ + { + "name": "Docker Node.js Launch", + "type": "docker", + "request": "launch", + "preLaunchTask": "docker-run: debug", + "platform": "node", + "node": { + "package": "${workspaceFolder}/node_modules/which-module/package.json", + "localRoot": "${workspaceFolder}/node_modules/which-module" + } + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..4e04ed9 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,46 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "docker-build", + "label": "docker-build", + "platform": "node", + "dockerBuild": { + "dockerfile": "${workspaceFolder}/node_modules/which-module/Dockerfile", + "context": "${workspaceFolder}/node_modules/which-module", + "pull": true + }, + "node": { + "package": "${workspaceFolder}/node_modules/which-module/package.json" + } + }, + { + "type": "docker-run", + "label": "docker-run: release", + "dependsOn": [ + "docker-build" + ], + "platform": "node", + "node": { + "package": "${workspaceFolder}/node_modules/which-module/package.json" + } + }, + { + "type": "docker-run", + "label": "docker-run: debug", + "dependsOn": [ + "docker-build" + ], + "dockerRun": { + "env": { + "DEBUG": "*", + "NODE_ENV": "development" + } + }, + "node": { + "package": "${workspaceFolder}/node_modules/which-module/package.json", + "enableDebugging": true + } + } + ] +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5a38c12 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM node:14.16 + +WORKDIR /ask-feed + +COPY package.json /ask-feed/package.json + +RUN npm install + +COPY . /ask-feed + +EXPOSE 3000 + +CMD ["npm","start"] \ No newline at end of file diff --git a/app.js b/app.js index 426de16..5ee4bc8 100644 --- a/app.js +++ b/app.js @@ -4,6 +4,8 @@ const cors = require("cors"); const bcryptjs = require("bcryptjs"); require("dotenv").config(); require("./db/connectionDB"); +require("./models/user"); +require("./models/survey"); const authRoutes = require("./routes/auth"); const surveyRoutes = require("./routes/survey"); @@ -14,7 +16,10 @@ app.use(express.json()); app.use(cors()); app.use("/survey", surveyRoutes); app.use("/api", authRoutes); - -app.listen(process.env.PORT || 2000, () => { - console.log("server running on port 2000"); +app.get("/health", function (req, res) { + const message = "Running on port " + process.env.PORT; + return res.send(message); +}); +app.listen(process.env.PORT || 3000, () => { + console.log("server running on port 3000"); }); diff --git a/controllers/auth.js b/controllers/auth.js index a5b7317..fa09913 100644 --- a/controllers/auth.js +++ b/controllers/auth.js @@ -3,15 +3,10 @@ const nodemailer = require("nodemailer"); const bcryptjs = require("bcryptjs"); const jwt = require("jsonwebtoken"); -const transporter = nodemailer.createTransport({ - service: "gmail", - auth: { - user: "santanrathore75209@gmail.com", - pass: "*Saheb13*", - }, -}); +const { transporter } = require("../utils/transporter"); const signup = async (req, res) => { + try{ const { username, password, email, phoneNo } = req.body; const userexist = await User.findOne({ email }); if (!userexist) { @@ -26,16 +21,32 @@ const signup = async (req, res) => { phoneNo, token, }; - const user = await User.create(newUser); if (user) { const data = { from: "no-reply@gmail.com", to: email, - subject: "Account activation link", - html: `

PLease click on given link to activate your account

-

http://localhost:2000/api/activate/${token}

- `, + subject: "This is your Email verification link", + html: `
+
+ +

Please click on the button to verify your mail!
We’re very excited to have you on board!

+ + +
+ +
+ + + + `, + attachments: [ + { + filename: "askfeedlogo.jpeg", + path: `${__dirname}/images/askfeedlogo.jpeg`, + cid: "askfeedlogo", + }, + ], }; try { await transporter.sendMail(data); @@ -48,6 +59,11 @@ const signup = async (req, res) => { } else { res.send("User already exist!"); } +} +catch(e) +{ + throw new Error("Failed to create the function") +} }; const verifyAccount = async (req, res) => { @@ -78,7 +94,6 @@ const verifyAccount = async (req, res) => { const resetlink = async (req, res) => { const { email } = req.body; const user = await User.findOne({ email }); - // console.log("user", user, email); if (user) { const token = jwt.sign({ email }, process.env.JWT_SECRET, { expiresIn: "30m", @@ -95,10 +110,26 @@ const resetlink = async (req, res) => { const data = { from: "no-reply@gmail.com", to: email, - subject: "Reset link", - html: `

PLease click on given link to reset your account

-

http://localhost:2000/api/changepassword/?token=${token}

- `, + subject: "This is your account reset link", + html: `
+
+ +

This is your account reset link!
Please click on the link to reset your password!

+ +
+ +
+ + + + `, + attachments: [ + { + filename: "askfeedlogo.jpeg", + path: `${__dirname}/images/askfeedlogo.jpeg`, + cid: "askfeedlogo", + }, + ], }; try { await transporter.sendMail(data); @@ -113,7 +144,7 @@ const resetlink = async (req, res) => { const changepassword = async (req, res) => { const { password } = req.body; - const token = req.query.token; + const token = req.params.token; const decodedtoken = jwt.verify(token, process.env.JWT_SECRET); const hashedPass = await bcryptjs.hashSync(password, 10); const user = await User.findOneAndUpdate( @@ -132,20 +163,45 @@ const changepassword = async (req, res) => { } }; const login = async (req, res) => { - const { email, password } = req.body; - const user = await User.findOne({ email }); - const { _id } = user; - if (user) { - console.log("user", user); - const matchpassword = await bcryptjs.compare(password, user.password); - if (matchpassword && user.isVarified) { - const token = jwt.sign({ email, _id }, process.env.JWT_SECRET); - res.send({ token }); + try { + const { email, password } = req.body; + const user = await User.findOne({ email }); + + if (user) { + const { _id } = user; + + const matchpassword = await bcryptjs.compare(password, user.password); + if (matchpassword && user.isVarified) { + const token = jwt.sign({ email, _id }, process.env.JWT_SECRET); + res.send({ token, email: user.email, username: user.username }); + } } else { - res.send("Login unsuccessful!"); + res.send("Incorrect Email or password!"); } - } else { - res.send("Incorrect Email or password!"); + } catch (e) { + throw new Error("Fail to create operation"); } }; -module.exports = { signup, verifyAccount, resetlink, changepassword, login }; +const updateProfile = async (req, res) => { + try { + const { _id } = req.body; + const userexist = await User.findOneAndUpdate({ _id }, { $set: req.body }); + if (userexist) { + res.send("user updated successfully"); + } else { + res.send("unable to update"); + } + } catch (e) { + throw new Error("Unable to update"); + } +}; + + +module.exports = { + signup, + verifyAccount, + resetlink, + changepassword, + login, + updateProfile, +}; diff --git a/controllers/images/askfeedlogo.jpeg b/controllers/images/askfeedlogo.jpeg new file mode 100644 index 0000000..19aa679 Binary files /dev/null and b/controllers/images/askfeedlogo.jpeg differ diff --git a/controllers/survey.js b/controllers/survey.js index 9693089..9c55e1c 100644 --- a/controllers/survey.js +++ b/controllers/survey.js @@ -1,8 +1,103 @@ const mongoose = require("mongoose"); const { Survey } = require("../models/survey"); +const { transporter } = require("../utils/transporter"); const createSurvey = async (req, res) => { - const survey = await Survey.create(req.body); + const { title, category, subject, body, recipients } = req.body; + const survey = await Survey.create({ + title, + category, + subject, + body, + recipients, + + dateSent: Date.now(), + }); + + const data = { + from: "no-reply@gmail.com", + to: recipients, + subject: "Account activation link", + html: ` + +
+ +

${survey.title}

+

${survey.subject}

+

${survey.body}

+
+ Yes +
+
+ No +
+
+ + + `, + attachments: [ + { + filename: "askfeedlogo.jpeg", + path: `${__dirname}/images/askfeedlogo.jpeg`, + cid: "askfeedlogo", + }, + ], + }; + + try { + await transporter.sendMail(data); + console.log("Email sent Successfully! survey"); + } catch (err) { + console.log("error occured while sending email!", err); + } res.send(survey); }; -module.exports = { createSurvey }; + +const responseYes = async (req, res) => { + try { + const id = req.params.id; + + const dataToSet = { + $inc: { + yes: 1, + }, + } + const result = await Survey.findByIdAndUpdate(id, dataToSet); + if (result) { + res.send("response recorded successfully"); + } else { + res.send("Could not record the respone"); + } + } catch (e) { + throw new Error("Internal Serever Error"); + } +}; + +const responseNo = async (req, res) => { + try { + const id = req.params.id; + const dataToSet = { + $inc: { + No: 1, + }, + }; + const result = await Survey.findByIdAndUpdate(id, dataToSet); + if (result) { + res.send("response recorded successfully"); + } else { + res.send("Could not record the respone"); + } + } catch (e) { + throw new Error("Internal Serever Error"); + } +}; +const getSurvey = async (req, res) => { + try { + const surveys = await Survey.find(); + res.send(surveys); + } catch (e) { + throw new Error("Internal Serever Error"); + } +}; + +module.exports = { createSurvey, responseYes, responseNo, getSurvey }; diff --git a/middlewares/requireLogin.js b/middlewares/requireLogin.js new file mode 100644 index 0000000..6013d4f --- /dev/null +++ b/middlewares/requireLogin.js @@ -0,0 +1,21 @@ +const jwt = require("jsonwebtoken"); + +const { User } = require("../models/user"); +const protect = async (req, res, next) => { + try { + const token = req.headers.authorization.split(" ")[1]; + const user = jwt.verify(token, process.env.JWT_SECRET); + + const userExist = await User.findOne({ email: user.email }); + + if (userExist) { + req.user = userExist; + next(); + } else { + res.send("user does not exist"); + } + } catch (e) { + res.send("invalid token"); + } +}; +module.exports = { protect }; diff --git a/models/recipient.js b/models/recipient.js new file mode 100644 index 0000000..f4a63f1 --- /dev/null +++ b/models/recipient.js @@ -0,0 +1,8 @@ +const mongoose = require("mongoose"); +const { Schema } = mongoose; +const recipientSchema = new Schema({ + email: String, + responded: { type: Boolean, default: false }, +}); + +module.exports = recipientSchema; diff --git a/models/survey.js b/models/survey.js index 1b56b7f..ad6a397 100644 --- a/models/survey.js +++ b/models/survey.js @@ -1,26 +1,39 @@ +const mongoose = require("mongoose"); +const recipientSchema = require("./recipient"); -const mongoose=require('mongoose') +const surveySchema = mongoose.Schema( + { + title: { + type: String, + }, + category: { + type: String, + }, + body: { + type: String, + }, + subject: { + type: String, + }, + recipients: [String], + yes: { + type: Number, + default: 0, + }, + No: { + type: Number, + default: 0, + }, -const surveySchema=mongoose.Schema({ - title:{ - type:String - }, - type:{ - type:String - }, - - questionsSet:[ - { - ques:{ - type: String - }, - ans:{ - type: [Boolean] - } - } -] + _user: { + type: mongoose.Schema.Types.ObjectId, + ref: "User", + }, -}) -//created the survey api now -const Survey = mongoose.model("Survey",surveySchema) -module.exports={Survey} + dateSent: Date, + lastResponded: Date, + }, + { timestamps: true } +); +const Survey = mongoose.models.Survey || mongoose.model("Survey", surveySchema); +module.exports = { Survey }; diff --git a/models/user.js b/models/user.js index eb7de48..04f831e 100644 --- a/models/user.js +++ b/models/user.js @@ -1,10 +1,8 @@ const mongoose = require("mongoose"); - const userSchema = mongoose.Schema({ username: { type: String, required: true, - max: 64, }, password: { type: String, @@ -30,6 +28,5 @@ const userSchema = mongoose.Schema({ default: null, }, }); - -const User = mongoose.model("User", userSchema); +const User = mongoose.models.User || mongoose.model("User", userSchema); module.exports = { User }; diff --git a/routes/auth.js b/routes/auth.js index d1c6751..6532d2a 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -1,4 +1,5 @@ const express = require("express"); + const router = express.Router(); const { @@ -7,12 +8,14 @@ const { resetlink, changepassword, login, + updateProfile, } = require("../controllers/auth"); router.post("/signup", signup); -router.post("/activate", verifyAccount); +router.post("/activate/:token", verifyAccount); router.post("/resetlink", resetlink); -router.post("/changepassword", changepassword); +router.post("/changepassword/:token", changepassword); router.post("/login", login); +router.put("/updateprofile", updateProfile); module.exports = router; diff --git a/routes/survey.js b/routes/survey.js index 3b48b47..47bc1b0 100644 --- a/routes/survey.js +++ b/routes/survey.js @@ -1,7 +1,16 @@ +const { response } = require("express"); const express = require("express"); -const { createSurvey } = require("../controllers/survey"); const router = express.Router(); +const { protect } = require("../middlewares/requireLogin"); +const { + createSurvey, + responseYes, + responseNo, + getSurvey, +} = require("../controllers/survey"); -router.post("/createsurvey", createSurvey); - +router.post("/createsurvey", protect, createSurvey); +router.put("/response/yes/:id", responseYes); +router.put("/response/no/:id", responseNo); +router.get("/getSurvey", getSurvey); module.exports = router; diff --git a/utils/transporter.js b/utils/transporter.js new file mode 100644 index 0000000..3a7c1f1 --- /dev/null +++ b/utils/transporter.js @@ -0,0 +1,13 @@ +const nodemailer = require("nodemailer"); + +const transporter = nodemailer.createTransport({ + service: "gmail", + auth: { + user: process.env.USER, + pass: process.env.PASS, + }, +}); + +module.exports = { + transporter, +};