Search by

adachsoft / access-control-json-file

Arkadiusz Adach

JSON file implementation of adachsoft/access-control-contracts.

Package info

gitlab.com/a.adach/access-control-json-file

Issues

pkg:composer/adachsoft/access-control-json-file

Statistics

Installs: 12

Dependents: 0

Suggesters: 0

Stars: 0

v0.1.0 2026-11-13 09:43 UTC

This package is auto-updated.

Last update: 2026-11-13 08:54:08 UTC


README

adachsoft/access-control-json-file implements the repository contracts from adachsoft/access-control-contracts using JSON files. It does not authenticate callers; the host application supplies an AccountId to the access-control services.

Requirements and installation

  • PHP 8.3 or later.
  • Composer.
  • adachsoft/access-control-contracts (installed as a runtime dependency).
  • adachsoft/rule-evaluator-expression-language when evaluating conditional grants (install it in the consuming application).
composer require adachsoft/access-control-json-file
composer require adachsoft/rule-evaluator-expression-language

File paths and formats

Configure two writable paths: one for account state and one for the read-only role definitions file. The account repository creates the account file on its first write. The definitions file must exist and contain both required top-level keys; a missing or invalid definition is an error and grants no access. Both files are UTF-8 JSON objects. The account storage uses a sidecar <path>.lock file and atomic replacement when it writes account state.

A definitions file follows the format in docs/spec/access-control.md:

{
  "roles": [
    {
      "id": "developer",
      "name": "Developer",
      "grants": [
        {"permission": "task.create"},
        {
          "permission": "task.edit",
          "condition": "resource.author == actor.id and resource.category == 'TODO'"
        },
        {"permission": "comment.*"}
      ]
    },
    {
      "id": "agent",
      "name": "Agent",
      "grants": [{"permission": "comment.add"}]
    }
  ],
  "assignment_rules": [
    {"account": "dev_*", "type": "AGENT", "roles": ["developer"]},
    {"account": "*", "type": "AGENT", "roles": ["agent"]}
  ]
}

Assignment rules are evaluated in file order; the first matching rule provisions a new account. Each role and rule must reference valid, unique role identifiers.

The account file is managed by JsonAccountRepository and has this shape:

{
  "accounts": [
    {
      "id": "dev_anna",
      "type": "AGENT",
      "roles": ["developer"],
      "active": true,
      "createdAt": "2025-01-01T00:00:00+00:00",
      "provisionedBy": "RULE",
      "version": 1
    }
  ]
}

createdAt is stored in DateTimeInterface::ATOM format. Each account update uses optimistic version checking; a successful save increments the stored version.

Usage

The repositories can be passed to AccessControlFactory. Conditional grants require a RuleEvaluatorInterface implementation; this example uses adachsoft/rule-evaluator-expression-language:

<?php

declare(strict_types=1);

use AdachSoft\AccessControlContracts\Factory\AccessControlFactory;
use AdachSoft\AccessControlContracts\ValueObject\AccountId;
use AdachSoft\AccessControlJsonFile\Definition\JsonDefinitionFileLoader;
use AdachSoft\AccessControlJsonFile\Repository\JsonAccountRepository;
use AdachSoft\AccessControlJsonFile\Repository\JsonRoleAssignmentRuleRepository;
use AdachSoft\AccessControlJsonFile\Repository\JsonRoleDefinitionRepository;
use AdachSoft\RuleEvaluatorExpressionLanguage\ExpressionLanguageRuleEvaluatorFactory;

$accountsFile = __DIR__ . '/var/access-control/accounts.json';
$definitionsFile = __DIR__ . '/config/access-control.json';
$loader = new JsonDefinitionFileLoader($definitionsFile);
$accounts = new JsonAccountRepository($accountsFile);
$roleDefinitions = new JsonRoleDefinitionRepository($loader);
$assignmentRules = new JsonRoleAssignmentRuleRepository($loader);
$ruleEvaluator = (new ExpressionLanguageRuleEvaluatorFactory())->createDefault();

$accessControl = AccessControlFactory::createAccessDecisionService(
    $accounts,
    $roleDefinitions,
    $assignmentRules,
    $ruleEvaluator,
);

$allowed = $accessControl->isGranted(
    new AccountId('dev_anna'),
    'task.edit',
    ['author' => 'dev_anna', 'category' => 'TODO'],
);

The first use of an account provisions it according to the first matching assignment rule. Access is denied by default; a conditional grant is effective only when the configured evaluator returns true.

License

This package is licensed under the MIT License, as declared in composer.json.