Node/Express session value insert - javascript

I'm currently working on a project using Node/Express/MongoDB. I'm using Mongoose to create my schema's and interface with DB. I'm using "express-sessions" module and have a session value set. Specifically, "req.session.user" which equals the username when logged in.
My question here, is how do I go about inserting the session value into mongodb? I have my model defined properly.
doc_type.model.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TypesSchema = new Schema({
type_id: {
type: String,
uppercase: true,
required: true
},
type_description: {
type: String,
required: true
},
created_by: {
type: String,
required: false
},
creation_date: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('document_types', TypesSchema);
admin.js with routes defined.
adminRouter.route('/doc_types')
.get((req, res) => {
Type.find({}, (err, types) => {
if (err) {
console.error(err)
res.json(err)
}
else if (!req.session.user || !req.session.badge) {
res.redirect('/login');
}
else if (req.session.user || req.session.badge) {
res.render('doc_types', { pageTitle: 'Document Types', types: types, currentUser: req.session.user })
}
})
})
.post((req, res) => {
var type = new Type();
type.type_id = req.body.input_type_id;
type.type_description = req.body.input_type_description;
type.created_by = req.session.user;
type.save((err) => {
if (err) {
console.error(err)
res.json(err)
}
else {
res.json("Success!");
}
})
});
If you look under the .post method, you'll notice the line "type.created_by = req.session.user;". I then save my data into my db via schema. Upon doing so, my session value isn't passed into mongoose scheme. It's empty. However, when I console.log the req.session value, it displays fine there.
Can someone clarify my issue here? I'm stumped. It's probably something stupid I've overlooked.

Welp, it was something stupid. :) I was using postman to "POST" my data to the page. Postman has no idea what the session value was, therefore, no data sent to the mongoose document id. The session was only stored on the server/browser side. Lesson learned, haha.

Related

cut user id mongoose response

I'm trying to response from my backend a piece of user id by using lodash, i tryed with id.slice(2, 9) but i get a response without _id. What i'm doing wrong? thanks in advance.
getUserData: (req, res, next) =>{
User.findById(req.params.userId,
(err, user) => {
if (!user)
return res.status(404).json({ status: false, message: 'User record not found.' });
else
return res.status(200).json({ status: true, user: _.pick(user, ['_id'.slice(2, 9), 'domain', 'store', 'settings']) });
}
);
},
getUserData: (req, res, next) =>{
User.findById(req.params.userId,
(err, user) => {
if (!user)
return res.status(404).json({ status: false, message: 'User record not found.' });
else {
let json = { status: true, user: _.pick(user, ['_id', 'domain', 'store', 'settings']) };
json.user._id = json.user._id.slice(2, 9);
return res.status(200).json(json);
}
}
);
},
Pick the parts you want
Slice the _id to replace it with just the part you want
return the object
Edit:
To cut the ObjectId is necessary first to parse to string, so you need something like this:
var newUserId = user._id.toString().substring(3,user._id.toString().length)
But there is a problem (I think, not tested). If you try to store the cut id into a model object, maybe mongoose don't allow you to add an string (and no valid ObjectId) value instead of ObjectId.
Maybe is neccesary create another object instead of the model with the schema.
Old answer (unrelated) but maybe usefull for somebody:
If you want to hide the result just use select() into your query.
You run a query and then select which fields do you want to get or not into the response.
The proper way to code it is as follows:
query.select({ field1: 1, field2: 1 });
//or
query.select('-field1');
//and many other ways
Docs here

Mongoose findOneAndUpdate doesn't find (or update) in Node

I'm trying to add user input (url's) to a database with Mongoose but also checking if the added data already exists. Instead it seems to be creating a new model every time.
This shows the res.json(input) on screen, not the test json
var mongo = require('mongodb');
var mongoose = require('mongoose');
var cors = require('cors');
// Basic Configuration
var port = process.env.PORT || 3000;
process.env.DB_URI="omg it's my secret url"
// Connect to DB.
mongoose.connect(process.env.DB_URI, { useNewUrlParser: true, useUnifiedTopology: true }).
catch(error => handleError(error));
mongoose.connection.on('error', err => {
console.log(err);
});
app.use(cors());
//First we create a schema and Model in MongoDB.
const urlSchema = new mongoose.Schema({
original_url: String,
short_url: Number
});
const urlModel = mongoose.model('urlModel', urlSchema);
app.post(/PATH, function(req, res, done) {
//Now we check if the input-url was actually valid.
if(!/(^https:\/\/)/.test(req.body.url)){
res.json({error: "Invalid url"});
}
//If it's valid we will start creating a model in the DB.
else {
var userUrl = req.body.url;
var urlNumber = 0;
var input = new urlModel({
original_url: userUrl
});
//Now we check if the url was already added to the database and return a new or updated item.
urlSchema.pre('save', function (next) {
var query = {'original_url': userUrl };
urlModel.findOneAndUpdate(query, userUrl, {upsert: true}, function(err, doc) {
if (err) return res.send(500, {error: err});
res.json({'test': 'test'});
});
});
res.json(input);
urlNumber++;
input.save(function(err, data) {
if (err) return console.log(err);
done(null, data);
});
};
});
As you can see I also have a problem updating the number that I want to attach to the url in the database, since I re-assign 0 to urlNumber at the beginning of the call. Must be because it's late but I can't seem to find a way to update that number correctly. I tried two variables and checking them against each other and an if(urlNumber > 0), but that's a problem I'm still solving. Seems so simple..
Anyway the question here is: why doesn't findOneAndUpdate seem to update? The returned res.json(input) shows a new '_id' every time, which tells me it does actually create new models every run.
Example returns
#1
{
_id: eksdjh3948wryeids293ren12;
original_url: "https://www.correct.com"
short_url: 0
}
#2
{
_id: eksdjh3948wryeids293ren13; // (<----- NEW NUMBER)
original_url: "https://www.correct.com"
short_url: 0
}
Your pre('save' function(next) {}) hook isn't calling next()
Turns out the .pre hook doesn't work with findOneAndUpdate! If I just remove that, the code now works as expected.

