Permix

Setup

Learn how to setup permissions in your project

Overview

After creating Permix instance, you need to define permissions with setup method. You can call setup in any time with any permissions and Permix will replace the previous permissions.

You always should describe all permissions in the setup method that was defined in the Permix generic type.

For role separation, you can use the template method.

Object definition

const permix = createPermix<{
  post: {
    action: 'create'
  }
  comment: {
    action: 'create' | 'update'
  }
}>()

permix.setup({
  post: {
    create: true,
  },
  comment: {
    create: true,
    update: true,
  }
})

You can also use enum based permissions. See Enum-based for more information.

Initial

You can set up initial rules directly when creating a Permix instance by passing them as the first parameter to createPermix.

import {  } from 'permix'

const  = <{
  : {
    : 'create' | 'read'
  }
  : {
    : 'create' | 'read' | 'update'
  }
}>({
  : {
    : true,
    : true,
  },
  : {
    : false,
    : true,
    : true,
  },
})

// The instance is immediately ready to use
.('post', 'create') // true

.() // true

When using initial rules, the Permix instance is immediately ready to use without calling setup first.

Type-Based

When creating a Permix instance, you can define entities that will be used in the setup method for each related entity. This allows you to check permissions for specific data entities. So instead of boolean you can use functions to check permissions.

import {  } from 'permix'

interface Post {
  : string
  : string
}

const  = <{
  : {
    : Post
    : 'update'
  }
  : {
    : 'update'
  }
}>()

.({
  : {
    :  => .
  • authorId
  • id
} : { : comment => c
comment: unknown
} })

Required

By default dataType providing optional type to callbacks but you can make it required by adding dataRequired: true.

import {  } from 'permix'

interface Post {
  : string
  : string
}

interface Comment {
  : string
  : string
}

const  = <{
  : {
    : Post
    : true
    : 'update'
  }
  : {
    : Comment
    : 'update'
  }
}>()

.({
  : {
    : post => !!.
post: Post
} : { : comment => !!.
comment: Comment | undefined
} })

unknown

If you cannot define entity types in the Permix instance, the types will be unknown by default, but you can still define them later in the setup method.

This approach is not recommended as it reduces type safety and IDE support.

import {  } from 'permix'

const  = <{
  : {
    : 'update'
  }
}>()

.({
  : {
    : (: { : string }) => . === user.id
  }
})

Dynamic

You can use async functions to fetch permissions from external sources and then set them up.

See the template for more examples and patterns.

import { createPermix } from 'permix'

const permix = createPermix<{
  post: {
    action: 'create' | 'read' | 'update' | 'delete'
  }
  comment: {
    action: 'create' | 'read' | 'update' | 'delete'
  }
}>()

// Fetch permissions from API
async function loadUserPermissions(userId: string) {
  const permissions = await getPermissionsFromAnyPlace()

  permix.setup({
    post: {
      create: permissions.includes('post:create'),
      read: permissions.includes('post:read'),
      update: permissions.includes('post:update'),
      delete: permissions.includes('post:delete'),
    },
    comment: {
      create: permissions.includes('comment:create'),
      read: permissions.includes('comment:read'),
      update: permissions.includes('comment:update'),
      delete: permissions.includes('comment:delete'),
    },
  })
}

// Usage
await loadUserPermissions('user-123')

Getting Rules

You can get the current rules from an existing Permix instance using the getRules function:

import { getRules } from 'permix'

// Get current rules
const rules = getRules(permix)

The getRules function returns the exact rules object that was set using setup, including any permission functions.