#Route guards for user permissions

4 messages · Page 1 of 1 (latest)

north forge
#

Hey. I want to add navigation guards that check if a user has a required permissions before nagivation to a given page, or any sub-pages of it. Right now I have a somewhat crude implementation, and I'm curious if there's a better way of handling it.

if (to.fullPath.startsWith('/customers') && currentUserPermissions?.includes(Permission.CUSTOMER_READ))
  return true;

if (to.fullPath.startsWith('/sales') && currentUserPermissions?.includes(Permission.SALES_READ))
  return true;

// .. more 

return abortNavigation(
  createError({
    statusCode: 403,
    message: 'You do not have permissions to access this page.',
  }),
);
latent barn
#

Depends on your architectur 🙂 But your way is easy & understandable to everyone whos checking your code.

If you want to abstract that part in the middleware itself and e.g. want to place the required permissions directly into page components, you could do something like:

<script setup lang="ts">
definePageMeta({
  acl: ['user:view']
})
</script>

<template>
  <div>
  </div>
</template>

While your middleware (e.g. acl.global.ts) could look like:

export default defineNuxtRouteMiddleware((to, from) => {
    // get your current user permissions
    const userPermissions = ['user:edit', 'user:view']
    const requiredPermissions = to.meta.acl

    if (!requiredPermissions || requiredPermissions.length === 0) {
        return
    }

    const granted = requiredPermissions.every((permission) => userPermissions.includes(permission))

    if (!granted) {
        return abortNavigation({
            statusCode: 403,
            statusMessage: 'Forbidden',
        })
    }
})

Disadvantage of that way is, that you do not have permissions based on the url path and needs to repeat yourself on subpages of e.g. /customers and /customers/{id} in the definePageMeta

To solve that you could work with NestedPages.
But keep in mind: with more layers and abstraction, its more complicated to understand for other developers how your code and permissions works, which permission is required to visit pages.

#

in case of type-safety you can add in your index.d.ts

declare module '#app' {
    interface PageMeta {
        acl?: string[]
    }
}

export {}
north forge