user privileges in mongodb - javascript

I'm new for mongodb.
i'm trying to understand how user privileges work on mongodb
i have a mongodb data base ( from mongoHQ sandbox 512 Mb free ).
and also i create a database and it contains some collections
here how it looks like
here is my database events and its collections (messages,*provider*)
events
- messages
- provider
what i want is :
i have 3 users with 3 different privileges on events database's different collections
here are 3 users with their privileges
providerUser : readonly access on provider collection and don't have access events database's other collections (and have no access on other data bases also )
eventreadUser : readonly access on message collection on events data base and don't have access to other collections on events database (and have no access on other data bases also )
eventreadWriteUser :only have read,write access on message collection on events data base and don't have access to other collections on events database (and have no access on other data bases also )
so i created a javascript that add these users to events database
addUsers.js
var conn = new Mongo('hostname:port');
var db = conn.getDB("events");
// For authentification on DB
db.auth('username', 'password');
function addCurlUserAndroidUser() {
var providerUser = {
user: 'providerUser',
pwd: 'providerUserPassword',
privileges: [{
resource: {collection: "provider" },
actions: [ "find"]
}],
roles: [ "read"]
};
var eventreadUser = {
user: 'eventreadUser',
pwd: 'eventreadUserPassword',
privileges: [{
resource: { collection: "messages" },
actions: [ "find"]
}],
roles: [ "read"]
};
var eventreadWriteUser = {
user: 'eventreadWriteUser',
pwd: 'eventreadWriteUserPassword',
privileges: [{
resource: { collection: "messages" },
actions: [ "find", "insert","remove","update"]
}],
roles: [ "readWrite"]
};
db.addUser(eventreadUser);
db.addUser(providerUser);
db.addUser(eventreadWriteUser);
}
after i execute this javascript by following command line :
mongo hostname:port/events addUsers.js
the problem is providerUser have access to read messages collection
and eventreadUser , eventreadWriteUser can also have access to read provider collection
please ask more information if needed or if there something not clearly explained
it will be very useful if i get some useful responses very quickly
Thank you
Dinesh

Related

How can i translate query to sequelize?

