Nodejs: validate if email already exists in the database when registering user - javascript

I've tried some methods but nothing works
and I'm trying to change
Anyone can give me a little trick to create this function in node js?
Your suggestions will be very helpful for me to solve it
//router_register.js
// Definisikan router dari express
const router = require('express').Router();
// Ambil index.js dari controller dan panggil variabel didalamnya
const registerController = require('../controllers').register;
// Definisikan middleware verify.js
const verifyUser = require('../configs/verify');
// Rute 'http://localhost:5050/register/' digunakan untuk menampilkan form register
router.get('/', verifyUser.isLogout, registerController.formRegister);
// Rute 'http://localhost:5050/register/save' digunakan untuk menyimpan data yang diinput user saat register
router.post('/save', verifyUser.isLogout, registerController.saveRegister);
// Export agar dapat dibaca oleh express
module.exports = router;
//controller_register
const config = require('../configs/database');
let mysql = require('mysql');
let pool = mysql.createPool(config);
pool.on('error', (err)=> {
console.error(err);
});
module.exports = {
formRegister(req, res) {
res.render("login", {
// Definisikan semua varibel yang ingin ikut dirender kedalam register.ejs
url: 'http://localhost:5050/',
});
},
saveRegister(req, res) {
let username = req.body.username;
let email = req.body.email;
let password = req.body.pass;
if (username && email && password) {
pool.getConnection(function(err, connection) {
if (err) throw err;
connection.query(
`INSERT INTO table_user (user_name, user_email, user_password) VALUES (?,?,SHA2(?,512)); `, [username, email, password], function (error, results) {
if (error) throw error;
req.flash('color', 'success');
req.flash('status', 'Yes..');
req.flash('message', 'Registrasi berhasil');
res.redirect('/login');
});
connection.release();
})
} else {
res.redirect('/login');
res.end();
}
}
}
And please tell me which parts I should fix to make it even better for this coding

You have a couple of options. May be even both to get a robust solution. As you asked for general direction, instead of giving you exact code, I will try to point you in right direction.
In your saveRegister function, before you run INSERT, using email, you can run another query to fetch any existing user's with the incoming email address. If you find one, throw an exception for user trying to register with existing email.
To make this even better, you can add a UNIQUE constraint on your table in the database for the user_email column. This way if you do try to save another user with a duplicate email, you should get an exception that your try block will catch.
All the best. Please update the question with specifics if you try this approach and still need more help.

Related

How to call a route at a particular time

I have a MERN stack Library Management System website.
In my app currently for admin i have given a Notify button to send emails to all user that have any books due in the library. For this an array of defaulty user gets passed as a req body to send emails. Admin gets this list of users from database on initial render of that particular component.
But i want to automate sending of emails and want my server to trigger automatic emails at 10:00 am to all the users who have due books.
On Notify button click my notifyBookDefaulties controller gets triggered.
I tried to use a setTimeout and a timer as well to call my route at 10:00 am and trigger emails but i am not able to get desired output.
Below i my notifyBookDefaulties controller:
const notifyBookDefaulties = asyncHandler(async (req, res) => {
const admin = await Auth.findById(req.user.id);
// to check if user exists by that id in the databse
// and that user is a admin (got by token)
if (!admin && admin.admin !== true) {
res.status(401);
throw new Error("Not Authorized");
}
const { users, bookID, title } = req.body; // here users is the list of user id's
let emails = "";
// to get email of each user from their user id
for (let user of users) {
try {
const defaulty = await Auth.findById(user);
emails += defaulty.email + ",";
} catch (error) {
res.status(400);
throw new Error(error);
}
}
// to get comma separated list of emails
const emailList = emails.slice(0, -1).toString();
// try block tries to send email and catch block catches any error if occured
try {
var transporter = nodemailer.createTransport({
service: process.env.SERVICE,
auth: {
user: process.env.USER,
pass: process.env.PASS,
},
});
var mailOptions = {
from: process.env.USER,
to: emailList,
subject: "Return Book",
html: `<!DOCTYPE html><html lang="en"><body>This is to remind you that the book titled ${title} and ID ${bookID} issued by you is due.</body></html>`,
};
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
res.status(400).json({ msg: error });
} else {
res.status(200).json({ msg: "E-Mail Successfully sent" });
}
});
} catch (error) {
console.log(error);
res.status(500).json({ msg: error });
}
});
Below is my server.js:
require("dotenv").config();
const express = require("express");
const { errorHandler } = require("./middleware/errorMiddleware");
const connectDB = require("./config/db");
const cors = require("cors");
const port = process.env.PORT || 5000;
connectDB();
const app = express();
const corsOptions = {
origin: 'http://localhost:3000',
optionsSuccessStatus: 204
};
app.use(cors(corsOptions))
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use("/api/admin", require("./routes/adminRoutes"));
app.use("/api/user", require("./routes/userRoutes"));
app.use("/api/actions", require("./routes/authRoute"));
app.use(errorHandler);
app.listen(port, () => {
console.log(`Running on ${port}`);
});
My controller gets called for below route:
router.post("/notify", protect, notifyBookDefaulties);
and the url is:
http://localhost:5000/api/admin/notify
Note: here i have not included my function which fetches the list of user id's, of users that have due books. To fetch defaulting users i have a separate controller and i will merge that into this controller once i get the logic to send mails at 10:00 am.
If there is any other way to implement this i would like to know. If any more clarity needed do tell. Thanks in advance.
Sounds like a cron job, check this package https://www.npmjs.com/package/node-cron

