New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Middleware arguments #1687

Closed
mtnptrsn opened this Issue Sep 19, 2017 · 38 comments

Comments

Projects
None yet
@mtnptrsn

mtnptrsn commented Sep 19, 2017

SImple question: Is it possible to pass arguments to a middleware?

For ex:

middleware: [
    middlewareName({myProp: 'myValue'})
]
This feature request is available on Nuxt.js community (#c1511)
@christophwolff

This comment has been minimized.

Show comment
Hide comment
@christophwolff

christophwolff Sep 19, 2017

Maybe you can pass a value to the state and read it in the middleware. not sure.

christophwolff commented Sep 19, 2017

Maybe you can pass a value to the state and read it in the middleware. not sure.

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 19, 2017

@christophwolff Gotcha. This feature would be really good to have, though!

mtnptrsn commented Sep 19, 2017

@christophwolff Gotcha. This feature would be really good to have, though!

@vuchl

This comment has been minimized.

Show comment
Hide comment
@vuchl

vuchl Sep 19, 2017

since the middleware receives the context you can use everything that is in it. So for example context.env variables or the context.store. So if you want to set something globally put the value in the env varables in your nuxt.config.js and check them in the middleware. If you need to modify the value at runtime you should use the store since you can use nuxtServerInit to put data before rendering inside it.

vuchl commented Sep 19, 2017

since the middleware receives the context you can use everything that is in it. So for example context.env variables or the context.store. So if you want to set something globally put the value in the env varables in your nuxt.config.js and check them in the middleware. If you need to modify the value at runtime you should use the store since you can use nuxtServerInit to put data before rendering inside it.

@mtnptrsn mtnptrsn closed this Sep 19, 2017

@mtnptrsn mtnptrsn reopened this Sep 19, 2017

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 19, 2017

@vuchl Not really what I want tho. Different pages need different arguments. My example:

export default ({ req, error, isServer, isClient, redirect, store }) => {
    const serverAuthed = (
        isServer &&
        req.session &&
        req.session.userIsAuthenticated &&
        req.session.user.general.authority > 1
    );

    const clientAuthed = (
        isClient &&
        store.getters['user/user'] &&
        store.getters['user/user'].isAuthenticated &&
        store.getters['user/user'].details.general.authority > 1
    );

    if (!serverAuthed && !clientAuthed) {
        return error({
            statusCode: 401,
            message: 'Du måste vara admin för att besöka denna sidan.'
        });
    }
}

(ignore the error message, it's in swedish)

I have different authority roles, and different pages needs a different 'authority' levels. Currently I have 3 files which looks exactly the same but with different authority requirment. That's why I want to pass an argument instead of having 3 files.

mtnptrsn commented Sep 19, 2017

@vuchl Not really what I want tho. Different pages need different arguments. My example:

export default ({ req, error, isServer, isClient, redirect, store }) => {
    const serverAuthed = (
        isServer &&
        req.session &&
        req.session.userIsAuthenticated &&
        req.session.user.general.authority > 1
    );

    const clientAuthed = (
        isClient &&
        store.getters['user/user'] &&
        store.getters['user/user'].isAuthenticated &&
        store.getters['user/user'].details.general.authority > 1
    );

    if (!serverAuthed && !clientAuthed) {
        return error({
            statusCode: 401,
            message: 'Du måste vara admin för att besöka denna sidan.'
        });
    }
}

(ignore the error message, it's in swedish)

I have different authority roles, and different pages needs a different 'authority' levels. Currently I have 3 files which looks exactly the same but with different authority requirment. That's why I want to pass an argument instead of having 3 files.

@vuchl

This comment has been minimized.

Show comment
Hide comment
@vuchl

vuchl Sep 19, 2017

Ah so you look for authorization via middleware. I think you therefore need the roles of the logged in user set upon authentication and then read upon page visits, am I getting this right?

Also when the pages loads the first time it will throw an error since the isclient is false.

vuchl commented Sep 19, 2017

Ah so you look for authorization via middleware. I think you therefore need the roles of the logged in user set upon authentication and then read upon page visits, am I getting this right?

Also when the pages loads the first time it will throw an error since the isclient is false.

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 19, 2017

@vuchl The user is set upon authentication, the problem is that I can't pass arguments to the middleware. Some pages needs the user to be authority 2, some pages needs the user to have authority 1.

Id like to do this:

middleware: auth_middleware({ authority: 0})
middleware: auth_middleware({ authority: 1})
middleware: auth_middleware({ authority: 2})

Instead of having different files for every authority level, doing like this:

middleware: 'auth_verified'
middleware: 'auth_admin'
middleware: 'auth_guest'

Hope this makes it more clear.

mtnptrsn commented Sep 19, 2017

@vuchl The user is set upon authentication, the problem is that I can't pass arguments to the middleware. Some pages needs the user to be authority 2, some pages needs the user to have authority 1.

Id like to do this:

middleware: auth_middleware({ authority: 0})
middleware: auth_middleware({ authority: 1})
middleware: auth_middleware({ authority: 2})

Instead of having different files for every authority level, doing like this:

middleware: 'auth_verified'
middleware: 'auth_admin'
middleware: 'auth_guest'

Hope this makes it more clear.

@vuchl

This comment has been minimized.

Show comment
Hide comment
@vuchl

vuchl Sep 19, 2017

Hmm I guess you then can unly use the store for that. But that couples it pretty tightly. So you save the user to the store upon authentication. Also save the authority level. then then in the middleware check the store.

vuchl commented Sep 19, 2017

Hmm I guess you then can unly use the store for that. But that couples it pretty tightly. So you save the user to the store upon authentication. Also save the authority level. then then in the middleware check the store.

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 19, 2017

Yeah but the pages requires different authority levels. I cant check the store for that.

mtnptrsn commented Sep 19, 2017

Yeah but the pages requires different authority levels. I cant check the store for that.

@vuchl

This comment has been minimized.

Show comment
Hide comment
@vuchl

vuchl Sep 19, 2017

So you need to set a property on the page then then and check that against the user in the middleware.

vuchl commented Sep 19, 2017

So you need to set a property on the page then then and check that against the user in the middleware.

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 19, 2017

Yes. That would solve it.

mtnptrsn commented Sep 19, 2017

Yes. That would solve it.

@vuchl

This comment has been minimized.

Show comment
Hide comment
@vuchl

vuchl Sep 19, 2017

the thing is, the middleware is called before the page, right? so you have no knowledge of the properties of the page when the middleware is ran 🙈

vuchl commented Sep 19, 2017

the thing is, the middleware is called before the page, right? so you have no knowledge of the properties of the page when the middleware is ran 🙈

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 19, 2017

Yup. Quite a tough one!

mtnptrsn commented Sep 19, 2017

Yup. Quite a tough one!

@christophwolff

This comment has been minimized.

Show comment
Hide comment
@christophwolff

christophwolff Sep 19, 2017

maybe register a route.afterEach?

christophwolff commented Sep 19, 2017

maybe register a route.afterEach?

@vuchl

This comment has been minimized.

Show comment
Hide comment
@vuchl

vuchl Sep 19, 2017

As another workaround you could go with the validate() method

vuchl commented Sep 19, 2017

As another workaround you could go with the validate() method

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 19, 2017

@vuchl True. I'll try that.

mtnptrsn commented Sep 19, 2017

@vuchl True. I'll try that.

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 19, 2017

@vuchl The problem with validate is that I can only show a 404 error page. I'd like to show a custo error page with error code 401. Good solution though!

mtnptrsn commented Sep 19, 2017

@vuchl The problem with validate is that I can only show a 404 error page. I'd like to show a custo error page with error code 401. Good solution though!

@vuchl

This comment has been minimized.

Show comment
Hide comment
@vuchl

vuchl Sep 20, 2017

Oh boy. This is not a "simple question" anymore 😄

Maybe you can get the context in the validate funtion somehow and from there the redirect funtion to redirect to your custom error page.

vuchl commented Sep 20, 2017

Oh boy. This is not a "simple question" anymore 😄

Maybe you can get the context in the validate funtion somehow and from there the redirect funtion to redirect to your custom error page.

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 20, 2017

@vuchl Haha, still a simple question, just a complicated answer ;) Hmm, yeah then I'd just rather have multiple files I think. I guess I'll have to live with that. But I'd love Nuxt to have arguments for middlewares.

mtnptrsn commented Sep 20, 2017

@vuchl Haha, still a simple question, just a complicated answer ;) Hmm, yeah then I'd just rather have multiple files I think. I guess I'll have to live with that. But I'd love Nuxt to have arguments for middlewares.

@vuchl

This comment has been minimized.

Show comment
Hide comment
@vuchl

vuchl Sep 20, 2017

Yes for now that seems to be the only valuable solution. I thought of extending the validate method to receive also the redirect method but that seems to be a bit out of the scope of validate(). I think we should introduce something like an authorize() method on a page. But this should not be in v1 since it would change the API.

what are your thoughts here @Atinux and @alexchopin?

vuchl commented Sep 20, 2017

Yes for now that seems to be the only valuable solution. I thought of extending the validate method to receive also the redirect method but that seems to be a bit out of the scope of validate(). I think we should introduce something like an authorize() method on a page. But this should not be in v1 since it would change the API.

what are your thoughts here @Atinux and @alexchopin?

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 20, 2017

@vuchl That's actually not a bad idea!

mtnptrsn commented Sep 20, 2017

@vuchl That's actually not a bad idea!

@alexchopin

This comment has been minimized.

Show comment
Hide comment
@alexchopin

alexchopin Sep 25, 2017

Member

Hi,
We have thought about middleware arguments once we have created this module.
As parameters are static, the first idea was to use it like that:

middleware: 'role:editor'

However, we thought that it's maybe more readable to do this:

middleware: ['isEditor', 'isAdmin']

instead of this:

middleware: 'role:editor,admin'
Member

alexchopin commented Sep 25, 2017

Hi,
We have thought about middleware arguments once we have created this module.
As parameters are static, the first idea was to use it like that:

middleware: 'role:editor'

However, we thought that it's maybe more readable to do this:

middleware: ['isEditor', 'isAdmin']

instead of this:

middleware: 'role:editor,admin'
@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 25, 2017

@alexchopin Do you mean it's more legible when it's multiple files vs being able to send arguments?

mtnptrsn commented Sep 25, 2017

@alexchopin Do you mean it's more legible when it's multiple files vs being able to send arguments?

@Atinux

This comment has been minimized.

Show comment
Hide comment
@Atinux

Atinux Sep 25, 2017

Member

@mtnptrsn actually we have even a better solution :)

