I'm new to server-side programming, and I'm trying to understand how to send data server-side, find a document in a collection and compare it against that data, and then send a status back to the client depending on whether or not it exists.
Here's what's being sent server-side via the /login post request:
{"email":"johndoe#gmail.com","password":"pass"}
Here's the document I'm wanting to compare against in the users collection in my DB:
{
"_id" : ObjectId("580bcf9874ae28934705c0fc"),
"email" : "johndoe#gmail.com",
"password" : "pass"
}
And here's my server-side script (areas I'm guessing are problematic have comments above them):
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var fs = require("fs");
var mongoose = require("mongoose");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static("./public"));
mongoose.connect('mongodb://localhost:27017', function (err, db) {
app.post("/login", function(req, res) {
var emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var userInDb;
// ***** HERE 1 ******
db.collection("users").findOne( {"email": req.body["email"], "password": req.body["password"]} ).toArray(function(err, results) {
userInDb = results;
db.close();
});
// ***** HERE 2 ******
var emailInDb = userInDb["email"];
var passwordInDb = userInDb["password"];
if (!req.body["email"] || !req.body["password"]) {
res.sendStatus(403);
} else if ( !emailRegex.test(req.body["email"])) {
res.sendStatus(403);
} else if ( (req.body["email"] != emailInDb) && (req.body["password"] != passwordInDb) ) {
res.sendStatus(403);
} else {
res.sendStatus(200);
}
});
});
I've also experimented with the following in place of the "HERE 1" section:
var findUser = function (db, callback) {
var users = db.collection("users");
users.findOne({"email": req.body["email"], "password": req.body["password"]}).toArray(function(err, results) {
userInDb = results;
callback(results);
});
=================== EDIT ========================
Here's what it looks like after implementing the below:
mongoose.connect('mongodb://localhost:27017', function (err, db) {
app.post("/login", function(req, res) {
var emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var userInDb;
if (!req.body["email"] || !req.body["password"]) {
return res.sendStatus(403);
} else if ( !emailRegex.test(req.body["email"])) {
return res.sendStatus(403);
} else {
db.collection("users").findOne( {"email": req.body["email"], "password": req.body["password"]}, function(err, results) {
if(err || !result) {
return res.sendStatus(403);
} else {
userInDb = results;
db.close();
return res.sendStatus(200);
}
});
}
});
});
But I'm getting this error in the terminal:
POST request for '/login' - {"email":"johndoe#gmail.com","password":"pass"}
TypeError: Cannot read property 'collection' of undefined at app.js:30:6
Here's what's at line 30:
db.collection("users").findOne( {"email": req.body["email"], "password": req.body["password"]}, function(err, results) {
Does the collection need to be stored somewhere other than the /db/data/ folder you set up when installing MongoDB, do I need to mongoose.connect directly to the users collection, or something else?
findOne is an async function, you have to put the code above here 2 on the callback like this :
db.collection("users").findOne( {"email": req.body["email"], "password": req.body["password"]} ).toArray(function(err, results) {
// ***** HERE 2 ******
var emailInDb = userInDb["email"];
var passwordInDb = userInDb["password"];
.....
});
Then, you forget to check error and result,
db.collection("users").findOne( {"email": req.body["email"], "password": req.body["password"]} ).toArray(function(err, results) {
if(err || !result)
res.sendStatus(403);
// ***** HERE 2 ******
var emailInDb = userInDb["email"];
var passwordInDb = userInDb["password"];
.....
});
Then, you call findOne with the toArray function, why ? You only want 1 result, you don't need to transformed it. In addition you don't use the result as an array, so replace it with
db.collection("users").findOne( {"email": req.body["email"], "password": req.body["password"]}, function(err, results) {
if(err || !result)
return res.sendStatus(403);
// ***** HERE 2 ******
var emailInDb = userInDb["email"];
var passwordInDb = userInDb["password"];
.....
});
Finally, do control before mongo call to prevent useless db call and no need to check (req.body["email"] != emailInDb) && (req.body["password"] != passwordInDb) as it has been already done in mongo query.
Final code :
var emailInDb = userInDb["email"];
var passwordInDb = userInDb["password"];
if (!req.body["email"] || !req.body["password"]) {
return res.sendStatus(403);
} else if ( !emailRegex.test(req.body["email"])) {
return res.sendStatus(403);
} else {
db.collection("users").findOne( {"email": req.body["email"], "password": req.body["password"], function(err, results) {
if(err || !result)
return res.sendStatus(403);
else
{
userInDb = results;
db.close();
return res.sendStatus(200);
}
});
});
}
Other optimisations :
you don't need to put your call in the mongo db connect callback.
hash your password in db
================ EDIT =============
Don't use db.collection
File app.js
var mongoose = require("mongoose");
var User = require("./models/User");
mongoose.connect('mongodb://localhost:27017');
app.post("/login", function(req, res) {
var emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var userInDb;
if (!req.body["email"] || !req.body["password"]) {
return res.sendStatus(403);
} else if ( !emailRegex.test(req.body["email"])) {
return res.sendStatus(403);
} else {
Users.findOne( {"email": req.body["email"], "password": req.body["password"]}, function(err, results) {
if(err || !results) {
return res.sendStatus(403);
} else {
return res.sendStatus(200);
}
});
}
});
app.listen(....
File models/User.js
var mongoose = require('mongoose');
var userSchema = new mongoose.Schema({
// auth fields
email: {type: String, unique: true, lowercase: true },
password: {type: String, default: ""}
... other fields
});
module.exports = mongoose.model('User', userSchema);
Related
I need to update nested array 'commentLikes' in mongodb using nodejs. I have tried like this but not helped.
My Collection is this
_id: 6368f9cd1d1ae931a66de06e
userId: "625400bc00575a0301756870"
desc: "helloooooooo..."
location: ""
taggedFriends: Array
edited: false
likes: Array
dislikes: Array
comments: Array
0: Object
1: Object
commentId: "0.9418743386578314"
dp: "pic1.jpg"
name: "Mohammad Ashraf"
id: "625400bc00575a0301756870"
comment: "avvdvd jhuygjhgd"
commentLikes: Array
nestedComments: Array
and I want to update commentLikes, And I have try like one
//like comment
router.put("/:id/comment/:commentId/like", async (req, res) => {
try {
const post = await Post.findById(req.params.id);
const comment = await post.comments.find((cmnt)=>cmnt.commentId===req.params.commentId);
if (!comment.commentLikes.includes(req.body.userId)) {
// await comment.updateOne({$push: {commentLikes: req.body.userId}});
await post.updateOne({"comments.commentId": req.params.commentId}, {$push: {"comments.$.commentLikes": req.body.userId}});
res.status(200).json("The comment has been liked");
} else {
// await comment.updateOne({ $pull: { commentLikes: req.body.userId } }); // toggle
res.status(200).json("like removed");
}
} catch (err) {
res.status(500).json(err);
}
});
please help
exports.postComments = catchAsync(async (req, res, next) => {
const comment = req.body;
const blogId = req.params.blogId;
if (
!Object.keys(comment).length != 0 ||
!Object.getPrototypeOf(comment) === Object.prototype ||
!ObjectId.isValid(comment?.userId)
) {
return res.status(400).json({
response,
success: false,
message: "invalid request for comments",
});
// console.log("hello");
}
const response = await Blog.updateOne(
{ _id: blogId },
{
$push: { comments: comment },
}
);
if (response.modifiedCount <= 0) {
return res.status(200).json({
response,
success: false,
message: "can not insert new comment please try again",
});
}
res.status(200).json({
response,
success: false,
message: "can not insert new comment please try again",
});
// console.log(response);
});
or you can ask me for more question
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
exports.postComments = catchAsync(async (req, res, next) => {
const comment = req.body;
const blogId = req.params.blogId;
if (
!Object.keys(comment).length != 0 ||
!Object.getPrototypeOf(comment) === Object.prototype ||
!ObjectId.isValid(comment?.userId)
) {
return res.status(400).json({
response,
success: false,
message: "invalid request for comments",
});
// console.log("hello");
}
const response = await Blog.updateOne(
{ _id: blogId },
{
$push: { comments: comment },
}
);
if (response.modifiedCount <= 0) {
return res.status(200).json({
response,
success: false,
message: "can not insert new comment please try again",
});
}
res.status(200).json({
response,
success: false,
message: "can not insert new comment please try again",
});enter code here
// console.log(response);
});
I try to query MongoDB inside nodejs to get data for _id x I use
async function getTestData(id){
return new Promise((resolve, reject) => {
MongoClient.connect(uri, { useNewUrlParser: true, keepAlive: 1 }, function(err, client) {
const dbo = client.db("test");
var query = { _id: id };
dbo
.collection("smscripts")
.find(query)
.project({ 'data' : 1})
.toArray(function(err, items) {
err
? reject(err)
: resolve(items);
});
});
});
}
Query is
{ _id: '5dada7dfdca94dbaf65d9547' }
But I always get back an empty array. Anybody can help me out why the array is always empty? By the way, err is null. The id definitely exists.
in mongo db _id are prefix with ObjectId
so you need value first try this
id = ObjectId("507c7f79bcf86cd7994f6c0e")
and then compare it to ID.
hope it helps
First You need to import..
import { ObjectId } from "bson"
Then in Your code " var query = { _id: id }; " replace it with this..
var query = { '_id' : ObjectId(id) }
Then, in your code you are using .toArray() method. this would takes more time to
convert result to array. so you need to use await keyword before moving on.
Using Async-Await pattern this is very simple ..
const client = await MongoClient.connect(uri, { useNewUrlParser: true, keepAlive: 1 })
.catch(err => { console.log(err); });
if (!client) return;
try {
const dbo = client.db('test');
let collection = dbo.collection('smscripts');
let query = { '_id' : ObjectId(id) };
let projection = { 'data' : 1 } ;
let cursor = await collection.find(query, projection).toArray();
console.log(cursor);
return cursor;
} catch (err) {
console.log(err);
} finally {
client.close();
}
hope this works for you.
I am facing one issue with Mongoose. When I use find or findOne method and there is no matching results, then callback function is not returning null / err and hung the process. Using Mongoss 5.1.5 , MongoDB V3.4.2. Please advise
module.exports.validateappsubscripition = function (userid, appkey, cb) {
//console.error(userid + ' ' + appkey)
var userobj_id = mongoose.Types.ObjectId(userid);
appsubscripitions.model.findOne({'subscribersuserid': userobj_id , 'appkey'
:appkey }, function(err,doc){
console.error('test2');
if(doc ){
cb(null, doc );
}
else{
cb(null, null );
}
} );
}
Calling Block : Trying to validate the key from req header. I am trying to call the function validateappsubscripition from below block.
module.exports.sendEmail = function (req, res, next) {
let appkey;
let userid;
if (req.headers.appkey) {
appkey = req.headers.appkey;
console.error(appkey);
}
else {
appkey = '';
}
if(req.user._id){
userid = req.user._id ;
console.error(userid);
}
if (!req.body.fromEmail || !req.body.toEmail || !req.body.subject || !req.body.content) {
res.json({ success: false, msg: 'Please pass all the required parameters' });
next();
}
appsubcripitions.validateappsubscripition(userid, appkey, function (err, doc) {
console.error('test2');
if (err) {
res.json({ success: false, msg: 'Unauthorized. App Key is misssing on the header or App key is not valid' });
next();
}
else if (doc ) {
this.getSMTP('smtp.gmail.com', 'arbalu#gmail.com', function (err, userInfo) {
if (err) {
res.json({ success: false, msg: err.message });
next();
}
if (userInfo) {
//userInfo = user;
var send = require('gmail-send')({
user: userInfo.user,
pass: userInfo.pass,
from: req.body.fromEmail,
to: req.body.toEmail,
subject: req.body.subject, // Override value set as default
text: req.body.content
});
send({ // Overriding default parameters
// to: req.toEmail,
// subject: req.subject, // Override value set as default
// text: req.content
// files: [filepath],
}, function (err, response) {
//console.log('* [example 1.1] send() callback returned: err:', err, '; res:', res);
if (err) {
res.json({ success: false, msg: err.message });
next();
}
else {
res.json({ success: true, msg: response });
next();
}
});
}
})
}
else {
res.json({ success: false, msg: 'Some issue on sending email.Please contact the support.' });
next();
}
});
}
I am trying to populate my array of an object id's how can i do ??
Function
$scope.assignEmployees = function () {
var chkArray = [];
var companyName = $scope.selectedComapny.companyName;
var Indata = {chkvalue:chkArray,company_name:companyName};
$("#employee_name:checked").each(function() {
chkArray.push($(this).val());
});
$http({
method : 'PUT',
url : '/api/projects',
data : Indata
})
.success(function (data){
console.log(data);
});}
Mongoose api
Population code:-
Project.findOne({client : company_name})
.populate('assignedTo')
.exec(function(err, project) {
if (err) return;
while(i<employee_id.length){
project.assignedTo.push(employee_id[i]);
project.save(function(err) {
if (err) return;
})
i++;
}
});
This code is work but it insert value 4 times any idea guys.
You can use this code to push all elements of Array to an Array in mongoose.
Project.update(
{ client: company_name },
{ "$pushAll": { "assignedTo": employee_id } },
function (err, raw) {
if (err) return handleError(err);
console.log('The raw response from Mongo was ', raw);
}
);
I meet some trouble need your help ~~ thx
I am use mongoose + superAgent + feedparser + eventProxy to get Rss and save these datas
now I can get and finish parse these dataes however I can't save them with moogose
I have 3 module are dao.js , app.js and service.js
I configure dao as this codes
var mongoose = require("mongoose"),
db,
modelName = "news"; // 设定操作的collections
mongoose.connect("mongodb://localhost:27017/test");
db = mongoose.connection;
db
.on("error", function (err) {
console.log("Connection Error!!! this's some prompts: ");
console.log(err);
})
.once("open", function () {
console.log("Open DataBase Successfully!!!");
});
// 设置
var newsSchema = mongoose.Schema({
"category": String,
"data": [{
"title": String,
"link": String,
"pubDate": String,
"source": String,
"author": String
}]
});
console.log(newsSchema.ObjectId);
newsSchema.pre("save", function (next) {
if( !this.title ) {
this.title = "未知标题";
}
next();
})
var newsModel = mongoose.model(modelName, newsSchema);
module.exports = {
model: newsModel,
schema: newsSchema,
mongoose,
db
}
and save data as these codes:
saveData(callback) {
var $self = this;
for(var i = 0; i<$self.result.length; i++) {
new model($self.result[i]).save(function (err) {
if(err) {
console.log(err)
} else {
console.log("数据存储成功!")
}
});
}
callback && callback();
db.close();
}
Now the data can't save successfully meanwhile the save callback func don't run
Could you give me some advise?