Updating MeteorJS accounts-password plugin - javascript

I am currently working on a profile page using the plugin "accounts-password" installed it via the command
meteor add accounts-password
I have run the program and so on and was able to add data; however, when I try to call or display the data on the browser using the
{{ currentUser.email }}
and
{{ currentUser.password }}
It doesn't display, but when I called
{{ currentUser.username }}
it works just fine. I tried to access the database via find().fetch(); and this is what I see.
id: "GP26SF2F8jmpqQuvT"
emails: Array[1]
0: Object
address: "testing#gmail.com"
verified: false
__proto__: Object
length: 1
__proto__: Array[0]
username: "testing"
__proto__: Object
Based on the arrangement, should I called the email as
{{ currentUser.emails.0.address }}
? Also I don't see the password in the data, is there a way to retrieve it? Actually my aim here to update the Meteor.users if user wants to change password or email address. Thanks.

accounts-password doesn't publish the password field of the document by default. This is to be expected - for security reasons!
In regards to the email: accounts package allows the application to add multiple emails to a user. This is why there's an array of emails.
Instead of doing
{{ currentUser.emails.0.address }}
What you could do is add a helper to the template:
Template.myTemplate.helpers({
email: function(){
return Meteor.user().emails[0].address;
}
});
And then you can just use this in the template:
{{ email }}
Actually my aim here to update the Meteor.users if user wants to change password or email address. Thanks.
I'd say that there's almost never a reason to publish the user's password to the client. It's a huge security risk. The accounts-password package has taken care of the common use-cases, so you can just use Accounts.changePassword() on the client to allow the user to change their password.
If you want to allow the user to change their email, what you want to do, is use a Method. A method can be called by the client, but the code is executed on the server. After it's executed, the server returns a response to the client. Kind of like how HTTP works.
In this case, the client could call a method named changeEmail, which tries to change the user's email. If all checks pass etc, the server changes the user's email and returns a response, e.g. "success", otherwise returns "fail". This is what the code could look like:
if(Meteor.isClient){
Meteor.call('changeEmail', newEmail, function(error, response){
if(error){
console.error(error);
} else {
console.log(response);
}
});
}
if(Meteor.isServer){
Meteor.methods({
changeEmail: function(newEmail){
Accounts.addEmail(this.userId, newEmail, false);
var userEmails = Meteor.users.findOne(this.userId, {fields: {emails: 1}}).emails;
if(userEmails.length > 1){
Accounts.removeEmail(this.userId, userEmails[0].address);
Accounts.sendVerificationEmail(this.userId, newEmail);
return "success";
} else {
throw new Meteor.Error('fail', 'email not correct!');
}
}
});
}
If you're not familiar with Methods, you can read either this tutorial by Meteor or this article. Also, my code might not be 100% functional, it's just an example.

Related

Firebase - Check Password

