I stood in a stupor. And I need help.
I do rest full api on express
I want to do this if a request comes in type: reset_password -> I sent an email to reset my password.(it can be both registration and auth)
But I don't know how to pass it into a query. And that is, how to do it.
I trimmed the code.
const send = async (req, res) => {
const key = req.query.apiKey;
const type = req.query.type;
const to = req.query.to;
if (err) {
console.log(err);
} else if (rows.length == 0) {
res.status(401).json({"apiKey":"error"})
} else {
if (email.validate(to)) {
sendmail(type, to)
} else {
res.status(422)
}
}
}
sendmail:
const nodemailer = require("nodemailer");
const ejs = require('ejs')
const path = require('path')
const sendmail = async (type, to, url) => {
try {
const reset_password = path.join(__dirname, "../template/resetpassword.ejs")
const signup_auth = path.join(__dirname, "../template/signupauth.ejs")
const sign_in_auth = path.join(__dirname, "../template/signinauth.ejs")
const data = await ejs.renderFile(reset_password,signup_auth,sign_in_auth, { to, url } )
let testAccount = await nodemailer.createTestAccount();
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "smtp.ethereal.email",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: testAccount.user, // generated ethereal user
pass: testAccount.pass, // generated ethereal password
},
});
const send = await transporter.sendMail({
from: 'dev#test.io',
to: to,
text: "Hello world?",
subject: "test",
html: ???
})
console.log("Success send: %s", nodemailer.getTestMessageUrl(send));
}catch (err) {
console.log('Error send: ' + err.message);
}
}
module.exports = sendmail;
Now I have a question. How do I send a request: reset_password,signup_auth,sign_in_auth
That is, how do I pass it on to the type: reset_password,signup_auth,sign_in_auth
http://localhost:3000/api?apiKey=key&type=reset_password,signup_auth,sign_in_auth
How do I take it and process it?
I need to accept type=auth signup reset to api rest
I'm sorry, maybe I didn't make my point correctly.
Related
I'm very new to backend development and I'm trying to figure out how to send my form data from front to backend. I watched a youtube tutorial on how and this is my code for server.js:
const express = require("express");
const app = express();
const port = 2009;
app.use(express.static("public"));
app.use(express.json());
app.get("/", (req, res) => {
res.status(200).json({info: "something"});
});
app.post("/", (req, res) => {
const { parcel } = req.body;
if (!parcel) {
return res.status(400).send({status: "failed"});
}
res.status(200).send({status: "recieved"});
});
app.listen(port, () => console.log(`server.js running on port: ${port}`));
And here is the code for script.js for my form:
const submit = document.getElementById("submit");
const userName = document.getElementById("user");
const password = document.getElementById("pass");
const email = document.getElementById("mail");
const baseUrl = "http://localhost:2009/"
async function post(e) {
e.preventDefault();
const res = await fetch(baseUrl + "website?key=hello", {
method: "POST"
})
}
Like I said I basically have no clue what I am doing could someone help me?
I haven't tested it yet because I'm afraid it won't work if would be very helpful if someone could show me some code or point me to some documentation so that I can work in the right direction.
you seem to be on the right track just a few changes and additions.
const registerForm = document.getElementById('register_form');
async function post(e) {
const form = document.forms.register_form;
const email = form.email.value;
const password = form.password.value;
const username = form.username.value;
try {
const res = await fetch(baseUrl + "website?key=hello", {
method: "POST",
body: JSON.stringify({
email,
username,
password,
}),
headers: { "Content-Type": "application/json" },
});
// handle the response here
} catch (error) {
// handle error here
}
}
registerForm.addEventListener('submit', post, false);
on the backend, you will need a route to handle this request
app.post("/", (req, res) => {
const { username, email, password } = req.body;
// validate the data from the request
if (!username || !email || !password) {
return res.status(400).send({
status: "failed",
message: "fields are required"
});
}
res.status(201).send({status: "recieved"});
});
StatusCode 201 indicates a new resource has been created
References:Using Fetch Api statusCode
I hope this helps.
basically when i change "http://localhost:5000/api/users" to "http://localhost:5000/api/posts" in Create Request its giving me error if i leave it as it is which is "http://localhost:5000/api/users" if functions properly but for some damn reason postman is giving me this error which is shown in the picture and wont tell me whats causing it. anybody got any anwer? Error is described here
Cannot POST /api/posts
post.model.js
"
const {model, Schema } = require(`mongoose`)
const postSchema = new Schema (
{
user_id: {
type: Schema.Types.ObjectId,
ref: `User`,
required:true
},
title: {
type: String,
required: true
},
body: {
type: String,
required: true
}
},
{timestamps: true, versionKey: false}
)
module.exports = model('Post', postSchema);
"
post.controller.js
"
const Post = require(`../models/post.model`)
// #desc Get todos
// #route Get /api/todos
// #acsses Public
exports.getAll = async (request, response)=> {
const posts = await Post.find();
response.status(200).json({ sucsses: true, posts: posts})
}
// #desc Get todo
// #route GET /api/todo/:id
// #acsses Public
exports.getOne = async (request, response)=> {
const post = await Post.findById({ _id: request.params.id});
response.status(200).json({ sucsses: true, post: post})
}
// #desc Create todo
// #route POST /api/todo
// #acsses Public
exports.create = async (request, response)=> {
const post = await Post.create(request.body);
response.status(200).json({ sucsses: true, post: post})
}
// #desc Update todos
// #route Get /api/todos/:id
// #acsses Public
exports.updateOne = async (request, response)=> {
const post = await Post.findByIdAndUpdate(request.params.id, request.body, {new : true, runValidators: true})
response.status(200).json({ sucsses: true, post: post})
}
exports.deleteOne = async (request, response)=> {
const post = await Post.findByIdAndDelete(request.params.id)
response.status(200).json({ sucsses: true, post: post.id})
}
post.routes.js
"
const { Router } =require("express");
const { create, deleteOne, getAll, getOne, updateOne } = require("../controller/post.controller");
const router = Router()
router.route("/")
.get(getAll)
.post(create)
router.route("/:id")
.get(getOne)
.put(updateOne)
.delete(deleteOne)
module.exports = router;
server.js
"
const express = require("express")
const chalk = require("chalk")
const connectDatabase = require(`./api/config/connect.database`)
// =========== Aplication Routes =====
const user_routes = require("./api/routes/user.routes")
const todo_routes = require("./api/routes/todo.routes")
const post_routes = require("./api/routes/post.routes")
const comment_routes = require("./api/routes/comment.routes")
const album_routes = require("./api/routes/album.routes")
const photo_routes = require("./api/routes/photo.routes")
const app = express();
// Incoming Request body parser?======
app.use(express.json())
app.use(express.urlencoded({ extended: true}))
connectDatabase();
app.use(`/api/users`, user_routes)
app.use(`/api/todos`, todo_routes)
app.use(`/api/post`, post_routes)
app.use(`/api/comoment`, comment_routes)
app.use(`/api/album`, album_routes)
app.use(`/api/photo`, photo_routes)
const PORT = 5000
const SERVER_MODE = "development"
app.listen(PORT, ()=> {
console.log(chalk.bold.yellow(`Server running in ${SERVER_MODE} mode on port ${PORT}`));
})
connect.database.js
"
const mongoose = require("mongoose")
const chalk = require(`chalk`)
const connectDatabase = async ()=> {
const connect = await mongoose.connect("mongodb+srv://xynlep:123#project.41nkj.mongodb.net/members-api-reactional")
console.log(chalk.bold.cyan(`Mongo Connected: ${connect.connection.host}`))
}
module.exports = connectDatabase;
i tryed checking code if thers some mistake in it but everythings perfectly fine not 100% sure tho but since it doenst give me reason why it cant send create request i really couldn't try anything else but google
I'm trying to implement JWT authentication, and I can't figure out why in Postman protected-route is available, while in my browser protected-route is Unauthorized.
I'm a beginner and its first time implementing jwt authentication in my project following this tutorial https://www.youtube.com/playlist?list=PLYQSCk-qyTW2ewJ05f_GKHtTIzjynDgjK
Problem
/login and /register work fine and I can see from the log they issue a JWT token in the req.headers
like 'Authorization':'Bearer <token>', however when I try to access GET /protected-route in my browser, it returns Unauthorized, and I can see no logging from JWTStrategy.
I think req.headers.Authorization is not set to all HTTP requests in the app, but only to POST /login, /register routes So my questions are:
Is this req.headers["Authorization"] = 'Bearer <toekn>'; correct way to set req headers to all GET and POST request in the app?
Does the jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken() checks for Authorization property in req.headers or res.headers?
I have provided the relevant code snippets please have a look!
Code:
app.js
//...
require('./config/database'); // require the db
// ...
const passport = require('passport');
const strategy = require('./config/passport').strategy;
// ...
app.use(passport.initialize());
passport.use(strategy);
// ...
module.exports = app
router/index.js
const router = express.Router();
//...
const User = require('../config/database').User;
const passport = require('passport');
const utils = require('../lib/utils');
// register route
router.post('/register', function(req, res, next){
const saltHash = utils.genPassword(req.body.password);
console.log("req.body.password is: " + req.body.password)
const salt = saltHash.salt;
const hash = saltHash.hash;
const newUser = new User({
username: req.body.username,
hash: hash,
salt: salt
})
newUser.save()
.then((user) => {
const jwt = utils.issueJWT(user);
if (jwt){
req.headers["Authorization"] = jwt.token;
}
res.redirect('/login')
})
.catch(err => next(err))
});
// login route
router.post('/login', function(req, res, next){
User.findOne({username: req.body.username})
.then((user) => {
if(!user) {
res.status(401).json({success: false, msg: "Could not find user "})
}
// validate the user
const isValid = utils.validPassword(req.body.password, user.hash, user.salt)
if(isValid) {
// issue a JWT
const jwt = utils.issueJWT(user);
if (jwt){
req.headers["Authorization"] = jwt.token;
}
res.redirect("/")
} else {
res.status(401).json({success: false, msg: "you entered the wrong password"})
}
})
.catch(err => next(err))
});
// GET protected route
router.get("/protectd-route", passport.authenticate('jwt', {session: false}), async (req, res, next) => {
res.render("user/getuser.pug")
next()
})
passport.js
const User = require('../config/database').User;
// ...
const Strategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
/// PUB_KEY
const pathToKey = path.join(__dirname, '..', 'id_rsa_pub.pem');
const PUB_KEY = fs.readFileSync(pathToKey, 'utf8');
// options
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: PUB_KEY,
algorithms: ['RS256']
};
// strategy
const strategy = new Strategy(options, (payload, done) => {
User.findOne({_id: payload.sub})
.then((user) => {
if(user) {
return done(null, user)
} else {
return done(null, false)
}
})
.catch((err) => done(err, null))
});
module.exports.strategy = strategy;
utils.js
genPassword() - Creating a salt and hash out of it to store in db
validPassword() - re-hashing user salt and hash to verify
issueJWT() - signing user with jsonwebtoken
const crypto = require('crypto');
const jsonwebtoken = require('jsonwebtoken');
const User = require('../config/database').User;
//...
const pathToKey = path.join(__dirname, '..', 'id_rsa_priv.pem');
const PRIV_KEY = fs.readFileSync(pathToKey, 'utf8');
// validate in /login
function validPassword(password, hash, salt) {
var hashVerify = crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex');
return hash === hashVerify;
}
// generate in /register
function genPassword(password) {
var salt = crypto.randomBytes(32).toString('hex');
var genHash = crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex');
return {
salt: salt,
hash: genHash
};
}
// sign
function issueJWT(user) {
const _id = user._id;
const expiresIn = '86400';
const payload = {
sub: _id,
iat: Date.now()
};
const signedToken = jsonwebtoken.sign(payload, PRIV_KEY, { expiresIn: expiresIn, algorithm: 'RS256' });
return {
token: "Bearer " + signedToken,
expires: expiresIn
}
}
module.exports.validPassword = validPassword;
module.exports.genPassword = genPassword;
module.exports.issueJWT = issueJWT;
Postman
In Postman, the protected route is showing successfully, with Headers set as above.
The browser network is showing this, there is no Authorization property both in response and request headers
Clearly, I'm missing something, but I can't figure it out. Any help is appreciated
here is also my db
database.js
const uri = process.env.MONGO_URI
const connection = mongoose.connection;
mongoose.connect(uri, {
useUnifiedTopology: true,
serverSelectionTimeoutMS: 5000
})
connection.on('error', console.error.bind(console, "connection error"))
connection.once('open', () => {
console.log('MongoDB database connection has been established successfully')
})
const userSchema = new mongoose.Schema({
username: String,
hash: String,
salt: String
});
const User = mongoose.model('User', userSchema )
module.exports.User = User;
It was working and then it wasn't. I sent a few mails and after a while it stopped working. I get
"Message sent:Undefined"
(node:9048) UnhandledPromiseRejectionWarning: Error: spawn sendmail ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:269:19)
I have no idea why.
Frontend- Axios console logs the response data therefore the server and the frontend both are working. It is just the issue with the Nodemailer.
Any help is appreciated. Thanks!
const express = require("express");
const app = express();
const cors = require("cors");
const nodemailer = require("nodemailer");
const path = require("path");
const fs = require("fs");
const readData = path.join(__dirname, "../email_take2/data.json");
const { v4: uuidv4 } = require("uuid");
app.use(express.json());
app.use(cors());
const port = process.env.PORT || 5000;
app.listen(5000, () => console.log(`Listening at port ${port}`));
if (process.env.NODE_ENV === "production") {
// Set static folder
app.use(express.static("../client/build"));
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "../client", "build", "index.html"));
});
}
function listUserData() {
const data = fs.readFileSync(readData);
return JSON.parse(data);
}
app.post("/sendEmail", function (req, res) {
console.log(req.body);
const emailInfo = {
id: uuidv4(),
email: req.body.email,
cc: req.body.cc,
message:req.body.message,
};
const dataArray = listUserData();
dataArray.push(emailInfo);
fs.writeFileSync(readData, JSON.stringify(dataArray));
res.send(emailInfo);
console.log("SentBody", emailInfo);
let transporter = nodemailer.createTransport({
sendmail:true,
host: "smtp.outlook.com",
port: 587,
secure: false, // true for 465, false for other ports
tls: {
ciphers: "SSLv3",
},
auth: {
user: "memail#outlook.com", // generated ethereal user
pass: "mypw", // generated ethereal passwordAccount.pass,
},
});
// send mail with defined transport object
let info = transporter.sendMail({
from: '"Fred Foo 👻" <foo#example.com>', // sender address
to: "garbageacc7878#outlook.com", // list of receivers
subject: "Hello ✔", // Subject line
text: "Hello world?", // plain text body
html: "<b>Hello world?</b>", // html body
});
console.log("Message sent: %s", info.messageId);
return emailInfo;
});
transporter.sendMail returns a promise, that's why your console log has undefined. So either attach a .then and .catch.
transporter.sendMail(...)
.then((data)=>{console.log('Mail sent', data)})
.catch(err => {console.error('Failure',err)})
Or make your request handler an async function and use async await and use tryCatch.
try{
let data = await transporter.sendMail(...)
console.log('Mail sent', data)
} catch (err) {
console.error('Failure',err)
}
I'm building a contact form using nodemailer.
To post it I'm using the fetch API.
But for some reason, I get req.body as undefined.
Here's the frontend code:
form.onsubmit = function (e) {
// Stop the regular form submission
e.preventDefault();
const name = document.querySelector("form#contactForm #name").value;
const email = document.querySelector("form#contactForm #email").value;
const textarea = document.querySelector("form#contactForm #textarea").value;
// Collect the form data while iterating over the inputs
var data = {};
data = { name, email, textarea };
console.log(data);
fetch("/mail", {
method: "POST", // or 'PUT'
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
.then(async (response) => {
if (response.ok) {
return response.json();
} else {
const resJson = await response.json();
console.log(resJson);
if (typeof resJson.errors === "undefined") {
formStatus.className += " alert-danger";
formStatus.innerText =
"An error occured, Please refresh the page. Or email us at ravchesed#kehilasbelz.be";
return;
}
let ul = document.createElement("ul");
resJson.errors.forEach((err) => {
const li = document.createElement("li");
li.innerText = `${err.msg}: ${err.param} `;
ul.append(li);
console.log(`${err.msg}: ${err.param} `);
});
formStatus.className += " alert-danger";
formStatus.innerText = "";
formStatus.append(ul);
throw response;
}
})
.then((data) => {
console.log("Success:", data);
})
.catch((error) => {
console.error("Error:", error);
});
};
Here's the backend:
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const { check, validationResult } = require("express-validator");
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // limit each IP to 100 requests per windowMs
});
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const mail = express.Router();
// app.post("/mail", (req, res) => {
// console.log(req.body);
// const result = {
// hellop: 5
// };
// res.send(JSON.stringify(result));
// });
mail.post(
"/mail",
// limiter,
[
// username must be an email
check("email").trim().isEmail(),
check("textarea").trim().isLength({ max: 6000 }),
check("name").trim().isLength({ min: 2, max: 20 }),
],
(req, res) => {
console.log(req.body); //undefined
// Finds the validation errors in this request and wraps them in an object with handy functions
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log(errors); //this returns empty values.
return res.status(422).json({ errors: errors.array() });
}
const mailInfo = {
name: req.body.name,
email: req.body.email,
message: req.body.testarea,
};
main(mailInfo).catch(console.error);
res.json({ success: true });
}
);
const nodemailer = require("nodemailer");
// async..await is not allowed in the global scope, must use a wrapper
async function main(data) {
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "xxx.xxx.com",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: "email#example.com", // generated ethereal user
pass: "abc123456", // generated ethereal password
},
});
// send mail with defined transport object
let info = await transporter.sendMail(
{
from: '"John Doe 👍" <robot#Doe.dev>', // sender address
to: "Doe#gmail.com", // list of receivers
subject: `📧 Mail from ${data.name}`, // Subject line
html: `
<b>${data.name}, ${data.email}</b><br>
Phone: ${data.phone}<br>
<br>
Message:
<br>
${data.message}
`, // html body
},
function (err, info) {
if (err) console.log(err);
else console.log(info);
console.log("Message sent: %s", info);
}
);
}
module.exports = mail;
Looked at a lot of posts, but this seems to be a different problem.
after looking at everything again I know where my mistake was but don't understand why.
My file structure is like this:
app.js
mail.js
mail.js was imported to app.js like this:
//handle mail
const mail = require("./mail");
app.use(mail);
in app.js I didn't import body-parser and the middleware because it was already imported in mail.js.
but looks like for some reason that I also have to import it in app.js before mail.js.