With vue-router, they recommend to use meta for handling this kind of strategy, I am currently implement this meta property directly into the pages components.

Example:

<template>
  <h1>Only an admin can see this page</h1>
</template>

<script>
export default {
  middleware: 'auth',
  meta: {
    auth: { authority: 2 }
  }
}
</script>

Then in your middleware/auth.js:

export default ({ store, route, redirect }) => {
  // Check if user is connected first
  if (!store.getters['user/user'].isAuthenticated) return redirect('/login')

  // Get authorizations for matched routes (with children routes too)
  const authorizationLevels = route.meta.map((meta) => {
    if (meta.auth && typeof meta.auth.authority !== 'undefined')
      return meta.auth.authority
    return 0
  })
  // Get highest authorization level
  const highestAuthority = Math.max.apply(null, authorizationLevels)

  if (store.getters['user/user'].details.general.authority < highestAuthority) {
    return error({
      statusCode: 401,
      message: 'Du måste vara admin för att besöka denna sidan.'
    })
  }
}
Member

Atinux commented Sep 25, 2017

@mtnptrsn actually we have even a better solution :)

With vue-router, they recommend to use meta for handling this kind of strategy, I am currently implement this meta property directly into the pages components.

Example:

<template>
  <h1>Only an admin can see this page</h1>
