I am trying to block user who open more than one browser being logged In.
I have a Meteor.user() object populated as follows when a user signs up:
{
"_id" : "uSS2RqZnnFwui67wk",
"createdAt" : ISODate("2017-05-15T07:28:10.546Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$DPgA59Gmob4ajzjYZyh5auoHRUyQuF1/7M0KaWz.nzW0mIEqzlDK6"
},
"resume" : {
"loginTokens" : [
{
"when" : ISODate("2017-05-15T13:42:29.322Z"),
"hashedToken" : "tkoQnweSQhgRKGzaJTAkUU3/Ljd3p4wrBJfrRvRRlcY="
}
]
}
},
"username" : "johndoe",
"emails" : [
{
"address" : "lkj#gmail.com",
"verified" : false
}
],
"profile" : {
"name" : "John Doe",
"mobile" : "9637637941",
"email" : "lkj#gmail.com",
"address" : "kfasd, asdas,d as dsad",
"gender" : "M",
"state" : "Uttar Pradesh",
"customerType" : "CLIENT",
"isBlocked" : true
},
"status" : {
"online" : true,
"lastLogin" : {
"date" : ISODate("2017-05-15T14:12:02.094Z"),
"ipAddr" : "127.0.0.1",
"userAgent" : "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0"
},
"idle" : false
}
}
Referring to the above code, I am trying to update a UI based on the user.profile.isBlocked* status.
My UI.html is as below:
<template name="App_watch">
{{#if isBlocked}}
User Has been Blocked.
{{else}}
User has Access.
{{/if}}
</template>
My UI.js is as below:
import { Meteor } from 'meteor/meteor';
import './UI.html';
Template.App_watch.helpers({
isBlocked() {
user = Meteor.users.find({_id: Meteor.userId});
return user.profile.isBlocked;
}
});
In the code below I am simply monitoring whether there are more than 1 browsers open with same log in. If YES then block the user, else Unblock the user.
import './fixtures.js';
import './register-api.js';
UserStatus.events.on("connectionLogin", function(fields) {
var count = UserStatus.connections.find({userId : fields.userId}).count();
if(count > 1) { //Block
Meteor.users.update({_id: Meteor.userId()}, {$set: {"profile.isBlocked": true}});
} else { // Unblock
Meteor.users.update({_id: Meteor.userId()}, {$set: {"profile.isBlocked": false}});
}
});
Problem Statement:
I want to make the isBlocked variable reactive as an when the isBlocked flag changes for the user. Currently it is static and needs refresh.
Try:
Template.App_watch.helpers({
isBlocked() {
return Meteor.user() && Meteor.user().profile && Meteor.user().profile.isBlocked;
}
});
If you're looking for a single object you need to use .findOne() instead of .find() as the latter returns a cursor. It's also Meteor.userId() not Meteor.userId
Related
I Have added allaning:roles in my meteor-react project but
Roles.userIsInRole(Meteor.userId(), ["ADMIN"]) always returning false.
I have roles in my mongo as follows,
{ "_id" : "9B3D757wQA9Mz4RGt", "name" : "BUYER" }
{ "_id" : "PDCJH8D6JDo9fttFj", "name" : "ADMINKAMB" }
{ "_id" : "XFGsrfB3Xsm6F8LbQ", "name" : "SELLER" }
{ "_id" : "hDLSvdo6wMnF47BBz", "name" : "ADMIN" }
{ "_id" : "ADMINKAMB", "children" : [ ] }
if you remove the autopublish from yours packages, try to add this code
For my case, I create a file /imports/startup/server/publications/index.js
Meteor.publish(null, function() {
if (this.userId) {
return Meteor.roleAssignment.find({ 'user._id': this.userId });
}
return this.ready();
});
Then in server/main.js
import '/imports/startup/server/publications'
From my firebase data I`m trying to access the users information like what government agency and displayname using this example from firebase docs. When I use this example came f
{
"users" : {
"citizen" : {
"NiPS4VtdFPgVMVyhCVfMtzdP85g1" : {
"displayName" : "user-citizen",
"email" : "user#user.com",
"password" : "palls123",
"pnumber" : "123",
"repassword" : "palls123"
},
"Pba7iULL4wYkTQxHB5tpbNDj7v02" : {
"displayName" : "kevin",
"email" : "ez#ez.com",
"password" : "palls123",
"pnumber" : "545",
"repassword" : "palls123"
},
"gf2o8dhs9VhIsCK5Ui5rEizESbj1" : {
"displayName" : "kevin",
"email" : "dli#dli.com",
"password" : "palls123",
"pnumber" : "5454",
"repassword" : "palls123"
}
},
"government" : {
"bfp" : {
"AgIqgADtMeNS5d3BJTnCI0uCjcl1" : {
"displayName" : "bfp-user",
"email" : "bfp#bfp.com",
"gov_agency" : "bfp",
"gov_id" : "123",
"password" : "palls123",
"pnumber" : "1234",
"repassword" : "palls123",
"toggle" : true
}
},
"ndrmmc" : {
"XdoC2Dny5ZM69z8B2BrSWBS3CIY2" : {
"displayName" : "ndrmmc-user",
"email" : "ndrmmc#ndrmmc.com",
"gov_agency" : "ndrmmc",
"gov_id" : "123",
"password" : "palls123",
"pnumber" : "123",
"repassword" : "palls123",
"toggle" : true
}
},
"pnp" : {
"MhKiEoCtytQAHooHclSZIB3gsK42" : {
"displayName" : "pnp-user",
"email" : "pnp#pnp.com",
"gov_agency" : "pnp",
"gov_id" : "23455",
"password" : "palls123",
"pnumber" : "1234",
"repassword" : "palls123",
"toggle" : true
}
},
"rta" : {
"fehvPVwX6NXnVkf3hOyRsQBDH2Y2" : {
"displayName" : "rta-user",
"email" : "rta#rta.com",
"gov_agency" : "rta",
"gov_id" : "1234",
"password" : "palls123",
"pnumber" : "123",
"repassword" : "palls123",
"toggle" : true
}
}
}
}
I`m trying to access the users information like what government agency and displayname using this example from firebase docs. When I use this example came from the docs
var user = firebase.auth().currentUser;
if (user != null) {
user.providerData.forEach(function (profile) {
console.log(" Gov Agency : " + profile.gov_agency);
console.log(" Provider-specific UID: " + profile.uid);
console.log(" Name: " + profile.displayName);
});
}
It returns null on my side except for the uid it gives email of the user. Where did I go wrong?
PS: There are two types of user a gov client and citizen client
It is normal that you get a null value for profile.gov_agency: as detailed here, the providerData property of a User is a "non-null Array of firebase.UserInfo"
In turns, a UserInfo has a set of defined properties: email, phoneNumber, etc. So the profile does not have any gov_agency property.
You are apparently mixing up the values you can get from firebase.auth with the ones that you have saved in the real time database.
You should therefore query the database, based on the userId or on the email (depends on your data model), in order to get the values of gov_agency (and displayName) to "determine if it is a gov client or a citizen client".
To query the database, refer to https://firebase.google.com/docs/database/web/read-and-write and https://firebase.google.com/docs/database/web/lists-of-data
Note that displayName IS also property of UserInfo, but apparently you have not set it when creating the users.
Note from the doc:
currentUser might also be null because the auth object has not
finished initializing...
Try:
firebase.auth().onAuthStateChanged(user => {
if (user) {
// User is signed in.
console.log('User is signed in:', user);
} else {
// No user is signed in.
console.log('No user is signed in', user);
}
});
CMIIW
My firebase database structure is as below. I would like to search with a particular "Info/Email", let's say "abc#abc.com".
{
"-KhWrBcYyMluJbK7QpnK" : {
"Info" : {
"Email" : "xyz#gmail.com"
},
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX0tgQvDtDYqt4XRoL" : {
"Info" : {
"Email" : "abc#abc.com"
},
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX1eo7uFnOxqncDXQ5" : {
"Info" : {
"Email" : "abc#abc.com"
},
"Settings" : {
"Status" : "Pending"
}
}
}
I added a rule too
"Invitation" : {
".indexOn": ["Info/Email","Settings/Status"]
}
My AngularFire code is as follows:
var rootRef = firebase.database().ref().child('Invitation');
var userInvitations = rootRef.child("Info").orderByChild("Email").equalTo("abc#abc.com");
var allInvitations = $firebaseArray(userInvitations);
But I am getting a FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "Email" at /Invitation/Info to your security rules for better performance. and of course I am not receiving any data.
What are the mistakes I made here? Also can I add multiple orderByChild, for example: if I want to find details of the record, which has "Info/Email" equal to "abc#abc.com" and "Settings/Status" equal to "Pending" ?
The Firebase API only allows you to filter children one level deep
So with reference to your data structure:
if it were to be this way,
{
"-KhWrBcYyMluJbK7QpnK" : {
"Email" : "xyz#gmail.com",
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX0tgQvDtDYqt4XRoL" : {
"Email" : "abc#abc.com",
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX1eo7uFnOxqncDXQ5" : {
"Email" : "abc#abc.com",
"Settings" : {
"Status" : "Pending"
}
}
}
You should write your rules this way instead.
"Invitation" : {
"Info" : {
".indexOn": "Email",
},
"Settings" : {
".indexOn": "Status",
}
}
Then you will be able to query the data
var allInvitations = [];
var rootRef = firebase.database().ref().child('Invitation');
var userInvitations = rootRef.orderByChild("Email").equalTo("abc#abc.com");
userInvitations.on('value', snap => {
var invitations = snap.val()
for (prop in invitations ) {
allInvitations.push(invitations[prop ]);
}
console.log(allInvitations);
})
I have a login validation function setup to check if a new user registered outside of the app. That users info is stored in a temporary collection. If the users info validates I want to be able to use Accounts.createUser on the Client side, but I can't figure out how to do that. The documentation says that "registered validate login callbacks are called with a single argument, the attempt info object", but I can't find any examples of how to do this.
environment.js
Accounts.config({
forbidClientAccountCreation : true
});
server.js
Accounts.validateLoginAttempt(function(info){
if (!info.allowed)
{
var userEmail = info.methodArguments[0].user['email'].toLowerCase();
var userPass = info.methodArguments[0].password['digest'];
// check if this is a temp user
if (tmpUsers.find({'email': userEmail}).count() == 1)
{
var user = tmpUsers.findOne({'email': userEmail})
// check for active
if (user.active == "Yes")
{
// check password
if (userPass == user.password)
{
var accountId = Accounts.createUser({
'password': userPass,
'email': userEmail,
'profile': ({'acctType': user.type})
});
return true;
} else {
throw new Meteor.Error(403, "Incorrect password.");
return false;
}
} else {
throw new Meteor.Error(403, "Your account has yet to be activated.);
return false;
}
} else {
throw new Meteor.Error(403, "Can not find user " + userEmail);
return false;
}
} else {
return true;
}
});
Update:
I ended up putting the Account.userCreate part on the server side and now it does get the user created but when I try to login I get "Email already exists." So it appears as though it doesn't expect the login to be successful and tries to create the user again.
{ // This user works
"_id" : "hCBLo3AJJwmtR6s62",
"createdAt" : ISODate("2014-12-26T20:27:58.44Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$pxlEy.JFomgwQwV2cpm72.TBG4.llP98BF9ssTCptC4WsekLzJO9G"
},
"resume" : {
"loginTokens" : []
}
},
"emails" : [{
"address" : "demo#demo.com",
"verified" : false
}]
}
{ // This one does not
"_id" : "w6SGuqJJPs5LoCTTj",
"createdAt" : ISODate("2015-01-10T20:54:16.032Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$VJFj0UOrQiLs7djfGWAeMeruDactDFrl1nlEsXh/r5Z/895C5ubAW"
}
},
"emails" : [{
"address" : "demo2#demo.com",
"verified" : false
}],
"profile" : {
"acctType" : null
}
}
Would something like this work for you?
var options = {
username: "username", // you'll need to fill this in
email: userEmail,
password: userPass,
profile: {name: "name"} // you'll need to fill this in
};
Accounts.createUser(options, function (error) {
if (error) {
console.log("Cannot create user");
}
});
I am using accounts-google package to register users
I have multiple users stored in mongo
db.users.find()
{ "_id" : "av8Dxwkf5BC59fzQN", "profile" : { "avatar" : "https://lh3.googleusercontent.com/-rREuhQEDLDY/AAAAAAAAAAI/AAAAAAAADNs/x764bovDfQo/photo.jpg", "email" : "lfender6445#gmail.com", "name" : "Luke Fender", "room" : "2" }, "services" : { "resume" : { "loginTokens" : [ { "when" : ISODate("2014-04-26T19:34:52.195Z"), "hashedToken" : "8na48dlKQdTnmPEvvxBrWOm3FQcWFnDE0VnGfL4hlhM=" } ] } } }
{ "_id" : "6YJKb7umMs2ycHCPx", "profile" : { "avatar" : "https://lh3.googleusercontent.com/-rREuhQEDLDY/AAAAAAAAAAI/AAAAAAAADNs/x764bovDfQo/photo.jpg", "email" : "lfender6445#gmail.com", "name" : "Luke Fender", "room" : "2" }, "services" : { "resume" : { "loginTokens" : [ { "when" : ISODate("2014-04-26T19:35:00.185Z"), "hashedToken" : "d/vnEQMRlc4VI8pXcYmBvB+MqQLAFfAKsKksjCXapfM=" } ] } } }
But Meteor.users.find().fetch() returns document for logged in user only - shouldn't this return entire collection? Are the other users somehow private by default?
This is the default behaviour. You can only see who you're logged in as.
You can make a custom publish function to publish a custom subset/what you want. In the example below I publish all the users (only the profile field)
Server side code
Meteor.publish('users', function() {
return Meteor.users.find({}, {fields:{profile: true}});
});
Client side code
Meteor.subscribe("users");
You might want to alter these to only publish what is relevant to the user. If you have over 100 users this begins to get wasteful to publish all of them to the client.