File size: 2,043 Bytes
d2d1903
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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}