Spaces:
Sleeping
Sleeping
harivarshannn commited on
Commit ·
590dd8a
1
Parent(s): 0dcc655
Simplify mockup auth to use Supabase anon key only
Browse files
README.md
CHANGED
|
@@ -30,8 +30,7 @@ Set these in your Hugging Face Space settings:
|
|
| 30 |
|
| 31 |
- `GROQ_API_KEY`: required
|
| 32 |
- `SUPABASE_URL`: required for auth/history
|
| 33 |
-
- `
|
| 34 |
-
- `APP_AUTH_SECRET`: required for signing backend auth tokens
|
| 35 |
|
| 36 |
Optional variables:
|
| 37 |
|
|
@@ -42,7 +41,6 @@ Optional variables:
|
|
| 42 |
- `UPLOAD_FOLDER=/tmp/agrogpt_uploads`
|
| 43 |
- `SUPABASE_HISTORY_TABLE=chat_history`
|
| 44 |
- `GROQ_TRANSCRIBE_MODEL=whisper-large-v3-turbo`
|
| 45 |
-
- `AUTH_TOKEN_MAX_AGE_SECONDS=604800`
|
| 46 |
|
| 47 |
## Supabase Table (History)
|
| 48 |
|
|
@@ -55,7 +53,7 @@ Create a table named `chat_history` (or set `SUPABASE_HISTORY_TABLE`) with colum
|
|
| 55 |
- `answer text`
|
| 56 |
- `created_at timestamptz default now()`
|
| 57 |
|
| 58 |
-
Auth endpoints in this backend use your existing `public.user` table (`email` + `password_hash`) and return a
|
| 59 |
|
| 60 |
## Model Size Strategy
|
| 61 |
|
|
|
|
| 30 |
|
| 31 |
- `GROQ_API_KEY`: required
|
| 32 |
- `SUPABASE_URL`: required for auth/history
|
| 33 |
+
- `SUPABASE_ANON_KEY`: required for auth/history in this mockup setup
|
|
|
|
| 34 |
|
| 35 |
Optional variables:
|
| 36 |
|
|
|
|
| 41 |
- `UPLOAD_FOLDER=/tmp/agrogpt_uploads`
|
| 42 |
- `SUPABASE_HISTORY_TABLE=chat_history`
|
| 43 |
- `GROQ_TRANSCRIBE_MODEL=whisper-large-v3-turbo`
|
|
|
|
| 44 |
|
| 45 |
## Supabase Table (History)
|
| 46 |
|
|
|
|
| 53 |
- `answer text`
|
| 54 |
- `created_at timestamptz default now()`
|
| 55 |
|
| 56 |
+
Auth endpoints in this backend use your existing `public.user` table (`email` + `password_hash`) and return a lightweight mockup Bearer token.
|
| 57 |
|
| 58 |
## Model Size Strategy
|
| 59 |
|
app.py
CHANGED
|
@@ -8,7 +8,6 @@ from flask_cors import CORS
|
|
| 8 |
import threading
|
| 9 |
from werkzeug.utils import secure_filename
|
| 10 |
from werkzeug.security import generate_password_hash, check_password_hash
|
| 11 |
-
from itsdangerous import URLSafeTimedSerializer, BadSignature, SignatureExpired
|
| 12 |
import uuid
|
| 13 |
|
| 14 |
# Import the new model functionality and prompts
|
|
@@ -29,14 +28,9 @@ app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file size
|
|
| 29 |
# Supabase and speech configuration
|
| 30 |
SUPABASE_URL = os.getenv("SUPABASE_URL", "").rstrip("/")
|
| 31 |
SUPABASE_ANON_KEY = os.getenv("SUPABASE_ANON_KEY", "")
|
| 32 |
-
SUPABASE_SERVICE_ROLE_KEY = os.getenv("SUPABASE_SERVICE_ROLE_KEY", "")
|
| 33 |
SUPABASE_HISTORY_TABLE = os.getenv("SUPABASE_HISTORY_TABLE", "chat_history")
|
| 34 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY", "")
|
| 35 |
GROQ_TRANSCRIBE_MODEL = os.getenv("GROQ_TRANSCRIBE_MODEL", "whisper-large-v3-turbo")
|
| 36 |
-
APP_AUTH_SECRET = os.getenv("APP_AUTH_SECRET", GROQ_API_KEY or "agrogpt-dev-secret")
|
| 37 |
-
AUTH_TOKEN_MAX_AGE_SECONDS = int(os.getenv("AUTH_TOKEN_MAX_AGE_SECONDS", "604800"))
|
| 38 |
-
|
| 39 |
-
token_serializer = URLSafeTimedSerializer(APP_AUTH_SECRET)
|
| 40 |
|
| 41 |
# Create uploads directory if it doesn't exist
|
| 42 |
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
|
@@ -52,16 +46,12 @@ def allowed_audio_file(filename):
|
|
| 52 |
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_AUDIO_EXTENSIONS
|
| 53 |
|
| 54 |
def supabase_enabled() -> bool:
|
| 55 |
-
return bool(SUPABASE_URL and
|
| 56 |
-
|
| 57 |
-
def supabase_api_key() -> str:
|
| 58 |
-
return SUPABASE_SERVICE_ROLE_KEY or SUPABASE_ANON_KEY
|
| 59 |
|
| 60 |
def supabase_headers() -> dict:
|
| 61 |
-
api_key = supabase_api_key()
|
| 62 |
headers = {
|
| 63 |
-
"apikey":
|
| 64 |
-
"Authorization": f"Bearer {
|
| 65 |
"Content-Type": "application/json"
|
| 66 |
}
|
| 67 |
return headers
|
|
@@ -73,20 +63,18 @@ def extract_bearer_token() -> str | None:
|
|
| 73 |
return None
|
| 74 |
|
| 75 |
def create_auth_token(user_row: dict) -> str:
|
| 76 |
-
return
|
| 77 |
-
"user_id": user_row["id"],
|
| 78 |
-
"email": user_row.get("email", "")
|
| 79 |
-
})
|
| 80 |
|
| 81 |
def decode_auth_token(token: str):
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
except BadSignature:
|
| 88 |
return None, "Invalid token"
|
| 89 |
|
|
|
|
|
|
|
| 90 |
def sanitize_user(user_row: dict) -> dict:
|
| 91 |
return {
|
| 92 |
"id": user_row.get("id"),
|
|
@@ -425,7 +413,10 @@ def auth_signup_v1():
|
|
| 425 |
try:
|
| 426 |
res = requests.post(
|
| 427 |
f"{SUPABASE_URL}/rest/v1/user",
|
| 428 |
-
headers=
|
|
|
|
|
|
|
|
|
|
| 429 |
params={
|
| 430 |
"select": "id,email,full_name,profession"
|
| 431 |
},
|
|
|
|
| 8 |
import threading
|
| 9 |
from werkzeug.utils import secure_filename
|
| 10 |
from werkzeug.security import generate_password_hash, check_password_hash
|
|
|
|
| 11 |
import uuid
|
| 12 |
|
| 13 |
# Import the new model functionality and prompts
|
|
|
|
| 28 |
# Supabase and speech configuration
|
| 29 |
SUPABASE_URL = os.getenv("SUPABASE_URL", "").rstrip("/")
|
| 30 |
SUPABASE_ANON_KEY = os.getenv("SUPABASE_ANON_KEY", "")
|
|
|
|
| 31 |
SUPABASE_HISTORY_TABLE = os.getenv("SUPABASE_HISTORY_TABLE", "chat_history")
|
| 32 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY", "")
|
| 33 |
GROQ_TRANSCRIBE_MODEL = os.getenv("GROQ_TRANSCRIBE_MODEL", "whisper-large-v3-turbo")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
# Create uploads directory if it doesn't exist
|
| 36 |
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
|
|
|
| 46 |
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_AUDIO_EXTENSIONS
|
| 47 |
|
| 48 |
def supabase_enabled() -> bool:
|
| 49 |
+
return bool(SUPABASE_URL and SUPABASE_ANON_KEY)
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
def supabase_headers() -> dict:
|
|
|
|
| 52 |
headers = {
|
| 53 |
+
"apikey": SUPABASE_ANON_KEY,
|
| 54 |
+
"Authorization": f"Bearer {SUPABASE_ANON_KEY}",
|
| 55 |
"Content-Type": "application/json"
|
| 56 |
}
|
| 57 |
return headers
|
|
|
|
| 63 |
return None
|
| 64 |
|
| 65 |
def create_auth_token(user_row: dict) -> str:
|
| 66 |
+
return f"user:{user_row['id']}"
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
def decode_auth_token(token: str):
|
| 69 |
+
if not token.startswith("user:"):
|
| 70 |
+
return None, "Invalid token"
|
| 71 |
+
|
| 72 |
+
user_id_raw = token.split(":", 1)[1].strip()
|
| 73 |
+
if not user_id_raw.isdigit():
|
|
|
|
| 74 |
return None, "Invalid token"
|
| 75 |
|
| 76 |
+
return {"user_id": int(user_id_raw)}, None
|
| 77 |
+
|
| 78 |
def sanitize_user(user_row: dict) -> dict:
|
| 79 |
return {
|
| 80 |
"id": user_row.get("id"),
|
|
|
|
| 413 |
try:
|
| 414 |
res = requests.post(
|
| 415 |
f"{SUPABASE_URL}/rest/v1/user",
|
| 416 |
+
headers={
|
| 417 |
+
**supabase_headers(),
|
| 418 |
+
"Prefer": "return=representation"
|
| 419 |
+
},
|
| 420 |
params={
|
| 421 |
"select": "id,email,full_name,profession"
|
| 422 |
},
|