0.5.1 • Published 6 months ago

@falcondev-oss/caps v0.5.1

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
6 months ago

@falcondev-oss/caps

Simple, fully type-safe library to handle permissions/access control by defining capabilities with generators.

Installation

npm add @falcondev-oss/caps

Example

type User = { userId: string; role: 'user' | 'moderator' | 'admin'; isBanned: boolean }
type Post = { author: User }

const useActor = createActor<User>().build((cap) => ({
  social: {
    posts: cap.subject<Post>().define(
      function* ({ actor, subject, args }) {
        // banned users can't do anything
        if (actor.isBanned || subject.author.isBanned) return []

        // everyone can read posts
        yield ['read']

        // users can update & delete posts themselves
        if (actor.userId === subject.author.userId) yield ['update', 'delete']

        // admins can delete any post & ban users
        if (actor.role === 'admin') {
          yield ['delete', 'ban']
        }

        // moderators can only delete posts from users
        if (actor.role === 'moderator' && subject.author.role === 'user') {
          yield ['delete']

          // moderators can also ban users temporarily
          if (args.ban?.temporary) yield ['ban']
        }

        return []
      },
      {
        ban: arg<{ temporary: boolean }>,
      },
    ),
  },
}))

const Users = {
  user1: { userId: '1', role: 'user', isBanned: false },
  user2: { userId: '2', role: 'user', isBanned: false },
  moderator: { userId: '3', role: 'moderator', isBanned: false },
  admin: { userId: '4', role: 'admin', isBanned: false },
} as const

const user = useActor(Users.user1)

user.social.posts.subject({ author: Users.user2 }).can('read').check() // => true
user.social.posts.subject({ author: Users.user1 }).can('update').check() // => true
user.social.posts.subject({ author: Users.user2 }).can('delete').check() // => false

const moderator = useActor(Users.moderator)

moderator.social.posts.subject({ author: Users.user1 }).can('delete').check() // => true
moderator.social.posts.subject({ author: Users.user1 }).can('update').check() // => false
moderator.social.posts.subject({ author: Users.user1 }).can('ban', { temporary: false }).check() // => false
moderator.social.posts.subject({ author: Users.user1 }).can('ban', { temporary: true }).check() // => true

const admin = useActor(Users.admin)

admin.social.posts.subject({ author: Users.user1 }).can('ban', { temporary: false }).check() // => true
0.5.1

6 months ago

0.5.0

9 months ago

0.4.2

10 months ago

0.4.1

10 months ago

0.4.0

10 months ago

0.3.1

11 months ago

0.3.0

11 months ago

0.2.3

12 months ago

0.2.2

12 months ago

0.2.1

12 months ago

0.2.0

12 months ago

0.1.1

12 months ago

0.1.0

12 months ago