I have a very simple app that right now allows you to make an account, and just adds a document to a database. When I try to query the information and send it back using res.send() it errors and says converting circular structure to JSON. What does this mean? All of the objects in the document are strings. There's nothing fancy going on.
Here's the route it's erroring on:
var express = require('express');
var router = express.Router();
var cookieParser = require('cookie-parser');
/* GET users listing. */
router.get('/', function(req, res, next) {
// res.send(req.params);
});
router.post('/', function(req, res, next) {
console.log(req.body.nickname + " from the " + req.body.grade + " class registered.");
db.collection('users').insert({email: req.body.email, password: req.body.password, nickname: req.body.nickname, grade: req.body.grade}, function(err, result) {});
res.cookie("fss-sched-account", req.body.email);
res.cookie("fss-sched-password", req.body.password);
console.log(db.collection('users').find({}));
res.json(db.collection('users').find({}));
});
router.get('/nocookies', function(req, res, next) {
});
module.exports = router;
Here's a link to all of my code: Github
It means that you are trying to pass the "cursor" from the .find() rather than the "results". You likely just want:
db.collection('users').find({}).toArray(err,results) {
if (err) throw err; // or handle somehow
console.log(results);
res.json(results);
})
Where the .toArray() converts to an array as well as executing the query, returning a form of data you can actually use.
Related
Hi am a beginner to Nodejs i have used passportjs token based authentication if the user logins it provides a token for each user i want to perform some operations based for the users who has token values for example if the user want to see the list of registered users they can view it if he has the token value. Now it provides me the token value perfectly in Postman but i don't know how to store it in a variable and call it via FRONT-END. I want do it via Front End(If he clicks the get users button) it should display the list of users.I have done that in POSTMAN it works finely i don't have an idea how to do it via frontend.
My user Code(Login/Logout)
var express = require('express');
var router = express.Router();
var User = require('../models/user');
var passport = require('passport');
var Verify = require('./verify');
/* GET users listing. */
router.route('/')
.get(Verify.verifyOrdinaryUser, function(req, res, next) {
User.find({}, function (err, users) {
if (err) throw err;
res.json(users);
});
});
router.post('/register', function(req, res, next) {
User.register(new User({ username : req.body.username }),req.body.password, function(err, user) {
if (err) {
return res.status(500).json({err: err});
}
user.save(function(err,user) {
passport.authenticate('local')(req, res, function () {
return res.status(200).json({status: 'Registration Successful!'});
});
});
});
});
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json({
err: info
});
}
req.logIn(user, function(err) {
if (err) {
return res.status(500).json({
err: 'Could not log in user'
});
}
var token = Verify.getToken(user);
res.status(200).json({
status: 'Login successful!',
success: true,
token: token
});
});
})(req,res,next);
});
router.get('/logout', function(req, res) {
req.logout();
res.status(200).json({
status: 'Bye!'
});
});
module.exports = router;
Main.js File. In this main.js file i want to send that token in this get method any idea?
$(".get-users-button").click(function() {
$.ajax({
method: "GET",
url: " http://localhost:3000/users"
})
.done(function(msg) {
console.log(msg);
template(msg);
});
});
When you get back a successful response from the POST to your /login endpoint, store the token on client-side (e.g., window.localStorage.setItem('<your-namespace>-user-token', <the token goes here>);)
Then, when user clicks the 'get-users-button', get the token out of storage (e.g., window.localStorage.getItem('<your-namespace>-user-token'); and store it in a variable if you want.
Then, on your request to get users, add your { 'x-access-token': <token variable goes here> } to your request headers.
As per the documentation for Passport:
If authentication succeeds, the next handler will be invoked and the req.user property will be set to the authenticated user.
Now if I'm understanding your question correctly, you want to pass the token value you obtain from:
var token = Verify.getToken(user)
to the view in which your front-end can do something with. You can pass variables to the view using the following middleware:
app.use((req, res, next) => {
res.locals.token = Verify.getToken(req.user)
next()
}
See the documentation for res.locals for more details.
Example usage:
app.js
const express = require('express')
const app = express()
app.set('view engine', 'pug')
app.use((req, res, next) => {
res.locals.text = 'asdf'
res.locals.token = 'abc'
next()
})
app.get('/', (req, res) => {
res.render('index')
})
app.listen(3000, () => {
console.log('listening on 3000')
})
views/index.pug
doctype html
html
head
title= title
body
h1= text
script.
console.log('#{token}')
I'm starting with Express and I have a question; I have the setup and everything, I've made some simple things but know I want to interact with an API, to do what I want to do I need to the data that I want to get it's from an input field. I want to refresh the main (/) page with the data that was sent. Like a client-side ajax request. I don't know how to send the data that was sent to the post router to the get router without having to go to another link (i.e. localhost:3000/link), i want to stay in the same page where the request was done. I'm using pug (jade) in the template
Express:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', (req, res, next) => {
res.render('index');
});
/* POST HANDLER */
router.post('/link', function(req, res, next) {
console.log(req.body);
});
module.exports = router;
jQuery:
$('#shortLink').on('click', () => {
$.ajax({
type: 'POST',
url: '/link',
data: $('linkInput').val()
});
});
So, to be clear. User puts something on the input field; sends that data to the post router, I want to get the information sent to the post router to be sent to the get router without having to leave the page where the request was done. Let me know if I didn't explain myself very well.
Let's just say you have the body parser set up and understand how does the templating work.
In this what you want is to somehow save the data somewhere on the server. Now in a very simple case you can just save it to variable:
var data = null;
router.get('/', (req, res, next) => {
res.render('index', { data: null });
});
router.post('/link', function(req, res, next) {
data = req.body
res.send('');
});
Then in your template you can do p= data.
Now after you post to the /link then on the next refresh / will show the data.
In most web applications though, people will save these things to the database. Here's an example for MongoDB saving the data to specific document:
router.get('/', (req, res, next) => {
collection.findOne({ id: 'specificDoc'}, function (err, result) {
if (err) {
next(err);
return;
}
res.render('index', { data: result.data });
});
});
router.post('/link', function(req, res, next) {
collection.update({ id: 'specificDoc', { data: req.data }, { upsert: true }, function (err, result) {
if (err) {
next(err);
return;
}
res.send('');
});
});
Probably you might also start using sessions and save the data depending on the user using cookies or other methods. Here's a toturial for using sessions in express.
I'm very new and I've looked through the archives but just what's going on in this code eludes me. I used express-generator to create a calendar app and now I want to hook it up to MongoDB. The actual connection to Mongo is working, but I can't get it to save a document.
The relevant portion of my global.js (where I'm running my front-end Javascript) looks like this:
$(document).ready(function() {
var ev = new Event({ date: "a6_13_2016", time: 900, description:"Fencing"});
ev.save(function(err) {
if (err) console.log(err);
else console.log("Success!")
})
This is where I'm getting the "TypeError: ev.save is not a function" message. My models/Events.js looks like this:
var mongoose = require('mongoose');
var eventSchema = new mongoose.Schema({
date: String,
time: Number,
description: String
});
module.exports = mongoose.model('Event', eventSchema);
My routes/events.js looks like this:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Event = require('../models/Events.js');
/* GET /event listing. */
router.get('/', function(req, res, next) {
Event.find(function (err, dates) {
if (err) return next(err);
res.json(dates);
});
});
/*POST event*/
router.post('/', function(req, res, next) {
Event.create(req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
/* GET /event/id */
router.get('/:id', function(req, res, next) {
Event.findById(req.params.id, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
module.exports = router;
I want to save something to test it, but it's giving me ".save is not a function. Other than
var events = require('./routes/events');
app.use('/events', events);
and the code establishing the Mongoose connection my app.js file is boilerplate. What do you think is the problem?
I see
$(document).ready(function() {
Are you trying to use Mongoose in browser?
It's supposed to be used on the server-side.
In browser you need to send AJAX request to the server:
$('#save').click(function() {
$.post('/event', function(response) { console.log(reposne) })
});
On the server you should add a route that will handle your AJAX request, and inside this route you can save your model:
router.post('/event', function(req, res) {
var ev = new Event({ date: "a6_13_2016", time: 900, description:"Fencing"});
ev.save(function(err) {
if (err) console.log(err);
else console.log("Success!")
})
});
Please note that you don't need the 3rd param next in your rotues. It is used only in middlewares
Are you sure that line
var Event = require('../models/Events.js');
has the correct path?
You are creating an ev object from Event function and it seems that ev is undefined, judging from the error description.
If your Event file is not properly loaded you will not have access to .save function.
I am new to MEAN stack. I am trying to retreive a list of documents from MongoDB. I have used Visual Studio 2013 community edition to create a basic Nodejs Express application. Visual studio created app.js file on the root for configuration. I have put following code in app.js which is relevant to mongodb:
var mongo = require('myDB');
var db = new mongo.Db("myDB", new mongo.Server("localhost", "27017"),
{ safe: true }, { auto_reconnect: true });
// Make our db accessible to our router
app.use(function (req, res, next) {
req.db = db;
next();
});
In the routes folder that visual studio created, I have created a js file which will perform CRUD operations. I have following code in this file:
var express = require('express');
var router = express.Router();
router.get('/myRecords', function (req, res) {
var db = req.db;
db.open(function (err, db) {
if (err)
console.log(err);
else {
var collection = db.collection('myCollection');
var dataToSend = collection.find();
res.send(dataToSend);
}
})
});
module.exports = router;
I am Type Error: Converting Circular structure to JSON.
I am trying to not using any schema.
Please advice.
For those of you, who encounter the similar problem, find() doesn't return the document, we need to use toArray to retrieve documents. Following code did the trick:
router.get('/myRecords', function (req, res) {
var db = req.db;
db.open(function (err, db) { // <------everything wrapped inside this function
db.collection('myCollection', function (err, collection) {
collection.find().toArray(function (err, items) {
res.send(items);
db.close();
});
});
});
});
I am currently working on the log in portion of my project but I am working with express, passport-local and mongoose. I have a set of routes:
module.exports = function (app) {
app.get('/', function (req, res) {
res.render('index', { user : req.user, title : "Home" });
});
app.get('/register', function(req, res) {
res.render('register', { });
});
app.post('/register', function(req, res) {
Athlete.register(new Athlete({
username: req.param('username'),
firstName: req.param('firstName'),
lastName: req.param('lastName'),
dob: req.param('dob')
}), req.param('password'), function(err, athlete) {
if (err) {
console.log(err);
return res.render('register');
}
res.redirect('/');
});
});
app.get('/login', function(req, res) {
res.render('login', { user : req.user.username });
});
app.post('/login', passport.authenticate('local'), function(req, res) {
res.redirect('/');
});
app.get('/logout', function(req, res) {
req.session.destroy(function (err) {
res.redirect('/');
});
});};
I am currently able to sign in and sign out no problem and it displays my name as per the jade template using the p= user.firstName jade syntax. This though is burping up a object that contains a salt, hash, as well as the model values. This is clearly a huge security issue and I want to wrap my hear around what is going on between the route and the template. How can I prevent the entire user database object from coming up and which part of my code is causing the miscommunication.
First of all your user object won't leak as jade will be rendered on server side until you expose the secret information in your template. So passing extra information won't result in leaking.
Still if you want to restrict the entire user passing into jade, you can add a method in your user schema and call that method while using res.render.
userSchema.methods.getSafeUser = function() {
var user = this;
//filter user as per your requirements here.
return user;
}
Then in your controller, use
res.render('index', { user : req.user.getSafeUser() });