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}