Waterline queries similar to HQL - javascript

I have models in Sails as follows:
User Model
attributes: {
firstName: {
type: 'string',
required: true
},
lastName: {
type: 'string',
required: true
},
company: {
model: 'Company'
}
}
Company
name: {
type: 'string',
required: true,
unique: true
},
description: {
type: 'string',
required: true
}
In HQL queries, for getting a user working in a specific company, we use something like this:
Select * from User where company.name=?
How can I achieve same in Sails, Right now there are two queries which I am running, one to get User and then another to get company for that user. Is there any way both can be combined in one?
and one more thing, how does waterline deal with scenarios where in we need to get something out of a foreign key directly i.e. If I get user data, then can I get company details by just calling:
User.findOne({id:1}, function(err, res){
//Res contains user data with just companyId now,
//how can i get whole company object here
var companyName = res.company.name; //This is not working currently
})

Try something like this:
User.findOne({id: 1})
.populate('company')
.exec(function(err, user) {
if(err){
//handle errors
}else{
//do stuff
}
});
This should get the values from the association (foreign key).

Related

How do i make specific users for only them to have access to their own specific data in mongodb and nodejs

I am working on a blog project. I am done with the functionality to create,edit and delete posts. I have also setup and login and signup with passport authentication and can already restrict pages to only logged in users. I want to also restrict editing and deleting of posts to only the users who created the post. I just can't seem to figure out how the link the two collections(one being the users collection and the other being the posts collection).
Below are the schemas for the two collections
posts schema
const articleSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
markdown: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now
},
slug: {
type: String,
required: true,
unique: true
},
sanitizedHTML: {
type: String,
required: true
}
})
users schema
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
}
});
In the articleSchema you need a field createdBy which will be linked with the id in userSchema. So, when the user is logged in you will get the user's id. Through which you can check if the post is created by that particular user. This is the best approach for your case right now.
If you want to have more extensive roles. For e.g. editors who can edit any articles. There are two ways to do it:
If you need multiple roles and their permissions are configurable
You need to create roleSchema which will have roleName, permissions etc. And in userSchema will be a field called role which corresponds to role_id for each user. This will allow you to change permissions and create new roles easily in future through UI.
If you just have few roles and confident that it won't change often
You can just define for yourself what these roles are: for e.g 1 -> Editor, 2 -> Subscriber, 3 -> Admin etc. And add a role field in userSchema to put the relevant role. This will allow you to have fixed permission for each role. Now when you are doing anything with article's you can get the role and filter accordingly.

meteor make user's schema collection2 to login

I'd like use this schema as user and login or extend form users.I read documentation and I don't understand how extends from users. how I can make it?
Dipendenti = new Mongo.Collection('dipendenti');
DipendentiSchema = new SimpleSchema({
nome: {
type: String
},
cognome:{
type: String
},
codiceFiscale:{
type: String
},
telefono:{
type: String
},
indirizzo:{
type: String
}
});
I believe you are trying to extend/merge the schema listed above to the users collection. If so, you just need to attach the schema to the collection.
Meteor.users.attachSchema(DipendentiSchema);
UPDATE:
To use this new merged schema, you should be able to do something like:
Accounts.createUser({
username: 'test',
email: 'test#example.com',
password: 'password',
nome: 'Richard',
cognome: 'Ortiz',
codiceFiscale: 'EUR',
telefono: '+39 06 49911',
indirizzo: 'Piazzale Aldo Moro, 5, 00185 Roma, Italy'
});
If you want to make email address optional in your schema, you can add the following to it.
emails: {
optional: true,
type: [Object]
},
"emails.$.address": {
optional: true,
type: String
},
"emails.$.verified": {
optional: true,
type: Boolean
}
UPDATE 2:
Ensure that you are defining and attaching the schema wherever you are trying to make changes to the users collection. It is generally considered a best practice to do your database changes only on the server for security. You could write a method on the server using Meteor.methods({}); and then call it on the client with Meteor.call({}); and pass it your user data. You can read more about this approach the Meteor documentation.

Nested mongoose Schema giving trouble when trying to query in controller

