node + express + mongoose query authentification - javascript

Im building a simple web app app in express, and I'm a bit stuck in the authentification for my sessions, im going to validate everything in the client with backbone and regExp eventually when i start building the front end of the app. no basycally i have an issue with the query in mongoose returning a mongoose document object. I've looked up a couple of solutions, in the query you can use a .lean() to get an object, or grab the return from the query and apply a .toObject(), that all works fine and dandy, however when i try and authenticate the value of the key with a string it returns false. i'll post an example code, its not exactly what i've got, but its close enough to get the point across.
this would be an example of my models file
var User = new Schema({}, { strict: false });
User.method('authenticate', function(plainText) {
var object = this.toObject();
return plainText == object.password; });
mongoose.model('User', User);
mongoose.connect( definitions.dbConnect );
and in my app file i would have something like
app.get('/session', routes.showLogin);
app.post('/session/new', routes.login);
and in my routes file id have something like
exports.login = function(req, res){
var userQuery = new RegExp(req.body.username , 'i');
var passwordQuery = new RegExp(req.body.password, 'i');
var Query = User.find();
Query.findOne().where('username', userQuery).exec(function(err, user){
if(user && user.authenticate((req.body.password))){
req.session.userId = user._id;
}else{
res.redirect('/session');
}
});
},
Any ideas would be appreciated, its probably very silly... : /
Thanks in advanced!

YEah robert klep was right on the money, After i seearched the mongoose Documentation and the mongodb docs as well, it became clear that queries return a mongo document object, in terms should be converted to the same object or variable types for opperands to work.

Related

Error: Authentication code missing (Mongoose-encryption)

