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,
Related
I'm using the template graphcool/templates/auth/email-password with Graphcool and I'd like to add the ability to manage user roles.
This is my definition schema:
type User #model {
id: ID! #isUnique
createdAt: DateTime!
updatedAt: DateTime!
email: String! #isUnique
password: String!
role: UserRole!
}
enum UserRole {
EDITOR,
MODERATOR,
ADMIN
}
I'm already receiving the role in the query and saving it in local storage, but anyone would be able to change it affecting the frontend UI (if we add permissions, we shouldn't worry in the server side). What's the best/secure way to manage it?
Are you using the Graphcool framework?
If you need to setup permissions in the graphcool.yml. I would include the following:
graphcool.yml
- operation: User.create
authenticated: true
query: permissions/User.graphql:adminRole
- operation: User.read
authenticated: true
query: permissions/User.graphql:adminRole
- operation: User.update
authenticated: true
query: permissions/User.graphql:adminRole
- operation: User.delete
authenticated: true
query: permissions/User.graphql:adminRole
- operation: User.read
authenticated: true
query: permissions/User.graphql:user
fields:
- id
- name
- role
- createdAt
- updatedAt
- email
- company
- operation: User.update
authenticated: true
query: permissions/User.graphql:user
fields:
- name
- company
User.graphql
query user($node_id: ID, $user_id: ID!) {
SomeUserExists(filter: {AND: [{id: $user_id}, {id: $node_id}]})
}
query adminRole($user_id: ID!) {
SomeUserExists(filter: {id: $user_id, role: ADMIN})
}
This way the user can only update their name and company. Then the ADMIN user can do read and edit everyone. Only ADMIN users can create or update new users.
Then you're probably asking how do you create new users?
I would use the FaaS code from Graphcool templates for email-password authentication found here:
https://github.com/graphcool/templates/tree/master/auth/email-password
The signup.ts file should you how a new user can signup and then the admin creates a new user for you. Inside the signup function you can default the UserRole to what ever you want.
https://github.com/graphcool/templates/blob/master/auth/email-password/src/signup.ts
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.
This is a model in sails.js.
module.exports = {
attributes: {
name: {
type: "string"
},
email: {
type: "email",
required: true
},
password: {
type: "string"
}
},
beforeCreate: function(values, next) {
console.log(values); //logs {email:"mail#someplace.com"}
console.log(values.email); // logs the email id sent via post
console.log(values.password); // logs undefined is required is set to false, If required is set to true, password will log properly.
next();
}
};
I am planning to perform some encrypting of the password in the beforeCreate function, Of course I will be requiring the password and can continue with it right now but how to manage this for optional values just in case the need arises?
I found the reason for the above issue,
In my controller, I was doing a create record but the record I was creating contained only one field, i.e the email see below:
Users.create({email:req.body.email}).exec(function(err, user){
// user created
});
The model is directly mapped with the object being inserted into the database, So internally sails removes/ignores the fields which are not present.
To not remove these empty fields, you might have to set schema:true in your model.
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.
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