I'm working on a small project and I have a solution to this problem, but it involves creating a new Schema with a reference to the new Schema in the old Schema. I would like to avoid this if at all possible because it will mean spending a couple hours rewriting some code and messing with tests.
The project is a forum site, and there are three main Schemas that comprise it (in addition to cursory Schemas for the forums, notifications, settings and the schemas for the user and the users activities). The Board Schema (contains a list of all forum sections if that wasn't apparent) Is a Schema that makes a reference to the Threads Schema so it can get the threads for each Board. My problem is in the Thread Schema.
var ThreadSchema = new mongoose.Schema({
... other unrelated Schema stuff...
comments: [{
created: {
type: Date,
default: Date.now
},
creator: {
type: mongoose.Schema.ObjectId,
required: true,
ref: 'User'
},
content: {
type: String,
required: true,
get: escapeProperty
},
likes: [{
type: mongoose.Schema.ObjectId,
required: false,
ref: 'User'
}],
liked: {
type: Boolean,
default: false
},
saved: [{
type: mongoose.Schema.ObjectId,
required: false,
ref: 'User'
}]
}]
});
blah blah blah.
I'm trying to pull for the users profile only the comments that that user has posted. The threads were easy, but comment data is not coming through. The request to the server goes through as successful, but I don't get any data back. This is what I am trying.
obj.profileComments = function (req, res) {
var userId = req.params.userId;
var criteria = {'comments.creator': userId};
Thread.find(criteria)
.populate('comments')
.populate('comments.creator')
.skip(parseInt(req.query.page) * System.config.settings.perPage)
.limit(System.config.settings.perPage + 1)
.exec(function (err, threads) {
if (err) {
return json.bad(err, res);
}
json.good({
records: threads
}, res);
});
};
This is a controller, and the json.bad and json.good are helpers that I have created and exported they basically are res.send.
var good = function (obj, res) {
res.send({
success: 1,
res: obj
});
};
and the bad is very similar, it just handles errors in an obj.res.errors and puts them into messages.
So now that that is all out of the way, I'm a little lost on what to do?
Is this something I should try to handle with a method in my Schema? It seems like I might have a little bit more luck that way. Thank you for any help.

How to add another field in a join sails js

Hey all just getting started with Sails js and mongoDB and im a bit confused.
I have two models with a many-to-many relationship:
User.js
module.exports = {
attributes: {
username: 'STRING',
password: 'STRING',
doors:{
collection: 'door',
via: 'users',
}
}
};
and Door.js
module.exports = {
attributes: {
name: 'STRING',
users:{
collection: 'user',
via: 'doors'
}
}
};
This works fine, I can create a user and a door and associate one with the other. However I'd like to have another field in the join, an expiry date (Say the user can only have access to a particular door until a particular date).
How would I go about doing that?
You need to create a many to many through association. However they are not officially supported as of yet.
You can manually do this however.
Now, in this example it may sometimes be a a little more difficult to get all the doors for a user and vice versa, because you have to preform a second look up. However you can do the following with this setup:
UserDoors
.find()
.where({expires:{'<':new Date()}})
.populate('doors')
.populate('users')
.exec(/*....*/)
Your models
User.js
module.exports = {
attributes: {
username: 'STRING',
password: 'STRING',
doors:{
collection: 'userDoors',
via: 'users',
}
}
};
userDoors.js
module.exports = {
attributes: {
doors:{
model: 'door'
},
users:{
model: 'user'
},
expires: 'datetime'
}
};
and Door.js
module.exports = {
attributes: {
name: 'STRING',
users:{
collection: 'userDoors',
via: 'doors'
}
}
};
Do a google search for sails.js many to many through to also help you find what your looking for.

Express returning "User is not authorized" when modifying object from another user

I have a Classroom model that looks like this:
/**
* Classroom Schema
*/
var ClassroomSchema = new Schema({
created: {
type: Date,
default: Date.now
},
participants: [{
type: Schema.ObjectId,
ref: 'User'
}],
lesson: {
type: Schema.ObjectId,
ref: 'Lesson',
required: 'Define a lesson for this classroom',
},
user: {
type: Schema.ObjectId,
ref: 'User'
},
currentTaskIndex: {
type: Number,
default: 0
},
});
As you can see, the model keeps a reference to the user that have created the Classroom (User) and it also has many participants (more Users).
I'm trying to add the functionality to allow other Users (not the creator of the Classroom) to join the Classroom by sending a PUT request to the classroom API with a new User in the participants field. However, since the User sending the request is not the one who created the object, Express is returning a 403 (Forbidden):
exports.hasAuthorization = function(req, res, next) {
if (req.classroom.user.id !== req.user.id) {
return res.status(403).send('User is not authorized');
}
next();
};
What's the best approach/pattern to solve this allowing Users to join Classrooms created by another User but not to do other actions like deleting the object. Other fields might be updated by another participants, like the currentTaskIndex.
Thanks for your help!
You could add a 'master' or 'admin' field to your classroom, and store the Creator's userId in it.
Then you can allow the delete/modify, etc actions only for the user who is master of this particular classroom, while letting everyone in.

Categories

Resources