In signing up there's no problem but when I sign in it's returning to catch block | nodejs expressjs | mongodb

//----------------db----------------------
app.use(bodyParser.json());
app.use(express.static('public'));
app.use(bodyParser.urlencoded({extended:true}));
mongoose.connect('mongodb://127.0.0.1:27017/signup');
var db = mongoose.connection;
db.on('error',()=>console.log("error in connection"));
db.once('open',()=>console.log("connected succesfulllly"));
app.post("/signup",(req,res)=>{
var name = req.body.name;
var email = req.body.uemail;
var password = req.body.upassword;
var data = {
"name" : name,
"email" : email,
"password" : password
}
db.collection('users').insertOne(data,(err,collection)=>{
if(err){
throw err;
}
console.log("record inserted");
});
return res.redirect("/");
})
//-------------------------signin check
app.post("/signin",async(req,res) => {
try{
const email = req.body.email;
const password = req.body.password;
const useremail = users.findOne({email:email});
if(useremail.password === password){
res.redirect("/");
}
else{
res.send("password incorrect");
}
res.send(useremail);
console.log(useremail);
}
catch{
res.send("in catch block invalid Email");
}
})
/------------end of db------------
//server create
app.listen(port, () =>{ console.log(hi, port: ${port}); })
//This is my app.js code. I'm having problem in "signin check". There's no problem with Sign up details are also stored in mongodb compass. Help me with sign in. Any help will be appreciated.
From the first glance, since you are using native mongodb, in signing query should look like this:
const useremail = await db.collection('users').findOne({email:email});
You had 2 mistakes there, first syntax was wrong since I assume you do not have user model(You do insertOne with same thing).
Also you need await keyword since database operations are async and they return promise. Without await value of useremail would be undefined, thus causing the error

Having some problems trying to call a function from another script

