Code Monkey home page Code Monkey logo

vue-kindergarten's Introduction

vue-kindergarten

Build Status codecov NPM Version NPM Dowloads Dependency Status

Introduction

vue-kindergarten is a plugin for VueJS 2.0 that integrates kindergarten into your VueJS applications. It helps you to authorize your components, routes and the rest of your application in very modular way. If you are not familiar with kindergarten yet, I highly recommend you to check out the README first.

Installation

yarn add vue-kindergarten
# or
npm install vue-kindergarten

And you can register the plugin like this:

import Vue from 'vue';
import VueKindergarten from 'vue-kindergarten';

import App from './App';
import router from './router';
import store from './store';

Vue.use(VueKindergarten, {
  // Getter of your current user.
  // If you use vuex, then store will be passed
  child: (store) => {
    return store.state.user;
    // or
    // return decode(localStorage.getItem('jwt'));
    // or your very own logic..
  }
});

new Vue({
  el: '#app',
  router,
  store,
  template: '<App/>',
  components: { App },
});

Usage

First we need to define our perimeters. Perimeter is a module that represents some part of your applications or a business domain. It defines rules that has to be respected and can additionally expose some methods that you can use in your application.

import { createPerimeter } from 'vue-kindergarten';

createPerimeter({
  purpose: 'article',

  can: {
    read: () => true

    // only admin or moderator can update articles
    update(article) {
      return this.isAdmin() || (this.isCreator(article) && this.isModerator());
    },

    // if user can update articles then she can also destroy them
    destroy(article) {
      return this.isAllowed('update', article);
    }
  },

  secretNotes(article) {
    this.guard('update', article);

    return article.secretNotes;
  },

  isAdmin() {
    return this.child.role === 'admin';
  },

  isModerator() {
    return this.child.role === 'moderator';
  },

  isCreator(article) {
    return this.child.id === article.author.id;
  },

  expose: [
    'secretNotes'
  ]
});
<template>
  <main>
    <article v-for="article in articles.items" v-show="$isAllowed('read')">
      <h1>{{ article.title }}</h1>

      <router-link :to="`/article/${article.id}/edit`" v-show="$article.isAllowed('update', article)">
        Edit Article
      </router-link>

      <p>{{ article.content }}</p>

      <p>{{ $article.secretNotes() }}</p>
    </article>
  </main>
</template>

<script>
  import { mapState } from 'vuex';

  export default {
    computed: {
      ...mapState([
        'articles'
      ])
    },

    // add your perimeters
    perimeters: [
      articlesPerimeter
    ]
  }
</script>

In example above we have injected our articlesPerimeter into our component. Our component act as sandbox now. We can call all the methods that are available in the Sandbox directly on our component.

Protecting Routes

import Router from 'vue-router';
import { createSandbox } from 'vue-kindergarten';

import Home from '@/components/Home';
import Articles from '@/components/Articles';
import EditArticle from '@/components/EditArticle';
import RouteGoverness from '@/governesses/RouteGoverness';

import articlesPerimeter from '@/perimeters/articlesPerimeter';

import child from '@/child';

const router = new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },

    {
      path: '/articles',
      name: 'articles',
      component: Articles,
      meta: {
        perimeter: articlesPerimeter,
        perimeterAction: 'read',
      }
    },

    {
      path: '/articles/:id/edit',
      name: 'edit-article',
      component: EditArticle,
      meta: {
        perimeter: articlesPerimeter,
        perimeterAction: 'update',
      }
    }
  ]
});

router.beforeEach((to, from, next) => {
  to.matched.some((routeRecord) => {
    const perimeter = routeRecord.meta.perimeter;
    const Governess = routeRecord.meta.governess || RouteGoverness;
    const action = routeRecord.meta.perimeterAction || 'route';

    if (perimeter) {
      const sandbox = createSandbox(child(), {
        governess: new Governess(),

        perimeters: [
          perimeter,
        ],
      });

      return sandbox.guard(action, { to, from, next });
    }

    return next();
  });
});

export default router;

Route Governess

import { HeadGoverness } from 'vue-kindergarten';

