Get facebook information in meteor - javascript

I'm using Meteor.loginWithFacebook
The user is storing as:
{
"_id" : "cnzMXwmvtF42Dfy4q",
"createdAt" : ISODate("2016-08-31T15:58:00.814Z"),
"services" : {
"facebook" : {
"accessToken" : "randomtoken",
"expiresAt" : 1477842969226,
"id" : "randomid",
"email" : "example#example.com",
"name" : "Name",
"first_name" : "Firstname",
"last_name" : "Lastname",
"link" : "https://www.facebook.com/...",
"gender" : "male",
"locale" : "en_US",
"age_range" : {
"min" : 21
}
},
"resume" : {
"loginTokens" : [
{
"when" : ISODate("2016-08-31T15:58:00.818Z"),
"hashedToken" : "randomtoken"
}
]
}
},
"profile" : {
"name" : "Firstname"
}
}
But when I do:
console.log(Meteor.user().services);
It returns as undefined.
But if I do console.log(Meteor.user().profile); it brings the name correctly.
Question
How do I retrieve the facebook information in meteor?

By default, only the username, email and profile object are published to the client. You need to write a publication and subscribe to that on the client to expose the fields you need.
That being said, it may not suit your purposes to publish the services.facebook object directly. If you're using more than one authentication method such as Google or username/password, you'll likely want to standardize your users documents by copying the information you need into different fields.
Here is how I handle a project that uses Facebook, Google, and regular old email/password:
Accounts.onCreateUser(function(options, user) {
// Copy first name and last name from user services
if (user.services.google) {
user.firstName = user.services.google.given_name;
user.lastName = user.services.google.family_name;
} else if (user.services.facebook) {
user.firstName = user.services.facebook.first_name;
user.lastName = user.services.facebook.last_name;
}
// You can use the profile object to pass in user information in a password signup form
if (options && options.profile) {
if (options.profile.firstName) {
user.firstName = options.profile.firstName;
}
if (options.profile.lastName) {
user.lastName = options.profile.lastName;
}
}
return user;
});
Note that it is NOT recommended that you use the profile object to store user data.

Related

How can I differentiate types of users at login?

I am building an app that has different types of users that must have access to different dashboard based on who they are. Similar to student, teacher and School director.
Each of them have separate dashboard they must be directed to upon authentication.
I am using firebase as my backend support. After they have been authenticated into firebase, I have them saved into their respective DB like below.
The question is because firebase sees them all as users and assign a UID to each in Authentication, what is the best way to know who is student, teacher or director when they log back in so that they can be directed to their respective dashboard.
You need to use role based authentication system for your application.
Based on those user roles you can redirect the users to their specific dashboards or allocate permissions.
In case of Firebase a role based database should look something like so:
{
"roles" : {
"teacher" : true,
"student" : true,
"director" : {
"335Fq6U6gZPWNEyDJRZd6ZYGkvn1" : true
}
},
"secret_data" : {
"access_code" : 390399333,
"users" : {
"335Fq6U6gZPWNEyDJRZd6ZYGkvn1" : true
}
},
"users" : {
"335Fq6U6gZPWNEyDJRZd6ZYGkvn1" : {
"username" : "shakti"
}
}
}
and the security roles should be something like so:
{
"rules" : {
".read" : false,
".write" : false,
// Secret data is only available to paid users.
"secret_data" : {
".read": "(root.child('roles').child('director').hasChild(auth.uid))
&& (data.child('users').hasChild(auth.uid))",
"users" : {
"$uid" : {
".read" : "($uid === auth.uid)"
}
}
}
}
}
please refer to: https://firebase.google.com/docs/database/security/user-security
and github : https://gist.github.com/sararob/331760829a9dcb4be3e7
also you may refer to the SO answer at Firebase: set security rules depending on user roles

adding an object that represents users to an array after signup using passport

