Redirect user on login - meteor

I've been trying to figure this out for hours but everything I try fails. I'm trying login a user and on success get route the user to the correct url based on the user's role. In the example below, I login successfully, and the user is successfully identified however when I try to redirect or push.history it doesn't let me. There are no errors, it just stays on the login url.
I'm using:
React router 4, Meteorjs
handleSubmit(event) {
event.preventDefault();
Meteor.loginWithPassword(email, password, (error, result) => {
if (error) {
this.setState({ loginError: 'Incorrect username or password.' });
} else {
if (!!Roles.userIsInRole(Meteor.userId(), 'isAdmin')) {
<Redirect to="/admin/dashboard" push />
}
}
});
}

A react component is something that is rendered, it's not just a function that you can call from anywhere.
Use history.push('/admin/dashboard")
If the router is being passed into your component as a prop you might also find yourself doing
this.props.history.push('/admin/dashboard")

Related

Correctly display modal screen in Angular 7

I have an ASP.Net Core 2.0 project with Angular 7 material.
I've correctly implemented the forgot password function within Angular which when invoked, would prompt a user to enter in their email address. This would send them a password reset email link. Once that link is clicked, they are redirected to Angular's page which is where my problem lye. What I'm hoping to achieve is redirect the user to a modal screen instead of a page.
.NET
[HttpGet("reset")]
public IActionResult Reset(string email, string token)
{
if (token == null)
{
return BadRequest();
}
if (token != null)
{
//sends them to angular application with email and token
return Redirect("http://localhost:4200/resetPassword" + $"?email={email}&token={token}");
}
else
{
return BadRequest();
}
}
This is what the link from the server side would look like =>
localhost:4200/reset?emailaddress=samsmith#gmail.com?token=fdsajfdfadsafdasfdsafdsafdasfdsaf
What I've tried so far is to specify the outlet as modal within the route, which didn't work.
{ path: 'reset', outlet: 'modal', component: ResetComponent }
To summarize:
User clicks on Forget password => then request goes to server side, generating a token => token and user email is sent back to Angular modal screen => user enters password and confirms password.
How should I go about it?

User redirect and authentication with middleware of Nuxt

I'm trying to redirect a user to a login page if the user is not logged in when he tries to access certain pages with the following code.
// middlware/authenticated.js
import firebase from 'firebase'
export default function ({ store, redirect }) {
let user = firebase.auth().currentUser
store.state.user = user //this doesn't work
if (!user) {
console.log('redirect')
return redirect('/login')
}
}
However, the problem is with this code when I refresh a page I'm redirected to login page although without using the middleware, I can stay in the same page with logged in. For some reasons, which I don't know why, firebase can't work in middleware.
How should I modify this middleware or implement this function?
Thanks.
//middleware/authenticated.js
export default function ({
store,
redirect
}) {
if (!store.getters['index/isAuthenticated']) {
return redirect('/login')
}
}
//post.vue
async mounted () {
if (process.browser) {
let user;
if (!this.user) user = await auth(); // this auth is a plugin
await Promise.all([
this.user ? Promise.resolve() : this.$store.dispatch("setUser", { user: user || null })
]);
this.isLoaded = true;
}
},
//plugins/auth.js
import firebase from '~/plugins/firebase'
function auth () {
return new Promise((resolve, reject) => {
firebase.auth().onAuthStateChanged((user) => {
resolve(user || false)
})
})
}
export default auth
By default Firebase persists the users logged in status on successful authentication. This example uses the session, to store the user uid and cookies to store the users token and used in situations where the sessions has ended (example when browser is closed) and then a new session started but where the user is still authenticated according to Firebase. In cases like these the user will not need to sign in to view protected resources.
Your basic Middleware to protect it should look like this (if you have a Store Module called User)
export default function ({ store, redirect }) {
if (!store.getters['modules/user/isAuthenticated']) {
return redirect('/auth/signin')
}
}
In your main Store you use the ServerInit Function to get the User if there is one saved in the Cookies and load it into your User Store Module which will be used for verification in the Middleware.
Your User Store Module should look like this, and keep in mind that you remove the Cookie when you Log the User out so that he is fully logged out.
I used the things i mentioned above as the beginning of my Authentication and modified it a bit, which you can also do. Most of the credit goes to davidroyer who has set up this nice Github Repo which includes all needed files as a good example on how to accomplish your goal.

meteor: show alert on created user

I want to show to the user a message like: "I have sent a email to activate your account".
I cannot because when the user has been created I have not found a hook for this.
Do you know some way to do this?
I currently show a message permanently, but I don't want this way. I just want to show once when user is singed up.
Well there are 2 options here, if you are creating the user on the client side, just use
Accounts.createUser({email: email, password: password}, function(err) {
if(!err){
alert(""I have sent a email to activate your account")
}
});
Or if you are creating the user from a method, it should look like this.
//Server.js
Meter.method({
createUser:function(username,email,password){
//create user logic.
}
})
And on the client it should look like this.
Meteor.call('createUser',username,email,password,function(err,result){
if(!err){
alert(""I have sent a email to activate your account")
}
});
On both cases we are using an extra parameter, named callback this function, accept 2 other parameters wich are err,result, so if there is not error when the accounts its created, the alert should be triggered
You should be able to add the alert in the callback from createUser() on the client. Assuming you have something like a form that you submit to create the user, then you would do ...
Template.myTemplate.events({
'submit #new-user-form': function(event) {
// These next few lines will depend on what your template looks like and what data you require on login
// Here I've assumed just username and pw in appropriately-named inputs on your page
var email = $('#email-input').val();
var password = $('#password-input').val();
event.preventDefault();
Accounts.createUser({email: email, password: password}, function(error) {
if (error) { alert("There was an error!"); }
else { alert("I have sent you an email to verify your account"); }
});
}
});
If you want to accomplish this behavior with accounts-ui installed, the documentation doesn't show anything you can hook into. However, you can do it manually like so:
Template.myTemplate.events({
'click .login-form-create-account #login-buttons-password': function() {
alert("I sent you an email to verify your account");
}
});
Unfortunately, that will still fire even if the user was not successfully created.

resetPassword issues in meteor

I sent enrollment email to the user and when he enters password and other details I'm trying to reset the password but it is throwing error
uncaught error extpected to find a document to change
As you can see in the mage
I've subscribed to the user record
my code
this.route('enroll', {
path: '/enroll-account/:token',
template: 'enroll_page',
onBeforeAction: function() {
Meteor.logout();
Session.set('_resetPasswordToken', this.params.token);
s = this.subscribe('enrolledUser', this.params.token).wait();
}
}),
After I'm displaying form and on the submit event
onSubmit: function(creds) {
var options = {
_id: Meteor.users.findOne()._id,
name: creds.name
}
var token=Session.get('_resetPasswordToken');
Meteor.call('updateUser', options, function(error, result) {
if(!error) {
Accounts.resetPassword(token, creds.password, function(error) {
if (error) {
toastr.error("Sorry we could not update your password. Please try again.");
return false;
}
else{
toastr.error("Logged In");
Router.go('/');
}
});
} else {
toastr.error("Sorry we could not update your password. Please try again.");
return false;
}
});
this.resetForm();
this.done();
return false;
}
Everything is working fine but resetpassword callback is not triggering and the above error is displaying in console.
my token is get deleted from the user record and I'm able to login using login form but
From the docs
Reset the password for a user using a token received in email. Logs the user in afterwards.
I'm not able to automatically login after resetting the password,above error is throwing
What am I missing here?
this.subscribe('enrolledUser', this.params.token).wait();
here you're subscribing using resetPassword token
when you call Accounts.resetPassword method the method will reset the password and delete the token from user record.
So your subscription is lost and there are no records available in client side to modify
(That is waht the error Expected to find a document to change)
Instead on first subscription save the user Id and subscribe to the user record using Id
so the subscription will not be lost
path: '/enroll-account/:token',
template: 'enroll_page',
onBeforeAction: function() {
Meteor.logout();
Session.set('_resetPasswordToken', this.params.token);
s = this.subscribe('enrolledUser', this.params.token).wait();
},
onAfterAction:function(){
if(this.ready()){
var userid=Meteor.users.findOne()._id;
Meteor.subscribe("userRecord",userid);
}
}
Alternatively, you could do something like as follows in your publication. This worked for me (but mine was a slightly more involved query than this).
Meteor.publish('enrolledUser', function (token) {
check(token, String);
return Meteor.users.find({
$or: [{
_id: this.userId
}, {
'services.password.reset.token': token
}]
});
});
From the docs, it says
Reset the password for a user using a token received in email. Logs the user in afterwards.
So basically, you have to subscribe to the logged in user after the fact as well. A little silly, but whatever.

Logging in via Firebase Email/Password

I am trying to build a basic web application w/ user authentication via email/password registration using Firebase.
My setup right now includes a main.js file that consists of the following:
var dbRef = new Firebase('https://url.firebaseIO.com');
var authClient = new FirebaseAuthClient(dbRef, function(error, user) {
if (error) {
// an error occurred while attempting login
console.log(error);
} else if (user) {
// user authenticated with Firebase
console.log('User ID: ' + user.id + ', Provider: ' + user.provider);
} else {
// user is logged out
console.log('logged out!');
}
});
function next(){
window.location = 'index.html';
}
function test(){
authClient.login('password', {
email: email,
password: password,
rememberMe: true
},next());
// window.location = 'index.html';
}
I obtain email/password values from a form and login. That works. But as soon as I include a callback function to then redirect them to a new authenticated page, it no longer works. In fact, most of the time I get an "UNKOWN ERROR" response.
When I get to the next page, I am no longer logged in. If I remove the next() function and stay on the same page, it works - even if I then trigger the next function from the console. Is there a different way you are supposed to proceed to another page?
I'm pretty sure there is some sort of communication issue (possibly the login does not get a return before the page is switched?) because if I add a 1s timeout before the next function, it then works. But surely this is not best practice?
Thanks!
Per https://www.firebase.com/docs/security/simple-login-email-password.html, the authClient.login() method does not actually accept a callback, so the problem you're seeing is likely the result of navigating away from the current page before the callback is returned, as you suggested.
I would recommend doing the redirect in the callback you're passing during the instantiation of the auth client. (new FirebaseAuthClient(ref, callback)) and redirect if you detect a logged-in user. This callback will be invoked once upon instantiation with the current authentication state of the user, and then again any time the user's authentication state changes (such as on login or logout).

Resources