Rendering a template/view in client side javascript - javascript

I am new to node and making a simple login page - The client-side javascript takes the values from input then makes a post request to a server which has a database containing all the user accounts. In the server this info is checked :
-If details are correct they should be taken to a new page which has dynamic content in (their username)
-If the details are incorrect then the main page should not change - I just want an element to be added saying "Incorrect password, try again"
This worked fine when i was making the post request directly from the form but have decided to change this so that i can display "incorrect password, try again" on the sign-in page.
My client-side javascript
"use strict"
document.querySelector("button").addEventListener("click",submit)
async function submit(e){
e.preventDefault();
let username=document.querySelector("#username").value
let password=document.querySelector("#password").value
let options = {
headers:{
"Content-Type" : "application/json"
},
method: "POST",
body: JSON.stringify({username,password})
}
let response = await fetch("/api",options)
let responseData = await response.json()
if(responseData.status == "fail"){
console.log("show the fail message");
}
}
My server-side js:
"use strict"
//Installing express
let express = require(`express`)
let app = express()
app.use(express.json())
var bodyParser = require('body-parser')
var urlencodedParser = bodyParser.urlencoded({ extended: false })
let ejs = require('ejs');
app.set("view engine","ejs")
//running the server
app.listen(3000,()=>{
console.log("server is running boi");
})
//Middleware to load the static content
app.use(express.static('public'))
//Database stuff
let Datastore = require('nedb')
let db = new Datastore({ filename: 'database.db' });
db.loadDatabase()
//Handler for any post requests made from the form
app.post('/api', urlencodedParser, function (req, res) {
let user = req.body.username
//querying the db
db.find({username:user},(err,docs)=>{
if(docs[0]){
if(docs[0].password == req.body.password){
console.log("You have logged in!");
res.send({status:"success"})
}else{
console.log("incorrect password")
res.send({status:"fail"})
}
}else{
console.log("incorrect username");
res.send({status:"fail"})
}
})
})
If the user passes the details and the details are correct then I want a template to be rendered with their name on (I use EJS), How can I do this from the client-side and if I can not, what can I do?