I am trying to make a list of username and passwords so that when a user signs in with their credentials they can see all the data that everyone else sees but they still have to use their own credential. I wanted to make a list of objects like this users : [{username : "user1", password : "pass1"}, {username : "user2", password : "pass2"}]. this should be created on signup. I though subdocs would help but I'm not getting what I want. I have this:
var userlist = new mongoose.Schema({username: String, password : String })
var userSchema = new mongoose.Schema({
users : [userlist]
})
and I attempted to add the new users to the array like this:
app.post("/signup", function(req, res){
var user = new User;
user.users.push({username : req.body.username, password : req.body.password})
user.save(function(err){
if(err) return handleError(err);
console.log("success")
})
// User.create(users : [{username : req.body.username, password : req.body.password}], function(err, doc){
// console.log(doc);
// })
res.redirect("/login")
})
this givs me this
> db.users.find().pretty()
{
"_id" : ObjectId("56ba6219763de71c03199a70"),
"users" : [
{
"username" : "user1",
"password" : "pass1",
"_id" : ObjectId("56ba6219763de71c03199a71")
}
],
"__v" : 0
}
{
"_id" : ObjectId("56ba6225763de71c03199a72"),
"users" : [
{
"username" : "user2",
"password" : "pass2",
"_id" : ObjectId("56ba6225763de71c03199a73")
}
],
"__v" : 0
}
>
It's making separate documents. I want it to look like this
{
"_id" : ObjectId("56ba6219763de71c03199a70"),
"users" : [
{
"username" : "user1",
"password" : "pass1",
"_id" : ObjectId("56ba6219763de71c03199a71")
},
{
"username" : "user2",
"password" : "pass2",
"_id" : ObjectId("56ba6225763de71c03199a73")
}
],
"__v" : 0
}
Having the objectIDs in the subdocs are not so important to me . I just want to group all the users together so that when they go to login I could do something like if the doc is there the credentials are good so continue to other parts of website.
I am not sure if you have resolved you question by now or not, regardless here is the answer to your problem.
Firstly if you don't need _id in subdocument then state that in the schema accordingly and no _id will be created.
var userSchema = new Schema({ username: String, password: String},{ _id: false });
If you use the above schema for user then there should be no _id field in the subdocument.
You should know that to insert a subdocument you need to know the parent for it. If you don't provide the parent while inserting the subdocument then for each insert a new parent is created. In this case parent contains _id and users subdocument. If I have the exact problem, I would go about solving it the following way:
The schema designs remain the same as shown below (I named them differently to avoid confusion):
var userSchema = new Schema({username: String, password: String},{ _id : false });
var userListSchema = new Schema({
users: [userSchema]
});
Now I will declare the parent model as follow:
var UserList = mongoose.model('UserList', userListSchema);
//see below what list gets assigned.
var list;
Now let's assume I have a route handler where I would like to keep adding the users upon sign up something as shown below:
app.get("/newuser/:username/:password", function(req, res) {
//create user model
var User = mongoose.model('User', userSchema);
//load user module, for testing i use params, you can change this to req.body
var user = new User({username: req.params.username, password: req.params.password});
//I would like to find the first document in userlists collection
UserList.findOne({}, function(err, result) {
if(err) console.log(err);
//below if condition is true, if there is one document with users subdoc
if(result) {
console.log('Found existing document with users subdocument. Adding user to array.')
//assign the parent where the subdoc should be inserted to list
list = result;
//there already is a document with subdocument users, so append to it
list.users.push(user);
//save the changed list.
list.save(function(err) {
if (err) console.log(err);
console.log('User saved.');
});
} else {
console.log('No document found. Creating one and adding this user to users subdocument.');
// initialize list model with first ever user
list = new UserList({ users: [user] });
//save the new changed list
list.save(function(err) {
if (err) console.log(err);
console.log('User saved.');
});
}
})
});
Done. Now when I run the app and access the following URL for the first time
http://127.0.0.1:8080/newuser/user1/pass1
The userslist collection would look as follow:
> db.userlists.find().pretty();
{
"_id" : ObjectId("56c349d6479f5b9b1eaea1c8"),
"users" : [
{
"password" : "pass1",
"username" : "user1"
}
],
"__v" : 0
}
I would like to access the link with different params as shown below:
http://127.0.0.1:8080/newuser/user2/pass2
And the output of the collection looks as follow:
{
"_id" : ObjectId("56c349d6479f5b9b1eaea1c8"),
"users" : [
{
"password" : "pass1",
"username" : "user1"
},
{
"password" : "pass2",
"username" : "user2"
}
],
"__v" : 1
}
Now I terminate the app and then re-run the app and access the following url:
http://127.0.0.1:8080/newuser/user7/pass7
And the output of the collection looks as follow:
{
"_id" : ObjectId("56c349d6479f5b9b1eaea1c8"),
"users" : [
{
"password" : "pass1",
"username" : "user1"
},
{
"password" : "pass2",
"username" : "user2"
},
{
"password" : "pass7",
"username" : "user7"
}
],
"__v" : 2
}
There you go. I feel bad to see that userlists collection would always always always have one document and its array would keep expanding, maybe not a good practice to solve your issue in this manner. If I were you, I would store each user as a single record and then do the group by or any other aggregation operation.

