7

I am trying to implement alanning Meteor-roles with react-router in my Meteor application. Everything is working fine except the fact I can't manage properly to restrict a route using alanning roles or Meteor.user()

I tried with meteor-roles:

I am trying to use the onEnter={requireVerified} on my route. This is the code:

const requireVerified = (nextState, replace) => {
    if (!Roles.userIsInRole(Meteor.userId(), ['verified'],'user_default')) {
        replace({
            pathname: '/account/verify',
            state: { nextPathname: nextState.location.pathname },
        });
    }
};

I tried with Meteor.user():

const requireVerified = (nextState, replace) => {
  if (!Meteor.user().isverified == true) {
    replace({
      pathname: '/account/verify',
      state: { nextPathname: nextState.location.pathname },
    });
  }
};

So this is working when I am clicking on a route link, but when i manually refresh (F5), it does not work. After digging into it, i have found that Meteor.user() is not ready when i manually refresh the page.

I know Meteor.userid() or Meteor.logginIn() are working, but i wanted to verify not just that they are logged but if they are "verified" or have a role.

I also tried to check inside the component with react, with componentDidMount() or componentWillMount(), in both cases it's the same, the manual fresh does not load Meteor.user() before the compenent is mounted.

So what is the best way to restrict components/routes with meteor/alaning roles + react router ? (I am using react-komposer inside TheMeteorChef's base)

Thank you.

NOaMTL
  • 193
  • 1
  • 4
  • 13
  • id this 'verifier' requirement any way related to email verification? – Ankit Aug 26 '16 at 15:13
  • no, I am verifying accounts with external api call (this app is working with a third party provider). In this example I am not showing exactly how is constructed the user object, but once the verification is completed on the external webiste i use a callback to update user object in meteor, adding a isverified = true in the database (no link with email verification provided by meteor) – NOaMTL Aug 26 '16 at 15:37
  • @NOaMTL did you find a solution? I'm running into the same problem... – cocacrave Oct 04 '16 at 07:12

1 Answers1

1

Note I have not tried it yet, it's only a suggestion

One thing you could try is to use componentWillReceiveProps alongside createContainer from 'react-meteor-data' like that:

import React, { Component, PropTypes } from 'react';
import { Meteor } from 'meteor/meteor';
import { createContainer } from 'meteor/react-meteor-data';
import { Roles } from 'meteor/alanning:roles';

class MyComponent extends Component {
  componentWillReceiveProps(nextProps) {
    const { user } = nextProps;
    if (user && !Roles.userIsInRole(user._id, ['verified'], 'user_default')) {
      browserHistory.push('/account/verify');
    }
    // If Meteor.user() is not ready, this will be skipped.
  }
}

MyComponent.propTypes = {
  user: PropTypes.object,
};

export default createContainer(() => {
  const user = Meteor.user() || null;
  return { user };
}, MyComponent);

To explain the flow, when the page is loaded, as you said Meteor.user() is not defined so you can't check the permissions. However, when Meteor.user() gets defined, this will trigger a refresh of the template, and the new props will be passed to componentWillReceiveProps. At this moment you can check if user has been defined and redirect if needed.

To be really sure not to miss anything, I would actually put the verification in the constructor() as well (defining a function that takes the props as arguments and calling it in both constructor() and componentWillReceiveProps()).

Max G.
  • 266
  • 1
  • 6