I have a scenario that requires checking an entered password against the user's firebase password before the user does an irreversible task. This is different from creating an account or signing in. How can you check against a firebase password? It doesn't look like there's a password property in firebase.auth().currentUser.
Update:
The user must verify their password and the Delete button will run a function to check it. If it matches the firebase password, the Delete button will succeed in triggering a pretty modal to pop up.
I would suggest you to store the user password somewhere if you need to check against it at some point.
Instead of storing it inside your database (which wouldn't be safe) I would personally store it on user's device using UserDefaults so that you can access it easily whenever you need to perform your sensible tasks.
Update:
Another possibility would be using the reauthenticateWithCredential method. If the method return success then, perform your sensitive task. If it fails, ask your user to type the correct password.
As per your request, this is how you would reauthenticate the user using his email & password :
// First you get your current user using Auth :
let currentUser = Auth.auth()?.currentUser
// Then you build up your credential using the current user's current email and password :
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
// use the reauthenticate method using the credential :
currentUser?.reauthenticate(with: credential, completion: { (error) in
guard error == nil else {
return
}
// If there is no error, you're good to go
// ...Do something interesting here
})
You can find some more explanation inside the Firebase documentation here : https://firebase.google.com/docs/auth/ios/manage-users

Redirect a user if they do not have a set password before publishing

I have an interface in my website where a user can create an "unclaimed" order for another user and send them an invitation. The invitation link will be formatted as /enrollment/orders/:_id, where _id is the id of the order.
One catch is that this can be sent multiple times. On the first time, the user that is invited might not have a password set.
Meteor.publish('enrolled_order', function (token) {
// if user has their password reset, token will also be set for user's account
return Orders.find({
'enrollment.token': token
});
});
Here's the catch: During this publication, I want to check certain aspects of the user record and take different actions instead of publishing it. For security, I believe this will need to be done on the server to work appropriately.
if there is no this.userId, I want to send them to login.
if the user does not have a password set, I want to redirect them to the reset password page.
Is this possible via a meteor publication?
I think you would need to do this in the router. If you're using Iron Router, you could use onBeforeAction to check whether the user is logged in:
Router.route('/enrollment/orders/:_id', {
subscriptions: function() {
return Meteor.subscribe('enrolled_order', this.params._id);
},
onBeforeAction: function() {
if( ! Meteor.userId() ) {
Router.go( 'loginTemplateName' );
}
}
});
You aren't going to want to return the hashed password directly to the client, so maybe setting a variable to say whether the password exists or not might be the best approach?
I can't remember if onBeforeAction happens before waitOn, but you might be able to get away with waitOn instead of subscriptions.

How can I update an email address in meteor?

Hi I am building an app using Meteor and need to update my email address. I am using the Meteor accounts package.
My form passes an email value into an accountDetails object, which I will pass into a method to update my profile (including my email):
Meteor.users.update({_id: this.userId},
{
$set: {
'emails.$.address': accountsDetail.email
}
});
This gives me the error:
Exception while invoking method 'saveAccountInfo' MongoError: The positional operator did not find the match needed from the query. Unexpanded update: emails.$.address
Here is my user schema:
{
"_id" : "12345",
"emails" : [
{
"address" : "abc123#gmail.com",
"verified" : false
}
Can someone help? Thank you in advance!
If you're sure the user has one address, which should be the case you can use emails.0.address instead of emails.$.address.
This should work for nearly all use cases. The exception is when there are many emails associated with a user. In this case:
If you are on the server & only on the server, you can use the positional operator to update a specific email, if there are multiple addresses. You need to, in this case specify the current email in the query portion of the update. I.e: {_id: this.userId, 'emails.$.address' : <current address> }
The $ positional update operator is not currently available on the mongo client in Meteor.
as each user is able to have multiple addresses (it´s an array - see http://docs.meteor.com/#/full/meteor_users for details) you need to specify which key you want to update (in this case the key is the address itself)
Meteor.users.update({_id: this.userId, "emails.address":"me#domain.com"},
$set:{'emails.$.address': accountsDetail.email}
});
If every user only has one email you could also think about dropping this one and inserting the new one. see http://docs.mongodb.org/manual/reference/operator/update/pop/ for details.
Hope this helps.
Regards,
René

Yodlee REST API - error adding new user "Exception Occurred"

I am trying to use the Yodlee REST API to access our Private Zone and add a new user. I am using the register3 api which I'm calling at
https://sdkint11.yodlee.com/yodsoap/srest/private-XXX/v1.0/jsonsdk/UserRegistration/register3
The dummy user credentials are as follows:
{ cobSessionToken: '10072014_0:58f1876ccc25848a712fade98d9d31c067cb5b4d322094845b4f8359ee59dc2ba01f1e94cfc9d5bd116d32ff6333f84fd848817b9b20cd9b1e85d50774a0ea32',
userCredentials:
{ loginName: 'AAAAAA',
password: 'BBBBBB',
objectInstanceType: 'com.yodlee.ext.login.PasswordCredentials' },
userProfile: { emailAddress: 'ABC#DEF.co.uk' } }
I've changed the credentials a bit for privacy, and for now I'm only using the 5 mandatory arguments required to establish a new user.
The (not very helpful) error I'm getting is
{"errorOccurred":"true","exceptionType":"Exception
Occurred","referenceCode":"_e37c33ab-b59c-4fbc-ab6a-1a2b83f5784f"}
which doesn't help debugging much.
Anyone any ideas?
You are passing the parameters in form of objects which will not be accepted by Yodlee. You will have to strictly follow the way it's represented in the document.
So your request parameter should look like for example -
cobSessionToken: '10072014_0:58f1876ccc220950774a0ea32',
userCredentials.loginName:'AAAAAA', userCredentials.password:'BBBBBB'
Please try out the suggested changes.

Meteor: Adding Fields on createAccount

I'm trying to use the Meteor Roles package: https://github.com/alanning/meteor-roles
to obviously create a new field in user model.
The user is created no problem but the 'roles' field I'm trying to define isn't created. I can add things like 'Profile' and details within that too. But for some reason I can't make a roles field. Here's my form:
Template.signup.events({
'submit #signup-form' : function(e, t) {
e.preventDefault();
var roles = ['admin'],
email = t.find('#email').value,
password = t.find('#password').value;
Accounts.createUser({email: email, password : password, roles: roles}, function(err){
if (err) {
alert("User Not Added")
} else {
console.log("User Added.")
}
});
}
});
Eventually I'll need to publish this to the client but for right now I just want the field to show in MongoDb, which it's not.
3 things:
I feel like the code above should work but I'm clearly missing something
In the package docs it mentions this Roles.addUsersToRoles which I
tried but no luck
Or do I need to possibly update the record, after it's been created?
I did go into the DB and manually added the field and associated string to update it (with $set) and it worked. But from the form itself though, no luck.
Any pointers would be much appreciated. Thank you.
The Accounts.createUser function only lets you add arbitrary user properties via the profile option which is where they end up getting stored in mongo. That is why Meteor is ignoring the roles: roles part of your Accounts.createUser call.
It is true that the meteor-roles package stores the list of roles assigned to a user directly in the users collection, but that is almost just an implementation detail and you are probably best off sticking to the API that meteor-roles provides for adding users to a role:
Roles.addUsersToRoles(<userId>,[<list of roles>])
The userId passed to Roles.addUsersToRoles is the value returned by Accounts.createUser when its called on the server which is probably where you want to be doing this as that feels way more secure.
The Accounts.createUser function only takes username, email, password and profile as params for the user object. See the documentation here. So, to add another field to a new user object, you need to add it in a second step:
var uid = Accounts.createUser({email: email, password: password});
Meteor.users.update(uid, {$set: {roles: roles}});

Categories

Resources