vue-meteor icon indicating copy to clipboard operation
vue-meteor copied to clipboard

Vue-router and alanning:roles

Open suezzo opened this issue 8 years ago • 14 comments

Hello, I am working on admin panel for my app. I use alanning:roles package. I've created authentication for user, but I have problem with adding authorization. My code looked like below:

router.beforeEach((transition) => {
  if(!Meteor.userId()) {
    router.go('/login')
  }
  transition.next();
});

This was working perfect. I tried to add authorization based on roles:

router.beforeEach((transition) => {
  if(!Meteor.userId() || Roles.userIsInRole(Meteor.userId(), 'admin')) {
    router.go('/login')
  }
  transition.next();
});

Roles.userIsInRole(Meteor.userId(), 'admin') always returns false. I have no idea how possible solution could look. Any help will be much appreciated.

Thanks in advance

suezzo avatar Jan 06 '17 14:01 suezzo

Could try this code?

Tracker.autorun(() => {
  console.log('role.admin', Roles.userIsInRole(Meteor.userId(), 'admin'))
})

Akryum avatar Jan 06 '17 15:01 Akryum

I tried your code, and at first it shows false in console, and after 1-2 secs it shows true. I tried to wrap my code in Tracker.autorun, but when condition is processing returned value is false, so now it redirects to /login everytime.

suezzo avatar Jan 06 '17 15:01 suezzo

I am about to use vue instead of react for next projects and found this ticket.
Is it possible to tell the router to wait?

In my last project I had a simmilar issue using kadira:flow-router and react.
It happens because the roles package relies on a roles-subscription that isn't ready when the router does its work. I solved it for flow-router with this snippet on beginning of the client startup scripts:

FlowRouter.wait();
Tracker.autorun(() => {
  // Wait for the roles subscrition to be ready before rendering the UI
  if (Roles.subscription.ready() && !FlowRouter._initialized){
    return FlowRouter.initialize();
  }
});

Is it possible to do something simmilar with vue-router, too?

qroac avatar Feb 17 '17 16:02 qroac

You can use asynchronous navigation guards.

Akryum avatar Feb 17 '17 19:02 Akryum

@suezzo did the suggestion to use navigation guards solve the issue you were having with alanning:roles and Vue in Meteor? I'm considering using the same setup and am curious to know. Thanks in advance.

CharlesMcKeever avatar May 05 '17 13:05 CharlesMcKeever

asynchonous navigation guards, i don't know what they are. using guard with meteor-subs-cache that just lets you hook for all subs doesn't appear to mean that cursor fetch resolves before then. Setting something that checks if stuff has resolved would be helpful, or plugging vue into meteor tracker better so that it knows to rerun.

janat08 avatar May 27 '17 11:05 janat08

I have the same problem. @Akryum, could example for this (asynchronous navigation guards). I tried

router.beforeResolve((to, from, next) => {
            // Check user
            if (!Meteor.loggingIn() && !Meteor.userId()) {
                next({path: '/login'});
            } else {
                // Check role
                Tracker.autorun(() => {
                    let loggedInUser = Meteor.userId();
                    let role = Roles.userIsInRole(loggedInUser, ['posts.insert'], 'Entry');

                    if (role) {
                        next();
                    }else{
                       alert('no role'); 
                   }
                });
            }
    });

Please advice...

thearabbit avatar Jun 01 '17 05:06 thearabbit

It always alert no role when refresh page.

thearabbit avatar Jun 01 '17 05:06 thearabbit

It should alert since else condition will just run on first load. What's not working is that it will fire next() letting user load the templates even if role is in fact undefined.

janat08 avatar Jun 01 '17 05:06 janat08

Thanks for your reply. could example how to solve (I don't understand)?

thearabbit avatar Jun 01 '17 06:06 thearabbit

I have no idea. In your case try to use subscription ready handle from roles package. I myself can't tell why if subscription fires ready handle the data isn't available in vue.

janat08 avatar Jun 01 '17 06:06 janat08

do you have any solution to manage Role in Vue? for example we check it outside of router...

thearabbit avatar Jun 01 '17 06:06 thearabbit

The idea is not render anything until you got your data. Might be issue with autopublish or something.

janat08 avatar Jun 01 '17 08:06 janat08

Now I tries

// Method
export const userIsInRole = new ValidatedMethod({
    name: 'userIsInRole',
    mixins: [CallPromiseMixin],
    validate: new SimpleSchema({
        role: {type: String},
    }).validator(),
    run({role}) {
        if (!this.isSimulation) {
            return Roles.userIsInRole(Meteor.userId(), role);
        }
    }
});

---------
// router
router.beforeResolve((to, from, next) => {
            // Check user
            if (!Meteor.loggingIn() && !Meteor.userId()) {
                next({path: '/login'});
            } else {
                userIsInRole.callPromise({role: to.name}).then((result) => {
                    if (result) {
                        next();
                    } else {
                        next(false);
                        alert('no roles');
                    }
                }).catch((err) => {
                    console.log(err.reason);
                });
            }
    });

It work fine, please advice...

thearabbit avatar Jun 01 '17 12:06 thearabbit