PassPortjs setting local signup to use nested json - javascript

Im trying to implement passsport on an old project and the scema's are set up to be nested for different things for example the name schema below is my sub schema.(There are more this is just for an example)
var nameSchema = new Schema(
{
_id: false,
"firstname" : {type: String, required: true},
"lastname" : {type: String, required: true}
});
// Schema setup
var schema = new Schema(
{
local :
{
name : nameSchema,
email : { type: String, required: true, trim: true, unique: true, select: true},
password : { type: String, required: true, trim: true, select: true},
regDate : { type: Date, select: false, createdAt: true},
alevel : { type: Number, min : 1, max : 5, default: 1, select: true },
}
});
But when I go to add this to my local strategy I get an error TypeError: Cannot set property 'firstname' of undefined How are nested json strategies implemented.
Currently what I have is:
passport.use('local-signup', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
aLevelField : 'aLevel',
namefield : {
firstnameField : 'firstname',
lastnameField : 'lastname'
},
passReqToCallback : true
},
function(req, email, password, done) {
process.nextTick(function() {
User.findOne({ 'local.email' : email }, function(err, user) {
if (err){
return done(err);
}
if (user){
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
} else {
var user = new User();
user.local.email = email;
user.local.password = password;
user.local.aLevel = req.body.aLevel;
user.local.name.firstname = req.body.firstname; // <-- error
user.local.name.lastname = req.body.lastname;
console.log('after define',user);
user.save(function(err){
if (err){
console.log(err)
throw err;
}
return done(null, user);
});
}
});
});
}));

Just incase anyone also comes across this and cant figure it out. When I called
user.local.name.firstname = req.body.firstname this from what i can assume was trying to access .name.firstname but because it was empty there was nothing to set .firstname too.
To fix it do:
user.local.name = {
firstname : req.body.firstname,
lastname : req.body.lastname
};

Related

How can I update an index object array by id

I have the object array's ID and I want to update the info with information I already have on my backend.
My code deletes every array and creates a new one with the new info.
I want to access the array with the variable ID and then change it's values:
const ProdcutSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
productDescription:{
type: String,
required: true
},
pricePerUnit:{
type: Number,
required: true
},
productAmmount:{
type:Number,
required: true
},
/*productImagePath:{
type:String,
required: true
}*/
});
const UserSchema = new mongoose.Schema({
name:{
type: String,
},
email:{
type: String,
},
password:{
type: String,
},
date:{
type: Date,
default: Date.now
},
products:[ProdcutSchema]
});
//Update products
router.put('/dashboard/:id', (req, res)=>{
const ID = req.params.id;
const {product_name, price_PerUnit, product_Description, product_Ammount} = req.body; //Get access to ajax data using body parser
if(!product_name || !price_PerUnit || !product_Description || !product_Ammount){
res.send('Please fill out all fields with valid content');
}else{
User.products.findOneAndUpdate(
{ _id : ID },
{ $set: { products: {
name :product_name,
productDescription : product_Description,
pricePerUnit : price_PerUnit,
productAmmount : product_Ammount
} } },
(err) => {
if (err) throw console.log('found errors');
console.log('no errors');
})
}
});
If you have ObjectId of that item you want to update, code should look like this:
User.products.findOneAndUpdate(
{ _id: ID, "products._id": <here goes id for an array element> },
{
$set: {
"products.$": {
name: product_name,
productDescription: product_Description,
pricePerUnit: price_PerUnit,
productAmmount: product_Ammount
}
}
},
err => {
if (err) throw console.log("found errors");
console.log("no errors");
}
);
Also u gotta be aware that u need to supply an specific ID of an array element for this kind of situation when you want to update subdocument.

Make a dynamic contact chatlist with sorting and paging using mongodb