export default class RouteGoverness extends HeadGoverness {
  guard(action, { next }) {
    // or your very own logic to redirect user
    // see. https://github.com/JiriChara/vue-kindergarten/issues/5 for inspiration
    return this.isAllowed(action) ? next() : next('/');
  }
}

Usage with Nuxt.js

Register plugin in plugins/vue-kindergarten.js:

import Vue from 'vue';
import VueKindergarten from 'vue-kindergarten';

import child from '~/child';

Vue.use(VueKindergarten, {
  child
});

Implement your child getter in child.js:

export default (store) => store && store.state.user;

Add reference to your plugin inside of nuxt.config.js:

module.exports = {
  plugins: ['~/plugins/vue-kindergarten']
};

You can now use vue-kindergarten in your Nuxt templates.

To protect our routes we need to create a Nuxt middleware in middleware/vue-kindergarten:

import { createSandbox } from 'vue-kindergarten';
import RouteGoverness from '~/governesses/RouteGoverness';

import child from '~/child';

export default (context) => {
  const { route, error, redirect, store, isServer } = context;
  route.matched.some((routeRecord) => {
    const options = routeRecord.components.default.options;
    const perimeter = options.routePerimeter;
    const Governess =  options.routeGoverness || RouteGoverness;
    const action = options.routePerimeterAction || 'route';

    if (perimeter) {
      const sandbox = createSandbox(child(store), {
        governess: new Governess(context),

        perimeters: [
          perimeter,
        ],
      });

      return sandbox.guard(action, { redirect });
    }
  });
}

and again register your middleware in you Nuxt config:

module.exports = {
  plugins: [
    '~/plugins/vue-kindergarten'
  ],

  router: {
    middleware: 'vue-kindergarten'
  },
};

This middleware will look in you component for routePerimeter and for routePerimeterAction and will check if the condition passes with the currently logged-in user.

import { createPerimeter } from 'vue-kindergarten';

import articlesPerimeter from '~/perimeters/articles';

// This component will only be accessible if user can update articles
export default {
  routePerimeter: articlesPerimeter,
  routePerimeterAction: 'update'
}

The implementation of your default routing governess might look like this:

import { HeadGoverness } from 'vue-kindergarten';

export default class RouteGoverness extends HeadGoverness {
  guard(action, { redirect }) {
    if (this.isNotAllowed(action)) {
      redirect('/');
    }
  }
}

You can also implement you own governess per each component to define a different redirect logic based on context:

import { createPerimeter } from 'vue-kindergarten';

import articlesPerimeter from '~/perimeters/articles';
import ArticlesRoutingGoverness from '~/governesses/ArticlesRoutingGoverness';

// This component will only be accessible if user can update articles
export default {
  routePerimeter: articlesPerimeter,
  routePerimeterAction: 'update',
  routeGoverness: ArticlesRoutingGoverness
}

More About Vue-Kindergarten

Role Based Authorization for your Vue.js and Nuxt.js Applications Using vue-kindergarten

License

The MIT License (MIT) - See file 'LICENSE' in this project

Copyright

Copyright © 2017 Jiří Chára. All Rights Reserved.

vue-kindergarten's People

Contributors

d0minicw0ng avatar jirichara avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-kindergarten's Issues

Infinite update loop

I'm using vue-kindergarten to manage user permissions in page components, local components and as a route guard. So when I try to login with first account, navigate between few pages, logout and then login with second account with other permissions, vuejs stucks with an error: "You may have an infinite update loop in a component render function.". That error arises in computed property, generated by plugin.

I am not able to show code, but I can say that I did everything according to tutorial.

The error can be possibly located in decorateComponents.js. Each call of sandboxGetter function creates new sandbox. So when new computed properties are setting up, each of them points to the new instance of the sandbox. This could be a source of the problem, but I am not sure about that.

I have changed decorateComponents.js code and it worked for me (sandboxGetter function is called only once).

      const sandboxGetter = () => createSandbox(sandboxChild(), {
        governess,
        perimeters
      });

      const sandbox = sandboxGetter();

      options.computed = options.computed || {};
      options.methods = options.methods || {};

      options.computed.$sandbox = () => sandbox;

      // Add helper methods from sandbox
      (useSandboxMethods || []).forEach((methodName) => {
        const $methodName = `$${methodName}`;
        const sandboxMethod = sandbox[methodName];
        options.computed[$methodName] = typeof sandboxMethod === 'function' ?
          () => sandboxMethod.bind(sandbox) : () => sandboxMethod;
      });

      // Add purpose
      if (exposePurpose) {
        sandbox.getPerimeters().forEach((perimeter) => {
          const purpose = perimeter.getPurpose();
          options.computed[`$${purpose}`] = () => sandbox[purpose];
        });
      }

