Data is not getting captured in mongodb - node.js

Data is not getting captured in mongodb . For frontend I am using angular and at backend I am using node js. I tested the backend api using postman , data is getting captured in mongoDb , where as when I am submitting from an angular form data is not getting captured.
//UI logic
<div class="row mt-5">
<div class="col-md-6 mx-auto">
<div class="card">
<div class="card-header">
<h3>Register</h3>
</div>
<div class="card-body">
<form>
<div class="form-group">
<label>Email:</label>
<input type="text" class="form-control" name="email" [(ngModel)]="registerUserData.email" email required>
</div>
<div class="form-group">
<label>Password:</label>
<input type="password" class="form-control" name="password" [(ngModel)]="registerUserData.password" required>
</div>
<button (click)="registerUser()" class="btn btn-info float-right">Register</button>
</form>
</div>
</div>
</div>
</div>
//service
private urlR="http://localhost:3000/register";
private urlL="http://localhost:3000/login";
constructor(private httpClient:HttpClient) { }
registerUser(abc){
return this.httpClient.post<any>(this.urlR,abc);
}
//submit method
registerUser() {
this.authService.registerUser(this.registerUserData)
.subscribe(
res=> console.log(res),
err=> console.log(err)
)
}
//backend node
app.post('/register' , (req,res) => {
const newUser = new Expo({
email:req.body.email,
password:req.body.password
});
newUser.save( (err , registeredUser) => {
if(err) {
console.log(err);
} else {
res.status(200).send(registeredUser);
}
});
});

Related

How to check if a username is taken in Mongo Schema with an AJAX API call

I am trying to create a registration form where a potential user is typing in their desired username it checks against the existing Mongo DB User Schema to see if that exact name exists.
The form I have is here:
<form class="needs-validation" action="/register" method="POST" novalidate>
<div class="text-center mb-3">
<p class="lead">Welcome to the team! We just need a few things to get started.</p>
<div class="row">
<div class="col-md-6 mb-4">
<div class="form-outline">
<input
type="text"
id="first_name"
name="first_name"
class="form-control"
required
/>
<label class="form-label" for="first_name"
>First name</label
>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Thats not right</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="form-outline">
<input
type="text"
id="last-name"
name="last-name"
class="form-control"
required
/>
<label class="form-label" for="last-name"
>Last name</label
>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Thats not right</div>
</div>
</div>
</div>
<!-- Email input -->
<div class="form-outline mb-4">
<input
type="email"
id="register_email"
name="register_email"
class="form-control"
required
/>
<label class="form-label" for="register_email">Email</label>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Thats not right</div>
</div>
<div class="text-center mb-3">
<div class="form-outline mb-4">
<input type="text" id="register_username" name="register_username" class="form-control" placeholder="enter your username" required />
<label class="form-label" for="register_username">Username</label>
<div id="username-check"></div>
</div>
<!-- Password input -->
<div class="form-outline mb-4">
<input type="password" id="register_password" name="register_password" class="form-control" required/>
<label class="form-label" for="register_password">Password</label>
</div>
</div>
<!-- Submit button -->
<div class="text-center">
<button type="submit" id="register" class="btn btn-lg btn-rounded bg-insider link-dark mb-3 fw-bold" disabled>
Lets Go! <i class="fa-solid fa-gauge-max"></i>
</button>
</div>
</form>
I have this script code working on the page to take the user input and check to a get route that should be checking my MongoDB:
$('#register_username').on('keyup', function () {
$.get('/usercheck?username=' + $(this).val().toLowerCase(), function (response) {
$('#username-check').text(response.message);
console.log('')
var btn = document.getElementById('register');
btn.disabled = true;
if ($('#username-check').html() === "user exists") {
$('#username-check').text('username not available').css('color', 'red');
}
else {
console.log($('#register_username').val())
$('#username-check').text('username is available').css('color', 'green');
btn.disabled = false;
}
})
});
This is the route it calls to check the database:
var express = require("express"),
router = express.Router(),
passport = require("passport"),
User = require("../models/user");
router.get('/usercheck', function(req, res) {
console.log(req.query);
User.findOne({username: req.query.register_username}, function(err, username){
if(err) {
console.log(err);
}
var message;
if(username) {
console.log(username);
message = "user exists";
console.log(message);
} else {
message= "user doesn't exist";
console.log(message);
}
res.json({message: message});
});
});
module.exports = router;
In case this helps, this is the user Schema in the database:
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: String,
password: String,
email: String,
isAdmin: { type: Boolean, default: false }
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User",UserSchema);
I am not sure what I am missing but anything would be extremely helpful. Thanks in advance!
Just so this question can be closed successfully:
Changing /usercheck?username= to /usercheck?register_username= did the trick, because this query param was used in the form:
$('#register_username').on('keyup', function () {
$.get('/usercheck?register_username=' + $(this).val().toLowerCase(), function (response) {
$('#username-check').text(response.message);
console.log('')
var btn = document.getElementById('register');
btn.disabled = true;
if ($('#username-check').html() === "user exists") {
$('#username-check').text('username not available').css('color', 'red');
}
else {
console.log($('#register_username').val())
$('#username-check').text('username is available').css('color', 'green');
btn.disabled = false;
}
})
});