FireBase Security Rules with User roles

First off, I've previously researched this and I have referenced a previous question. I have done what is stated in this question with no positive result.
Firebase: set security rules depending on user roles
I am using:
Angular JS
Firebase
AngularFire -- Integrate Firebase with AngularJS
E-mail and Password Firebase Authentication
I have a node in Firebase for my users:
"users" : {
"simplelogin:49" : {
"email" : "myemail#something.com",
"full_name" : "First Last",
"roles" : {
"administrator" : true
}
},
"simplelogin:64" : {
"email" : "me#me.com",
"full_name" : "first last",
"roles" : {
"administrator" : false
}
}
}
I am trying to add an entry in my clients table while being logged into the simplelogin:49 that as you can see is an administrator.
// Create the Client
var clientRef = firebaseUrl+'clients';
var clientsListRef = new Firebase(clientRef);
clientsListRef.push({
'uid': userData.uid,
'number': cl.number,
'company': cl.company,
'full_name': cl.full_name,
'email': cl.email,
'phones': {
'primary': cl.phones.primary,
'cell': cl.phones.cell,
'alte': cl.phones.alte
},
'addresses': {
'billing': {
'line1': cl.addresses.billing.line1,
'line2': cl.addresses.billing.line2,
'city' : cl.addresses.billing.city,
'state': cl.addresses.billing.state,
'zip' : cl.addresses.billing.zip
},
'shipping': {
'line1': cl.addresses.shipping.line1,
'line2': cl.addresses.shipping.line2,
'city' : cl.addresses.shipping.city,
'state': cl.addresses.shipping.state,
'zip' : cl.addresses.shipping.zip
}
}
});
I have set up some rules in Firebase for the clients node and they are as follows:
"clients": {
"$auth": {
".write": "root.child('users').child('$auth.uid').child('roles').child('administrator').val() === true"
}
}
I've also tried this for rules:
"clients": {
".write": "root.child('users').child('auth.uid').child('roles').child('administrator').val() === true"
}
All I get when I run this and it all gets put together is a permission denied error. If I run it in the Firebase Simulator, this is the result:
Attempt to write Success({"user":"Test"}) to /clients with auth=Success({"id":49,"provider":"password","uid":"simplelogin:49"})
/
/clients:.write: "root.child('users').child('auth.uid').child('roles').child('administrator').val() === true"
=> false
No .write rule allowed the operation.
Write was denied.
I would just like to know what I'm missing. The person in the question says he/she was successful in their ventures.
First things first, you should use the Firebase Authentication user id that is automatically generated for each user. You will have to look at the AngularFire documentation on how to access the authenticated user id, but usually its something along the lines of:
firebase.auth().currentUser().uid
Then, once you have created the user with that id as the name of the dictionary like so:
"users" : {
"Rx6H4mjwwgVo6UKy2vSuOD5dTwk2" : {
"email" : "myemail#something.com",
"full_name" : "First Last",
"roles" : {
"administrator" : true
}
},
"U1x3narB2AQQ0FvMxu7RVQAxb7A2" : {
"email" : "me#me.com",
"full_name" : "first last",
"roles" : {
"administrator" : false
}
}
}
you can use the auth.uid variable in the Firebase Database Security Rules to get their user id:
"rules" : {
"clients": {
".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() == true"
}
}

