Role-Based login in nodejs and mongoose - node.js

I have an application with 2 roles, a User and a Photographer. the difference between these 2 models is a isAdmin field in User and a Photo[ ] in Photographer and a order[ ] in User. But I need only one login for both of them! Clearly, need different views and routs for them! how can I do this? If any guide, I would be appreciated! Thanks a lot!
The schemas are as below:
var userSchema = new Schema({
//some other fields, the same with photographer
isAdmin: { type: Boolean, default: false },
orders: [{
price: { type: Number, default: 0 }
},
{timestamps: true}
]
});
var photographerSchema = new Schema({
//some other fields, the same with user
photos: [{
title: { type: String, default: '' },
path: { type: String },
price: { type: Number, default: 0 },
isAppoved: { type: Boolean, default: false },
},
{timestamps: true}
]
});

You should rethink your architecture. Better solution would be to have 1 User model and 2 profile submodels. User model would contain the type of the user and fetch profile info(writer_profile/user_profile) from the submodels.
If you won't refactor, this will turn in to a mess pretty fast. Think about it, what happens when a User and a Writer registers with the same credentials? You will need to check that too.

Related

How to do a Mongoose query with two collections and filtering by the second one?

I'm using mongoose to connect to MongoDB and I have a doubt about how can I make a query between two related collections
I have these Schemas.
const users = new mongoose.Schema({
name: String,
lastname: String,
age: Number,
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comments',
}
],
}, { timestamp: true, strict: false });
const comments = new mongoose.Schema({
message: {
type: String,
},
description: {
type: String,
},
candidates: Number,
}, { timestamp: true, strict: false });
well, the idea is get all users that contains comments with candidates value > 100
Is this possible to do just one query that will return the users that have comments with that condition?
TIA !

Mongoose find and update all