</template>

<script>
export default {
  middleware: 'auth',
  meta: {
    auth: { authority: 2 }
  }
}
</script>

Then in your middleware/auth.js:

export default ({ store, route, redirect }) => {
  // Check if user is connected first
  if (!store.getters['user/user'].isAuthenticated) return redirect('/login')

  // Get authorizations for matched routes (with children routes too)
  const authorizationLevels = route.meta.map((meta) => {
    if (meta.auth && typeof meta.auth.authority !== 'undefined')
      return meta.auth.authority
    return 0
  })
  // Get highest authorization level
  const highestAuthority = Math.max.apply(null, authorizationLevels)

  if (store.getters['user/user'].details.general.authority < highestAuthority) {
    return error({
      statusCode: 401,
      message: 'Du måste vara admin för att besöka denna sidan.'
    })
  }
}
@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 25, 2017

@Atinux Wow, that's awesome! Thank you! This should def be included in the documentation.

Thank you so much!

mtnptrsn commented Sep 25, 2017

@Atinux Wow, that's awesome! Thank you! This should def be included in the documentation.

Thank you so much!

@Atinux

This comment has been minimized.

Show comment
Hide comment
@Atinux

Atinux Sep 25, 2017

Member

Yes, but right now it's not implemented @mtnptrsn

You have to be a bit patient!

Member

Atinux commented Sep 25, 2017

Yes, but right now it's not implemented @mtnptrsn

You have to be a bit patient!

@mtnptrsn

This comment has been minimized.

Show comment
Hide comment
@mtnptrsn

mtnptrsn Sep 25, 2017

@Atinux Oh, right. Thought you said that was already implemented, soz. That's great tho, great work!

mtnptrsn commented Sep 25, 2017

@Atinux Oh, right. Thought you said that was already implemented, soz. That's great tho, great work!

@vuchl

This comment has been minimized.

Show comment
Hide comment
@vuchl

vuchl Sep 25, 2017

@Atinux looks nice! So we need to wait for you guys to implement the merging of meta: {auth: ''} into route.meta? Sounds fair!

