I try to make a library for use in node.js with mongoose (mongoDB).
In my library, I want simply check if a user is_admin (group admin) or not.
Here is my model :
var mongoose = require('mongoose');
module.exports = mongoose.model('UsersGroups',{
user_id: String,
group_id: String
});
Here is my library :
var UsersGroups = require('../models/users_groups');
is_admin = function(userid)
{
console.log('USERID : '+userid);
var query = UsersGroups.find({'user_id': userid});
query.select('user_id');
query.where('group_id').equals('54d2264ed9b0eb887b7d7638');
return query.exec();
}
module.exports = is_admin;
I want to the query return true or false.
I call the library like this :
var is_admin = require('../library/mylib.js');
...
if (is_admin(group.user_id))
{
console.log('IS_ADMIN');
}
else
{
console.log('NOT_ADMIN');
}
Someone can coach me for this?
You can just run this query
UsersGroups.find({'user_id': userid, 'group_id': '54d2264ed9b0eb887b7d7638'}).count().exec();
it will find the matching pair - return 1 if it exists which is truthy in javascript. If it does not exist it will return 0 which is falsy so you will be able to use it inside if statements
query.exec() return Promise not Boolean
Using mongoose Schema and Model will give more nice feature;
Example User Model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
name: { type: String, required: true, trim: true }
// set user types as enumeration
type: { type: String, enum: ["admin", "user", "guest"], required: ture, default: 'user' }
});
var User = mongoose.model('User', UserSchema);
User.prototype.isAdmin = function(){
return this.type === "admin";
}
module.exports = User;
On controller
var user = require('model/user');
user.findById("54d2264ed9b0eb887b7d7638", function(err, user){
if(err)
return console.error(err.stack);
if(!user)
return console.error("User not found!");
if(!user.isAdmin())
console.log("User is not admin");
else
console.log("User is admin");
});
If you want to check with user group, you can change isAdmin function as you want
Related
I am using mongoose v5.2.17.
I was wondering is it possible to have multiple models map to the 1 schema.
For example - I have the following model
const mongoose = require('mongoose');
const validator = require('validator');
const jwt = require('jsonwebtoken');
const _ = require('lodash');
const bcrypt = require('bcryptjs');
const UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
trim: true,
minlength: 1,
unique: true,
validate: {
validator: validator.isEmail,
message: '{VALUE} is not a valid email',
},
},
password: {
type: String,
required: true,
minlength: 6,
},
isTrialUser: {
type: Boolean,
default: true,
},
isAdminUser: {
type: Boolean,
default: false,
}
});
UserSchema.methods.toJSON = function () {
const user = this;
const userObject = user.toObject();
return _.pick(userObject, ['_id', 'email', 'isTrialUser']);
};
UserSchema.pre('save', function (next) {
const user = this;
if (user.isModified('password')) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(user.password, salt, (hashErr, hash) => {
user.password = hash;
next();
});
});
} else {
next();
}
});
const User = mongoose.model('User', UserSchema);
module.exports = { User, UserSchema };
Is it possible for me to create another AdminModel where admin specific methods can live?
I also want to return all data from the toJSON method from the AdminModel.
Please let me know if this is possible or if there is a better way to perform such a task
Thanks
Damien
If I am understanding you correctly you want to inherit the UserModel in an AdminModel and decorate that one with extra methods etc. For that you can use util.inherits (or the so called Mongoose discriminators) like so:
function BaseSchema() {
Schema.apply(this, arguments);
this.add({
name: String,
createdAt: Date
});
}
util.inherits(BaseSchema, Schema);
var UserSchema = new BaseSchema();
var AdminSchema = new BaseSchema({ department: String });
You can read more about it in Mongoose docs.
There is also a good article on the mongoose discriminators here
I want users to have the ability to click a button that pushes their username and id into an array associated with a collection in a database, but only if they're not already in that array.
My solution is:
var isInGroup = function(user, arr){
var match = arr.indexOf(user);
console.log(">>>>>>>" + match);
if(match === -1){
arr.push(user);
console.log("added user");
} else {
console.log("Already in group");
}
};
This works when I test it against example arrays in the console, but not when I'm querying the database. When I execute the function in my app, arr.indexOf = -1 even if the user is already in the array.
This is the relevant code:
Player.js
var express = require("express"),
router = express.Router({mergeParams:true}),
Game = require("../models/game"),
Player = require("../models/player"),
User = require("../models/user"),
middleware = require("../middleware");
//Add A Player
router.post("/", middleware.isLoggedIn, function(req, res){
//find game
Game.findById(req.body.game, function(err, foundGame){
console.log(">>>>" + foundGame);
if(err){
req.flash("error", "Something went wrong.");
} else {
//create player
Player.create(req.user, function(err, player){
if(err){
console.log(">>>> error" + player);
res.redirect("back");
} else {
player.id = req.user_id;
player.username = req.user.username;
middleware.isInGroup(player, foundGame.players);
foundGame.save();
res.redirect("back");
}
});
}
});
});
Game Schema
var mongoose = require("mongoose");
var gameSchema = new mongoose.Schema({
name:String,
author:{
id:{
type: mongoose.Schema.Types.ObjectId,
ref:"User"
},
username:String,
},
court:{
id:{
type:mongoose.Schema.Types.ObjectId,
ref:"Court"
},
name:String,
},
players:[
{
id:{ type:mongoose.Schema.Types.ObjectId,
ref:"Player",
},
username:String
}
],
time:{
start:String,
end:String
},
date:String,
});
module.exports = mongoose.model("Game", gameSchema)
Player Schema
var mongoose = require("mongoose");
var playerSchema = new mongoose.Schema({
id:{type:mongoose.Schema.Types.ObjectId,
ref:"User"
},
username: String
});
module.exports = mongoose.model("Player", playerSchema);
User Schema
var mongoose = require("mongoose"),
passportLocalMongoose = require("passport-local-mongoose");
var userSchema = new mongoose.Schema({
username: String,
password: String
});
userSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", userSchema);
As mentioned above, arr.indexOf(user) returns -1 even if user is already in the array. Why is this happening? Is there better solution to this problem? Thanks for the help. I've been banging my head for awhile on this one.
I'm using Mongodb and Nodejs.
I have two collections projects and users.
I want to retrieve name in the login collection based on the memberId i will give in the Project collection.I tried the code below, its populating as null.
My question is how to give values to memberId in projectModel in the frontEnd.Beacause it is of type of objectId.I want to pass value to memberId as "sam#gmail.com". Based on this, i want retrieve name from user schema.
Heremy schema :
UserSchema
'use strict';
var mongoose = require('mongoose'),
bcrypt = require('bcryptjs'),
crypto = require('../lib/crypto');
var userModel = function () {
var userSchema = mongoose.Schema({
name: String,
login: { type: String, unique: true }, //Ensure logins are unique.
password: String,
role: String
});
userSchema.pre('save', function (next) {
var user = this;
if (!user.isModified('password')) {
next();
return;
}
next();
});
userSchema.methods.passwordMatches = function (plainText) {
var user = this;
return bcrypt.compareSync(plainText, user.password);
};
return mongoose.model('User', userSchema);
};
ProjectSchema
'use strict';
var mongoose = require('mongoose'),
schema = mongoose.Schema;
var projectModel = function () {
var projectSchema = schema({
projectName: String,
projectNo: String,
startDate: String,
endDate: String,
releases:String,
sprintDuration:String,
sprintCount:String,
teamname: String,
teamno: String,
memberId :
{type: schema.Types.ObjectId, ref: 'users'},
story: [{
name: String,
creator: String,
date: String,
desc:String,
teamMember:String,
sprintNo: String,
sprintStartDate: String,
sprintEndDate: String,
status: String
}]
});
module.exports = new projectModel();
router.post('/home', function (req, res) {
var projectName = req.body.projectName && req.body.projectName.trim();
var projectNo = req.body.projectNo && req.body.projectNo.trim();
var memberId = req.body.memberId;
Project.
find({})
.populate('memberId')
.exec(function(err, people) {
if (err) return handleError(err);
console.log( people);
});
This is my User.js
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
var UserSchema = mongoose.Schema({
email: {
type: String,
unique: true
},
password: String,
});
var User = mongoose.model('User', UserSchema);
function createDefaultUsers() {
User.find({}).exec(function (err, collection) {
if (collection.length === 0) {
User.create({
email: 'name#eemail.com',
password: 'password0',
});
}
exports.createDefaultUsers = createDefaultUsers;
module.exports = mongoose.model('User', UserSchema);
I call createDefaultUsers in another file to create initial users.
But when this gives me the following error:
userModel.createDefaultUsers();
^ TypeError: Object function model(doc, fields, skipId) {
if (!(this instanceof model))
return new model(doc, fields, skipId);
Model.call(this, doc, fields, skipId); } has no method 'createDefaultUsers'
But if I comment out module.exports = mongoose.model('User', UserSchema); it compiles fine.
What am I doing wrong.
Cheers.
In this case, you should attach that function as a static method and export the model.
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
var UserSchema = mongoose.Schema({
email: {
type: String,
unique: true
},
password: String,
});
UserSchema.statics.createDefaultUsers = function createDefaultUsers(cb) {
return User.find({}).exec(function (err, collection) {
if (collection.length === 0) {
User.create({
email: 'name#eemail.com',
password: 'password0',
}, cb);
} else {
if (cb) {
cb(err, collection);
}
}
});
};
var User = mongoose.model('User', UserSchema);
module.exports = User;
Now you can use it directly from the model (which is likely very similar to how you're already using it):
require('./models/user').createDefaultUsers();
I have tried several different ways to validate a foreign key in Mongoose and cannot figure it out.
I have a schema like this:
//Doctors.js
var schema = mongoose.Schema({
email: { type: String }
}
module.exports = mongoose.model('Doctors', schema);
//Patients.js
var Doctors = require('./Doctors');
var schema = mongoose.Schema({
email: { type: String },
doctor: { type: String, ref: 'Doctors' }
}
schema.pre('save', function (next, req) {
Doctors.findOne({email:req.body.email}, function (err, found) {
if (found) return next();
else return next(new Error({error:"not found"}));
});
});
module.exports = mongoose.model('Patients', schema);
however I get an this error: Uncaught TypeError: Object #<Object> has no method 'findOne'
Anyone know how to do something similar to what I am trying to do here?
I kept googling over the past hour, and saw something about scope that got me thinking. The following code fixed my problem.
//Doctors.js
var mongoose = require('mongoose');
var schema = mongoose.Schema({
email: { type: String }
}
module.exports = mongoose.model('Doctors', schema);
//Patients.js
//var Doctors = require('./Doctors'); --> delete this line
var mongoose = require('mongoose');
var schema = mongoose.Schema({
email: { type: String },
doctor: { type: String, ref: 'Doctors' }
}
schema.pre('save', function (next, req) {
var Doctors = mongoose.model('Doctors'); //--> add this line
Doctors.findOne({email:req.body.email}, function (err, found) {
if (found) return next();
else return next(new Error({error:"not found"}));
});
});
module.exports = mongoose.model('Patients', schema);
Although this was a quick fix, in no way was it an obvious fix (at least to me). The issue was the scope of variables.