Jethro85 commited on
Commit
b2a55ac
·
1 Parent(s): e573ae1

log to supabase

Browse files
Files changed (1) hide show
  1. app/routes.py +112 -11
app/routes.py CHANGED
@@ -7,6 +7,33 @@ from app.training.mock_trainer import MockTrainer
7
  from app.training.privacy_calculator import PrivacyCalculator
8
  from flask_cors import cross_origin
9
  import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  # Try to import RealTrainer, fallback to MockTrainer if dependencies aren't available
12
  try:
@@ -289,15 +316,70 @@ def _ensure_vid_cookie(resp=None):
289
  return vid, resp
290
  return vid, resp
291
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  @main.route("/api/whoami", methods=["GET"])
293
  @cross_origin()
294
  def whoami():
295
  ua = request.headers.get("User-Agent", "")[:200]
296
  dnt = request.headers.get("DNT") == "1"
297
  gpc = request.headers.get("Sec-GPC") == "1"
298
- vid, resp = _ensure_vid_cookie()
299
- payload = {"vid": vid, "user_agent": ua, "dnt": dnt, "gpc": gpc}
300
- return jsonify(payload)
 
 
 
 
 
 
 
301
 
302
  @main.route('/api/track', methods=['POST', 'OPTIONS'])
303
  @cross_origin()
@@ -311,15 +393,21 @@ def track_event():
311
  gpc = request.headers.get("Sec-GPC") == "1"
312
  ua = request.headers.get("User-Agent", "")[:200]
313
  ref = request.headers.get("Referer", "")[:200]
314
- vid, resp = _ensure_vid_cookie()
315
 
316
- # Allow only specific user fields if provided
 
 
 
 
 
317
  user = evt.get("user") if isinstance(evt.get("user"), dict) else {}
318
- allowed_user = {k: user[k] for k in ["id", "role", "org", "plan"] if k in user and isinstance(user[k], (str, int))}
 
319
 
320
  evt.update({
321
  "server_time": datetime.utcnow().isoformat() + "Z",
322
- "visitor_id": vid,
 
323
  "client_ip_truncated": _client_ip(),
324
  "user_agent": ua,
325
  "referer": ref,
@@ -328,11 +416,24 @@ def track_event():
328
  "user": allowed_user
329
  })
330
 
331
- logfile = os.path.join(current_app.root_path, 'analytics.log.jsonl')
332
- with open(logfile, 'a', encoding='utf-8') as f:
333
- f.write(json.dumps(evt, ensure_ascii=False) + '\n')
 
 
 
 
 
 
 
 
 
 
 
334
 
335
- return jsonify({'ok': True})
336
  except Exception as e:
337
  return jsonify({'ok': False, 'error': str(e)}), 400
 
 
 
338
  # ===== End Analytics =====
 
7
  from app.training.privacy_calculator import PrivacyCalculator
8
  from flask_cors import cross_origin
9
  import os
10
+ import requests
11
+
12
+
13
+ SUPABASE_URL = os.getenv("SUPABASE_URL", "")
14
+ SUPABASE_SERVICE_KEY = os.getenv("SUPABASE_SERVICE_KEY", "")
15
+
16
+ def supabase_insert_event(row: dict) -> None:
17
+ """Insert one event row into Supabase (best-effort)."""
18
+ if not SUPABASE_URL or not SUPABASE_SERVICE_KEY:
19
+ # No secrets set; silently skip to avoid breaking your app
20
+ return
21
+
22
+ r = requests.post(
23
+ f"{SUPABASE_URL}/rest/v1/events",
24
+ headers={
25
+ "apikey": SUPABASE_SERVICE_KEY,
26
+ "Authorization": f"Bearer {SUPABASE_SERVICE_KEY}",
27
+ "Content-Type": "application/json",
28
+ "Prefer": "return=minimal",
29
+ },
30
+ json=row,
31
+ timeout=3,
32
+ )
33
+ # optional: raise if you want strictness
34
+ if r.status_code >= 300:
35
+ print("Supabase insert failed:", r.status_code, r.text[:300])
36
+
37
 
38
  # Try to import RealTrainer, fallback to MockTrainer if dependencies aren't available
39
  try:
 
316
  return vid, resp
317
  return vid, resp
318
 
