loopback angular sdk get all users with a certain role - angularjs

I'm currently stuck on getting all the users with certain role, for example admin users, in one angular SDK controller.
according to the docs of strongloop. what I did was:
User.find({
filter: {
include: [{'relation':'roles', 'scope': {
where:{
name:'admin',
}}
}],
},
}, function(list) {
console.log(list);
});
But the list i got is all the users, the non-admin users are included too. On the server side it is the default codes, i didn't change them.
{
"name": "user",
"plural": "Users",
"base": "User",
"properties": {
},
"relations": {
"roles": {
"type": "belongsTo",
"model": "RoleMapping",
"foreignKey": "principalId"
}
},
"acls": [],
"methods": []
}
Could you tell me what I made wrong? I don't want to loop through all the "list" from that query and filter the admin users, because it is a very huge list of users, but admin is for only 2 or 3 persons.

Here is the solution of what i did, from the common/models/user.js, i created a remotemethod, called "getUsersByRole", and only accept "role", which is the name of the role:
User.remoteMethod('getUsersByRole', {
accepts: [
{ arg: 'role', type: 'string', required: true },
],
returns: {arg: 'users', type: 'string'},
http: {
verb: 'get',
path: '/byrole/:role'
}
});
then here is the function of it:
User.getUsersByRole = function(role, cb) {
var loopback = require('loopback');
var Role = loopback.getModel('Role');
var userIdList = [];
Role.findOne({include:'principals', where: {name:role}}, function(err, role) {
role.principals(function(err, principals) {
for (var i = 0; i < principals.length; i++) {
userIdList.push(parseInt(principals[i].principalId));
}
if (userIdList.length > 0) {
User.find({where: {id: {inq: userIdList}}}, function(err, users) {
cb(err, users);
});
} else {
cb(err, false);
}
});
});
}
then run the lb-ng command to generate the service for angular client side, then run:
User.getUsersByRole({role:rolename}, function(list) {
});
in the controller.

Can you run the query from the role instead?
Role.find({
filter: {
where: {name:'admin'},
include: {'relation':'users'}
},
}, function(list) {
console.log(list);
});

Related

Exclude field from a document based on another field value mongodb mongoose

I have a users schema in which there is a companies field which I only want to select if role field value is admin else it should not be returned in find query.
user Schema:
const userInfoSchema = new mongoose.Schema({
...,
companies: [
{
type: mongoose.Schema.ObjectId,
ref: 'companyinfos',
},
],
role: {
type: String,
enum: ['user', 'admin', 'employee'],
default: 'user',
},
});
I have tried to solve this by using pre find hook but was unable to exclude the companies field.
userInfoSchema.post(/^find/, function (doc, next) {
if (doc.role !== 'admin') {
this.find({}).select('-companies');
}
next();
});
Or is there any way to conditionally set select in the companies field in the userInfoSchema based on the role value?
Please help.
use aggregate
db.collection.aggregate([
{
"$project": {
companies: {
"$cond": {
"if": {
$eq: [
"$role",
"admin"
]
},
"then": "$companies",
"else": 0
}
}
}
},
{
$match: {
companies: {
$ne: 0
}
}
}
])
https://mongoplayground.net/p/I8HGvz6h7MP

MongoDb unable to populate user