Rule names collision

Hello @JiriChara, first of all thank you for your work on kindergarten and vue-kindergarten.

I'm working right now on a Vuejs project where I have multiple perimeters, some of which have the same rule name (e.g. read()).
Everything works fine except when I use 2 or more perimeters into the same component.
The typical example could be a top menu, that needs to know whether to render a link based on user role.

In such a case, it seems that the $user.isAllowed('read') and $account.isAllowed('read') interfere each other, so that both return the same thing (please, see the code below).

The only workaround I found is to differentiate the names as "readUser" and "readAccount" (instead of just "read").
But this seems to be redundant, considering we already have the "purpose" that could work as a scope.

To give you a context, here follows a small piece of code:

// topmenu.vue
<template>
    <v-toolbar class="blue darken-4" light>
        <v-toolbar-items class="hidden-sm-and-down">
            <v-toolbar-item v-show="$user.isAllowed('read')" :router="true" :href="{ name: 'users.index' }" ripple>Users</v-toolbar-item>
            <v-toolbar-item v-show="$account.isAllowed('read')" :router="true" :href="{ name: 'accounts.index' }" ripple>Accounts</v-toolbar-item>
        </v-toolbar-items>
    </v-toolbar>
</template>
<script>
    export default {
        computed: {
            ...mapGetters('auth', ['isLoggedIn', 'profile']),
        },
      ...
        perimeters: [
            accountsPerimeter,
            usersPerimeter
        ]
    }
</script>


// BasePerimeter.js
import { Perimeter } from 'vue-kindergarten'
import store from 'vuex'
import _ from 'lodash'

export default class BasePerimeter extends Perimeter {
    isSuperAdmin() {
        const res = this.hasRole('super_admin');
        return res;
    }

    hasRole(roleName) {
        if (!this.child) {
        return false;
    }
        const res = _.includes(this.child.role_names, roleName);
        return res;
    }
}


// Account.js
import BasePerimeter from './BasePerimeter';
export default new BasePerimeter({
    purpose: 'account',
    can: {
        read() {
            const _isSuperAdmin = this.isSuperAdmin();
            return _isSuperAdmin;
        }
    },
});


// User.js
import BasePerimeter from './BasePerimeter';
export default new BasePerimeter({
    purpose: 'user',
    can: {
        read() {
            const _isSuperAdmin = this.isSuperAdmin();
            return !_isSuperAdmin;
        }
    },
});

Another strange thing is that, looking at the console, $account and $user objects seem to be indefinitely nested each other, like this:

user_account

Is there something I misunderstood?

Thank you in advance,
Enzo

Different routing decisions based on purpose / context

Hi @JiriChara,

First, thanks for this lib, which is very interesting to use.

I am stuck in my authorization based application using your lib. In your excellent article, you say:

This code works, however as I mentioned earlier the governess is responsible for the default behavior when user is trying to access protected resource.

In order to handle a "not allowed" case correctly, I have implemented the guard() method of my RouteGoverness according to your example. However, I don't have just one default behavior but several different behaviors based on "why you were not allowed to do this".

In other words, I would like to be able to:

  • redirect to /login if the child is not authenticated
  • redirect to /home if the child is authenticated
  • redirect to /admin/home if the child is admin

and so on...

The logic is actually executed by the guard() method of my RouteGoverness and I am pretty sure there's a better way to do it. On top of that, it doesn't work as expected.

Here's a sample of what I tried to do:

import { HeadGoverness } from 'vue-kindergarten';

export default class RouteGoverness extends HeadGoverness {
  constructor({from, to, next}) {
    super();

    this.next = next;
    this.from = from;
    this.to = to;
  }