319
+ # @main.route("/api/whoami", methods=["GET"])
320
+ # @cross_origin()
321
+ # def whoami():
322
+ # ua = request.headers.get("User-Agent", "")[:200]
323
+ # dnt = request.headers.get("DNT") == "1"
324
+ # gpc = request.headers.get("Sec-GPC") == "1"
325
+ # vid, resp = _ensure_vid_cookie()
326
+ # payload = {"vid": vid, "user_agent": ua, "dnt": dnt, "gpc": gpc}
327
+ # return jsonify(payload)
328
+
329
+ # @main.route('/api/track', methods=['POST', 'OPTIONS'])
330
+ # @cross_origin()
331
+ # def track_event():
332
+ # if request.method == 'OPTIONS':
333
+ # return jsonify({'status': 'ok'})
334
+ # try:
335
+ # evt = request.get_json(force=True, silent=True) or {}
336
+ #
337
+ # dnt = request.headers.get("DNT") == "1"
338
+ # gpc = request.headers.get("Sec-GPC") == "1"
339
+ # ua = request.headers.get("User-Agent", "")[:200]
340
+ # ref = request.headers.get("Referer", "")[:200]
341
+ # vid, resp = _ensure_vid_cookie()
342
+ #
343
+ # # Allow only specific user fields if provided
344
+ # user = evt.get("user") if isinstance(evt.get("user"), dict) else {}
345
+ # allowed_user = {k: user[k] for k in ["id", "role", "org", "plan"] if k in user and isinstance(user[k], (str, int))}
346
+ #
347
+ # evt.update({
348
+ # "server_time": datetime.utcnow().isoformat() + "Z",
349
+ # "visitor_id": vid,
350
+ # "client_ip_truncated": _client_ip(),
351
+ # "user_agent": ua,
352
+ # "referer": ref,
353
+ # "dnt": dnt,
354
+ # "gpc": gpc,
355
+ # "user": allowed_user
356
+ # })
357
+ #
358
+ # logfile = os.path.join(current_app.root_path, 'analytics.log.jsonl')
359
+ # with open(logfile, 'a', encoding='utf-8') as f:
360
+ # f.write(json.dumps(evt, ensure_ascii=False) + '\n')
361
+ #
362
+ # return jsonify({'ok': True})
363
+ # except Exception as e:
364
+ # return jsonify({'ok': False, 'error': str(e)}), 400
365
+
366
+
367
  @main.route("/api/whoami", methods=["GET"])
368
  @cross_origin()
369
  def whoami():
370
  ua = request.headers.get("User-Agent", "")[:200]
371
  dnt = request.headers.get("DNT") == "1"
372
  gpc = request.headers.get("Sec-GPC") == "1"
373
+
374
+ payload = {"vid": request.cookies.get(COOKIE_NAME) or uuid.uuid4().hex,
375
+ "user_agent": ua, "dnt": dnt, "gpc": gpc}
376
+
377
+ resp = make_response(jsonify(payload))
378
+ if not request.cookies.get(COOKIE_NAME):
379
+ resp.set_cookie(COOKIE_NAME, payload["vid"], max_age=60*60*24*365*2,
380
+ httponly=True, secure=True, samesite="Lax", path="/")
381
+ return resp
382
+
383
 
384
  @main.route('/api/track', methods=['POST', 'OPTIONS'])
385
  @cross_origin()
 
393
  gpc = request.headers.get("Sec-GPC") == "1"
394
  ua = request.headers.get("User-Agent", "")[:200]
395
  ref = request.headers.get("Referer", "")[:200]
 
396
 
397
+ resp = make_response(jsonify({'ok': True}))
398
+ cookie_vid, resp = _ensure_vid_cookie(resp)
399
+
400
+ visitor_id = evt.get("vid") or cookie_vid
401
+ session_id = evt.get("sessionId")
402
+
403
  user = evt.get("user") if isinstance(evt.get("user"), dict) else {}
404
+ allowed_user = {k: user[k] for k in ["id", "role", "org", "plan"]
405
+ if k in user and isinstance(user[k], (str, int))}
406
 
407
  evt.update({
408
  "server_time": datetime.utcnow().isoformat() + "Z",
409
+ "visitor_id": visitor_id,
410
+ "session_id": session_id,
411
  "client_ip_truncated": _client_ip(),
412
  "user_agent": ua,
413
  "referer": ref,
 
416
  "user": allowed_user
417
  })
418
 
419
+ row = {
420
+ "visitor_id": str(visitor_id),
421
+ "session_id": str(session_id) if session_id else None,
422
+ "event_type": str(evt.get("eventType", "unknown")),
423
+ "payload": evt,
424
+ "user_agent": ua,
425
+ "referer": ref,
426
+ "client_ip_truncated": _client_ip(),
427
+ "dnt": dnt,
428
+ "gpc": gpc
429
+ }
430
+ supabase_insert_event(row)
431
+
432
+ return resp
433
 
 
434
  except Exception as e:
435
  return jsonify({'ok': False, 'error': str(e)}), 400
436
+
437
+
438
+
439
  # ===== End Analytics =====