Hi I am trying to populate user into another schema called feedbackschema.
Feedback schema
const mongoose = require('mongoose');
const {
Schema,
} = mongoose;
// Create Schema
const FeedbackSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'users',
},
pro: {
type: String,
required: true,
},
con: {
type: String,
required: true,
},
comments: {
type: String,
required: true,
},
rating: {
type: String,
required: true,
},
});
// Create model
const feedback = mongoose.model('feedbacks', FeedbackSchema);
module.exports = feedback;
User Schema
const mongoose = require('mongoose');
const {
Schema,
} = mongoose;
// Create Schema
const UserSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
lowercase: true,
},
password: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
required: true,
default: false,
},
});
// Create a model
const user = mongoose.model('users', UserSchema);
// Export the model
module.exports = user;
and here is my controller where I am trying to populate the user
getAllFeedbacks: async (req, res) => {
const errors = {};
try {
const feedbacks = await Feedback.find().populate('user');
return res.json(feedbacks);
} catch (err) {
errors.noFeedbacks = 'Please try again';
return res.status(404).json(errors);
}
},
Json I am receiving through postman is this
[
{
"_id": "5b3adf88f3c4cd836bdc2eda",
"pro": "knfklngfdklgnfdgknkln",
"con": "Sales executive updates",
"comments": "This is a another funfact for me is me too",
"rating": "8",
"__v": 0
}
]
It is supposed to show user key but somehow its not working. I checked the current user data is already there but for some reason its not pushing the user info feedback object.
FeedBack collection
[
{
"_id": {
"$oid": "5b3adf88f3c4cd836bdc2eda"
},
"pro": "knfklngfdklgnfdgknkln",
"con": "Sales executive updates",
"comments": "This is a another funfact for me is me too",
"rating": "8",
"__v": 0
}
]
User Collection
[
{
"_id": {
"$oid": "5b37e456565971258da97d5e"
},
"isAdmin": false,
"name": "montygoldy",
"email": "montygoldy#gmail.com",
"password": "$2a$10$zWbxV0Q3VPUxRC6lzJyPBec3P/8zYBaSCTJ2n88Uru3zzFlicR2rq",
"__v": 0
}
]

How to increment property's value(integer) inside .update() and $set mongoose?

I'm trying to find a document in my database using findOne() and then search that document for options array that contains objects. Then I check object's property if it's equal to pollOption then I want to increment that object's another property votes by 1, but I can't get that property's value so I can increment it. Please help.
Routes.js
router.post('/submitVote', function(req, res){
const {pollId, pollOption} = req.body;
Polls.findOne({_id: pollId}
).update({'options.option': pollOption}, {'$set': {
'options.$.votes': '', // INCREMENT BY 1 //
}}, function(err){
if(err){
return console.log(err);
} else {
return res.send('success');
}
});
});
Sample Model:
{
"_id": {
"$oid": "5b2ec4852a51d06734f71e79"
},
"options": [
{
"option": "Amazing!",
"votes": 0
},
{
"option": "Good.",
"votes": 0
}
],
"creator": "Guest",
"name": "Rate this website!",
"__v": 0
}
Polls.js - Schema
var mongoose = require('mongoose');
const Poll = new mongoose.Schema({
name: { type: String, required: true },
options: { type: Array, required: true },
creator: { type: String, default: 'Guest' }
});
const Polls = mongoose.model('Polls', Poll);
module.exports = Polls;

How to remove Object from array using mongoose

