I have a user profile view where users can edit their profile information. Everything below works great and the update is successful. However, when I logout of the account and login with a different user account, the update fails and returns an Access denied error. It isn’t until I refresh the page that I can edit the profile information again with the second account.
I know this case is very rare and a user would not normally be logging out of one account, logging in with another and trying to update their profile but I would like to better understand why this is happening. Is the client token not flushed when a user logs out or is there something else that’s being preserved that requires a complete reload of the page?
On client JS:
Template.user_profile_form.events({
'click #submit_profile_btn': function(evt) {
evt.preventDefault();
var first_name = $('#profile_first_name').val()
,last_name = $('#profile_last_name').val()
,email = $('#profile_email').val()
,email_lower_case = email.toLowerCase()
,gravatar_hash = CryptoJS.MD5(email_lower_case)
;
gravatar_hash = gravatar_hash.toString(CryptoJS.enc.Hex);
// TODO need to create user sessions so that when you log out and log back in, you have a fresh session
Meteor.users.update({_id: this.userId }, {
$set: {
profile: {
first_name: first_name,
last_name: last_name,
gravatar_hash: gravatar_hash
}
}
}, function(error) {
if (!error) {
Session.set('profile_edit', 'success');
Meteor.setTimeout(function() {
Session.set('profile_edit', null);
}, 3000);
} else {
Session.set('profile_edit', 'error');
Template.user_profile_form.error_message = function() {
return error.reason;
};
}
});
Meteor.call('changeEmail', email);
}
});
The server JS:
Meteor.publish('list-all-users', function () {
return Meteor.users.find({_id: this.userId }, {
fields: {
profile: 1,
emails: 1
}
});
});
Meteor.methods({
sendEmail: function(to, from, subject, text) {
this.unblock();
Email.send({
to: to,
from: from,
subject: subject,
text: text
});
},
changeEmail: function(newEmail) {
// TODO Need to validate that new e-mail does not already exist
Meteor.users.update(Meteor.userId(), {
$set: {
emails: [{
address: newEmail,
verified: false
}]
}
});
}
});
The template:
<template name="user_profile_form">
<h2>Update Profile</h2>
<div id="profile-form">
{{#if success}}
<div class="alert alert-success">
<strong>Profile updated!</strong> Your profile has been successfully updated.
</div>
{{/if}}
{{#if error}}
<div class="alert alert-error">
<strong>Uh oh!</strong> Something went wrong and your profile was not updated. {{error_message}}.
</div>
{{/if}}
<p>
{{#each profile}}
<input type="text" id="profile_first_name" placeholder="First Name" value="{{first_name}}">
<input type="text" id="profile_last_name" placeholder="Last Name" value="{{last_name}}">
{{/each}}
<input type="email" id="profile_email" placeholder="Email" value="{{email_address}}">
</p>
</div>
<div id="submit-btn">
<input type="submit" id="submit_profile_btn" class="btn btn-primary">
</div>
</template>
The Meteor logout function does almost nothing. It certainly does not tear down Session state or the rest of your app’s context. Your code must reset these variables during your app’s logout event. A manual refresh of the page causes the client side JavaScript to reload wiping out existing Session data.