Recursive Memberships and Permissions for the Education Warehouse Authentication System
Project description
edwh-auth-rbac
Role-Based Access Control (RBAC) library with recursive memberships for Python applications.
Overview
This library implements a comprehensive RBAC system that supports:
- Users, groups, and items as identities
- Recursive group memberships (groups can contain other groups)
- Time-bound permissions with start/end dates
- Wildcard permissions (* for all privileges, all identities, or all targets)
- Password hashing with HMAC-SHA512 and per-entry random salts
Mental Model
The system is built around three core concepts:
- Identities: Users (people), Groups (collections), and Items (resources)
- Memberships: Direct relationships between identities (who belongs to what)
- Permissions: Granted privileges on targets with time constraints
Key Features
- Recursive membership resolution through database views
- Efficient permission checking using JOINs with recursive membership views
- Flexible identity lookup by email, ID, UUID, or name
- Secure password storage with constant-time validation
Installation
pip install edwh-auth-rbac
Basic Usage
This requires a setup like the demo, see below for details, but this is how you would mostly use it in every day use:
from pydal import DAL
from edwh_auth_rbac import AuthRbac
# Initialize database
db = DAL('sqlite://storage.sqlite')
# Initialize RBAC
rbac = AuthRbac(db)
rbac.define_model(allowed_types=['user', 'group', 'item'], migrate=True)
Creating Users and Groups
# Create a group
admin_group = rbac.add_group(
email="admin@example.com",
name="Administrators",
member_of=[]
)
# Create a user
user = rbac.add_user(
email="john@example.com",
firstname="John",
fullname="John Doe",
password="secure_password",
member_of=[admin_group['object_id']] # Add user to admin group
)
Adding Permissions
# Grant read permission to a user on a resource
rbac.add_permission(
identity_key=user['object_id'],
target_oid="document_123",
privilege="read"
)
# Grant write permission to a group (affects all members)
rbac.add_permission(
identity_key=admin_group['object_id'],
target_oid="document_123",
privilege="write"
)
Checking Permissions
# Check if user has permission
has_read = rbac.has_permission(
identity_key=user['object_id'],
target_oid="document_123",
privilege="read"
)
print(f"User has read permission: {has_read}")
Advanced Features
Recursive Group Memberships
Groups can contain other groups, creating a hierarchy:
# Create nested groups
root_group = rbac.add_group(email="root@example.com", name="Root", member_of=[])
middle_group = rbac.add_group(email="middle@example.com", name="Middle", member_of=[root_group['object_id']])
leaf_group = rbac.add_group(email="leaf@example.com", name="Leaf", member_of=[middle_group['object_id']])
# Add user to leaf group
user = rbac.add_user(
email="user@example.com",
firstname="User",
fullname="Test User",
password="password",
member_of=[leaf_group['object_id']]
)
# User now has permissions granted to any of the parent groups
Time-Bound Permissions
Permissions can be granted for specific time periods:
import datetime as dt
rbac.add_permission(
identity_key=user['object_id'],
target_oid="document_123",
privilege="read",
starts=dt.datetime(2023, 1, 1),
ends=dt.datetime(2023, 12, 31)
)
Edge Cases and Assumptions
- Circular group memberships are prevented by the recursive view logic
- Non-existent targets in permissions are allowed (flexible resource modeling)
- Time-bound permissions with precise datetime validation
- Wildcard permissions that grant broad access rights (using "*")
- Case-insensitive email handling
- Automatic cleanup of related records when identities are removed
- Passwords are stored securely with HMAC-SHA512 and per-entry random salts
- Group names can be used as lookup keys for groups
- Email addresses needn't be unique across different identity types
Setup demo database
For your own application, you'd probably want to use your own migration tool or use ours. But you'd have a list
of migrations where you will want to include these from the src/edwh_auth_rbac/migrations.py file
Prepare the migration:
cd your-demo-folder
mkdir flags
export MIGRATE_URI=sqlite://storage.sqlite
export FLAG_LOCATION=./flags
Execute the migration:
$ migrate src/edwh_auth_rbac/migrations.py
testing migrate lock file with the current version
Using lock file: flags/migrate-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.complete
Using argument src/edwh_auth_rbac/migrations.py as a reference to the migrations file.
importing migrations from src/edwh_auth_rbac/migrations.py
starting migrate hook
2 migrations discovered
table not found, starting database restore
RECOVER: attempting recovery from a backup
RECOVER_DATABASE_FROM_BACKEND started
RECOVER: /data/database_to_restore.NOTFOUND not found. Starting from scratch.
test: rbac_tables
run: rbac_tables
ran: rbac_tables successfully (0.01s wall, 0.00s CPU)
test: rbac_views
run: rbac_views
ran: rbac_views successfully (0.00s wall, 0.00s CPU)
migration completed successfully, marking success.
Execute the example.py demo:
$ python3 example.py
=== Creating Users and Groups and Documents ===
Created document item: {'object_id': '208247a1-cf2f-4f4e-a0c9-3edc813a78b6', 'email': 'document@example.com', 'name': 'Test Document'}
Created admin group: {'object_id': '481c6a16-672f-43b7-ad71-2b1830a3dc09', 'email': 'admin@example.com', 'name': 'Administrators'}
Created user: {'object_id': 'c797b2da-47b4-42a4-ab1d-2c0b6150555f', 'email': 'john@example.com', 'firstname': 'John', 'fullname': 'John Doe'}
=== Adding Permissions ===
Granted read permission to user on document_123
Granted write permission to admin group on document_123
=== Checking Permissions ===
User has read permission: True
User has write permission: True
=== Example completed successfully! ===
Database Schema
The library creates the following tables:
identity: Core identity records with object_id, type, and credentialsmembership: Direct membership relationships between identitiespermission: Time-bound privilege grants from identity to targetrecursive_memberships: View showing all indirect membershipsrecursive_members: View showing all indirect members
API Reference
For detailed API documentation, see the docstrings in the source code:
AuthRbacclass insrc/edwh_auth_rbac/rbac.py- Model functions in
src/edwh_auth_rbac/model.py
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file edwh_auth_rbac-1.0.2.tar.gz.
File metadata
- Download URL: edwh_auth_rbac-1.0.2.tar.gz
- Upload date:
- Size: 74.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.2","id":"zara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
872dc1227d5bd4f57a700288cdc3c815616f3e92e3a13d4e726b30f809763805
|
|
| MD5 |
4f3de49fcaddf0b52c7d30ef1a2fc009
|
|
| BLAKE2b-256 |
dd7b66377e4a78df731615b21b1692948c4234344ef4e035cafc8373580fea78
|
File details
Details for the file edwh_auth_rbac-1.0.2-py3-none-any.whl.
File metadata
- Download URL: edwh_auth_rbac-1.0.2-py3-none-any.whl
- Upload date:
- Size: 23.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.2","id":"zara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32ff1c3c7effbb98ac6f0eec09d2790ec40dcf4c167bf3b5be4a927f3ba404d8
|
|
| MD5 |
ade9a5641f816f7075aa563b85c103c9
|
|
| BLAKE2b-256 |
83f9cb1517e72eb78d1b01e342be66c6a7f9ac301bdb979f4a03354ab6b32cd5
|