Return multiple mongodb entries with the same attribute using express

I'm trying to log all mongodb entries which are associated with a username using express.
This is my code:
transcriptRepository.getTranscriptByUsername = (username) => {
return Transcript.find({ username })
.then( transcript => {
console.log('ALL TRANSCRIPTS: ', transcript)
return transcript
})
}
I'm sure there's supposed to be an array in there somewhere, but I don't know how to implement it.
When I run that code using supertest, I get the following error message:
Unhandled rejection CastError: Cast to string failed for value "{}" at
path "username" for model "Transcript"
at new CastError (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/error/cast.js:29:11)
at castString (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/cast/string.js:34:9)
at SchemaString.cast (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/schema/string.js:445:10)
at SchemaString.SchemaType.applySetters (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/schematype.js:724:12)
at SchemaString.SchemaType._castForQuery (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/schematype.js:1113:15)
at SchemaString.castForQuery (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/schema/string.js:500:15)
at SchemaString.SchemaType.castForQueryWrapper (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/schematype.js:1082:15)
at cast (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/cast.js:248:34)
at model.Query.Query.cast (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/query.js:3710:12)
at model.Query.Query._castConditions (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/query.js:1515:10)
at model.Query.Query._find (/Users/annacuddeback/work/emblem-site/node_modules/mongoose/lib/query.js:1530:8)
at process.nextTick (/Users/annacuddeback/work/emblem-site/node_modules/kareem/index.js:333:33)
at process._tickCallback (internal/process/next_tick.js:61:11)
What's the best way to return multiple database entries with the same attribute?
Edit:
My Transcript model is as follows:
const Schema = mongoose.Schema
const TranscriptSchema = new Schema({
pdfContent: {
type: String,
required: true,
index: { unique: true }
},
hashValue: { //hash of transcript pdf contents
type: String,
required: true,
},
username: { //matches an email in users, used to see who issued the transcript hash
type: String,
required: true
},
studentUsername: { //username of the student the transcript belongs to
type: String,
required: true
},
schoolID: {
type: String,
required: true
},
sequence: Number,
updatedAt: { type: Date, default: Date.now }
})
My database is set up from front to back as server.js-->controller-->service--repository
My server route is:
app.get('/transcript/query/username/:username', userController.getTranscriptByUsername) //gets transcripts by username
My controller function is:
userController.getTranscriptByUsername = (req, res) => {
userService.getTranscriptByUsername(req.body)
.then( (transcript) => {
res.end(transcript.hashValue)
})
}
My service function is:
userService.getTranscriptByUsername = (username) => {
return transcriptRepository.getTranscriptByUsername(username)
}
My supertest unit test is:
it('should return 200 for getting transcripts', function(done) { //this is how mocha expects HTTP requests to be written: with a done parameter to the function
request(server).get('/transcript/query/username/euler#python.com').expect(200, done)
})
You are passing a empty object in username, the function is expecting a string
Unhandled rejection CastError: Cast to string failed for value "{}" at path "username" for model "Transcript"
You have to check that you are passing a string.
It is this line that looks problematic:
app.get('/transcript/query/username/:username', userController.getTranscriptByUsername) //gets transcripts by username
I say that because it gets routed to userController.getTranscriptByUsername, and you have that function defined to take a username argument. But the Express callback functions expect request and response arguments.
Try changing it to this:
app.get('/transcript/query/username/:username', (req, res) => {
const {username} = req.params
userController.getTranscriptByUsername(username)
})
Also, to return the transcripts from the get request, you could change getTranscriptByUsername to accept a callback as the second argument:
transcriptRepository.getTranscriptByUsername = (username, cb) => {
Transcript.find({ username })
.then( transcript => {
console.log('ALL TRANSCRIPTS: ', transcript)
cb(transcript)
})
}
And to update the Express function one more time:
app.get('/transcript/query/username/:username', (req, res) => {
const {username} = req.params
userController.getTranscriptByUsername(username, transcript => {
res.json({transcript}) // returning it as JSON in the response
})
})