Proxy error: Could not proxy request /send from localhost:3000 to http://localhost:3001/

I'm sending some data from my ReactJS front-end application to my node/express backend, however, whenever I send the data, I get the error message mentioned in the title.
https://ibb.co/KbpwqZv
contact.js
This is my react js code where i declare my react from those who communicate with backend via axios
import React, { useState } from 'react'
import "./Contact.css";
import Axios from 'axios';
import {API} from '../backend';
const Contact = () => {
const [state,setState]= useState({
name:'',
lastname:'',
email:'',
message:'',
})
const [result,setResult] = useState(null);
const sendMail = e =>{
e.preventDefault();
Axios.post('/send',{...state})
.then(response => {
setResult(response.data);
setState({
name:'',
lastname:'',
email:'',
message:''
})
})
.catch(()=>{
setResult({
success:false,
message:"Something went wrong. Try again later"
})
setState("");
})
}
const onInputChange = e =>{
const {name,value} = e.target;
setState({
...state,
[name]: value
})
}
console.log("API is",API);
return (
<>
{result && (
<p className={`${result.success ? 'success' : 'error'}`}>
{result.message}
</p>
)}
<section className='contactus'>
<div className="container">
<h1 className='title'>CONTACT US</h1>
<form >
<div className="singleItem">
<label htmlFor="name">Name</label>
<input type="text"
name="name"
className="name"
placeholder="Your Name..."
value={state.name}
onChange={onInputChange}
/>
</div>
{/* <div className="singleItem">
<label htmlFor="Lastname">LastName</label>
<input type="text"
name="LastName"
className="LastName"
placeholder="Your Last Name..."
value={state.lastname}
onChange={onInputChange}
/>
</div> */}
<div className="singleItem">
<label htmlFor="email">Email</label>
<input type="email"
name="email"
className="email"
placeholder="Your Email..."
value={state.email}
onChange={onInputChange}
/>
</div>
<div className='textArea singleItem'>
<label htmlFor="message">Message</label>
<textarea name="message"
id=""
col="30"
rows="5"
placeholder="Your Message..."
value={state.message}
onChange={onInputChange}
>
</textarea>
</div>
<div className="msg">Message has been Sent</div>
<button type="button" className='btn btn-primary' onClick={sendMail}>Submit</button>
</form>
</div>
</section>
</>
)
}
export default Contact;

Multer and CSRF and <form action="?_method=PUT">