vuchl commented Sep 25, 2017

@Atinux looks nice! So we need to wait for you guys to implement the merging of meta: {auth: ''} into route.meta? Sounds fair!

@Atinux

This comment has been minimized.

Show comment
Hide comment
@Atinux

Atinux Sep 25, 2017

Member

Yes :)

Member

Atinux commented Sep 25, 2017

Yes :)

@Alex-Sokolov

This comment has been minimized.

Show comment
Hide comment
@Alex-Sokolov

Alex-Sokolov Dec 6, 2017

This will be released with 1.0?

Alex-Sokolov commented Dec 6, 2017

This will be released with 1.0?

@feryardiant

This comment has been minimized.

Show comment
Hide comment
@feryardiant

feryardiant Mar 11, 2018

@Atinux I hope that feature will release soon.

feryardiant commented Mar 11, 2018

@Atinux I hope that feature will release soon.

@wildan2711

This comment has been minimized.

Show comment
Hide comment
@wildan2711

wildan2711 Mar 21, 2018

Same here. I think route meta is very useful for conditional rendering in parent routes or root. Can't wait..

wildan2711 commented Mar 21, 2018

Same here. I think route meta is very useful for conditional rendering in parent routes or root. Can't wait..

@andrecavallari

This comment has been minimized.

Show comment
Hide comment
@andrecavallari

andrecavallari Mar 23, 2018

What about if any logged user goes to chrome developer pannel and use $nuxt.$store.commit(...) to change it's authority level?? How to avoid it?

andrecavallari commented Mar 23, 2018

What about if any logged user goes to chrome developer pannel and use $nuxt.$store.commit(...) to change it's authority level?? How to avoid it?

@hAppywAy

This comment has been minimized.

Show comment
Hide comment
@hAppywAy

hAppywAy Jun 18, 2018

@Atinux there is no way to use metas introduced into head () function to handle auth using your example ? Tenants of my SaaS application are able to create custom pages and fill meta tags for each one. It would be awesome if they could add auth meta to give access to page for their users.
PS: I know middleware is executed before fetching data. I'm open to any advices. In store I set every role of each user and tenant admin can create new roles for their users

hAppywAy commented Jun 18, 2018

@Atinux there is no way to use metas introduced into head () function to handle auth using your example ? Tenants of my SaaS application are able to create custom pages and fill meta tags for each one. It would be awesome if they could add auth meta to give access to page for their users.
PS: I know middleware is executed before fetching data. I'm open to any advices. In store I set every role of each user and tenant admin can create new roles for their users

This comment has been minimized.

Show comment
Hide comment
@Atinux

Atinux Jun 19, 2018

Member

@hAppywAy I am not sure to understand fully what you want to achieve. You can use the store to know the rights of your users and then use head() to add more meta tags depending of the user.

Member

Atinux commented Jun 19, 2018 — with CMTY

@hAppywAy I am not sure to understand fully what you want to achieve. You can use the store to know the rights of your users and then use head() to add more meta tags depending of the user.

1 similar comment

This comment has been minimized.

Show comment
Hide comment
@Atinux

Atinux Jun 19, 2018

Member

@hAppywAy I am not sure to understand fully what you want to achieve. You can use the store to know the rights of your users and then use head() to add more meta tags depending of the user.

Member

Atinux commented Jun 19, 2018 — with CMTY

@hAppywAy I am not sure to understand fully what you want to achieve. You can use the store to know the rights of your users and then use head() to add more meta tags depending of the user.

@SteveEdson

This comment has been minimized.

Show comment
Hide comment
@SteveEdson

SteveEdson Aug 13, 2018

Are there still plans to merge meta: {} into route.meta? I'd like to be able to use meta properties to define page specific features outside of the main component. For example, using a meta property to define a header theme, or to disable certain features in my footer.

Thanks.

SteveEdson commented Aug 13, 2018

Are there still plans to merge meta: {} into route.meta? I'd like to be able to use meta properties to define page specific features outside of the main component. For example, using a meta property to define a header theme, or to disable certain features in my footer.

Thanks.

@Atinux

This comment has been minimized.

Show comment
Hide comment
@Atinux

Atinux Aug 17, 2018

Member

Hi @SteveEdson

Could you please create a pull request on http://cmty.app/nuxt so we can keep track of it please?

Member

Atinux commented Aug 17, 2018

Hi @SteveEdson

Could you please create a pull request on http://cmty.app/nuxt so we can keep track of it please?

@Atinux Atinux closed this Aug 17, 2018

@SteveEdson

This comment has been minimized.

Show comment
Hide comment
@SteveEdson

SteveEdson commented Aug 17, 2018

@Atinux done at #3751. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment