adding a field to a user after created - meteor

This code attempts to add a field to a user which already exist in meteor users.
The error I am getting is
Exception while invoking method 'logMeIn' Error: insert requires an argument
Which I don't understand, how can it be fixed? Thanks
/////////////////////////////////////
// client code
/////////////////////////////////////
Template.login.events({
'click #logMe': function() {
var username = $('#id').val();
var password = $('#pin').val();
Meteor.call('logMeIn', [username,password], function (err, data) { //create new user
if ( err ) {
if (err.message.match(/username already exists/i)) {
Meteor.loginWithPassword(username+password,password)
}
} else {
console.log('new user created');
}
});
}
});
/////////////////////////////////////
// server code
/////////////////////////////////////
Meteor.methods({
logMeIn: function (credentials) {
//do work , if logged in, do next line
var idPin = credentials[0] + credentials[1];
Accounts.createUser({username: idPin, password: credentials[1]});
}
});
Accounts.onCreateUser(function (options, user) {
user.menuGroup = 'a';
});

You need to return the user on the Account.onCreatedUser (documentation here). Also, additional data of the user should be put under the profile branch (check the documentation in here)
Accounts.onCreateUser(function (options, user) {
if (options.profile) {
user.profile = options.profile;
}
if (user['profile'] == null) {
user['profile'] = {};
}
user['profile']['menuGroup'] = 'a';
return user;
});

Related

How to match phone number with the phone number present in firebase real-time database (react-native)

I want to create a login form using firebase authentication in which the only user who is register in our database can login. Here I want to take user phone number from login form and match it with firebase real-time database, if the is present in database then the OTP will send to that phone number otherwise they get a popup message you are not register please register then login.
My database structure is like this,
{
+914587354986
{
name:abc
address:kolkata
email:abc#gmail.com
}
}
I have tried this way, you can see my code
function getData(phoneNumber){
var ref=firebase.app().database('https://phone-otp-verify-17c40-default-rtdb.firebaseio.com/').ref("/user/")
ref.once('value')
.then(snapshot => {
console.log('User data: ', snapshot.val());
})
if((snapshot.val()) == phoneNumber){
signInWithPhoneNumber(phoneNumber);
}else{
alert('number is not register ');
}
}
const signInWithPhoneNumber=async()=> {
try{
const confirmation = await auth().signInWithPhoneNumber(phoneNumber)
setConfirm(confirmation);
alert('Otp send sucessfully');
console.log('Otp send sucessfully');
}catch(error){
alert('Not register');
console.log(' Not register');
}
};
const confirmCode = async()=> {
try {
await confirm.confirm(code);
alert('sucessfull ');
console.log('sucessfull');
navigation.navigate('Home');
} catch (error) {
alert('Invalid code.');
console.log('Invalid code.');
}
};
I was getting error :ReferenceError: Can't find variable: snapshot
image of the error I was getting error image
You are accessing snapshot outside then callback. Move it inside.
function getData(phoneNumber) {
var ref = firebase.app().database('https://phone-otp-verify-17c40-default-rtdb.firebaseio.com/').ref("/user/");
ref.once('value')
.then(snapshot => {
console.log('User data: ', snapshot.val());
if (snapshot.val() == phoneNumber) {
signInWithPhoneNumber(phoneNumber);
} else {
alert('number is not register ');
}
});
}
Just a minor mistake
You are using snapshot.val() outside from scope.
The function should look like this
function getData(phoneNumber) {
var ref = firebase.app().database('https://phone-otp-verify-17c40-default-rtdb.firebaseio.com/').ref("/user/")
ref.once('value')
.then(snapshot => {
console.log('User data: ', snapshot.val());
if ((snapshot.val()) == phoneNumber) {
signInWithPhoneNumber(phoneNumber);
} else {
alert('number is not register ');
}
})
}

Accounts.onCreateUser clean up my code

When a new user account is created I'm using the Accounts.onCreateUser function to insert data into a new collection. I want to check that the insert has successfully worked before progressing. My code appears to work however it seems very messy. I'm wondering if there is a cleaner way to write this code.
Accounts.onCreateUser((options, user) => {
if (user) {
CandidateProfile.insert({
userId: user._id,
firstName: options.profile.name.first,
lastName: options.profile.name.last
});
var checkForNewCandidateProfile = CandidateProfile.findOne(
{ userId: user._id },
{ fields: { userId: 1 } }
);
var userId =
checkForNewCandidateProfile && checkForNewCandidateProfile.userId;
if (userId === user._id) {
return user;
}
}
});
Personally, I don't see any sense in your test. You don't trust insert?
But OK, you need it.
Be sure, that you run your code on the server side. Import it only on server side or just wrap it in if (Meteor.isServer)
Why check if user arg exists? It is, that's how that callback works.
If something's wrong, throw an error to abort user creation.
Possible variant:
if (Meteor.isServer) {
Accounts.onCreateUser((options, user) => {
// You insert sync, so it's up to you to handle errors.
try {
CandidateProfile.insert({
userId: user._id,
firstName: options.profile.name.first,
lastName: options.profile.name.last
});
var checkForNewCandidateProfile = CandidateProfile.findOne(
{ userId: user._id },
{ fields: { userId: 1 } }
);
var userId =
checkForNewCandidateProfile && checkForNewCandidateProfile.userId;
if (userId === user._id) {
return user;
}
} catch (error) {
throw new Error(error);
}
throw new Error("Something's wrong.");
});
}

Put the email address from Meteor.loginWithGoogle into a Session variable

