Coverage for app/controllers/database.py: 55%

22 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-05-02 02:49 +0000

1import base64 

2import hashlib 

3import secrets 

4 

5from supabase.client import Client, ClientOptions, create_client 

6from werkzeug.local import LocalProxy 

7from flask import g, session, current_app 

8 

9def get_session_storage(): 

10 from app import FlaskSessionStorage 

11 return FlaskSessionStorage() 

12 

13def get_db() -> Client: 

14 if "db" not in g: 

15 g.db = Client( 

16 current_app.config["SUPABASE_URL"], 

17 current_app.config["SUPABASE_KEY"], 

18 options=ClientOptions( 

19 storage=get_session_storage(), 

20 flow_type="pkce" 

21 ), 

22 

23 ) 

24 return g.db 

25 

26def get_service_client() -> Client: 

27 return create_client( 

28 current_app.config["SUPABASE_URL"], 

29 current_app.config["SUPABASE_SERVICE_KEY"], 

30 options=ClientOptions( 

31 auto_refresh_token=False, 

32 persist_session=False, 

33 ) 

34 ) 

35 

36client: Client = LocalProxy(get_db) 

37 

38def generate_code_verifier(): 

39 """Generate a secure random code verifier (43-128 characters).""" 

40 return secrets.token_urlsafe(64) # Secure random 64-character string 

41 

42def generate_code_challenge(verifier): 

43 """Create a SHA256 challenge from the code verifier (RFC 7636).""" 

44 sha256_hash = hashlib.sha256(verifier.encode()).digest() 

45 challenge = base64.urlsafe_b64encode(sha256_hash).decode().rstrip("=") # Remove '=' padding 

46 return challenge