I am using mongoose and setting up schema for users as follows:
var users=new mongoose.Schema({
username:String,
password:String,
type:String
});
var User=mongoose.model('user',users);
Now i need this to have a initial row with values as admin,admin,admin
How to do this?
I am using express server to verify a user like this
app.post("/verifyLogin",function(request,response){
var usr=request.body.username;
var pass=request.body.password;
//VERIFICATION FROM DATABASE CODE GOES HERE
});
P.S I am new to mongodb/document-based data storage. Until now i used to work with phpmyadmin and insert data directly from the interface provided.
WHAT I TRIED:
i made a temp post handler like this
app.post("/initialize/database",function(request,response){
var user=new userModel({username:'admin',password:'password', type:'admin'});
user.save(function(err){
if(!err){return console.log('created')}else{console.log(err)}
return response.send(user);
});
})
and then in the console did this:
jQuery.post('/initialize/database',function(data){console.log(data)})
Don't know whether this is the best approach or not :(
I find it easiest to enter initialization data from the terminal.
$ mongo
> use database-name
> db.users.insert({ username: 'admin', password: 'admin', type: 'admin' })
That would work for simply getting things going, but I forbid you to store plain-text passwords in the database when in production. To implement hashing and to use node instead of the terminal you could create a route for creating a new user instead. Something like:
app.post("/signup",function(request,response){
var usr = request.body.username,
pass = request.body.password;
somePasswordHashingAlgoritm(pass, function (hashedPassword) {
User.insert({
username: usr,
password: hashedPassword,
type: 'admin'
});
});
});
Even better would be to implement a pre-save hook in mongoose, but that's the subject for another topic. If you don't want others to sign up to your site, just remove that code when you've created yourself.
Related
I am completely new to the fields of Mongoose and MongoDB.
I am currently trying trying to remove one element from my database.
This is my code so far:
My issueModel:
var mongoose = require('mongoose'); // loading module for mongoose
var db = mongoose.connect('mongodb://localhost/issuedb');
var issueSchema = new mongoose.Schema({
title: String,
description: String,
priority: String,
status: String
});
// Constructor Function:
var issueModel = mongoose.model('issues', issueSchema); // have to give the
name of the collection where the element should be stored + Schema
// Export this Construction Function for this Module:
module.exports = issueModel; // careful: module != model !
My post method for using the delete method:
// creating the router for deleting one item:
router.post('/delete/:id', (req, res) => {
console.log(req.params.id);
issueModel.remove({id: req.params.ObjectId})
.setOptions({ single: true }).exec(function (err, deleted) {})
.then(issues => res.render('issue', {issues: issues}));
The thing i would like to do here is using the object id - which is correctly stored in req.params.ObjectID according to my console.log, and deleting the corresponding object.
But currently , when i have got a table with about 3-4 entries, always the first one gets deleted. Why is that? I am really TOTALLY new and really tried searching a lot, but i could not find any solution until now. I am happy about any tips that would help me.
What am i doing wrong?
The ID in the URL and the Object.ID are the same! Why is the first object deleted then, not the second or the third?
I am hopeless right now.
I also read about the remove() option not being really used in todays time. But we were told at university to use this method right now.
I also tried findOneByID and delete methods i found in the mongoose database.
If you need any more code please let me know!
You can use one of the convenience methods for this: findByIdAndRemove:
issueModel.findByIdAndRemove(req.params.ObjectId, function(err) {
if (err) { ... failed }
});
This will remove a whole document matching the ID which I think its what you want, if you want to a remove property from a document that's a different query.
If you don't use one of the convenience methods which just take IDs (have ById in them), then you have to convert your ID from a string to an ObjectId:
const { ObjectId } = require('mongodb');
issueModel.remove({ id: ObjectId(req.params.ObjectId) }).setOptions({ single: true })
I'd like to prevent a user's encrypted password from getting sent over the wire each time a user requests their information. I know that in mongo I can apply a projection to achieve this
db.users.findByID(_id, { password: 0 } )
but I would prefer to have some sort of .pre() hook to that will apply it to every query. Is this or a functional equivalent possible?
You can configure a field so it'll be excluded from queries by default using select:
let UserSchema = new Schema({
...
password : { type : String, select : false },
...
});
You can override that on a per-query basis if you do require the field to be returned:
db.users.findByID(_id, { password: 1 } )
Documented here: http://mongoosejs.com/docs/api.html#schematype_SchemaType-select
so I'm currently trying to develop a mmorpg from scratch and got up to trying to save users from my client side (I'm using game maker studio). Im using robomongo as my Mongodb management tool.
My client connects just fine to my server and im able to take in a username and password but nothing is being saved to the database i created. Here is my user.js file:
var mongoose=require('mongoose');
var userSchema=new mongoose.Schema({
username: {type: String, unique:true},
password: String,
sprite:String,
current_room: String,
pos_x:Number,
pos_y:Number
});
userSchema.statics.register=function(username,password,cb){
var new_user=new User({
username: username,
password: password,
sprite: "spr_Hero",
current_room:maps[config.starting_zone].room,
pos_x:maps[config.starting_zone].start_x,
pos_y:maps[config.starting_zone].start_y,
});
//save user to database
new_user.save(function(err){
if(!err){
cb(true)
}else{
cb(false);
}
});
};
userSchema.statics.login=function(username,password,cb){
//findOne searched db - mongodb specific method
//searches db using json objects (cant do that in other sql/mysql)
User.findOne({username:username},function(err,user){
if(!err && user){
if(user.password==password){
cb(true,user);
}else{
cb(false,null);
}
}else{
//error||user doesnt exist
cb(false,null);
}
})
};
//export into gloabl space of our application
module.exports=User=gamedb.model('User',userSchema);
and here is my mongodb.js file. I configured the database location in my config.js. Im just using my local ip. Any help on fixing this would be great thanks!
var mongoose=require('mongoose');
mongoose.Promise=global.Promise;
module.exports=gamedb=mongoose.createConnection(config.database);
Seems like you are using MongoDB 3.4 which is not supported by Robomongo currently, but it will be soon. You can follow this ticket for updates: https://github.com/Studio3T/robomongo/issues/1250
Note: I am one of the contributors of Robomongo.
I'm looking at the example in the Waterline docs here.
var User = Waterline.Collection.extend({
types: {
// snip
password: function(password) {
return password === this.passwordConfirmation;
});
},
attributes: {
// snip
password: {
type: 'string',
password: true
},
passwordConfirmation: {
type: 'string'
}
}
});
Is there a way to tell Waterline that passwordConfirmation is not part of the schema so that it is not created if migrate is set to alter or drop, or if using a schemaless DB engine?
The actual use case I want is for a clear text password field to validated from the request, but use beforeCreate to populate a hash field that is actually stored (but not allowing the password property to be stored in the process).
Thanks.
Waterline doesn't support transient fields that are validated but not persisted. You can add the schema: true property to your model which will have it filter out any attributes that aren't explicitly declared, but still make them available in lifecycle callbacks. You'd have to do the validation for those attributes manually (in beforeCreate() or beforeValidate() for example), and you'd lose the ability to add arbitrary fields to schemaless dbs, but it's not necessarily a bad solution.
For your case though, I don't see why it's exactly necessary. Why not just hash the password in beforeCreate and save it back to password?
beforeCreate: function (values, cb) {
values.password = hash(values.password);
return cb();
}
I am not able to update my mongoose schema because of a CastERror, which makes sence, but I dont know how to solve it.
Trip Schema:
var TripSchema = new Schema({
name: String,
_users: [{type: Schema.Types.ObjectId, ref: 'User'}]
});
User Schema:
var UserSchema = new Schema({
name: String,
email: String,
});
in my html page i render a trip with the possibility to add new users to this trip, I retrieve the data by calling the findById method on the Schema:
exports.readById = function (request, result) {
Trip.findById(request.params.tripId).populate('_users').exec(function (error, trip) {
if (error) {
console.log('error getting trips');
} else {
console.log('found single trip: ' + trip);
result.json(trip);
}
})
};
this works find. In my ui i can add new users to the trip, here is the code:
var user = new UserService();
user.email = $scope.newMail;
user.$save(function(response){
trip._users.push(user._id);
trip.$update(function (response) {
console.log('OK - user ' + user.email + ' was linked to trip ' + trip.name);
// call for the updated document in database
this.readOne();
})
};
The Problem is that when I update my Schema the existing users in trip are populated, means stored as objects not id on the trip, the new user is stored as ObjectId in trip.
How can I make sure the populated users go back to ObjectId before I update? otherwise the update will fail with a CastError.
see here for error
I've been searching around for a graceful way to handle this without finding a satisfactory solution, or at least one I feel confident is what the mongoosejs folks had in mind when using populate. Nonetheless, here's the route I took:
First, I tried to separate adding to the list from saving. So in your example, move trip._users.push(user._id); out of the $save function. I put actions like this on the client side of things, since I want the UI to show the changes before I persist them.
Second, when adding the user, I kept working with the populated model -- that is, I don't push(user._id) but instead add the full user: push(user). This keeps the _users list consistent, since the ids of other users have already been replaced with their corresponding objects during population.
So now you should be working with a consistent list of populated users. In the server code, just before calling $update, I replace trip._users with a list of ObjectIds. In other words, "un-populate" _users:
user_ids = []
for (var i in trip._users){
/* it might be a good idea to do more validation here if you like, to make
* sure you don't have any naked userIds in this array already, as you would
*/in your original code.
user_ids.push(trip._users[i]._id);
}
trip._users = user_ids;
trip.$update(....
As I read through your example code again, it looks like the user you are adding to the trip might be a new user? I'm not sure if that's just a relic of your simplification for question purposes, but if not, you'll need to save the user first so mongo can assign an ObjectId before you can save the trip.
I have written an function which accepts an array, and in callback returns with an array of ObjectId. To do it asynchronously in NodeJS, I am using async.js. The function is like:
let converter = function(array, callback) {
let idArray;
async.each(array, function(item, itemCallback) {
idArray.push(item._id);
itemCallback();
}, function(err) {
callback(idArray);
})
};
This works totally fine with me, and I hope should work with you as well