I'm using Meteor.loginWithGoogle in my app. I'm trying to get the email address of the google user to put it into a Session variable.
Template.login.events({
'click #google-login': function(event){
Meteor.loginWithGoogle({}, function(err){
if ( err ) {
throw new Meteor.Error("Google login failed");
} else {
const emailAddress = ?; // how do I get this from google?
Session.set('email',emailAddress);
Router.go('/profile');
}
});
}
});
I'm not sure whether i understood your question, but i guess what you're trying to ask is: "After a user performed a loginWithGoogle, how can i get his email address, and set it into his Session?"
After a login, Meteor.user() holds the current user document. Having that in mind:
const currentUser = Meteor.user();
const userGoogleServiceMain = currentUser.services.google.email;
With that, you can have:
Template.login.events({
'click #google-login': function(event){
Meteor.loginWithGoogle({}, function(err){
if ( err ) {
throw new Meteor.Error("Google login failed");
} else {
const currentUser = Meteor.user();
const emailAddress = currentUser.services.google.email;
Session.set('email',emailAddress);
Router.go('/profile');
}
});
}
});
You may find more details about that in: Meteor documentation and http://cs.wellesley.edu/~mashups/pages/meteor6.html

Meteor reactive publish

This Meteor code displays a message on a headerLabel on a template, the server and/or the client changes the message by inserting a new message in HeaderLabelCol mongo collection and expect the client template to change since it publishes the last inserted document.
I was able to insert a new message using the client browser but did not show till I refreshed the page which may indicate that the reactiveness chain is broken somewhere. What is the problem? How can it be fixed? Thanks
//client.js
Template.header.helpers({
headerLabel: function () {
return HeaderLabelCol.findOne() ? HeaderLabelCol.findOne().headerLabel : 'Make a selection';
}
});
//server.js
HeaderLabelCol = new Mongo.Collection('headerLabelCol');
Meteor.publish('headerLabelCol', function () {
return HeaderLabelCol.find({userId: this.userId}, { sort: { createdAt: -1 } });
});
HeaderLabelCol._ensureIndex({createdAt: -1});
HeaderLabelCol.before.insert(function (userId, doc) {
doc.userId = userId;
doc.createdAt = Date.now();
});
HeaderLabelCol.allow({
insert: function (userId, doc) {
return (userId && doc.owner === userId);
}
});
I think you need to add the condition in your helper as well.
//client.js
Template.header.helpers({
headerLabel: function () {
var result = HeaderLabelCol.findOne({}, { sort: { createdAt: -1 } });
return result ? result.headerLabel : 'Make a selection';
}
});

Meteor showing Accounts.createUser errors

I have the following code in my Meteor app where I create new users, assign them 'basic' role. Yet I am having a trouble showing on the client side errors returned while processing Accounts.createUser, can someone please tell me how I can return errors returned by Accounts.createUser while having it on the server as my code below. Thanks
/server/users.js
Meteor.methods({
'createMemberAccount': function (data, role) {
var userId;
Meteor.call('createNewAccount', data, function(err, result) {
if (err) {
return err;
}
console.log('New account id: '+ result);
Roles.addUsersToRoles(result, role);
return userId = result;
});
return userId;
},
'createNewAccount': function (adminData) {
return Accounts.createUser({email: adminData.email, password : adminData.password, roles: adminData.roles});
}
});
/client/signup.js
Template.signupForm.events({
'submit #signup-form': function(e, t){
e.preventDefault();
var userData = {};
userData.email = $(e.target).find('[name=email]').val();
userData.password = $(e.target).find('[name=password]').val();
userData.roles = ['basic'];
Meteor.call('createMemberAccount', userData, 'basic', function(err, userId) {
if (!err) {
console.log('All OK');
} else {
console.log('Error: ' + err.message);
}
});
return false;
}
});
Since You are creating an static rol "basic", you don't need to do that pair of methods, and Meteor.calls, instead you can use
So, use the v on the client side, just like this.
Template.register.events({
'submit #register-form' : function(e, t) {
e.preventDefault();
var email = t.find('#account-email').value
, password = t.find('#account-password').value;
// Trim and validate the input
Accounts.createUser({email: email, password : password}, function(err){
if (err) {
// Inform the user that account creation failed
} else {
// Success. Account has been created and the user
// has logged in successfully.
}
});
return false;
}
});
If you see there is not any role yet incude, so now on the server.js use the onCreateUser method.
//Server.js
Accounts.onCreateUser(function(options, user) {
if (options.profile)
user.profile = options.profile;
user.role = "basic"
return user;
});
Now thats is more easy, and with less code, if you are trying to create 2 differents roles like "Admin" and "Basic", just on the client side create a profile field named "profile.roles" and do a if statement on the onCreateUser.
return Accounts.createUser({email: adminData.email, password : adminData.password, roles: adminData.roles});
This part returns the userId once it is created, it doesn't return any errors when it fails.
When it fails, the returned value will be undefined
Also, in the server, we cannot use callbacks with Accounts.createUser
If you want find the errors, you have to use Accounts.createUser in client side.
Coming to this late, but on the server side, you can assign the createUser to a variable and it will return the new user’s _id; then you can check if that exists. For example (server side only):
let email = 'foo#bar.com';
let password = 'bar';
let profile = {firstName: 'foo', lastName: 'bar'};
let newId = Accounts.createUser({
password: password,
email: email,
profile: profile
});
if (!newId) {
// New _id did not get created, reason is likely EMail Already Exists
throw new Meteor.Error(403, "Cannot create user: " + error.reason);
}
else {
// Stuff here to do after creating the user
}
The Meteor.Error line will be passed back as an error in the callback on the client side, so you can reflect that error to the browser.

Resources