select reservation_datetime
from LectureReservation
Inner Join Lecture
On LectureReservation.lecture_id = Lecture.id
Where Lecture.mentor_id = 1
This is my query and I want to change it to sequelize like
if (req.params.id) {
LectureReservation
.findAll({
include: [{
model: Lecture,
where: { mentor_id: req.params.id },
}],
attributes: ['reservation_datetime'],
where: {
lecture_id: Lecture.id,
},
this.. I tried it so hard but can't find solution and my postman keep showing me
"name": "SequelizeEagerLoadingError"
this err..
plz help me to translate query to sequelize..!
Sequelize will do _outer join without required = true.
The errors you have received usually is from association problem.
Try set logging :console.log and check the raw query.

How to keep the api alive even if a datasource is not available on loopback 3?

I have a doubt about the data sources:
Context: Currently I'm working on a project where my API uses two datasources: A and B.
Sometimes the datasource B has troubles and is not available while A is always available.
When B is not available the whole web service collapses.
My question: Is there any way to program the api to keep it working with the part that only evolves the datasource A when the datasource B is not accessible?
Note: I'm working with Loopback 3
lazyConnect:true Will defer connection until you query a model attached to it, and send the client an error without crashing the server if the connection fails.
"myDatasource": {
"name": "myDatasource",
"host": "ds.com",
"database": "db",
"username": "root",
"password": "",
"connector": "postgres",
"lazyConnect": true
},
My question: Is there any way to program the api to keep it working with the part that only evolves the datasource A when the datasource B is not accessible?
You can use your datasource's events to know when to swap models. Here is something I tested briefly.
server/boot/swap.js
function swapModelDatasource(app, model, ds) {
const name = model.name;
app.deleteModelByName(name);
const m = app.model(ds.createModel(name, model.definition.properties, {
settings: model.settings,
relations: model.settings.relations,
acls: model.settings.acls
}));
}
module.exports = app => {
const ds1 = app.datasources.aws;
const m = app.models.Node;
ds1.on('connected', () => swapModelDatasource(app, m, ds1));
}

Meteor React Subscribe to specific collection data

I am building a React - Meteor web app and I need to get access to a specific piece of data from a collection.
There are three main components, the company list, the project list and the task list. When I list all of the companies, I can select one and then display all of the project associated with that company. What I want to then do is click on a project and see all of the tasks which are associated with that project. My data structure is as follows (as you can see, projects are an array of objects):
{
"_id" : "aQnrkqMi6ugEvav4a",
"owner" : "7Gp49ZCtGC9oEx3jN",
"createdAt" : ISODate("2017-05-08T15:52:27.777Z"),
"data" : {
"name" : "lkhgb",
"contacts" : [
{
...
}
],
"projects" : [
{
...
},
{
"name" : "ljhvljhvblhkjvblhkj",
"id" : "258757206",
"tasks" : [
"task1",
"task2"
]
}
]
}
}
In my TaskList Component, I'm exporting it like so:
export default createContainer((props) => {
const {companyId} = props.match.params;
Meteor.subscribe('company');
return {project: Company.findOne(companyId)};
}, TaskList)
Where I'm pulling the companyId off the props. I am also pulling off the projectId from props, but when I query the collection it's just returning undefined. I have published the GitHub repo as live here - https://github.com/GlueDigiStu/ClientManager and would appreciate any help.
You did indeed subscribe to the "company" publication on the server.
Although that publication does not exist.
Meteor.publish('company', function (companyId) {
const publications = [];
publications.push(Company.find(
{
_id: companyId,
},
));
return publications;
});
This will publish the id you want from the server.
Then the subscription from the client would be:
Meteor.subscribe('company', props.companyId);
Let me know if you have any further questions.
If I may I'll also give you some suggestions. Having documents in documents in documents isn't really great for publications.
I would suggest to place projects and tasks into new collections and only subscribe to tasks once their project is selected.

Modelling a Chat like Application in Firebase

I have a Firebase database structuring question. My scenario is close to a chat application. Here are the specifics
- users(node storing several users of the app)
- id1
name: John
- id2
name: Meg
- id2
name: Kelly
- messages(node storing messages between two users)
- message1
from: id1
to: id2
text: ''
- message2
from: id3
to: id1
text: ''
Now imagine building a conversations view for an individual user. So I want to fetch all messages from that particular user
and to that particular user
I am writing it as follows right now:
let fromMessagesRef = firebase.database().ref('messages').orderByChild('from').equalTo(firebase.auth().currentUser.uid)
fromMessagesRef.once("value").then((snapshot) => {/* do something here*/})
let toMessagesRef = firebase.database().ref('messages').orderByChild('to').equalTo(firebase.auth().currentUser.uid)
toMessagesRef.once("value").then((snapshot) => {/* do something here*/})
Questions:
Is this the right way to model the problem?
If yes, is there a way to combine the above 2 queries?
I would store the data like this:
- users(node storing several users of the app)
- id1
name: John
messages
message1: true
message2: true
- id2
name: Meg
messages
message1: true
message3: true
- id3
name: Kelly
messages
message2: true
message3:true
- messages(node storing messages between two users)
- message1
from: id1
to: id2
text: ''
- message2
from: id3
to: id1
text: ''
- message3
from: id2
to: id3
text: ''
Firebase recommends storing things like this. So in your case your query would be
let fromMessagesRef = firebase.database().child('users').child(firebase.auth().currentUser.uid).child('messages')
This allows it to be very fast as there is no orderBy being done. Then you would loop over each message and get it's profile from the messages node.
The structure you have is one possible way to model this data. If you're building an application like this, I would highly recommend the angularfire-slack tutorial. One potentially faster way to model the data would be to model the data like is suggested in this tutorial https://thinkster.io/angularfire-slack-tutorial#creating-direct-messages
{
"userMessages": {
"user:id1": {
"user:id2": {
"messageId1": {
"from": "simplelogin:1",
"body": "Hello!",
"timestamp": Firebase.ServerValue.TIMESTAMP
},
"messageId2": {
"from": "simplelogin:2",
"body": "Hey!",
"timestamp": Firebase.ServerValue.TIMESTAMP
}
}
}
}
}
The one thing you need to watch for in this case if you choose to do it like this is that before your query, you need to sort which user will be the "primary user" under whom the messages will be stored. As long as you make sure that is the same every time, you should be good to go.
One improvement you could make to this structure is something you already pointed out - flattening your data and moving the messages to another node - like you did in your example.
To answer your second question, if you were to keep that structure, I think you would need both of those queries, because firebase does not support a more complicated OR query that would allow you to search both at the same time.
No. Firebase Auth subsystem is where you want to store the email, displayName, password, and photoURL for each user. The function below is how you do it for a password-based user. oAuth-based users are easier. If you have other properties you want to store, like age for example, put those under a users node with each users uid that Firebase Authentication provides you.
function registerPasswordUser(email,displayName,password,photoURL){
var user = null;
//NULLIFY EMPTY ARGUMENTS
for (var i = 0; i < arguments.length; i++) {
arguments[i] = arguments[i] ? arguments[i] : null;
}
auth.createUserWithEmailAndPassword(email, password)
.then(function () {
user = auth.currentUser;
user.sendEmailVerification();
})
.then(function () {
user.updateProfile({
displayName: displayName,
photoURL: photoURL
});
})
.catch(function(error) {
console.log(error.message);
});
console.log('Validation link was sent to ' + email + '.');
}
As for the messages node, get the random id from Firebase Realtime Database's push method and use that as the id of each message under messages. Firebase queries are used:
var messages = firebase.database().ref('messages');
var messages-from-user = messages.orderByChild('from').equalTo('<your users uid>');
var messages-to-user = messages.orderByChild('to').equalTo('<your users uid>');
messages-from-user.once('value', function(snapshot) {
console.log('A message from <your users uid> does '+(snapshot.exists()?'':'not ')+' exist')
});
messages-to-user.once('value', function(snapshot) {
console.log('A message to <your users uid> does '+(snapshot.exists()?'':'not ')+' exist')
});
Define an index for messages-from-user and messages-to-user in your Rules:
{
"rules": {
"messages": {
".indexOn": ["from", "to"]
}
}
}
Below data structure gives you more flexibility with you data. Instead of having to store each messages that user sent back and forth I would suggest to store it in separate node and store the messageID with each user that is involved in the conversation.
Obviously you need to set the security rules, so other user can't see conversation if they are not in the conversation.
By doing this we are not creating deep chain node inside user info
- users(node storing several users of the app)
- id1
name: John
messages: [msID1, msID9]
- id2
name: Meg
messages: [msID1, msID7]
- id3
name: Kelly
messages: [msID9, msID7]
- messages(node storing messages between two users)
- msID1
from: id1
to: id2
text: ''
- msID7
from: id3
to: id2
text: ''
- msID9
from: id3
to: id1
text: ''
Firebase has actually built a demo (and extendible) chat application called Firechat. The source and documentation is provided, and of particular note is the section on their data structures.
Although they've implemented chatrooms, you can see that they've flattened their data structures as in many of the other answers. You can read more about how and why this is done in the Firebase guide.

Access user email address in Meteor JS app

I am building an app using Meteor and need to access the stored email address of a logged-in user.
I am currently using:
var userObj = Meteor.user();
console.log(userObj);
to access the user. However, I am only able to access the id. The email address is stored in a nested object that looks like this:
[Object {address="address#gmail.com", verified=false}]
I have tried various ways to traverse the JSON object but can't figure out how to access the value I need.
Meteor.user().emails[0].address works for me.
Here's what the doc says:
By default the server publishes username, emails, and profile. See
Meteor.users for more on the fields used in user documents.
Example user document:
{
_id: "bbca5d6a-2156-41c4-89da-0329e8c99a4f", // Meteor.userId()
username: "cool_kid_13", // unique name
emails: [
// each email address can only belong to one user.
{ address: "cool#example.com", verified: true },
{ address: "another#different.com", verified: false }
],
createdAt: 1349761684042,
profile: {
// The profile is writable by the user by default.
name: "Joe Schmoe"
},
services: {
facebook: {
id: "709050", // facebook id
accessToken: "AAACCgdX7G2...AbV9AZDZD"
},
resume: {
loginTokens: [
{ token: "97e8c205-c7e4-47c9-9bea-8e2ccc0694cd",
when: 1349761684048 }
]
}
}
}
You don't specify how you are authenticating users. For example, if you were using Google authentication only, the email address would be found only in
Meteor.user().services.google.email
So, it depends.
Try this:
Meteor.user().emails[0].address
Regards,

Categories

Resources