So, ive just added multer and cloudinary to my project.
whenever I add something to my db using my form. it gives this error
"ForbiddenError: invalid csrf token"
but i've fixed that by adding ?_csrf=<%= csrfToken %>" to my action attribute in my form
<form action="/admin?_csrf=<%= csrfToken %>" method="POST" enctype="multipart/form-data">
Now, I'm trying to do the same thing for my update route.
and it's giving me the same error from before "ForbiddenError: invalid csrf token"
I've tried doing
<form action="/admin/<%= prod._id %>?_method=PUT?_csrf=<%= csrfToken %>" method="POST" enctype="multipart/form-data">
or this
<form action="/admin/<%= prod._id %>?_method=PUT?_csrf=<%= csrfToken %>" method="POST" enctype="multipart/form-data">
or this
<form action="/admin/<%= prod._id %>?_method=PUT_csrf=<%= csrfToken %>" method="POST" enctype="multipart/form-data">
or this
<form action="/admin/<%= prod._id %>?_csrf=<%= csrfToken %>_method=PUT" method="POST" enctype="multipart/form-data">
you know... different kind of variations... hoping one would work. hahah
anyways, is what I am doing impossible? that I could have 2 methods in my action attribute?
is there another way i could do this somehow?
Edit.ejs
<section class="no-padding-top">
<div class="container-fuid">
<div class="row">
<div class="col-lg-12">
<div class="block">
<div class="title"><strong>Edit Item</strong></div>
<form action="/admin/<%= prod._id %>?_method=PUT" method="POST" enctype="multipart/form-data">
<div class="form-group row">
<label class="col-sm-3 form-control-label">Product Name</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="prod[name]" value="<%= prod.name %>" required>
</div>
</div>
<div class="form-group row">
<label for="image" class="col-sm-3 form-control-label">Product Image</label>
<div class="col-sm-9">
<input type="file" id="image" name="image" accept="image/*" >
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 form-control-label">Product Price</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="prod[price]" value="<%= prod.price %>" required>
</div>
<label class="col-sm-1 form-control-label">Product Quantity</label>
<div class="col-sm-2">
<input type="text" class="form-control" name="prod[quantity]" value="<%= prod.quantity %>" required>
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 form-control-label">Product Brand</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="prod[brand]" value="<%= prod.brand %>" required>
</div>
<label class="col-sm-1 form-control-label">Product type</label>
<div class="col-sm-2">
<input type="text" class="form-control" name="prod[type]" placeholder="Types of produces. i.e Wheels, Lights, Steering Wheels..." value="<%= prod.type %>" required>
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 form-control-label">Product Description</label>
<div class="col-sm-9">
<textarea cols="30" rows="10" class="form-control" name="prod[description]" required> <%= prod.description%> </textarea>
</div>
</div>
<div class="form-group row">
<div class="col-sm-9 ml-auto">
<button type="submit" class="btn btn-primary">Edit Item</button>
Cancel
</div>
</div>
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
</form>
</div>
</div>
</div>
</div>
</section>
multer and cloudinary start
var multer = require('multer');
var storage = multer.diskStorage({
filename: function(req, file, callback) {
callback(null, Date.now() + file.originalname);
}
});
var imageFilter = function (req, file, cb) {
// accept image files only
if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/i)) {
return cb(new Error('Only image files are allowed!'), false);
}
cb(null, true);
};
var upload = multer({ storage: storage, fileFilter: imageFilter})
var cloudinary = require('cloudinary');
cloudinary.config({
cloud_name: 'pitscaraccessories',
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
});
update route
router.put("/:id", middleware.isLoggedIn, middleware.isAdmin, upload.single('image'), function(req, res) {
Product.findById(req.params.id, async function(err, prod) {
if (err) {
req.flash("error", err.message);
} else {
if (req.file) {
try {
await cloudinary.v2.uploader.destroy(prod.imageId);
var result = await cloudinary.v2.uploader.upload(req.file.path);
prod.image = result.secure_url;
prod.imageId = result.public_id;
} catch (err) {
req.flash("error", err.message);
return res.redirect("back");
}
}
prod.save();
req.flash("success", "Updated Successfully");
res.redirect("/admin");
}
});
});
fixed this by doing this to my code. changed my route from .put to .post
and manually just updating each input inside.
router.post("/:id", middleware.isLoggedIn, middleware.isAdmin, upload.single('image'), function(req, res) {
Product.findById(req.params.id, async function(err, prod) {
if (err) {
req.flash("error", err.message);
} else {
if (req.file) {
try {
await cloudinary.v2.uploader.destroy(prod.imageId);
var result = await cloudinary.v2.uploader.upload(req.file.path);
prod.image = result.secure_url;
prod.imageId = result.public_id;
} catch (err) {
req.flash("error", err.message);
return res.redirect("back");
}
}
prod.name = req.body.name;
prod.price = req.body.price;
prod.quantity = req.body.quantity;
prod.brand = req.body.brand;
prod.type = req.body.type;
prod.description = req.body.description;
prod.save();
req.flash("success", "Updated Successfully");
res.redirect("/admin");
}
});
});
and doing this to my form element
<form action="/admin/<%= prod._id %>?_csrf=<%= csrfToken %>" method="POST" enctype="multipart/form-data">
I was having the same problem, maybe you didn't try enough permutations ;D
This syntax worked for me
<form action="/users/<%= user._id %>?_method=PUT&_csrf=<%= csrfToken %>" method="POST" enctype="multipart/form-data">

React, Node: Variable shows undefined on app.post()

