Metadata-Version: 2.4
Name: tagth
Version: 1.2.2
Summary: Pure Python Stateless Tag-Based Authorization Library
Author-email: Boris Resnick <boris.resnick@gmail.com>
Project-URL: Homepage, https://github.com/scartill/tagth
Project-URL: Changelog, https://github.com/scartill/tagth/blob/main/CHANGELOG.md
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyparsing>=3.1.4
Dynamic: license-file

# Stateless Tag-Based Authorization Library

## Background

Traditional role-based authorization models are not flexible enough to cover all required use cases. On the other side, full-managed ACLs are too complex for account managers to handle. `tagth` is a simple and flexible authorization model that can be easily implemented and maintained.

## Installation

```sh
pip install tagth
```

## Tag-Based Authorization

A lightweight model that is based on three concepts:
* a principal and its associated tags,
* a resource and its associated tags,
* an action.

The model adheres to the following principles:
* the model is stateless and purely functional, and it has no internal persistence,
* the model does not interpret the tags or actions, besides the special values,
* the model produces a binary result: either the action is allowed or not.

### Principal and Principal Tags

A Principal is an acting entity. A Principal can be a user, a role, a group, or any other entity that can perform actions.

Principal’s auth tag string looks like a comma-separated list of tags: `tag_one, tag_two, tag_three`. Each tag should be a string that is a valid Python identifier.

A supertag is a tag that is a prefix of another tag. For example, `admin` is a supertag of `admin_user`.

A principal is said to possess a tag if the tag or its supertag exists in the principal’s auth tag string.

Special values:
* `void` (can only access resources with `anyone` access, see below),
* `root` (unlimited access).

### Resource and Resource Tags

A Resource is an object that can be accessed by a Principal. A Resource can be a user, a channel, a source asset, an extension, a tenant, a campaign, etc.

A resource tag is a string that is a valid Python identifier. *NB: there is no such thing as a supertag for a resource tag.*

An action is a string that is a valid Python identifier. A superaction is an action that is a prefix of another action. For example, `create` is a superaction of `create_asset`.

Resource auth tag string looks like a comma-separated of colon-separarted pairs of tags and actions: `tag_one:read, tag_two:write` or multiple actions:  `tag_one:{read, write}`(tags with associated actions).

An action is allowed for a principal if it possesses:
* a tag that is associated with the action
* a tag that is associated with the superaction of the action
* the `root` tag

Special values:
* `anyone` resource tag (any principal is allowed to perform action).
* `all` action (all action are allowed).

### Access Resolution

The model makes a decision based on the following three values **only**:
* the principal’s auth tag string
* the resource’s auth tag string
* the action to be performed

The resolution is binary: either the action is allowed or not.

## Examples

### Basic Usage

```python
from tagth import allowed

# A regular user with basic permissions
principal_tags = 'user, content'
resource_tags = 'content:read, metadata:write'

# Check if user can read content
allowed(principal_tags, resource_tags, 'read')  # Returns True
# Check if user can delete content
allowed(principal_tags, resource_tags, 'delete')  # Returns False

# Multiple actions for a resource
principal_tags = 'user, content'
resource_tags = 'content:{read, write}'

# Check if user can read content
allowed(principal_tags, resource_tags, 'read')  # Returns True
# Check if user can write content
allowed(principal_tags, resource_tags, 'write')  # Returns True
# Check if user can delete content
allowed(principal_tags, resource_tags, 'delete')  # Returns False

# Root user has unlimited access
principal_tags = 'root'
allowed(principal_tags, resource_tags, 'anything')  # Returns True

# Void user can only access 'anyone' resources
void_tags = 'void'
allowed(void_tags, 'anyone:read', 'read')  # Returns True
allowed(void_tags, 'content:read', 'read')  # Returns False
```

### Supertags and Superactions

```python
# Principal tags can be supertags
principal_tags = 'admin'
resource_tags = 'admin_user:write, admin_content:delete'

# 'admin' is a supertag of 'admin_user' and 'admin_content'
allowed(principal_tags, resource_tags, 'write')  # Returns True
allowed(principal_tags, resource_tags, 'delete')  # Returns True

# Actions can have superactions
principal_tags = 'content'
resource_tags = 'content:create'

# 'create' is a superaction of 'create_asset'
allowed(principal_tags, resource_tags, 'create_asset')  # Returns True
```

### Special Values

```python
# 'anyone' resource tag allows access to all principals
principal_tags = 'basic_user'
resource_tags = 'anyone:read'
allowed(principal_tags, resource_tags, 'read')  # Returns True

# 'all' action allows all actions
principal_tags = 'content'
resource_tags = 'content:all'
allowed(principal_tags, resource_tags, 'read')  # Returns True
allowed(principal_tags, resource_tags, 'write')  # Returns True
```
