Saving a user's favorites - node.js

I am trying to associate a user authenticated with passport.js with a backbone.js collection or an array of ids (I don't which solution is the best) and save this in mongoDB.
I use node.js on server side.
Is it possible?
(for instance saving a user's favorites).

You can define a User schema like this:
var User = new Schema({
favorites: [{
whatHaveYou: String,
}]
})
Now, with using passport.js, after you have authenticating the user with this schema, you will be able to access the favorites with: req.user.favorites.
I suggest you go throw this demo project on github for setting up a node-express-mongoose project with passportjs if you have any more questions: https://github.com/madhums/node-express-mongoose-demo, this helped me a lot.

Related

Creating USERs table in Express

I'm pretty new to Express and NodeJS (less than a week) and I have a noobish question.
Background
I have made a REST API from a tutorial using Express and Passport for Authentication (which is just a basic auth with username and password and I get a token back in my requests).
I want to have something like Instagram or Facebook in which users have some information (name, birthdate etc.) and they can post texts.
Model/Account.js
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
import passportLocalMongoose from 'passport-local-mongoose';
let Account = new Schema({
email: String,
password: String
});
Account.plugin(passportLocalMongoose);
module.exports = mongoose.model('Account', Account);
Problem
I don't know if I should add fields to the Model that I created for Authentication (which only has email and password) or I should create a separate Table, like USERS in my Database (I know it's a JSON file and not a database but don't know the technical name).
Please if any, give some hints here or keywords so that I can google myself.
Thanks a lot in advance :)
i think you should add the field is existing model that you create for Authentication because if you made another model you have to repeat the data in your case it is email and password which does not make any sense and it also cause problems and confusion to fetch or manage data in both tables so i prefer you to insert the field in same model that you create for Authentication
I would be inclined to reuse your accounts mongoose model for your user model.
Reason being is that you already have captured email and password which is what you would usually store in a user model.
You can add your additional fields to what you already have.
I think you should consider a general schema for account authentication model and use the schema in all authentication cases. I prefer add other fields to exist model.

How to populate objects in mongoose

What am i trying to do is a single todo app where you can create user and log in with that user.Every user can CRUD for single todo and can fetch all of the todos that are linked to that particular user.
this is the schema for the userSchema
const userSchema = new Schema({
firstName:{type:String,trim:true},
lastName:{type:String,trim:true},
userName:{type:String,required:true,unique:true,sparse:true,trim:true},
email:{type:String,required:true,unique:true,sparse:true,trim:true},
phoneNumber:{type:String,unique:true,sparse:true,required:true},
hash:{type:String,required:true}
})
and i have todoSchema
author:{type: Schema.Types.ObjectId},
title:{type:String, required:true, trim:true},
context:{type:String, trim:true,},
isFinished:{type:Boolean,required:true,default: false},
finishedAt:{type:Date}
Also i have login system that works with JWT,My question is how can i save todo with the id of the user that is currently logged in..And also how can i fetch all todos that are linked to the user that is currently logged in
I dont want todos to be stored in userSchema as array,rather as different schema where you can do CRUD for each todo
-I was reading something called populate that comes with mongoose but i dont know how to implement that
--It will be very nice if you can give me some ideas how to do that..I don't need full implementation..Thank you
-If you need more of the code here it is https://github.com/jkuzmanovik/todoApi
Once the user is logged in ( I guess you are using passport ) passport creates req.user which can be. req.user will contain all the details given in the user schema while creating passport plugin.
This can be used to populate your toDo schema like follows:
in the get request you do
toDo.find({})
.populate('author')
...
But if your goal is to find all toDos by the user you can do as follows
toDo.find({author:req.user._id})
This can be done only after authentication.
This will get you all the todos by the user.
PS: Once you populate only the author field will be replaced (not the proper word but understandable) by the user object itself, it does not help in filtering. Mongoose population should be used meticulously as it is database resource hungry and will reduce the server performance.
About JWT, whenever you make a req you need to pass the JWT to the server (by URL, authorization header etc.). There is a method called extract which will extract the user from the JWT token and thus authentication is possible.
More about that read documentation on passport-jwt and jsonwebtoken.

Cant access property of req.user

I'm writing in Node using passport.js to authenticate.
console.log(req.user);
returns
{ group: 'CuManager',
password: 'password',
username: 'administrator',
cu_id: 2,
_id: 569fd3f4328ef124be533caf }
but
console.log(req.user.cu_id);
returns
undefined
I was thinking that cu_id property maybe is not available due to serialization/deserialization, but it's there. I just can't access it.
How can I do that?
I need it for
find({cu_id : req.user.cu_id})
BTW I can't help thinking passport.js is little overcomplicated (maybe we just don't get along). What else can I use to authenticate users in Node (I use express)?
If req.user is a Mongoose document, you should probably add cu_id to the proper schema.
Otherwise you can use something like req.user.toObject().cu_id to access the property, or make sure that somehow the result of doc.toObject() is assigned to req.user.
As for a Passport-replacement: this depends on how exactly you want to authenticate your users. If you're POST'ing a login form to an Express route, you can perform the password validation and session setup yourself.
try parsing it in JSON.
JSON.parse(req.user)['cu_id']