I need to build a chat using nodejs and mongodb. In this chat I need to mount the contact list by ordering the latest posts and applying paging 15 items per page. I wonder how I can do this dynamically using mongodb / mongoose.
For example, on the first page I seek contacts ordered by those who sent messages last. If loading the second page, and any new message has arrived, the order of chatlist have probably changed.
How I can ride my query and do this treatment?
My User Schema is:
var schema = new Schema({
name: {type: String, required: true},
email: {type: String, required: true, unique: true},
password: {type: String, required: true, select: false},
created_at: {type: Date, required: true, default: Date.now}
});
My Message Schema is:
var schema = new Schema({
content: {type: String, required: true},
type: {type: String, required: true, default: 'text'},
status: {type: String, default: 'not_read'},
created_at: {type: Date, default: Date.now},
read_at: {type: Date},
userFrom: {type: Schema.Types.ObjectId, ref: 'User', required: true},
userTo: {type: Schema.Types.ObjectId, ref: 'User', required: true}
});
Thank you in advance.
EDIT 1:
var itensPerPage = 15;
var skip = page !== undefined ? page * itensPerPage : 0;
pages = Math.ceil(pages / itensPerPage);
Message
.aggregate([
{ '$sort': {
'created_at': -1
}},
{ "$skip": skip },
{ "$limit": itensPerPage },
{ '$match': {
$or: [
{ userFrom: psychologist.id_user },
{ userTo: psychologist.id_user }
]
}},
{ '$group': {
'_id': {
'userFrom': '$userFrom',
'userTo': '$userTo'
},
}
},
])
.exec(function (err, id_users) {
if(err){
callback(new Error("Something went wrong while trying to agregate the psychologist users."), null);
}else{
var users_from_id_map = id_users.map(function(x) { return x._id.userFrom} );
var users_to_id_map = id_users.map(function(x) { return x._id.userTo} );
var chatlist = [];
var received = users_from_id_map.length;
for(var i = 0; i < users_from_id_map.length; i++){
Message
.findOne({$or : [{userFrom: users_from_id_map[i], userTo: users_to_id_map[i]}]})
.sort('-created_at')
.exec(function (err, message) {
if(err){
callback(new Error("Something went wrong while trying to find last message."), null);
}else{
if(message){
var user_chat_id;
if(psychologist.id_user.equals(message.userFrom)){
user_chat_id = message.userTo;
}else{
user_chat_id = message.userFrom;
}
var is_mine = false;
if(message.userFrom.equals(psychologist.id_user)){
is_mine = true;
}
chatlist.push({
id_user: user_chat_id,
lastMessage: {
content: (message.content.length > 35 ? message.content.substring(0,35)+"..." : message.content),
date: message.created_at,
is_mine: is_mine
}
});
}else{
chatlist.push({
id_user: user_chat_id,
lastMessage: null
});
}
received--;
if(received == 0){
next(err, psychologist, chatlist, pages);
}
}
});
}
}
});
Paging can be implemented in various ways in MongoDB.
You could use limit and offset although this will become slow when requesting higher pages.
Another way is to use greaterThan with the last contact you have seen together with limit to, say, get the next 15 contacts.
Inconsistencies (if new messages are send during paging) cannot easily be prevented.
That said, MongoDB may not be a good choice for a live chat because it has no support for streaming queries.

Why does MongoDB allow creating identical users? [duplicate]

This question already has answers here:
Mongoose Unique index not working!
(35 answers)
Closed 6 years ago.
I am trying to sign up a new user via Angular app, but when I am registering a user with the same username, Mongo allows me to do this, so it does not reurn an error and afterwards I can see two users with same names in the db. But I do mark name field as unique.
part of api:
apiRoutes.post('/signup', function(req, res) {
if (!req.body.userId || !req.body.password) {
res.json({success: false, msg: 'Please pass name and password.'});
} else {
var newUser = new User({
name: req.body.name,
password: req.body.password,
wallet: req.body.wallet,
userPic: req.body.userPic
});
// save the user
newUser.save(function(err) {
if (err) {
return res.json({success: false, msg: 'Username already exists.'});
}
res.json({success: true, msg: 'Successful created new user.'});
});
}
});
model code:
// set up a mongoose model
var UserSchema = new Schema({
name: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
},
wallet: {
type: Number,
required: true
},
userPic: {
type: String,
required: true,
unique: true
}
});
And POST request code(login and password are taken from outside):
let newUser = {
password: password,
wallet: 0,
userPic: md5(login),
name: login
};
this.$http.post('http://127.0.0.1:8080/api' + '/signup', newUser);
try in your model:
name: {
type: String,
index:{unique: true},
required: true
}