  guard(action) {
    if (super.isNotAllowed(action)) {
      // Redirection based on the "to" route the user wanted to reach
      console.warn('UNAUTHORIZED access to', this.to.name);

      switch (this.to.name) {
        case 'login':
          this.redirectTo('index');
          break;
        case 'index':
          this.redirectTo('login');
          break;
        default:
          this.redirectTo('unauthorized');
          break;
      }
    } else {
      this.next();
    }
  }

  redirectTo(routeName) {
    this.next({
      name: routeName
    });
  }
};

Is there a way to do it efficiently or am I wrong about the process ?
Thanks.

using routePerimeter in layouts nuxt.js

Hello @JiriChara , how I can use routePerimeter in nuxt.js layouts? For example, I have 'admin' layout and I want all my pages which inherit 'admin' layout will use routePerimeter that I defined in 'admin' layout or I should import my perimeter is each page and use on each page routePerimeter?

Is it possible to create generic perimeter

Is it possible to create generic perimeter like this

export default new BasePerimeter({
  govern: {
    'can': function (action) {
        return this.permissions.some(a => a.name === action);
    }
  },
});

Is there a way to create custom perimeter for custom roles

I have a nuxt application where a user can create custom roles. e.g CustomRoleA , CustomRoleB etc. Is there a way to handle this using vue-kindergarten. Is there a way to generate the perimeters dynamically?

import { Perimeter } from 'vue-kindergarten'
export default class BasePerimeter extends Perimeter {
  isSuperAdmin () {
    return this.child === 'SuperAdministrator'
  }

  isPartyAdmin () {
    return this.child === 'PartyAdministrator'
  }

  isTeamAdmin () {
    return this.child === 'TeamAdministrator'
  }

  isPartyUser () {
    return this.child === 'PartyUser'
  }
}


import BasePerimeter from './base'

    export default new BasePerimeter({
      purpose: 'user',

      can: {
        read: () => true,

        add () {
          return this.isSuperAdmin() || this.isPartyAdmin() || this.isTeamAdmin()
        },

        update () {
          return this.isSuperAdmin() || this.isPartyAdmin() || this.isTeamAdmin()
        },

        allowDelete () {
          return this.isSuperAdmin() || this.isPartyAdmin() || this.isTeamAdmin()
        },
        changePassword () {
          return this.isSuperAdmin() || this.isPartyAdmin() || this.isTeamAdmin()
        }
      }
    })

SandBox

I have a code

router.beforeEach((to, from, next) => {
  to.matched.some((page) => {
    const perimeter = page.meta.perimeter
    const Governess = page.meta.governess || RouteGoverness
    const action = page.meta.action || 'view'

    if (perimeter) {
      const sandbox = createSandbox(child(store), {
        governess: new Governess({
          from,
          to,
          next
        }),

        perimeters: [
          perimeter
        ]
      })
      console.log(sandbox)

      return sandbox.guard(action)
    }

    return next()
  })
})

export default router

this part console.log(sandbox) never works, so return sandbox.guard(action) never works too. No errors in console... Any idea why?

Disable Perimeter Injection

Hi, Thank you for this library. How can I disable automatic inject of perimeter to vue instance?

example:

import backyard from './perimeters/backyard.js'

  export default {
    computed: {
      ...mapState([
        'articles'
      ])
    },

    // add your perimeters
    perimeters: [
      backyard
    ]
  }

it is nice I can access this.$backyard.isAllowed('pick', 'plant') but I dont want to overwrite existing plugins that uses the same name ($backyard) and this.$sandbox.backyard.isAllowed('pick', 'plant') instead. How can is do it?

any upgrade instructions to 0.2.0 and 0.3.0?

I noticed there are new releases 0.2.0 and 0.3.0 on npmjs.com. But in this GitHub repo, these 2 new releases are not listed under Releases. I tried to upgrade to these new releases using yarn upgrade, and met strange errors when running in browser, like:

Cannot read property 'isAllowed' of undefined

I wrote my code when I was using 0.1.3. Currently I am using 0.1.4 without a problem. Maybe I need to make some changes to adapt to 0.3.0? Is there any instructions or release notes on how to upgrade to these new releases?

Thanks!
Zhu Ming

Asynchronous child