im getting this error while login a registred user
ofcourse i got this error after using dotenv package to secure my database encryption key
but proccess.env.SECRET is working currectly
i guess my problem is here :
userSchema.plugin(encrypt, {
secret: process.env.SECRET,
encryptedFields: ["password"],
});
app.js :
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const encrypt = require("mongoose-encryption");
const app = express();
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));
mongoose.connect("mongodb://localhost:27017/userDB", {
useUnifiedTopology: true,
useNewUrlParser: true,
});
const userSchema = new mongoose.Schema({
email: String,
password: String,
});
//_
// encrypting password field // |
userSchema.plugin(encrypt, { // | i guess problem is here
secret: process.env.SECRET, // |
encryptedFields: ["password"], //_|
});
const User = mongoose.model("User", userSchema);
error :
Error: Authentication code missing
at Object.schema.methods.authenticateSync (C:\Users\Amir\Desktop\security\node_modules\mongoose-encryption\lib\plugins\mongoose-encryption.js:419:23)
at model.<anonymous> (C:\Users\Amir\Desktop\security\node_modules\mongoose-encryption\lib\plugins\mongoose-encryption.js:239:47)
at Kareem.execPreSync (C:\Users\Amir\Desktop\security\node_modules\kareem\index.js:115:16)
at model.syncWrapper [as $__init] (C:\Users\Amir\Desktop\security\node_modules\kareem\index.js:232:12)
at model.Document.init (C:\Users\Amir\Desktop\security\node_modules\mongoose\lib\document.js:513:8)
at completeOne (C:\Users\Amir\Desktop\security\node_modules\mongoose\lib\query.js:2853:12)
at model.Query.Query._completeOne (C:\Users\Amir\Desktop\security\node_modules\mongoose\lib\query.js:2094:7)
at Immediate.<anonymous> (C:\Users\Amir\Desktop\security\node_modules\mongoose\lib\query.js:2138:10)
at Immediate.<anonymous> (C:\Users\Amir\Desktop\security\node_modules\mquery\lib\utils.js:116:16)
at processImmediate (internal/timers.js:456:21)
I had the same problem and this worked for me:
Navigate to your database using your terminal using (as much I can see you use mongo) ex:
show dbs, use databaseName, show collections, db.databaseName.find() and then
Empty your database db.databaseName.drop() (If it is important stuff, then keep it somewhere safe so you can reuse it again, should be easy if you use Postman)
And recreate your database
You should delete the existing documents in your database and run the code again with an empty document.
Actually, the thing is that you might be using your new encryption on data which was stored before the addition of encryption , whereas if you check the same with the new data it will work fine , thus you should create a new database first so that you add new items in it , and it will hopefully work for you . :)
Well, I was facing with the same issue, but it occurs only to the data which you have stored in the database previously using mongoose-encryption without dotenv.
However, it works fine
when you create a new data by registering as new user.
Drop the database and create a new one. (Make sure you save the data before doing it).
:)
The reason is you might changed the "encryption key". If you can find out the one you made it at start, then you can still check and use this database in your (.js) file. However, "Error: Authentication code missing (Mongoose-encryption)" does not mean you destroy it. You still can use. Have a try!
Yes,
You should try to Drop your Database once and Start the server agein.
It may be possible that you have changed your encryption "secret" code a bit while transferring it to the .env file.
Don't forget to take backup before dropping it.
To fix this error, drop the collection you are trying to encrypt (with db.<collection-name>.drop() and create it again.
You are seeing this error because some of the data in your database is not encrypted while the rest of it is encrypted.
In my case, the error was triggered by the usage of findOneAndReplace.
I wanted to replace the record if it already existed in this way:
const newCredentials = { userId, securedCredentials};
await Credentials.findOneAndReplace({ userId }, newCredentials, {upsert:true});
I noticed that the code works if we try to add the object in the standard way:
await new Credentials(newCredentials).save();
Thus the problem is that we are trying to upsert a non-encrypted object. Ok, let's encrypt it then! I tried by calling the encrypt method, but that doesn't work
// The following line doesn't work. `encrypted` is undefined
const encrypted = await new Credentials(newCredentials).encrypt();
// This does work though...
const credentials = new Credentials(newCredentials);
credentials.encrypt((err) => {console.log(credentials)});
As I couldn't figure out how to do this in an atomic operation, I just went the long way:
await Credentials.deleteOne({userId});
await new Credentials(newCredentials).save();
If someone has an idea about how to atomize the operation, it would be great!
You don't have the MongoDB server port 27017 active on your system.
To do that, simply write "mongod" command in another tab of your hyper terminal.

Mongodb does not save a document

I am trying to store some data from an HTML formulary. I send the data using the HTTP POST method and I received them using Express framework in Node.js. The data arrives and it seems to work, but when I try to store them into MongoDB using Mongoose, the database is created but no data is stored when I execute DB.sis_dictionary.find()
I've tried to build different types of schemas and models, but none seems to work. And I get no error from Node.js, it seems to be working, but the MongoDB database does not store anything.
const Mongoose = require('mongoose');
Mongoose.connect('mongodb://localhost:27017/sis_dictionary', {useNewUrlParser: true});
const Schema = Mongoose.Schema;
const wordSchema = new Schema({
word: String
})
const Word = Mongoose.model('Word', wordSchema);
app.post('/saveWord', (req, res) => {
var word = new Word({word: String(req.body)});
word.save(function(err){
if(err) {
return console.error(err);
} else {
console.log("STATUS: WORKING");
}
})
console.log(req.body);
})
server.listen(3000);
console.log("SERVER STARTUP SUCCESS");
In the console, I get the message: "STATUS: WORKING".
sis_ditionary is your DB name and Words should be your collection name. As mongoose automatically creates a plural name for collection from a model if model name not specified when creating from a schema
db.collection.find() is a command to find a collection data when using mongo-shell. Run below command to get data:
use sis_dictionary
db.Words.find()
To beautify result use pretty method
db.Words.find().pretty()
First command will select DB and second command list collection data.
So when you execute db.sis_dictionary.find() it won't work because sis_dictinary is your DB name.
Nodejs way with 'mongoose'
//Model.find({});
Word.find({});
Also, check this line var word = new Word({word: String(req.body)});
What does req.body have? If req.body is {word:"example word"} then you directly pass req.body to modal constructor ie new Word(req.body);
According to your database URL, mongodb://localhost:27017/sis_dictionary, sis_dictionary is the database name.
And according to your mongoose model, Word is your collection name.
When you save a document, it saves under a collection. So you have to make a query under the collections.
So when you try to get data using DB.sis_dictionary.find(), definitely it won't work.
Your query should be like db.collection.find()
Use the following query,
use sis_dictionary
db.words.find()
// for better view
db.words.find().pretty()
For more please check the documentation.
Thank you everybody. You were all right, it was a problem related to my collections names. db.words.find().pretty() worked perfectly!The problem is solved.

Mongoose is connected but can't find data

I have a problem and could really use some help.
We had an application that used MySQL and we are switching over to MongoDB.
We are using Node.js with Express and have MongoDB and Mongoose for the database
We have looked at the MongoDB and Mongoose documentation and searched for related questions on Stack Overflow but we seem to be missing something.
This is what we have in app.js:
var mongo = require('mongodb');
var mongoose = require('mongoose');
var db = mongoose.connect('mongodb://localhost:27017/DBName');
This is our usersModel.js
var db = require('mongoose');
var Schema = db.Schema;
var userSchema = new Schema({
u_id : Number,
u_name : { type: String, required: true },
u_lastname : String
});
module.exports = db.model('user', userSchema);
And this is what we use in the userController:
var User = require('../models/usersModel');
User.find({}, function(err, users) {
if (err) throw err;
console.log("Found users: ", users);
});
The console.log(db.connection.readyState); says it is connecting.
And the User.find() doesn't seem to give out an error, but instead gives an empty array/undefined.
We would really appreciate it if someone could tell us what we overlook.
Thanks in advance.
Not sure why anyone thought this was a good idea, but here's what mongoose does:
Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name.
As a bonus, it's in lower-case which sucks when you have table names with camel case convention.
You can fix it by setting below option in your scheme:
var userSchema = new Schema({..}, { collection: 'user' });
More on this here.
Your find() call looks fine to me.
Are you sure there are users in your collection? Does creating a new user throw an error that you didn't notice? Maybe you can verify that there are indeed users in your collection by popping open a terminal and writing:
> mongo
> use DBName
> show collections
> db.user.find()
And that will return all users that exist.
At: iuliu.net: We get both errors the first was [] and the second is undefined.
At JohnnyHK: Thank you for your submit, but we are sure the the user collection is in this database and the properties we search exists.
At Juuso: Thanks for your feedback your but in the mongo terminal we got the collection output.
Some one asked us a critical question if we tried this with monk. We
installed monk and we have find the database, collection and got
result back. We're still not sure what the problem with Mongoose was,
but with monk it works.
Thank you guys for your feedback and time.

Custom constructor Mongoose

I started taking some tutorials and some books about NodeJS, and started to test out stuff using Mongoose and Rest API requests.
The problem that I encountered is related to the creation of a constructor which will take a parameter (requestBody) and then implement the whole binding on the module (on my case user.js). That is to make the code more reusable and the user module to handle the bindings not the server module which will increase the source code a lot there.
Example
The code below is working as it should, but it's not efficient
var express = require('express')
, bodyParser = require('body-parser')
, expressValidator = require('express-validator')
, mongoose = require('mongoose');
var router = express.Router();
router.route('/users')
// Create a user (accessed at POST http://localhost:8080/api/users)
.post(function (req, res) {
// Bind user (repeating the same procedure for every User object)
var user = new User();
user.info.name = req.info.name;
user.info.surname = req.info.name;
.... // around 10 other properties
req.info.birthday = req.info.name;
// Save
user.save(function (err) {
.... // Handling completion
});
})
My approach
// app/models/user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
info: {
name: {type: String, required: true},
surname: {type: String, required: true},
......
birthday: {type: String, required: true}, // dd/mm/yyyy
},
likes: [Schema.Types.ObjectId],
dislikes: [Schema.Types.ObjectId]
});
function initUser(model) {
userSchema.info.name = model.info.name;
userSchema.info.surname = model.info.surname;
......
userSchema.info.birthday = model.info.birthday;
userSchema.likes = model.likes;
userSchema.dislikes = model.dislikes;
}
module.exports = mongoose.model('User', userSchema);
module.exports.initUser = initUser;
Based on this code, on the request I could easily use (Javascript beginner so explanation will be great)
var user = new User();
user.initUser(req);
but I come up with a really long error which causes the server to crash and the cleanest message is:
TypeError: Converting circular structure to JSON
Questions
Is there anyone who has solved this? I also took a look at Mongoose site, but there doesn't seem to have a specific thing like this.
I'm not sure about your circular json problem, but your initial problem is the way in which you are reading your model properties off your request.
If you post values to that endpoint, the json values you are looking for are going to be on the body property on the request. Pass your function this:
user.initUser(req.body)
You'll need to install a body parser in express to handle the value properly. Once you've done that and pass in request.body, your approach will work.
Pro tip: don't bother mapping the properties individually. If the keys are correctly named just use them to construct your model directly.

Display the data onto webpage retrieved from mongodb using node.js

Heres my problem. Might be a bit trivial. I am using node.js to write a form which has radio buttons, drop down boxes. I have been able to save data and also retrieve it successfully but I am not able to write it onto web page. What is the correct way to write the data onto a page
You can do this pretty easily with express and mongoose. First you would connect to mongoDB using mongoose, and then set up some of the variables used to interact with mongoDB from mongoose (i.e. mongoose.scheme & mongoose.model), and finally you simply send your mongoDB data to a web page through express's res.render function:
mongoose.connect('mongodb://localhost/test', function(err){
if(!err){
console.log('connected to mongoDB');
} else{
throw err;
}
});
var Schema = mongoose.Schema,
ObjectID = Schema.ObjectID;
var Person = new Schema({
name : String
});
var Person = mongoose.model('Person', Person);
app.get('/', function(req, res){
Person.find({}, function(err, docs){
res.render('index', { docs: docs});
});
});
After sending the data, you can simply reference the 'docs' variable in your web page. Express automatically uses the Jade framework. In Jade you could do something like list all the names of the people in your database:
- if(docs.length)
each person in docs
p #{person.name}
- else
p No one is in your database!

Categories