Mongoose NodeJS only undefined values [duplicate]

This question already has answers here:
Mongoose always returning an empty array NodeJS
(7 answers)
Closed 7 years ago.
Now I've played with nodeJS and SocketIO and all went fine.
But now I get caught at one query!
// User Auth Event
socket.on('userAuth', function(userObj) {
var queryUserAuth = User.find({
name : userObj.name
})
.where('password',userObj.pword);
queryUserAuth.exec(function(err, userData){
if(err) {
socket.emit('userAuthOK',err);
console.log('!! User: %s or PW not OK', userObj.name);
return handleError(err);
}else {
console.log('User: %s known, userID: %s', userObj.name, userData.userid);
socket.emit('userAuthOK', userData.userid);
socket.join(userData.userid); // Create new room / join this room
}
});
});
But all the time the var "userData" is empty and the console.log above tells me "User: testuser known, userID: undefined".
I can't get this user object from MongoDB this ways, but I can find the user if I take the mongo console.
///////////
EDIT:
After some changes... here the new code... but still without finding the right record and getting a result of null.
// User Auth Event
socket.on('userAuth', function(userObj) {
var queryUserAuth = User.findOne({
name : userObj.name,
password : userObj.pword
});
//.where("password").equals(userObj.pword);
queryUserAuth.exec(function(err, userData){
if(err) {
socket.emit('userAuthOK',err);
console.log('!! User Auth Error: %s', err);
return handleError(err);
}else {
if(!userData){
console.log('!! User: %s or PW not OK.', userObj.name);
socket.emit('userAuthOK','fail');
}else {
console.log('User: %s known, userID: %s', userObj.name, userData);
socket.emit('userAuthOK', userData);
socket.join(userData.userid); // Create new room / join this room
}
}
});
});
Here the output by manual query on mongo shell:
db.user.find({name: 'testuser', password: 'test'}) { "_id" : ObjectId("55a8cc8240fdc97f108d4d11"), "userid" : "1", "name" : "testuser", "email" : "test#test.com", "password" : "test" }
And this is the value of userObj: { name: 'testuser', pword: 'test' }
/////
EDIT2:
here the user.js including the mongoose model of User:
// Load the MongoDB module
var mongoose = require('mongoose');
// user schema
var userSchema = mongoose.Schema({
userid: Number,
name: String,
email: String,
password: String,
status: Number
});
// compiling the user schema
var User = mongoose.model('User', userSchema);
// make this available to our users in our Node applications
module.exports = User;
Here the include of the model:
// Load Mongoose models
var User = require('./models/user');
Try logging userData instead of just userData.userid. It's an Array, not an Object. You want to use .findOne(), not .find().
Also, the syntax for the query methods is:
.where("password").equals(userObj.pword)
Or, you could just add it to your original .findOne():
var queryUserAuth = User.findOne({
name: userObj.name,
password: userObj.pword
});
In addition, your console.log('!! User: %s or PW not OK', userObj.name); doesn't make any sense. Not finding anyone is different than getting an error. You'll want to handle that part as a separate if statement nested within the else block.

How to create an update function on nodejs/mongodb?

Hi I am currently new to nodejs and mongodb what I want to do is make a function to update my win,lose,draw record from my userschema.
My Schema:
UserSchema = new mongoose.Schema({
username:'string',
password:'string',
email:'string',
//Change Made
win:{ type: Number, default: 0 },
lose:{ type: Number, default: 0 },
draw:{ type: Number, default: 0 }
});
My Function for updating:
//Update scores
app.post("/user/updateScores", function (req, res) {
var user = new User({
username:req.body.username,
win:req.body.win,
lose:req.body.lose,
draw:req.body.draw
});
Users.findOne({ username : req.params.username }, function(error, user) {
if (error || !user) {
res.send({ error: error });
} else {
user.update(function (err, user) {
if (err) res.json(err)
req.session.loggedIn = true;
res.redirect('/user/' + user.username);
});
}
});
});
The problem is when I try updating, when I try updating via my html file. It does not update anything and just stays the same (the values win,lose,draw the default value is 0 so when I logout and login again the values of the win,lose,draw record is still zero). I thoroughly checked if the problem was the html and javascript functions that I have made but this is not the case so I think that the problem is the update function I have made. Any of you guys have an idea where I went wrong? Thanks!
Assuming your post is being called correctly from the client, you'll need to be careful about variable and parameter names, as the scope right now is that you're saving an exact duplicate of the user object that was just fetched via findOne.
You had user declared as a variable of the post callback, and then again within the findOne. The inner variable user will take precedence.
app.post("/user/updateScores", function (req, res) {
var username = req.body.username;
Users.findOne({ username : username }, function(error, user) {
if (error || !user) {
res.send({ error: error });
} else {
// update the user object found using findOne
user.win = req.body.win;
user.lose = req.body.lose;
user.draw = req.body.draw;
// now update it in MongoDB
user.update(function (err, user) {
if (err) res.json(err) {
req.session.loggedIn = true;
}
res.redirect('/user/' + user.username);
});
}
});
});

Categories

Resources