Hi there! I'm working on my first Vue project and while looking for a good way to do role based stuff I came across your magnificent framework and tutorial. I've been following along and everything works like a charm except one thing. I'm obtaining the user's role through a REST api. This means of course that the child cannot be set on initialization because the role is not yet obtained and stored in the Vuex store.

Any workaround for this? Any way to lazyload the child while still keeping it accessible everywhere?

Thanks in advance

Guarding routes tree/hierarchy

In your example, you use to.name to create a single perimeter.

router.beforeEach((to, from, next) => {
  const perimeter = perimeters[`${to.name}Perimeter`];
  if (perimeter) {
    const sandbox = createSandbox(child(store), {
      perimeters: [
        perimeter,
      ],
    });
    if (!sandbox.isAllowed('route')) {
      return next('/');
    }
  }
  return next();
});

But what if I have a routes tree where a parent route has a perimeter and a child route has another one? Or even multiple... I guess I need to look into the to.matched array... but can you give me an example on how to correctly deal with it? Thanks.

Nuxt.js example

Is it possible to add an example for Nuxt.js in repo?

Using the information from the Readme, I was able to configure Perimeter, but do not understand how to configure Sandbox and Governess for Nuxt.js app

this returns null inside can

Hi,

I created the following perimeter and "this" returns always null:

perimeter.js

export default createPerimeter({
   purpose: 'myPerimeter',
   can: {
        read: () => {
            return this && this.hasPermissions('read');
        }
    },
   hasPermissions(roles) {
        // check roles
    }
});

And imported it in my application like this:

   Vue.use(VueKindergarten, {
        child(store) {
            return () => store.state.currentUser;
        }
   });
   var app = new Vue({
        el: '#myDiv',
        store: store,
         ...
        perimeters: [myPerimeter] // this is coming from the perimeter.js
    });

What could be the reason behind this?

Passing variables to routePerimeterAction in nuxt

Hi,

I'm trying to follow your examples re guarding routes in nuxt. You add a perimeter with routePerimeterAction = 'update' in the example at https://github.com/JiriChara/vue-kindergarten#usage-with-nuxtjs

However, when this code then runs, using the example article perimiter further up the page, the "article" property of update(article) is always undefined. Is this expected? Is there a way to wire up values from the route into the perimeter action?

Thanks

Redirecting before child resolve

I'm trying to use Vue-Kindergarten in an application with Nuxt.js. But when trying to control which routes(screens) open I cannot use an url to directly open a screen, because when my Perimeter executes to validate the access of the current child, she is not fully resolved and return a undefined value, so my perimeter return false, then the RouteGoverness redirects to my home page, just like a not logged user would need.

Note: I get no problems when navigating through my system with normal links, just with a direct url to specific screens.

Is there something I am missing?

Thanks.
Great project.

govern vs can / cannot

Hi,

What is the difference between the properties on the perimeter class 'govern' and 'can'. You seem to use them interchangeably in different documentation.

Example 'can'