Mongodb/Mongoose: Storing Subdocument of a Variable to a Variable

I am trying to create a shotgun npm command for deleting all topics ever created by a user
This is a sample user entry (users are stored in a collection called 'users'):
{
"__v" : 0,
"_id" : ObjectId("536c4c8fafec055606f01840"), //the id I want to store to a variable and use the variable to find all topics with that id in the 'creator' document
"joinDate" : ISODate("2014-05-09T18:13:28.079Z"),
"lastActiveDate" : ISODate("2014-05-09T18:13:48.918Z"),
"lastSocketId" : null,
"password" : "Johndoe6",
"roles" : [],
"username" : "johndoe6"
}
This is a sample topic entry (topics are stored in a collection called 'topics'):
{
"__v" : 4,
"_id" : 202, //unreliable as these change all the time
"body" : "example topic text",
"commentCount" : 0,
"creator" : ObjectId("536c4c8fafec055606f01840"), //this is the id I want to be found with my variable from a found user
"date" : ISODate("2014-05-14T13:58:13.668Z"),
"editedBy" : ObjectId("536f0392ca01fb0e39364c02"),
"editedDate" : ISODate("2014-05-14T13:59:27.607Z"),
"lastCommentDate" : ISODate("2014-05-14T13:58:13.670Z"),
"tags" : [],
"title" : "test",
"views" : [],
}
Here is a snippet of my code:
exports.invoke = function (shell, options) {
if (!options.confirm) {
shell.warn("Are you sure you want to delete all topics made by {{0}}? (Y/N)".format(options.username));
return shell.setPrompt('confirm', 'purgeTopic', options, 'Are you sure?');
}
shell.db.User.findOne({ username: options.username }, function (err, user) {
var userid = something //this is where I want it to pluck out the user's ID and store it for later
if (err) return shell.error(err);
if (!user) return shell.error("No user {{0}} exists.".format(options.username));
//otherwise
shell.db.Topic.where('creator').equals(userid).remove(function (err) {
As you can see, options.username is a variable that has been typed in by the user doing the command. On the last line I want it to remove topics that have a subdocument 'creator' with the id of the 'user'. How can this be accomplished?
It would simply be:
var userid = user._id;
But you'd want to put that after your if (!user) check in case user is null.

Javascript literal nested object - refer to top level properties

I'm writing a client side for mobile app that work with restful style web services.
var globApp = {
sessionId : "",
lastActionName: "",
userName : "2victor",
md5Pwd : "1234",
hostApiPath : "http://host/api",
action : {
login : {
scriptPath : "/acc/login",
method : "PUT",
requestParams : {
user : this.userName,
pwd : this.md5pwd
},
responseParams : {
}
},
register : {
scriptPath : "/acc/reg",
method : "POST",
requestParams : {
user : "myUserName",
fname : "myFirstName" ,
lname : "myLastName" ,
email : "mail#mail.com" ,
age : "28" ,
gender : "male" ,
pwd : "1234" ,
priv : "good"
},
responseParams : {
}
}
}
}
Properties userName and md5pwd will be assigned when application start.
What I want to achieve is, to assign this values to user and pwd properties under requestParams object for each action. Of course using this doesn't work and return undefined cause this in that case refers to the nested object if I understand correct.
This requestParams object is sent as JSON by AJAX.
I can define few variables out of this object and use them but I don't want to.
How it can be done?
It can't be done. The object is not available in any way until it has been fully defined. So you can't do it on one single step.

Categories

Resources