Metadata-Version: 2.3
Name: pyfacl
Version: 1.3.0
Summary: Package to manage access control using POSIX ACLs
License: MIT
Author: tobiaspk
Author-email: tobiaspk1@gmail.com
Requires-Python: >=3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Provides-Extra: dev
Requires-Dist: black (>=23.0.0) ; extra == "dev"
Requires-Dist: flake8 (>=6.0.0) ; extra == "dev"
Requires-Dist: isort (>=5.12.0) ; extra == "dev"
Requires-Dist: pre-commit (>=3.0.0) ; extra == "dev"
Requires-Dist: pytest (>=7.0.0) ; extra == "dev"
Requires-Dist: typer (>=0.15.0)
Description-Content-Type: text/markdown

# PyFACL

[![PyPI version](https://badge.fury.io/py/pyfacl.svg)](https://badge.fury.io/py/pyfacl)
[![Python](https://img.shields.io/pypi/pyversions/pyfacl.svg)](https://pypi.org/project/pyfacl/)
[![Documentation Status](https://readthedocs.org/projects/pyfacl/badge/?version=latest)](https://pyfacl.readthedocs.io/en/latest/?badge=latest)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A Python library for parsing and checking POSIX File Access Control Lists (FACL).

**Documentation:** [https://pyfacl.readthedocs.io/en/latest/](https://pyfacl.readthedocs.io/en/latest/)

## Installation

### From PyPI
```bash
pip install pyfacl
```

## Usage

### CLI

The CLI tool checks permissions through the entire directory hierarchy, checks whether the permissions are met and identifies which permission rule applies at each level.

```bash
pyfacl trace /path/to/file user:<user2>:r-x --mode exact
```

Example output:
```bash
$ pyfacl trace /data1/collab002/sail/example/permission/folder user:user2:r-x
0) ✅ other::r-x /
1) ✅ other::r-x /data1
2) ✅ group::rwx /data1/collab002
3) ✅ group::r-x /data1/collab002/sail
4) ✅ group::r-x /data1/collab002/sail/example
5) ❌ user:user2:--x /data1/collab002/sail/example/permission
6) ✅ group::r-x /data1/collab002/sail/example/permission/folder
```

In this trace, items 0-4 and 6 show ✅ **passing** permissions, while item 5 shows ❌ **failing** permissions where the user only has execute (`--x`) but needs read+execute (`r-x`).

However, often we only care about if the user has the required permission for the final file/directory, not the full trace. For that, we can use the `has` command:

```bash
$ pyfacl has /path/to/file user:<user2>:r-x --mode exact
0) ✅ other::r-x /
1) ✅ other::r-x /data1
2) ✅ group::rwx /data1/collab002
3) ✅ group::r-x /data1/collab002/sail
4) ✅ group::r-x /data1/collab002/sail/example
5) ✅ user:user2:--x /data1/collab002/sail/example/permission
6) ✅ group::r-x /data1/collab002/sail/example/permission/folder
```

### Python

#### Check one file/folder permission

```python
from pyfacl import FACL

# Initialize and parse FACL for a file/directory
facl = FACL(path="/path/to/file")

# Check permissions with different modes
facl.has_permission("user:user2:r-x", mode="exact")     # exact match
facl.has_permission("user:user2:r--", mode="at_least") # has at least read
facl.has_permission("user:user2:rwx", mode="at_most")  # has at most rwx
```

#### Check trace through directory hierarchy

```python
from pyfacl import FACLTrace

# Initialize FACLTrace for a directory
facl_trace = FACLTrace(path="/path/to/directory", v=1)

# Trace permissions for a specific user
trace_result = facl_trace.has_permission("user:user2:r-x", mode="at_least")
```

#### Check if user/group has permission for a file/directory

```python
from pyfacl import FACLHas

# Initialize FACLHas for a file/directory
facl_has = FACLHas(path="/path/to/file")

# Check if user/group has the specified permission
has_permission = facl_has.has_permission("user:user2:r-x", mode="at_least")
```

### Permission Modes

- **`exact`**: Permissions must match exactly
- **`at_least`**: Must have at least the specified permissions
- **`at_most`**: Must have at most the specified permissions

## Development

### Setup Development Environment
```bash
pip install -e ".[dev]"
pre-commit install
```

### Run Pre-commit Checks
```bash
pre-commit run --all-files
```

