How do I reference a schema inside another schema with Mongo, NodeJS, and Angular? - angularjs

I'm building a MEANjs app and I have two schemas: user and a claim. I want to be able to reference user information from a claim.
Right now I can successfully access the display name in my view by using the expression {{vm.claim.user.displayName}}. How do I access the other properties of the embedded user schema?
For example, I'd like to be able to reference a user's firstName and lastName. Something like {{vm.claim.user.firstName}} doesn't yield any result in my view.
user.server.model.js
/**
* User Schema
*/
var UserSchema = new Schema({
firstName: {
type: String,
trim: true,
default: '',
validate: [validateLocalStrategyProperty, 'Please fill in your first name']
},
lastName: {
type: String,
trim: true,
default: '',
validate: [validateLocalStrategyProperty, 'Please fill in your last name']
},
displayName: {
type: String,
trim: true
}
});
mongoose.model('User', UserSchema);
claim.server.model.js
'use strict';
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
/**
* Claim Schema
*/
var ClaimSchema = new Schema({
description: {
type: String,
default: '',
required: 'Please fill Claim description',
trim: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.Types.ObjectID,
ref: 'User'
}
});
mongoose.model('Claim', ClaimSchema);

If you want use User schema in Claim schema you can do it like this:
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
User = require('./../models/user'); //proper path here
var UserSchema = require('mongoose').model('User').schema;
/**
* Claim Schema
*/
var ClaimSchema = new Schema({
description: {
type: String,
default: '',
required: 'Please fill Claim description',
trim: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: UserSchema,
ref: 'User'
}
});
mongoose.model('Claim', ClaimSchema);
and User schema needs export statement. Replace mongoose.model('User', UserSchema); with:
exports.UserSchema = UserSchema;
module.exports = mongoose.model('User', UserSchema);
Regarding problems with proper path in dependencies, './../models/user' should work for
├── server
| ├── models
| | └──user.server.model.js
| └── server.js

Related

Does uuidv1() generate differently?

I am confused about uuidv1(). In the following code it uses uuidv1() as a salt and encrypt a password. But I thought that uuidv1() generates different strings so that I am not able to use it to encrypting a password.
Does uuidv1() generate always the same strings?
const mongoose = require("mongoose");
const uuidv1 = require("uuid/v1");
const crypto = require("crypto");
const { ObjectId } = mongoose.Schema;
const userSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
required: true
},
email: {
type: String,
trim: true,
required: true
},
hashed_password: {
type: String,
required: true
},
salt: String,
...
});
// virtual field
userSchema
.virtual("password")
.set(function(password) {
// create temporary variable called _password
this._password = password;
// generate a timestamp
this.salt = uuidv1();
// encryptPassword()
this.hashed_password = this.encryptPassword(password);
})
.get(function() {
return this._password;
});
// methods
userSchema.methods = {
authenticate: function(plainText) {
return this.encryptPassword(plainText) === this.hashed_password;
},
encryptPassword: function(password) {
if (!password) return "";
try {
return crypto
.createHmac("sha1", this.salt)
.update(password)
.digest("hex");
} catch (err) {
return "";
}
}
};
uuidv1 does generate a unique output everytime which is why you save that as salt in the user model
so uuid creates salt which is like alphabet for crypting strings, uuid has like v1, v2 ... check out their npm doc, i checked it and it was simple, then your userSchema encryptPassword crypts your password using crypto (you imported it in user model) based on that "salt" alphabet and you store the outcome as hashed_password which in future will be used in comparison, based on the saved salt every time

How to add mongoose db for auto increment?

I want add in auto increment for my model class in mean stack. How I do bellow class?
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/sampleApp');
module.exports = mongoose.model('User', {
email : { type: String, required: true, index: { unique: true } },
password : { type: String}
});

How to access, delete and edit contents in an Array using MongoDB and Express