createPerimeter({
  purpose: 'article',

  can: {
    read: () => true

    // only admin or moderator can update articles
    update(article) {
      return this.isAdmin() || (this.isCreator(article) && this.isModerator());
    },

    // if user can update articles then she can also destroy them
    destroy(article) {
      return this.isAllowed('update', article);
    }
  },

Example 'govern'

export default new BasePerimeter({
  purpose: 'bye',
  govern: {    
    'can route': () => true,
    'can viewParagraph': function () {
      return this.isAdmin();
    },
  },
});

Thanks,

$isAllowed() method does not work in template for nuxt

Hi @JiriChara !
I use nuxt. I installed and connected the plugin.
I have implemented role based access for routing but I am facing issues while implementing show/hide menu items depending on the logged in user

This code does not work for me:

v-show="$isAllowed('read')"
v-show="$article.isAllowed('update', article)"

What can I do to make it work?
Thanks

`$isAllowed('action', object)` it performs twice in `created`, `mounted` hook.

Hi

I used $isAllowed with v-show.
There is a error in console because whenever created, mounted hook, it performs twice.
So, before post object receive value, post is undefined.

What should I do ?

*.vue

<template>
    <button v-show="$notice.isAllowed('update', post)" @click.prevent="$router.push({ name: `post-update-${$route.meta.type}` ,params:{'postNo':$route.params.postNo}})">update<button>
</template>
<script>
export default {
  name: 'post-detail',
  data () {
    return {
      post: {}
    }
  },
  perimeters: [
    noticePerimeter
  ]
  },
  created () {
    ajax('GET', `/posts/${this.$route.params.postNo}`, null).then(_data => {
        this.post = _data
      }).catch(_err => {
        this.$router.push({ name: `post-list-${this.$route.meta.type}` })
      })
  }
}
</script>

Perimeter

import BasePerimeter from './base-perimeter'

export default new BasePerimeter({
  purpose: 'notice',
  can: {
    read () { return this.isLogin() },
    create () { return this.isAllowed('read') },
    update (post) {
      return this.isAdmin() || this.isCreator(post)
    },
    destroy (post) { return this.isAllowed('update', post) }
  }
})

error

image

child reactivity

I am still quite new to Vue.js. Maybe I made a mistake somewhere with reactivity of Vuex state.

I am using Vue.js 2 with Vuex, vue-router, etc. I dispatch login action to authenticate a user. My problem is: after logging in, the authroization is not reflected.

To debug the problem, I added the following condole.debug:

// in app.js
Vue.use(VueKindergarten, {
    child: (store) => {
        const child = store.state.auth.user;
        console.debug('VueKindergarten: child = ', child);
        return child;
    },
});

and

// in perimeters/BasePerimeter.js
export default class BasePerimeter extends Perimeter {
    isAdmin() {
        console.debug('BasePerimeter.isAdmin():');
        console.debug('  this.child is ', (this.child && this.child.full_name));
        console.debug('  this.child = ', this.child);
        return this.child && this.child.role &&
            this.child.role.name === 'Administrator';
    }
...

What I see is that BasePerimeter.isAdmin() is called before child is set to the logged in user. The problem is after child is set to the logged in user, BasePerimeter.isAdmin() is not called again and authorization is not refreshed.

Is it possible that the problem is related with any potential issue with vue-kindergarten's child reactivity, or some mistakes in my Vuex store implementation? If needed, I can show the relevant part of my Vuex store modules. It's a bit lengthy.

Thanks!
Zhu Ming

Guarding Routes

Hi, I managed to do the tutorial https://codeburst.io/role-based-authorization-for-your-vue-js-and-nuxt-js-applications-using-vue-kindergarten-fd483e013ec5

But how do I use this format as stated in this repository?

router.beforeEach((to, from, next) => {
  to.matched.some((routeRecord) => {
    const perimeter = routeRecord.meta.perimeter
    const Governess = routeRecord.meta.governess || RouteGoverness
    const action = routeRecord.meta.perimeterAction || 'route'

    if (perimeter) {
      const sandbox = createSandbox(child(), {
        governess: new Governess(),
        perimeters: [
          perimeter,
        ],

      })

      return sandbox.guard(action, { to, from, next })
    }

    return next()
  })
})

Can you help me? I attached some parts of my config files

attachment.zip

Importing Perimeters Error

Not sure if I should post this here.
This is about the tutorial in the link https://codeburst.io/role-based-authorization-for-your-vue-js-and-nuxt-js-applications-using-vue-kindergarten-fd483e013ec5

If I added this code, import * as perimeters from '../perimeters';

Then an error is thrown.

probably es6 errors, or duplication of imports. I just don't know.

[HMR] bundle has 1 errors
client.js?7955:176 ./src/router/index.js
Module not found: Error: Can't resolve '../perimeters' in 'E:\kay\vue\vuecomplete\src\router'
@ ./src/router/index.js 15:0-44
@ ./src/main.js
@ multi ./build/dev-client ./src/main.js

I made a stackoverflow post https://stackoverflow.com/questions/47666323/why-cant-i-import-these-javascript-files?noredirect=1#comment82292155_47666323 about this

Error in nuxt example?

Example says:

const options = isServer ? routeRecord.components.default : routeRecord.components.default.options;

Im not sure what this check is supposed to do, but with it server side checking dont work. It just get a wrong variable. So the first load of protected routes will always work even if its not allowed.
If i change it just to

const options = routeRecord.components.default.options

All works as expected

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.