Skip to content

chrhi/permission-system

Repository files navigation

Drakonis Guard

Mythical Access Control System for Node.js Applications
Inspired by ancient dragon guardians, enforce your application's permissions with mythical precision.


Installation

npm install drakonis-guard

Quick Start

import { AccessControl, PolicyBuilder } from "drakonis-guard";

// 1. Define your policy
const policy = new PolicyBuilder()
  .forRole("dragon-rider")
  .onResource("dragon")
  .can({
    feed: true,
    ride: (user, dragon) => dragon.tamed && user.hasSaddle,
  })
  .forRole("blacksmith")
  .onResource("forge")
  .can({
    craft: true,
    upgrade: (user, item) => item.quality < user.skillLevel,
  })
  .build();

// 2. Create guardian instance
const guardian = new AccessControl(policy);

// 3. Check permissions
const user = { roles: ["dragon-rider"], hasSaddle: true };
const dragon = { name: "Ignisar", tamed: true };

guardian.hasPermission(user, "dragon", "ride", dragon); // true

Core Concepts

1. Policy Configuration

Define your access rules using the fluent builder:

type User = { id: string; guild: string };
type Treasure = { value: number; guild: string };

const policy = new PolicyBuilder<User>()
  .forRole("guild-master")
  .onResource<Treasure>("treasure")
  .can({
    view: true,
    claim: (user, treasure) => treasure.guild === user.guild,
  })
  .build();

2. Permission Checks

Combine simple rules and magical conditions:

.can({
  // Boolean rule (always true/false)
  basicAccess: true,

  // Function rule (dynamic evaluation)
  specialAccess: (user, resource) => {
    return user.magicLevel > resource.requiredPower;
  }
})

what should i do

3. Access Control Instance

Create your realm's guardian:

const guardian = new AccessControl(policy);

// Check permissions with optional resource data
guardian.hasPermission(user, "treasure", "claim", ancientRelic);

Advanced Features

Multiple Roles

// Users can have multiple roles
const user = {
  roles: ["alchemist", "scribe"],
  potionLicense: true,
};

guardian.hasPermission(user, "library", "transcribe"); // Checks all roles

Optional Data

// Data-free checks (uses boolean rules only)
guardian.hasPermission(user, "tavern", "enter");

// Data-dependent checks (requires resource object)
guardian.hasPermission(user, "quest", "accept", currentQuest);

Custom User Types

type Mage = {
  rank: number;
  spells: string[];
  tower: string;
};

const policy = new PolicyBuilder<Mage>()
  .forRole("archmage")
  .onResource("spell-tome")
  .can({
    read: (mage, tome) =>
      mage.rank >= tome.requiredRank && mage.tower === tome.originTower,
  });

Best Practices

Start Restrictive

"Better to deny a dragon than unleash chaos."

// Default deny policy
const policy = new PolicyBuilder()
  .forRole("peasant")
  .onResource("*")
  .can({ "*": false });

TypeScript First

Leverage full type safety:

.onResource<Dragon>('dragon')
  .can({
    // Autocomplete dragon properties
    train: (user, dragon) => dragon.age < 100
  })

Realm Segmentation

Organize by domain:

function configureTavernRules(builder: PolicyBuilder) {
  return builder.forRole("barkeep").onResource("ale-cask").can({ tap: true });
}

Error Handling

try {
  guardian.hasPermission(invalidUser, "artifact", "summon");
} catch (error) {
  console.error("Guardian blocked forbidden magic:", error);
}

Real-World Example: Blog Platform

type BlogUser = { id: string; isPremium: boolean };
type Article = { authorId: string; status: "draft" | "published" };

const blogPolicy = new PolicyBuilder<BlogUser>()
  .forRole("admin")
  .onResource("article")
  .can({ "*": true })

  .forRole("author")
  .onResource<Article>("article")
  .can({
    create: true,
    edit: (user, article) => article.authorId === user.id,
    publish: (user, article) => article.authorId === user.id && user.isPremium,
  })

  .forRole("reader")
  .onResource<Article>("article")
  .can({
    view: (_, article) => article.status === "published",
  })
  .build();

Contribution

Join our guild of code smiths!
Read our Contribution Guidelines to help sharpen the dragon's claws.


"Beware the guardian's gaze - for it sees all, permits only what is right."

MIT License © 2024 Abdellah Chehri

About

this is a description

Resources

Stars

Watchers

Forks

Packages

No packages published