orgstate / legacy /orgstate_engine /api_key_auth.py
Legal-i's picture
Initial OrgState deploy via Stage 150 free-tier stack
d2d1903 verified
import hashlib, secrets
from datetime import datetime
from auth_repository import AuthRepository
from permissions import permissions_for_role, role_has_permission
from audit_logger import log_action
PREFIX = 'org_sk_live_'
def hash_key(raw_key): return hashlib.sha256(raw_key.encode('utf-8')).hexdigest()
def create_api_key(tenant_id, user_id, role='Admin', expires_at=None):
raw = PREFIX + secrets.token_urlsafe(32)
key_hash = hash_key(raw); key_id = 'key_' + secrets.token_hex(6); key_prefix = raw[:18]
repo = AuthRepository(); repo.seed_role_permissions()
rec = repo.create_api_key_record(key_id, tenant_id, user_id, role, key_prefix, key_hash, expires_at)
log_action(tenant_id, user_id, 'api_key_created', 'api_key', key_id, metadata={'role': role})
return {'api_key': raw, 'record': rec}
def verify_api_key(raw_key):
rec = AuthRepository().get_api_key_by_hash(hash_key(raw_key))
if not rec: return {'ok': False, 'error': 'invalid_api_key'}
if rec.get('expires_at') and rec['expires_at'] < datetime.utcnow().isoformat(): return {'ok': False, 'error': 'expired_api_key'}
repo = AuthRepository(); membership = repo.get_membership(rec['tenant_id'], rec['user_id'])
if not membership: return {'ok': False, 'error': 'no_active_membership'}
repo.touch_api_key(rec['key_id'])
principal = {'tenant_id': rec['tenant_id'], 'user_id': rec['user_id'], 'role': rec['role'], 'permissions': sorted(permissions_for_role(rec['role'])), 'key_id': rec['key_id']}
log_action(rec['tenant_id'], rec['user_id'], 'auth_success', 'api_key', rec['key_id'])
return {'ok': True, 'principal': principal}
def require_permission_principal(principal, permission):
ok = role_has_permission(principal.get('role'), permission)
if not ok:
log_action(principal.get('tenant_id','unknown'), principal.get('user_id','unknown'), 'permission_denied', 'permission', permission, outcome='failure')
return {'ok': False, 'error': 'permission_denied', 'permission': permission}
return {'ok': True}