I would really like some help with this problem, I am sorta stuck. I am trying to manipulate this UserSchema. I want to be able to edit and delete the shippings array within the model but I am having trouble trying to figure out how to access individual items in the array to use an express restAPI. Below is a snippet of the schema and the restAPI endpoint for creating multiple shipping addresses I was able to write. The create endpoint is working but for some reason I am unable to wrap my head around updating and deleting. Any help would be appreciated.
Thanks
var UserSchema = new Schema({
firstname: {
type: String,
default: ''
},
lastname: {
type: String,
default: ''
},
email: {
type: String,
unique: true,
lowercase: true,
},
password: {
type: String,
},
shippings: [{
recipient: {
type: String,
default: ''
},
street: {
type: String,
default: ''
},
city: {
type: String,
default: ''
},
state: {
type: String,
default: ''
},
zip: {
type: String,
default: ''
}
}],
exports.postShipping = function(req, res, next) {
req.assert('recipient', 'Recipient cannot be blank').notEmpty();
req.assert('street', 'Street Address cannot be blank').notEmpty();
req.assert('city', 'City cannot be blank').notEmpty();
req.assert('state', 'State cannot be blank').notEmpty();
req.assert('zip', 'Zip Code cannot be blank').notEmpty();
// req.assert('country', 'Country cannot be blank').notEmpty();
User.findById(req.user.id, function(err, user) {
if (err) return next(err);
var shipping = {};
shipping.street = req.body.street;
shipping.recipient = req.body.recipient;
// shipping.unit = req.body.unit;
shipping.city = req.body.city;
shipping.state = req.body.state;
shipping.zip = req.body.zip;
// shipping.country = req.body.country;
var s = JSON.stringify(shipping);
console.log(s);
var duplicatedShipping = 0;
for (var i in user.shippings) {
console.log(JSON.stringify(user.shippings[i]));
if (JSON.stringify(user.shippings[i]) == s) {
duplicatedShipping = 1;
break;
}
}
if (duplicatedShipping === 0) {
user.shippings.push(shipping);
}
user.save(function(err) {
if (err) return next(err);
console.log(user.shippings);
req.flash('success', {
msg: 'Shipping Address Added'
});
res.redirect('/account/me/shipping');
});
});

"User is not authorized" on meanjs

I would like to ask if there is anyone getting the same response on JSON format:
Objectdata: "User is not authorized"headers: (name) {status: 403statusText: "Forbidden"
Scenario:
User A post a product and add comment on the product.
Result: Successful.
User B comment on the same product:
Result: User is not authorized.
The code I'm using to update the product comment is here:
applicationname/`
// Add comment to Product
$scope.comment = function(){
// console.log("name: ",$scope.user);
// console.log("textarea: ",this.commentarea);
var comment = {
name: $scope.product.user.displayName,
text: this.commentarea
};
$scope.product.comments.push(comment);
$scope.product.$update(function() {
console.log('success update');
}, function(errorResponse) {
console.log('success error', errorResponse);
});
};
This is the server side.
'use strict';
/**
* Module dependencies.
*/
var init = require('./config/init')(),
config = require('./config/config'),
mongoose = require('mongoose'),
chalk = require('chalk');
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Bootstrap db connection
var db = mongoose.connect(config.db, function(err) {
if (err) {
console.error(chalk.red('Could not connect to MongoDB!'));
console.log(chalk.red(err));
}
});
// Init the express application
var app = require('./config/express')(db);
// Bootstrap passport config
require('./config/passport')();
// Start the app by listening on <port>
app.listen(config.port);
// Expose app
exports = module.exports = app;
// Logging initialization
console.log('MEAN.JS application started on port ' + config.port);
If your Products schema looks like this:
var ProductSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
default: '',
trim: true,
required: 'Title cannot be blank'
},
comments: [{
type: String,
default: '',
trim: true
}]
});
And you have restricted your products route in your app/routes/products.server.routes.js file like so:
app.route('/products/:productId')
.get(products.read)
.put(users.requiresLogin, products.hasAuthorization, products.update)
.delete(users.requiresLogin, products.hasAuthorization, products.delete);
Then a non-authorized user cannot add a comment because they can't update the Product record.
You probably want to create a separate CommentsSchema and use the Mongoose ObjectId type to create a one-to-many relationship with the product:
var CommentSchema = new Schema({
product: ObjectId,
content: {
type: String,
default: '',
trim: true,
required: 'Content cannot be blank'
},
})
That will preserve the security of your product and allow non-authorized users to comment, but would require you to do slightly more complex queries to get your comments in your product view.

Mongoose deep populate with self-referencing children

This is working code to populate my Locations collection, which can have self-referencing child Locations. It uses mongoose-deep-populate. But I need to add another ".childLocations" to my path variable for every extra level of depth that I want to handle. Is there a better way to accomplish unknown depths of self-references?
I have this node.js code.
var path = 'childLocations.childLocations.childLocations.childLocations.childLocations.childLocations';
exports.list = function(req, res) {
Location.find().sort('-created').populate('user', 'displayName').deepPopulate(path).exec(function(err, locations) {
console.log(locations);
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(locations);
}
});
};
Here is the schema:
var LocationSchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Location name',
trim: true
},
projectsExecutedHere: Boolean,
childLocations: [{
type: Schema.ObjectId,
ref: 'Location'
}],
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Location', LocationSchema);
var deepPopulate = require('mongoose-deep-populate');
LocationSchema.plugin(deepPopulate);
----------
Before trying mongoose-deep-populate, I had seen that mongoose 3.6 had support for deep population, but I could only make it go one level deep. This is what I tried:
Location.find().sort('-created').populate('user', 'displayName').populate('childLocations').exec(function (err, locations) {
Location.populate(locations, {path: 'childLocations.childLocations'},
function (err, data) {
console.log(err);
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(locations);
}
}
);
For the path I also tried 'childLocations.childLocations.childLocations' but it didn't populate it at all.

Resources