As I can see, you are using EJS but not rendering anything. Instead, you are sending a JSON response to your client. Now, from your client you can do this:
Client code:
let responseData = await response.json()
if(responseData.status == "fail"){
alert('Failed to login');
// You can do DOM manipulation here. Like: show a message to user
} else {
// Login success. Do something here
alert('Login success')
}
UPDATE: Using EJS
app.post('/api', urlencodedParser, function (req, res) {
let user = req.body.username;
db.find({username:user},(err,docs)=>{
if(docs[0]) {
res.render('template', {user: docs[0]})
} else {
res.render('template', {user: null})
}
})
}
In your EJS:
<% if (user === null) { %>
<h1>Login failed</h1>
<% } else { %>
<h1>Login success</h1>
<% } %>

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

I can't access req.session variables in other post requests

I am developing an apt management app.
Basically, if a user is a resident, they get to see their apt fee payment data.
If the user is from apt management, they select one of the 5 db update options from the apt mgmt menu page by clicking one of the submit buttons numbered from 1 to 5.
I am trying to make my code session-based so I am attaching my own variables to req.session object as req.session.loggedin, req.session.userid and req.session.userpwd.
I authenticate username and userpwd inputs from login page in the first post request to '/server' and if they match in db then I set req.session.loggedin to true.
I was hoping that I would be able to use the req.session.loggedin and req.session.username variables in the second request to '/mgtmenupg' and other requests but unfortunately it doesn’t work because I get undefined error.
At the moment I can’t progress any further. What do I have to do to able able to access req.session.loggedin and req.session.username variables in other requests?
Any help will be appreciated.
Attached is my minimal reproducable examples of js code.
var express = require('express'); // Import Express package
var session = require('client-sessions');
//var session = require('express-session');
var bodyParser = require('body-parser'); // Import body-parser module to parse incoming requests
var cookieParser = require('cookie-parser');
var path = require('path'); //import path module.
var app = express(); // Create an Express app variable so that we can use Express in anywhere.
var router = express.Router();
var cors = require('cors'); //import cors from "cors". CORS allows frontend and backend to share data because they are on different servers.
var port = 3000; //Set port to 3000. This is where our backend server will be.
var mysql = require('mysql');
var alert = require('alert');
const { config } = require('process');
//var { response } = require('express');
var con = mysql.createConnection({ // Create connection object.
host: 'localhost',
user: 'root',
password: 'hsAdmin',
database: 'havuzsDB'
});
//const { request } = require('http');
// Below, we use the imported modules in our Express app.
app.use(express.json() ); // use Express module body-parser to parse JSON-encoded request bodies
app.use(express.urlencoded({extended: true})); // use Express module body-parser to parse URL-encoded request bodies
app.use(cookieParser());
// Use the sessions package to determine if user is logged-in.
app.use(session({
cookieName: 'session',
secret: 'top99secret',
duration: 30 * 60 * 1000,
activeDuration: 5 * 60 * 1000,
httpOnly: true,
secure: true,
ephemeral: true
//resave: true,
//saveUninitialized: true
}));
app.use(cors());
// Set up view engine.
app.engine('html',require('ejs').renderFile);
app.set('view engine', 'ejs');
//app.set('views', path.join(_dirname, 'views'));
// Start your server on a specified port and listen for http request on that port.
// app.listen() is the function that starts a port and host, in our case the localhost for the connections
// to listen to incoming requests from a client.
app.listen(port, () => {
alert("server is running at http://127.0.0.1:", port); //Show server url at console. Use this url in <script> tag of your html code.
});
/* You can use this to check if your server is working.
app.get('/', (req, res)=>{
res.send("Welcome to my server");
}); */
// Connect to havuzsDB database.
con.connect(function(err) {
if (err) {
throw err;
alert("DB Connection failed");
}
else
alert("DB Connected!");
});
// Route to send the local image file to be used as app homepage background, to the client.
app.get('/havuzlusite-img.jpg', function(req, res) {
res.sendFile("D:/Behrans-files/Web-projects/havuzlusite/havuzlusite-img.jpg");
});
// Route to send home page file to the client.
app.get('/', function(req, res) {
res.sendFile("D:/Behrans-files/Web-projects/havuzlusite/homepg.html");
});
// Route to send the login form to the client.
app.get('/loginpg', function(req, res) { //Send login page file to the client.
res.sendFile("D:/Behrans-files/Web-projects/havuzlusite/loginpg.html");
});
//Route to receive and authenticate user login data.
app.post('/server', (req, res) => {
req.session.username = req.body.isim; // save username input in a local variable.
req.session.userpwd = req.body.sifre; // save user pwd in a local variable.
if (req.session.username && req.session.userpwd) { //Check if user has entered name and password in the login form.
con.query('SELECT * FROM havuzs_sakinleri WHERE isim = ? AND sifre = ?', [req.session.username, req.session.userpwd], function(err, rows) {
if (rows.length > 0) {
req.session.loggedin = true;
req.session.rows = rows;
} else {
return alert('İsim ve şifre veri tabanında bulunamadı. Lütfen geçerli bir isim/şifre girin!');
//return res.render('loginpg');
}
res.end();
})
} else {
return res.send('Lütfen isim ve şifre giriniz!');
res.end();
}
//console.log('loggedin:', req.session.loggedin, 'username: ', username);
//If user is a resident, display resident data.
if (req.session.loggedin && req.session.username !== 'Yonetim') {
if (req.session.rows) { // If user name/pwd match db,
var rows = req.session.rows;
return res.render('userdatapg', {rows}); // Display resident data.
res.end;
}
};
//If user is an authorized building management team member, display management menu.
if (req.session.loggedin && req.session.username == 'Yonetim') {
return res.render('mgtmenupg'); //Display db update menu page.
res.end();
}
});
// Determine which button is clicked.
app.post('/mgtmenupg/:btnno', (req, res) => {
// Route to handle apt fee payment - If button#1 is clicked.
if (req.params.btnno == 1) {
res.render('userpmtpg'); //Display user apt fee payment page.
app.post('/userpmtpg', (req, res) => { //Post request to access payment month and payment amount inputs from user.
var username = req.body.username;
var pmtmnth = req.body.pmt_mnth;
var pmtamt = req.body.pmt_amt;
queryusername(username, function(response) { //Pass username and call function to see if the user is in db.
if (response == 'Found') { //If response has no error message, call function to update user payment data in db.
updateUsrPmtData(username, pmtmnth, pmtamt, function(response) { //Call function to update user apt fee payment data in db.
return alert(response); //Display db update status message from called function.
});
} else if (response == 'Not found')
res.send('İsim veri tabanında bulunamadı. Ana sayfaya dönmek için lütfen Ana sayfa butonuna tıklayınız!'); //If response has error message, display error message.
else
res.send('Site sakini ismi veri tabanında aranırken sorun oluştu.');
})
res.render('mgtmenupg');
res.end();
})
}
// Route to handle deletion of existing resident user - If button#2 is clicked.
if (req.params.btnno == 2) {
res.render('deluserpg');
app.post('/deluserpg', (req,res) => {
var username = req.body.username;
queryusername(username, function(response) { //Pass username and call function to see if the user is in db.
if (response == 'Found') { //If response has no error message, it means user is in db, call function to delete it.
deleteUser(username, function(response) { // Pass username input data as parameter to call deleteuser function.
return alert(response); //Display db delete status message from called function.
res.render('mgtmenupg');
})
} else if (response == 'Not found') {
return alert('İsim veri tabanında bulunamadı. Lütfen sistemde mevcut bir isim girin.'); //If response has error message, display error message.
return res.render('deluserpg');
} else
return res.send('Site sakini ismi veri tabanında aranırken sorun oluştu.');
})
res.end();
})
};

How do I query with url parameter?

I am new to Node.js and trying to check if an e-mail is already taken by sending the email as a url parameter from iOS app. It is not working, not sure what I am doing wrong.
I am unable to console.log the email parameter in VSCode sent from the front-end, it DOES print in XCODE ( http://localhost:3000/api/user/email/test#gmail.com ) and I know the backend is getting the GET request.
My router code is:
const express = require(`express`)
const router = new express.Router()
const User = require(`../models/user-model`) // import User model
router.get(`/api/user/email/:email`, async (req, res) => {
console.log(req.params) // does NOT print email: test#gmail.com
try {
const user = await User.findOne(req.params.email)
if (user) {
console.log(user._id)
res.send({ available: false })
} else {
res.send({available: true})
}
} catch {
res.status(404).send()
}
})
Thank you!
const express = require(`express`)
const app = new express();
app.get(`/api/user/email/:email`, async (req, res) => {
console.log(req.params) // does NOT print email: test#gmail.com
try {
// const user = await User.findOne(req.params.email)
const user = {_id:123};
if (user) {
console.log(user._id)
res.send({ available: false })
} else {
res.send({available: true})
}
} catch {
res.status(404).send()
}
})
app.listen(3000,function(){
console.log("running");
})
Editing this.. I dont have enough points to comment.. your route seems to be fine, maybe you are not telling your application to use this route, somewhere before starting your application you should have something like:
this.app = new express();
...
this.app.use('/api', MailRouter); //<=== Adding your required mail route
...
I use to split url one parte here (/api) and the other one in the router (/user/email/:email). I'm not sure how to do it by adding it fully to the router (Maybe '/' maybe '')

Verifying username match from outside API during the registration process

I am making a web application that allows Fortnite players to find other players to play with. Users should be able to register, login, post and comment. I have designed the frontend portion of the user login and registration features as well as the backend of the user registration but one of my requirements is that:
Before registration, the server should check whether the username provided is a real Fortnite username using the FortniteTracker API which provides user profiles using their very simple API.
Example Call: GET https://api.fortnitetracker.com/v1/profile/{platform}/{epic-nickname}
How do I verify the username exists before allowing the user to create the account?
I have tried creating a separate endpoint for the API call from the server side but I didn't know how to implement it into my /register endpoint
script.js
function registerRequest(username,password) {
$.ajax({
url: "http://localhost:8080/register",
type: 'POST',
data: JSON.stringify({username,password}),
contentType: "application/json",
error : function(err) {
console.log('Error here!', err)
},
success: function(data) {
console.log('Success!')
// What do I put here?
}
});
}
function handleRegisterSubmit(event) {
event.preventDefault();
const username = $(event.currentTarget).find('.username-register').val()
const password = $(event.currentTarget).find('.password-register').val()
const passwordConfirm = $(event.currentTarget).find('.password-confirm').val()
if (password === passwordConfirm) {
registerRequest(username,password)
}
else {
console.error("Passwords did not match")
}
}
$(function onLoad() {
displayRegisterPage()
$(`.js-content-section`).on('submit', '.js-register-form', handleRegisterSubmit)
}
})
server.js
app.post('/register', jsonParser, (req, res) => {
const requiredFields = ['username', 'password']
for (let i = 0; i < requiredFields.length; i++) {
const field = requiredFields[i]
if (!(field in req.body)) {
const message = `Missing \`${field}\` in request body`
console.error(message)
return res.status(400).send(message)
}
}
let username = req.body.username;
let password = req.body.password;
User.findOne({username})
.then(user => {
if (user) {
const message = `username is already taken`
console.error(message)
return res.status(400).send(message)
}
else {
User.create({username, password})
.then(user => {
const userRes = {
id: user._id,
username: user.username
}
res.status(201).json(userRes)
}
)
}
})
.catch(err => {
console.error(err)
res.status(500).json({ error: 'something went horribly wrong'})
})
})
app.get('/login', (req, res) => {
const usernameReq = User.findById(req.body.username);
if (usernameReq) {
console.log(usernameReq)
res.status(201).json(usernameReq)
}
})
schema.js
const UserSchema = new mongoose.Schema({
username: {
type: String,
unique: true,
required: true,
trim: true
},
password: {
type: String,
required: true,
}
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
I expect that if I register with "ninja" as a username I should be able to register since that is a valid Fortnite username. The actual output currently allows users to register with any username that isnt already taken in the database.
You would need packages like axios, request, request-promise (Promise supported version of request) etc to make the external api call. You can try implementing within the register like.
const rp = require('request-promise');
app.post('/register', jsonParser, async (req, res) => {
...
let username = req.body.username;
let password = req.body.password;
const options = {
method : 'GET',
uri: 'https://api.fortnitetracker.com/v1/profile/{platform}/{epic-nickname}',
resolveWithFullResponse: true
}
const data = await rp(options)
// check if response code is 200 and check for the expected body
...
// continue rest of the code
}
Or have another middleware to call the external endpoint and do the checks like:
async function checkUser (req, res, next) {
const options = {
method : 'GET',
uri: 'https://api.fortnitetracker.com/v1/profile/{platform}/{epic-nickname}',
resolveWithFullResponse: true
}
const data = await rp(options)
// check if response code is 200 and check for the expected body
if (checks ok)
// if all check ok go to next middleware
next()
else
// if checks did not succeed
// you could pass error to error handler like next(new Error("Hey you do not exist"))
// or render something here
}
Then mount it like:
app.post('/register', jsonParser, checkUser, (req, res) {
...
You can do it simply by sending the username to the API https://api.fortnitetracker.com/v1/profile/{platform}/{epic-nickname}
It will give you a response mentioning about the user exists or not. Based on the response you can make another AJAX request to register the user only if the user does not exist.
I use a Promise request to resolve, reject when someone enters their username. It is only called onClick. in your request you will be able to determine if the call was successfull or not with the username.

Jquery ajax request response 404 when make a post request

I am creating a basic friend request feature. This is one of the function I am working on, when Ajax send the post request it shows 404. It works if I put the code directly in the server.js file but I am trying to organize the code. Any solution? Thanks!
client.pug make a ajax request when user add friend by using email and hit submit
$('#addFriend').on('click', function(ev) {
ev.preventDefault();
var searchByEmail = $('#searchByEmail').val();
$.ajax({
type: 'POST',
url: '/add',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: {
email: searchByEmail
},
success: function(data) {
console.log('success');
}
});
document.getElementById("searchByEmail").value = "";
$('#userModal').modal('hide'); });
controllers/friend.js
const express = require('express');
const app = express();
const User = require('../models/user');
const bodyParser = require('body-parser');
var friendRequest = function() {
app.post('/add', function(req, res) {
var requestToEmail = req.body.email;
console.log(requestToEmail);
User.findOne({
email: requestToEmail
}, function(err, email) {
if (!email) {
console.log('cannot find the email', err);
return res.send(err);
}
/*
Add into database
Display the friend list
*/
})
});
} // End friend request
module.exports = friendRequest;
server.js include and use the module
const friendInvite = require('./controllers/friend');
app.use('/friend', friendInvite);
file structure
- server.js
- controllers
- friend.js
- views
- client.pug
Try change your code on controllers/friend.js like below :
const express = require('express');
const app = express();
const User = require('../models/user');
const bodyParser = require('body-parser');
var friendRequest = function() {
app.post('/add', function(req, res) {
var requestToEmail = req.body.email;
console.log(requestToEmail);
User.findOne({
email: requestToEmail
}, function(err, email) {
if (!email) {
console.log('cannot find the email', err);
return res.send(err);
}
/*
Add into database
Display the friend list
*/
//add this response to client side
res.json({ 'status': '200', 'desc': 'Success' });
})
});
} // End friend request
module.exports = friendRequest;
you must send response to client side what is sign if the data has saved.
maybe you can try to check snippets code here :
https://github.com/egin10/node_mongoose/blob/master/routes/student.js
I didn't see response in your app.post()
So it will be 404(Not found).
When you find a User, you can response something.
For example, a 'success' message and friend list.
app.post('/add', function(req, res) {
res.json(['success', friend list]);
});

Categories

Resources