I'm building a mockup website to try and learn NodeJS. I want a login system and I'm trying to connect my register page with my database script. The sql function that sends queries to the database is working as intended, however, when trying to call the query function from the script that manages the register webpage all I get is an error 500.
It would be cool if someone could point me in the right direction, surely it's some quirk from NodeJS I don't know about yet.
Here is my register page script that should call the query function from POST routing:
var express = require('express');
var router = express.Router();
var db = require('../public/javascripts/dbController');
router
.get('/', function(req, res, next) {
res.render('register.html', {title: 'Register'})
})
.post('/', function(req, res, next) {
register(req.body);
res.render('register.html', {title: 'Register'})
})
function register(request)
{
let username = request.login;
let password = request.password;
let sql = "INSERT INTO users (user_username, user_password, user_status) VALUES ('"+username+"','"+password+"', 1);";
console.log("query");
//Why is this not working?
db.query(sql);
}
module.exports = router;
And here is (part of) my dbController script:
const sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database('./public/database/db.db', sqlite3.OPEN_READWRITE, (err) => {
if (err && err.code == "SQLITE_CANTOPEN") {
createDatabase();
return;
} else if (err) {
console.log("Getting error " + err);
exit(1);
}
});
//This function is not running when I ask for it in register.js
function query(sql){
console.log("running query: " + sql)
db.all(sql, [], (err, rows) => {
if (err) {
throw err;
}
rows.forEach((row) => {
console.log(row.name);
});
});
}
module.exports = query;
I figure that I probably have to route my scripts through the main app script or maybe I'm exporting wrong? Anyway, any nudge in the right direction would be great because I've been stuck on it a few days. Thanks!
For what I can see, you're indeed importing the "query" function into your "register" page. But you're setting a name of "db" to it.
var db = require('../public/javascripts/dbController');
but you're not exporting "db" you're exporting "query":
module.exports = query;
But that's not really the issue, you could just call it "myRandomNameImport" and it would still work. The problem is that you're accessing a property of "db" that does not exist.
db.query(sql); /* <- db.query does not exist.
* Try db(sql) instead. */
"db" does not have any properties called "query", the function you're trying to use is "db".
function register(request) {
let username = request.login;
let password = request.password;
let sql = "INSERT INTO users (user_username, user_password, user_status) VALUES ('"+username+"','"+password+"', 1);";
console.log("query");
db(sql); /*<- Just call db()*/
}

Directly authenticate(login) after successful signup in Node.js

How can i directly authenticate the user after signup.
Below are the the deatail of serializeUser and deserializeUser.
passport.serializeUser(function(user, done) {
done(null, {tutorId: user.tutorId, userType: user.userType});
});
passport.deserializeUser(function(userData, done) {
Tutor.getTutorById(userData.tutorId, (err, user) => {
if (err) {
try {
logger.silly(`message: POST inside passport.deserializeUser; file: index.js; error: ${err}; user: ${JSON.stringify(user)}`);
logger.error(`message: POST inside passport.deserializeUser; file: index.js; error: ${err}; user: ${JSON.stringify(user)}`);
} catch (e) {
You can use req.login() after successful registration.
From official Passport documentation:
Note: passport.authenticate() middleware invokes req.login()
automatically. This function is primarily used when users sign up,
during which req.login() can be invoked to automatically log in the
newly registered user.
A sample registration code might look like this:
router.post("/register",(req,res) => {
var user = new User();
user.name = req.body.name;
user.email = req.body.email;
//define other things here
//create hash and salt here
user.save().then(user => {
//on successfult registration
//login user here, using req.login
req.login(user ,err => {
if(!err){
//redirect to logged-in page
//or user page
res.redirect('/')
}
})
})
})
Read about req.login() in official passport documentsation
I hope this helps you out.
you can create token just after successful registration and send it back in registration response

string interpolation with sqlite3 and Node

Somewhat new to this, but I'm having an issue inserting a variable into my sqlite3 query. I get the error { [Error: SQLITE_ERROR: no such column: shmee] errno: 1, code: 'SQLITE_ERROR' } where shmee in this case is req.body.username
Not sure what I'm doing wrong here? Any guidance?
app.post('/users/login', function (req, res) {
console.log(req.body)
var query = "SELECT username, password FROM users WHERE username = "+req.body.username+";"
db.all(query, function (err, data) {
if (err) {
console.log(err);
} else if (req.body.password === data.password) {
//set cookie with user info
req.session.user = data;
res.redirect('/users/'+data.username);
} else {
console.log(data)
console.log('password not correct');
res.redirect('/cbt');
}
})
});
Do not concatenate data into query strings; this is a serious source of security vulnerabilities!
Use query parameters; wherever you want to pass data into a query, put a ?, and pass it as an additional argument to run:
db.run("SELECT username, password FROM users WHERE username = ?",
username,
function(err, data) {...});
Also hash your passwords.

Categories

Resources