TypeError: Object #<Object> has no method 'findById' at exports.save

I have found several of these question on here, however the ones I have found deal mostly with HTML, I am having this problem on submitting of a login in java.
Very Simple Save Function
var model = require('../../models/User')
exports.save= function(req,res){
model.findById(req.body.id,function(err,doc){
if(!doc) doc = new model()
doc.email = req.body.email
doc.password = req.body.password
doc.save(function(err){
if(err){
req.flash('error',err)
}
else{
req.flash('success','User saved')
res.redirect('/')
}
})
})
}
my model is very long but here is a sample of it
//define schema
schema = new mongoose.Schema({
email: {
label: 'Email',
type: String,
lowercase: true,
unique: true,
required: true,
index: true,
validate: [
validate('len','6','100'),
validate('isEmail')
]
},
password: {
label: 'Password',
type: String,
required: true,
select: false,
get: function(){ return '********' },
set: function(v){
return bcrypt.hashSync(v,bcrypt.genSaltSync(12))
},
validate: [
validate('len','8','64')
]
},
model = mongoose.model('User',schema)
exports.name = 'user'
exports.description = 'User Model'
exports.schema = schema
exports.model = model
Submits to the function via modal and on every submit I get the err
TypeError: Object #<Object> has no method 'findById' at exports.save
Any help or ideas would be greatly appreciated
Change
var model = require('../../models/User')
to
var model = require('../../models/User').model
Also see the documentation on modules.

Node.js ORM2 check if field already exists

What is the best method to check if field value already exists.
This is my model:
// Set global
var moment = require('moment');
var _ = require('lodash');
// Create model
module.exports = function (orm, db) {
var Profile = db.define('profile',
// Field Properties
{
username: {type: 'text', required: true, unique: true},
name: {type: 'text', required: true},
email: {type: 'text', required: true},
password: {type: 'text', required: true},
birthday: {type: 'date', required: true},
gender: {type: 'enum', values: ["male", "female"], required: true},
join_date: {type: 'date'}
},
{
// Model hooks. Manual: https://github.com/dresende/node-orm2/wiki/Model-Hooks
hooks: {
beforeValidation: function() {
// Set join date to current date
this.join_date = new Date();
}
},
// Model Validations. Manual: https://github.com/dresende/node-orm2/wiki/Model-Validations
validations: {
username: [orm.enforce.security.username({length: 4}, 'Invalid username')],
email: [orm.enforce.patterns.email('Please enter a valid email')],
password: [orm.enforce.security.password('6', 'Invalid password')],
birthday: [orm.enforce.patterns.match(/\d{2}-\d{2}-\d{4}/, null, 'Invalid birthday')]
},
// Model methods. Extra functions and stuff
methods: {
}
});
};
And this is my register controller:
module.exports = function (req, res, next) {
// Get post params
var params = _.pick(req.body, 'formAction', 'username', 'password', 'email', 'confirm_password',
'birthday', 'gender', 'terms');
// If we try to register
if (params['formAction'] == 'register') {
// Manual validations
// Check if we agreed with the terms
if (params['terms'] != 1) {
res.send({error: 'You must agree to the terms of service'});
return false;
}
// Check if password was confirmed
if (params['password'] && params['password'] != params['confirm_password']) {
res.send({error: 'Please confirm your password'});
return false;
}
// Check if username already exists
// Try to register
req.models.profile.create({username: params['username'],
password: params['password'],
email: params['email'],
birthday: params['birthday'],
gender: params['gender'],
name: params['username']}, function (err, items) {
// Check to see if we have error
error = helpers.getError(err);
// Return error
if (error)
res.send({error: error});
});
}
// Show login form
else
res.sendfile(settings.path + '/public/register.html');
};
How can i check if username already exists in db? Now if i try to create i get DUP_KEY error from database.
Thanks,
Radu
Looks like adding a hook and using next() worked out
beforeCreate: function (next) {
obj = this;
Profile.exists({email: this.email}, function (err, exists) {
if (exists) {
return next(new Error("Email already exists"));
}
else
{
Profile.exists({username: obj.username}, function (err, exists) {
console.log(exists);
if (exists) {
return next(new Error("Username already exists"));
}
else
return next();
});
}
});
}

Categories