Security utilities — route protection and password hashing.
Route protection decorators::
from chirp.security import login_required, requires
@app.route("/dashboard")
@login_required
def dashboard():
...
@app.route("/admin")
@requires("admin")
def admin_panel():
...
Password hashing (pip install chirp[auth])::
from chirp.security import hash_password, verify_password
hashed = hash_password("my-password")
ok = verify_password("my-password", hashed)
Login verification with a user-enumeration timing defence, plus opportunistic hash upgrades::
from chirp.security import verify_login, verify_and_upgrade
# Unknown user (hash is None) still runs a decoy verify → constant-ish time.
if not verify_login(password, user.password_hash if user else None):
return reject()
# Re-derive stale hashes on a successful login (never on a wrong password).
# Pass upgrade_algorithm=True during a controlled scrypt→argon2 migration.
ok, new_hash = verify_and_upgrade(
password, user.password_hash, upgrade_algorithm=True
)
if new_hash is not None:
user.password_hash = new_hash # app must persist
Group -> permission rollup for the flatuser.permissionsgate::
from chirp.security import resolve_permissions
# Inside your own load_user — most-permissive-wins union over the user's
# groups, dotted-key flatten, result lands on user.permissions.
perms = resolve_permissions(
[group.permissions for group in record.groups],
base=frozenset(record.direct_permissions),
)
security
| Name | Type | Default | Description |
|---|---|---|---|
type
|
|
— | |
qualified_name
|
|
— | |
element_type
|
|
— | |
description
|
|
— | |
source_file
|
|
— | |
line_number
|
|
— | |
is_autodoc
|
|
— | |
autodoc_element
|
|
— | |
_autodoc_template
|
|
— | |
_autodoc_url_path
|
|
— | |
_autodoc_page_type
|
|
— | |
title
|
|
— | |
doc_content_hash
|
|
— |
View source · /home/runner/work/chirp/chirp/site/../src/chirp/security/__init__.py:1