Get all in MongoDB collection using SocialCMS with Breeze

I'm using SocialCMS Database middleware https://github.com/dai-shi/social-cms-backend with BreezeJS support.
I'm able to save changes to a MongoDB collection fine using manager.saveChanges() and manager.acceptChanges() and retrieve records in local cache using getEntities()
Using this middleware
With BreezeJS support:
var SCB_options = {
mongodb_url: 'mongodb://localhost:27017/socialcmsdb',
breeze_mongo: true,
routes: [{
object_type: 'user',
object_prefix: '/breeze-service/users'
}, {
object_type: 'post',
object_prefix: '/breeze-service/posts'
}, {
object_prefix: '/breeze-service/SaveChanges'
}]
};
How do I retrieve all remote records belonging to a particular route? For example, I want to retrieve all total posts remotely not in the users cache.
Do I modify app.js, my Angular apps datacontext, both or neither?
I solved this problem. It's a bit hard to discern from the Social CMS docs that the routes are local first. Which is great if you want to route without internet access! But I needed to create new routes outside of the SCB_options in order to request mongoDB directly.

Authentication with passport. Can I trust that req.user is indeed the logged in user?

I'm using passport to authenticate users at my site. Users can register orders, which have and foreignKey (ObjectId) to the User object.
Example-objects (written as mongoose schemas):
var orderSchema = new mongoose.Schema({
...
address: String,
_userID: {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User'}
});
var userSchema = new mongoose.Schema({
email: String,
});
Mongoose will create the primary key for each object.
My question is; is it enough to check if req.user._id === order._userID? Or can the req.user object be tampered with? Can I trust that req.user._id is the id of the logged in user?
I've found a couple of good resources, but it's not exactly what I'm asking of.
http://toon.io/articles/understanding-passportjs-authentication-flow/
http://passportjs.org/guide/authenticate/
So the question:
can the req.user object be tampered with?
Is difficult to answer, since you could have code within your application that will have access to your request object, and within it, modify the user. It's important to understand what code you have running within the flow of each request for anyone really, but especially those concerned about the security of their application. With that said, I can at least point you to where in the code this is established, and you can trace it with a debugger to assure yourself of the flow.
As you've mentioned, the passport documentation discusses authentication configuration options in their guide, and by default will process "logging in" the user when your strategy dictates successful authentication. You can provide a custom callback (mentioned in the referenced documentation above) to process this as well. In the end, it's important that req.logIn is called (which is done by default without any custom callbacks provided). Here's a link to the source. (Passport extends the request object via this code to provide helper functions which it later uses.)
The specific line you maybe interested in is here, which assigns to the req object the property user with a value of the authenticated user:
this[property] = user;
From there on, you have access to the logged in user under req.user, and their ID under req.user.id. Again note that this logIn function should only be called when the passport strategy states that successful authentication has occurred. But in this way, passport has provided you with a way of easily authenticating the user, and then getting access to this user via the request object.

Resources