I'm trying to remove an object from an array in a document using mongoose.
The Schema is the following:
var diveSchema = new Schema({
//irrelevant fields
divers: [{
user: { type: Schema.Types.ObjectId, ref: 'User', required: true },
meetingLocation: { type: String, enum: ['carpool', 'onSite'], required: true },
dives: Number,
exercise: { type: Schema.Types.ObjectId, ref: 'Exercise' },
}]
});
a possible entry can be
{
//irrelevant fields
"divers": [
{
"_id": "012345678",
"user": "123456789",
"meetingLocation": "carpool",
"exercise": "34567890",
},
{
"_id": "012345679",
"user": "123456780",
"meetingLocation": "onSite",
"exercise": "34567890",
}
]
}
Say I want to remove the entry where user is 123456789 (note I do not know the _id at this point).
How do I do this correctly?
I tried the following:
var diveId = "myDiveId";
var userIdToRemove = "123456789"
Dive.findOne({ _id: diveId }).then(function(dive) {
dive.divers.pull({ user: userIdToRemove });
dive.save().then(function(dive) {
//do something smart
});
});
This yieled no change in the document.
I also tried
Dive.update({ _id: diveId }, { "$pull": { "divers": { "diver._id": new ObjectId(userIdToRemove) } } }, { safe: true }, function(err, obj) {
//do something smart
});
With this I got as result that the entire divers array was emptied for the given dive.
What about this?
Dive.update({ _id: diveId }, { "$pull": { "divers": { "user": userIdToRemove } }}, { safe: true, multi:true }, function(err, obj) {
//do something smart
});
I solve this problem using this code-
await Album.findOneAndUpdate(
{ _id: albumId },
{ $pull: { images: { _id: imageId } } },
{ safe: true, multi: false }
);
return res.status(200).json({ message: "Album Deleted Successfully" });
Try this
Dive.update({ _id: diveId },{"$pull": { "drivers": {"user": "123456789"}}})
Try this async code
var diveId = "myDiveId";
var userIdToRemove = "123456789"
const dive=await Dive.findOne({ _id: diveId })
await dive.divers.pull({ user: userIdToRemove });
await dive.save();
Use this with try/catch:
await Group.updateOne(
{ _id: groupId },
{ $pull: { members: {id: memberId }}}
);

Strongloop loopback how to assign static roles to new users

I have cloned a https://github.com/beeman/loopback-angular-admin
and I have created a couple of new roles using the loopback explorer but how do I assign roles to users that I create
I have a user model which extends from User model in loopback
and the model file is like this -
{
"name": "user",
"plural": "users",
"base": "User",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {
"accessTokens": {
"type": "hasMany",
"model": "accessToken",
"foreignKey": "userId"
},
"identities": {
"type": "hasMany",
"model": "userIdentity",
"foreignKey": "userId"
},
"credentials": {
"type": "hasMany",
"model": "userCredential",
"foreignKey": "userId"
},
"roles": {
"type": "hasMany",
"model": "Role",
"foreignKey": "principalId",
"through": "RoleMapping"
}
},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "admin",
"permission": "ALLOW"
},
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$unauthenticated",
"permission": "DENY"
},
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}
],
"methods": {}
}
and my user.js is like -
module.exports = function (user) {
// Set the username to the users email address by default.
user.observe('before save', function setDefaultUsername(ctx, next) {
if (ctx.instance) {
if(ctx.isNewInstance) {
ctx.instance.username = ctx.instance.email;
}
ctx.instance.status = 'created';
ctx.instance.created = Date.now();
}
next();
});
};
Now, I want to assign roles and principals to users based on a property ctx.instance.type that I am passing from client
Assuming you already have a finite set of Roles created in your Role table, use an after save hook to assign the just-created User a specific Role:
User.observe('after save', function setRoleMapping(ctx, next) {
if (ctx.instance) {
if(ctx.isNewInstance) {
var RoleMapping = User.app.models.RoleMapping;
// var roleId = based on type lookup or static?
RoleMapping.create({
principalType: "USER",
principalId: ctx.instance.id,
roleId: roleId
}, function(err, roleMapping) {
if (err) {return console.log(err);}
// success stuff
}):
}
}
next();
});
Code not tested, just a general idea. You can't use a before save hook since you won't know the ID of the User to use for the principalId in the RoleMapping table.
UPDATE: Version including looking up the Role by type passed in:
user.observe('after save', function setRoleMapping(ctx, next) {
if (ctx.instance) {
if(ctx.isNewInstance) {
// look up role based on type
//
Role.find({where: {name: ctx.instance.type}}, function(err, role) {
if (err) {return console.log(err);}
RoleMapping.create({
principalType: "USER",
principalId: ctx.instance.id,
roleId: role.id
}, function(err, roleMapping) {
if (err) {return console.log(err);}
console.log('User assigned RoleID ' + role.id + ' (' + ctx.instance.type + ')');
}):
});
}
}
next();
});
Query docs are here: https://docs.strongloop.com/display/public/LB/Querying+data

Resources