binauth
A bitwise permission system for Python with SQLAlchemy and FastAPI integration.
Features
- Bitwise permission storage (up to 32 actions per scope)
- Type-safe permission definitions using
IntEnum - Async SQLAlchemy repository
- FastAPI integration with dependency injection
- Permission discovery endpoint for admin UIs
- TTL-based permission caching
- Generic user ID support (int, UUID, str)
Installation
From GitHub
# Core only
pip install git+https://github.com/insmnia/binauth.git
# With SQLAlchemy support
pip install "binauth[db] @ git+https://github.com/insmnia/binauth.git"
# With FastAPI support
pip install "binauth[fastapi] @ git+https://github.com/insmnia/binauth.git"
# All dependencies
pip install "binauth[all] @ git+https://github.com/insmnia/binauth.git"
From PyPI (when published)
pip install binauth
pip install binauth[db] # With SQLAlchemy
pip install binauth[fastapi] # With FastAPI
pip install binauth[all] # All dependencies
Quick Start
Define Permissions
from enum import IntEnum
from typing import ClassVar
from binauth import PermissionActionRegistry, PermissionsManager
class TaskPermissions(PermissionActionRegistry):
scope_name = "tasks"
category = "Content Management" # For grouping in admin UI
description = "Task management permissions"
class Actions(IntEnum):
CREATE = 1 << 0 # 1
READ = 1 << 1 # 2
UPDATE = 1 << 2 # 4
DELETE = 1 << 3 # 8
# Optional: descriptions for admin UI
action_descriptions: ClassVar[dict[str, str]] = {
"CREATE": "Create new tasks",
"READ": "View tasks",
"UPDATE": "Edit tasks",
"DELETE": "Remove tasks",
}
manager = PermissionsManager([TaskPermissions])
Check Permissions
class User:
def __init__(self, permissions: dict[PermissionScope, PermissionBinLevel]):
self.permissions = permissions
# User has CREATE and READ permissions (level = 3)
user = User(permissions={"tasks": 3})
# Check single permission
has_read = manager.check_permission(user, "tasks", TaskPermissions.Actions.READ)
# Check multiple permissions (all required)
has_all = manager.check_permissions(
user,
"tasks",
[TaskPermissions.Actions.READ, TaskPermissions.Actions.UPDATE],
require_all=True,
)
# Check multiple permissions (any required)
has_any = manager.check_permissions(
user,
"tasks",
[TaskPermissions.Actions.CREATE, TaskPermissions.Actions.DELETE],
require_all=False,
)
FastAPI Integration
from fastapi import FastAPI, Depends
from binauth import (
create_permission_dependency,
get_permissions_router,
setup_permission_exception_handler,
)
app = FastAPI()
setup_permission_exception_handler(app)
# Option 1: Pass user ID directly
permission = create_permission_dependency(
manager=manager,
get_db=get_db,
get_current_user_id=get_current_user_id, # Returns int/UUID/str
cache_ttl=60,
)
# Option 2: Pass user object with .id attribute
permission = create_permission_dependency(
manager=manager,
get_db=get_db,
get_current_user=get_current_user, # Returns User with .id
cache_ttl=60,
)
# Protected endpoint
@app.get("/tasks")
async def list_tasks(
user_id: int = Depends(permission.require("tasks", TaskPermissions.Actions.READ))
):
return {"tasks": [...]}
# Permission discovery endpoint (for admin UI)
app.include_router(get_permissions_router(manager, get_current_user))
# GET /permissions returns all available permissions grouped by category
Database Storage
from binauth import AsyncPermissionRepository, Base
# Create tables
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
# Use repository
async with async_session() as session:
repo = AsyncPermissionRepository(session, manager)
# Grant permissions
await repo.grant_actions(user_id, "tasks", TaskPermissions.Actions.READ)
# Check permissions
has_perm = await repo.has_permission(
user_id, "tasks", TaskPermissions.Actions.READ
)
# Get all user permissions
perms = await repo.get_all_user_permissions(user_id)
Permission Discovery
Get all available permissions for admin UIs:
schema = manager.get_permissions_schema()
# Returns:
# [
# {
# "name": "Content Management",
# "scopes": [
# {
# "name": "tasks",
# "description": "Task management permissions",
# "actions": [
# {"name": "CREATE", "value": 1, "description": "Create new tasks"},
# {"name": "READ", "value": 2, "description": "View tasks"},
# ...
# ]
# }
# ]
# }
# ]
Limitations
- Maximum 32 actions per scope (uses PostgreSQL INTEGER for storage)
- Action values must be powers of 2 (
1 << nwhere0 <= n <= 31)
Metadata
Release files for binauth 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| binauth-0.3.1.tar.gz | 13.0 kB | With provenance | Details for binauth-0.3.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| binauth-0.3.1-py3-none-any.whl | Python 3 | none | any | Details for binauth-0.3.1-py3-none-any.whl |
Total release size: 28.8 kB
Release files / binauth-0.3.1.tar.gz
| Download URL | binauth-0.3.1.tar.gz |
|---|---|
| Size | 13.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3d17cf7a9bf37718dec8f0b269c169bd36b45d13f0f35407229b1cdb5c174771
|
|
BLAKE2b-256 checksum How to use checksums |
a714a835773f59617a3e17ad70704bafe6df4e7786783efd12074b34a0c5c725
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Dec 30, 2025.
Transparency logRelease files / binauth-0.3.1-py3-none-any.whl
| Download URL | binauth-0.3.1-py3-none-any.whl |
|---|---|
| Size | 15.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e5f11522a66ad9eefa20e99f4f40795723f16b2d25a4e1f2666750c7b35ac3cc
|
|
BLAKE2b-256 checksum How to use checksums |
4eca4602a14c0c3424067b1696e34e9c504b23d8d0aa780839a60fefb9db2fe1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Dec 30, 2025.
Transparency logSecurity for binauth 0.3.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for binauth-0.3.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Dec 30, 2025.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.