So currently I am using this
await User.findOneAndUpdate({email: req.user.email }, {lastLoad: 'dfConsignee'});
But I want to be able to update all users with the same truckNumber to be updated when the form is submitted.
SO I tried using this
await User.update({truckNumber: truckNumber }, {lastLoad: 'dfConsignee'});
But this only updated the active user for some reason. How would I go about updating all the accounts with the same truck number on form completion?
Thank you guys in advance <3
Edit ----------------------------------------------------------------------------------------------------------------------------
By active user, I meant logged in user.
Mongoose Schema:
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
isVerified: {
type: Boolean,
default: false
},
profilePic: {
type: String,
default: 'abc'
},
truckDriver: {
type: Boolean,
default: false
},
truckNumber: {
type: Number
},
admin: {
type: Boolean,
default: false
},
customer: {
type: Boolean,
default: false
},
loadPlanning: {
type: Boolean,
default: false
},
lastLoad: {
type: String,
default: "dfConsignee"
}
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
Sample Document:
{"_id":{"$oid":"aaaaaaaaaaaaaaaa"},
"isVerified":true,
"profilePic":"abc",
"truckDriver":true,
"admin":false,
"customer":false,
"loadPlanning":false,
"lastLoad":"aAtShipper",
"name":"Nicholas Cage",
"email":"NicholasCage#thegreatestactorever.com",
"password":"password",
"date":{"$date":{"$numberLong":"1580858993547"}},"__v":{"$numberInt":"0"},
"truckNumber":"123",}
To add a bit more clarification, when the form is submitted, it will pull the logged in users truck number. When the form is submitted, I am wanting everyone who shares that same truck number to have their value in lastLoad be updated as well.
Try using updateMany(). The resulting code would look something like this:
User.updateMany({truckNumber: truckNumber}, {lastLoad: 'dfConsignee'});
If you really want to familiarize yourself with Mongoose and MongoDB as a whole, I'd suggest taking a look at the API docs for Mongoose and the MongoDB Manual, it goes into much more detail about the tools you have available to you when using MongoDB. That's how I found the answer to this question!
OMG Finally figured this out :D
I thought that when I restarted Nginx it would restart the app running on the server ( I would see front end changes doing this, but the back end changes wouldn't show up), once I restarted PM2 all the back end changes came along with it.
Thank you everyone for the help :D
Now "await Users.updateMany({truckNumber: req.user.truckNumber}, {lastLoad: 'aAtShipper'}" will update all accounts with a shared truck Number :D

Best way to check category owner

Task model
const TaskSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'User'
},
title: {
type: Schema.Types.String,
required: true
},
description: Schema.Types.String,
createdDate: {
type: Schema.Types.Date,
default: Date.now()
},
position: {
type: Schema.Types.Number,
default: 0
},
categoryId: [{
type: Schema.Types.ObjectId,
ref: 'Category'
}]
});
Category model
const CategorySchema = new Schema({
title: {
type: Schema.Types.String,
required: true
},
description: {
type: Schema.Types.String,
},
categoryThumbnail: {
type: Schema.Types.String,
default: ''
},
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
createdDate: {
type: Schema.Types.Date,
default: Date.now()
}
});
When creating a task, the user can assign a category. Do I need to check the category owner before adding the task to Mongodb. If so, what is the best way to do this? Options:
1. Make a request to the database for all categories and check the user id.
2. Store the category id in the user document and, upon receipt of the request, check this list.
So if the User can create multiple categories and each category is only accessible by the User who created it you have a one-to-many association. In this situation it seems your Option 1 is what you want. Keep the user id on the category and then query all categories that have the user id you're looking for.
Edit:
If possible, I would recommend that you limit the categories the user sees when creating a task to only be categories created by that user. If that is not possible, then you could do one query to grab all the categories from the list of category IDs sent to the server and loop through the results checking if the user IDs are the same.
Category.find({
'id': { $in: [
mongoose.Types.ObjectId('4ed3ede8844f0f351100000c'),
mongoose.Types.ObjectId('4ed3f117a844e0471100000d'),
mongoose.Types.ObjectId('4ed3f18132f50c491100000e')
]}
}, function(err, docs){
docs.forEach(item => {
return item.userId === userId; //compare to userId that sent the request
}
});

Friend Request System with Express & MongoDB

I am trying to let users send friend requests to other users similar to that of Facebook and other social media platforms. I have started creating this functionality, but quickly got stuck since I am new to mongoDB and the whole Schema thing.
Here are the models I currently have:
// User Schema
var UserSchema = new Schema({
_id: {
type: Number
},
name: {
type: String
},
username: {
type: String,
index: true
},
password: {
type: String,
required: true
},
email: {
type: String
},
friends: [{
friendName: {
type: Schema.ObjectId,
required: true,
ref: 'User'
},
duration: {
type: Number
}
}]
});
// Friendship Schema
var FriendshipSchema = new Schema({
participants: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
requestTo: {
type: Schema.Types.ObjectId,
ref: 'User'
},
accepted: {
type: Boolean,
default: false
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
var Friendship = module.exports = mongoose.model('Friendship', FriendshipSchema);
var User = module.exports = mongoose.model('User', UserSchema);
This is as far as I have gotten. From here, I do not know how to use these schemas to establish friendships between 2 users. My ultimate goal is to have a button on a webpage that sends a friend request to the intended recipient, where they can then accept or deny the request.
Any help with this would be awesome, since I do not know what to do from here with these 2 schemas. Thanks!
We would need to take one schema only which is userSchema(as is Israel said above, you only need an array/object to list your friendship on the userSchema). But we will need to add another schema(said it friendRequestSchema).
FriendRequest schema would be:
- ID user request (int)
- ID user recipient (int)
- status (int) //let say 1= requested, 2=accepted, 3=rejected
And the controller it should be from the user A click "Friend Request" button on your user B page.
Friend Request Button will call a function let saying it "sendFriendRequest()"
If function running it would be recorded on friendRequest DB, which is will record ID of user A(as requester), ID of user B and request status.
If request status = 1 then user B will be notified and give him two option which is accepted and rejected.
User B accept or reject it
If user press button accept, then the status updated in friendRequest DB to be=> 2 (Accepted). Then, you have to call another function to add user ID A to friendship list of User B. Conversely. Then if you want to make a notification you can call it as well.
Else user B will press reject (status will be => 3) then notif it.
UserSchema
var UserSchema = new Schema({
name: String,
username: {
type: String,
index: true
},
password: {
type: String,
required: true
},
email: String,
friendship: [String] });
Then FriendRequestschema
var FriendRequestSchema = new Schema({
requester: {
type: int,
required: true
},
recipient: {
type: int,
required: true
},
status:
type: int,
required: true });
This just to let you know, how its work. More complex method about (sendrequest,block .etc) you can check this link, It's flow process for PHP, but you can easily move it to your js. Hope it help you man.
Your model can be improved, and your code can be cleaned:
First, you don't need the brackets if you only give type for the field:
var UserSchema = new Schema({
name: String,
username: {
type: String,
index: true
},
password: {
type: String,
required: true
},
email: String,
friends: [String]
});
This should be a simplified version of your schema. The _id field doesn't need to be specified because mongoose creates it automatically. If you wanna put a customized value there, just do it when you insert.
Second:
If you wanna reference other users, why not to use only a simple array that contains ids from other users. For example, if you have user A, the "friendship" of this user are user ids contained in his "friends" field.
{id:12345, username:"A", password:***, email:"a#fakemail.com", friends:[B_id,C_id,D_id]}
In that case, whenever you wanna make a list of friends of A, you can just perform a $lookup operation in mongodb and it will fill the other users information for you.
I don't think I covered all of your questions, but I hope my answer was helpful.

Get info from 2 separate Mongo documents in one mongoose query

Im using MongoDb, and I have a workspace schema with mongoose (v4.0.1):
var Workspace = new mongoose.Schema({
name: {
type: String,
required: true
},
userId: {
type: String,
required: true
},
createdOn: {
type: Date,
"default": Date.now
}
});
And a user schema:
var User = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true
},
organisation: {
type: String,
required: true
},
location: {
type: String,
required: true
},
verifyString: {
type: String
},
verified: {
type: Boolean,
default: false
},
password: {
type: String,
required: true
},
createdOn: {
type: Date,
"default": Date.now
},
isAdmin: {
type: Boolean,
default: false
}
});
So the Workspace userId is the ObjectID from the User document.
When Im logged in as an adminstrator, I want to get all workspaces, as well as the email of the user that owns the workspace.
What Im doing is getting very messy:
Workspace.find({}).exec.then(function(workspaceObects){
var userPromise = workspaceObects.map(function(workspaceObect){
// get the user model with workspaceObect.userId here
});
// somehow combine workspaceObjects and users
});
The above doesnt work and gets extremely messy. Basically I have to loop through the workspaceObjects and go retrieve the user object from the workspace userId. But because its all promises and it becomes very complex and easy to make a mistake.
Is there a much simpler way to do this? In SQL it would require one simple join. Is my schema wrong? Can I get all workspaces and their user owners email in one Mongoose query?
var Workspace = new mongoose.Schema({
userId: {
type: String,
required: true,
ref: 'User' //add this to your schema
}
});
Workspace.find().populate('userId').exec( (err, res) => {
//you will have res with all user fields
});
http://mongoosejs.com/docs/populate.html
Mongo don't have joins but mongoose provides a very powerfull tool to help you with you have to change the model a little bit and use populate:
Mongoose population
You have to make a few changes to your models and get the info of the user model inside your workspace model.
Hope it helps

Resources