Not sure if I've done it correctly on the server or client side, but in the client side when I console.log(values) they appear, but in server, I get undefined. But when i do enter the right credentials for a user in the database i get status:ok, so something is found. And also a extra bug is i cannot to the post request twice, then i get the error: Error: Cannot enqueue Handshake after invoking quit.
Client Code:
class Login extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
const data = new FormData(event.target);
const email = data.get('email');
const password = data.get('password');
fetch('/authentication', {
method: 'POST',
body: JSON.stringify({
"email": email,
"password": password
}),
}).then(function (response) {
if (response.ok) {
alert("Login Successful!");
} else {
console.log("Failed");
}
});
console.log("Email: " + email);
console.log("pwd: " + password);
}
render() {
return (
<form className="col s12 m12 l12" onSubmit={this.handleSubmit}>
<div className="row">
<div className="col s12 center-align">
<img className="logo" src="images/bibdata-center.png" alt="BibData Logo"/>
</div>
<div className="input-field col s12">
<i className="material-icons prefix">email</i>
<input id="email" name="email" type="email" className="validate" onChange={this.handleEmailChange}/>
<label htmlFor="email">Email</label>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<i className="material-icons prefix">lock</i>
<input id="password" name="password" type="password" className="validate" onChange={this.handlePasswordChange}/>
<label htmlFor="password">Password</label>
</div>
</div>
<div className="row">
<div className="col s12 m6 l6 center-align">
<button className="btn waves-effect btn-large waves-light" type="submit" value="Submit" name="action">Sign in
<i className="material-icons right">send</i>
</button>
</div>
<div className="col s12 m6 l6 center-align">
<button className="btn waves-effect btn-large waves-light blue" type="submit" name="action"
onClick={() => renderReactComponent(newUser, 'root')}>
Register
</button>
</div>
</div>
<div className="row">
<div className="col s12 center-align">
<a href="#" onClick={() => renderReactComponent(forgotPassword, 'root')}>
<span className="helper-text grey-text text-darken-1"
data-error="wrong" data-success="right">
Forgot password?
</span>
</a>
</div>
</div>
</form>
);
}
}
And Server Code:
app.post('/authentication', function (req, res) {
connection.connect();
let email = req.body.email;
let password = req.body.password;
console.log(email);
console.log(password);
connection.query('SELECT * FROM user WHERE email = ? AND password = ?',
[email, password], function (error, results, fields) {
if (error) {
return res.status(500).send(error);
}
return res.send({ error: false, data: results, message: 'ok'})
});
connection.end();
});
All help will be appreciated!
When you make your fetch call to /authentication endpoint, you are sending serialized JSON data in your request body. The server however has no means of knowing that you have actually sent an JSON. When posting JSON, you must indicate that by providing appropriate content-type header.
In this case your fetch options (2nd param) should have one more property like this:
...
headers: {
"Content-Type": "application/json",
},
...
This is assuming, you have already setup body-parser or another similar module on your server side code which can parse JSON request body.

Insert in bulk using Sequelize with Node and Express

Looking for a way to insert activities to the database in bulk using Sequelize Model.bulkCreate.
Not sure how to bring the activities from the view to the route function in order to insert them using bulkCreate. Right now I only insert one activity.
View:
<form action="/create" method="POST">
<div class="form-group">
<label>Plan Name</label>
<input type="text" name="plan_name" placeholder="Plan Name">
</div>
<div class="form-group">
<label>Description</label>
<input type="text" name="description" placeholder="Description">
</div>
<div class="form-group">
<label>Activity</label>
<input type="text" name="activity_name" placeholder="Activity">
<label>Comment</label>
<input type="text" name="comment" placeholder="Comment">
<input type="button" id="add" class="btn btn-success" value="Add">
</div>
<div class="form-group" id="new">
</div>
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<input type="submit" class="btn btn-success" value="Submit">
</form>
<script type="text/javascript">
$('#add').click(function() {
let activity = $('<div class="form-group"><label>Activity</label><input type="text" name="activity_name" placeholder="Activity"><label>Comment</label><input type="text" name="comment" placeholder="Comment"></div>');
$('#new').append(activity);
});
</script>
Route:
app.post('/create', (req, res) => {
const user_id = req.user.id;
const data = {
plan_name: req.body.plan_name,
description: req.body.description,
userId: user_id
};
PlanModel.Plan.create(data).then(plan => {
const activity = {
activity_name: req.body.activity_name,
comment: req.body.comment,
plans_id: plan.id
};
ActivityModel.Activity.create(activity);
res.redirect('/');
});
});
1) Make fields to have names like an array
<div class="activities">
<div class="form-group">
<label>Activity</label>
<input type="text" name="activities[0][name]" placeholder="Activity">
<label>Comment</label>
<input type="text" name="activities[0][comment]" placeholder="Comment">
</div>
<div class="form-group">
<label>Activity</label>
<input type="text" name="activities[1][name]" placeholder="Activity">
<label>Comment</label>
<input type="text" name="activities[1][comment]" placeholder="Comment">
</div>
</div>
<div class="form-group>
<input type="button" id="add" class="btn btn-success" value="Add">
</div>
2) At server-side just take that req.body.activities and generate array of objects and call bulkCreate
app.post('/create', async (req, res) => {
try {
const data = {
plan_name: req.body.plan_name,
description: req.body.description,
userId: req.user.id
};
const plan = await PlanModel.Plan.create(data);
if (req.body.activities && Array.isArray(req.body.activities)) {
const activities = req.body.activities.map(
activity => {
return {
activity_name: activity.name,
comment: activity.comment,
plans_id: plan.id
}
});
await ActivityModel.Activity.bulkCreate(activities);
}
res.redirect('/');
}
catch(error) {
res.status(500).send(error);
}
});
3) Since body parser for urlencoded mode has extended option that parses deeply all of the fields. You've to enable it.
MAKE SURE that bodyParser middleware attached with extended: true :
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));

Resources