dipan004 commited on
Commit
88ccef7
·
verified ·
1 Parent(s): 97f9664

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +181 -5
app.py CHANGED
@@ -84,13 +84,15 @@ app = FastAPI(
84
  lifespan=lifespan
85
  )
86
 
87
- # CORS middleware (configure as needed)
88
  app.add_middleware(
89
  CORSMiddleware,
90
- allow_origins=["*"], # Configure appropriately for production
91
  allow_credentials=True,
92
- allow_methods=["*"],
93
- allow_headers=["*"],
 
 
94
  )
95
 
96
 
@@ -134,6 +136,23 @@ class VerificationResponse(BaseModel):
134
  assistant: Optional[dict] = None
135
 
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  # ============================================================================
138
  # ERROR HANDLERS
139
  # ============================================================================
@@ -386,6 +405,160 @@ async def verify_proof(request: VerifyProofRequest):
386
  )
387
 
388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  # ============================================================================
390
  # AI ASSISTANT ENDPOINTS (OPTIONAL)
391
  # ============================================================================
@@ -436,7 +609,10 @@ async def root():
436
  "create_text_proof": "POST /proof/create/text",
437
  "create_file_proof": "POST /proof/create/file",
438
  "get_proof": "GET /proof/{proof_id}",
 
439
  "verify_proof": "POST /proof/verify",
 
 
440
  "ask_assistant": "POST /assistant/ask (optional)"
441
  }
442
  }
@@ -453,7 +629,7 @@ if __name__ == "__main__":
453
  uvicorn.run(
454
  "app:app",
455
  host="0.0.0.0",
456
- port=7860,
457
  reload=True, # Enable auto-reload in development
458
  log_level="info"
459
  )
 
84
  lifespan=lifespan
85
  )
86
 
87
+ # CORS middleware - PERMISSIVE for Flutter/Dreamflow
88
  app.add_middleware(
89
  CORSMiddleware,
90
+ allow_origins=["*"], # Allow all origins (Flutter web, HF spaces, localhost)
91
  allow_credentials=True,
92
+ allow_methods=["*"], # Allow all HTTP methods
93
+ allow_headers=["*"], # Allow all headers
94
+ expose_headers=["*"], # Expose all response headers
95
+ max_age=3600, # Cache preflight for 1 hour
96
  )
97
 
98
 
 
136
  assistant: Optional[dict] = None
137
 
138
 
139
+ # ============================================================================
140
+ # CORS PREFLIGHT HANDLER
141
+ # ============================================================================
142
+
143
+ @app.options("/{rest_of_path:path}")
144
+ async def preflight_handler(rest_of_path: str):
145
+ """Handle CORS preflight requests."""
146
+ return JSONResponse(
147
+ content={"message": "OK"},
148
+ headers={
149
+ "Access-Control-Allow-Origin": "*",
150
+ "Access-Control-Allow-Methods": "*",
151
+ "Access-Control-Allow-Headers": "*",
152
+ }
153
+ )
154
+
155
+
156
  # ============================================================================
157
  # ERROR HANDLERS
158
  # ============================================================================
 
405
  )
406
 
407
 
408
+ @app.post("/proof/verify/file")
409
+ async def verify_proof_with_file(
410
+ proof_id: str = Form(...),
411
+ file: UploadFile = File(...)
412
+ ):
413
+ """
414
+ Verify a proof by uploading the original file.
415
+
416
+ This endpoint:
417
+ 1. Accepts proof ID + file upload
418
+ 2. Retrieves original proof from storage
419
+ 3. Recomputes hash from uploaded file
420
+ 4. Compares hashes
421
+ 5. Returns verification result with original timestamp
422
+
423
+ Args:
424
+ proof_id: Unique proof identifier
425
+ file: Original file to verify
426
+
427
+ Returns:
428
+ - is_valid: True if hashes match, False if tampered
429
+ - original_hash: Hash from original proof
430
+ - computed_hash: Hash from uploaded file
431
+ - original_timestamp: When proof was created
432
+ - message: Human-readable result
433
+ """
434
+ if not orchestrator:
435
+ raise HTTPException(status_code=503, detail="Service not initialized")
436
+
437
+ logger.info(f"Verifying proof {proof_id} with file: {file.filename}")
438
+
439
+ # Read uploaded file
440
+ content = await file.read()
441
+
442
+ if len(content) == 0:
443
+ raise ValidationError("Uploaded file is empty")
444
+
445
+ # Verify proof
446
+ result = orchestrator.verify_proof(proof_id, content)
447
+
448
+ if not result["success"]:
449
+ raise HTTPException(
450
+ status_code=500,
451
+ detail=result.get("message", "Verification failed")
452
+ )
453
+
454
+ verification_result = result["verification_result"]
455
+
456
+ # Get original proof for timestamp
457
+ proof_result = orchestrator.get_proof(proof_id)
458
+ original_proof = proof_result.get("proof") if proof_result["success"] else None
459
+
460
+ return {
461
+ "success": True,
462
+ "is_valid": verification_result.is_valid,
463
+ "proof_id": proof_id,
464
+ "original_hash": verification_result.original_hash,
465
+ "computed_hash": verification_result.computed_hash,
466
+ "original_timestamp": original_proof.timestamp if original_proof else None,
467
+ "original_filename": original_proof.metadata.get("filename") if original_proof else None,
468
+ "file_size": len(content),
469
+ "message": verification_result.message,
470
+ "assistant": result.get("assistant")
471
+ }
472
+
473
+
474
+ @app.get("/proof/{proof_id}/details")
475
+ async def get_proof_details(proof_id: str):
476
+ """
477
+ Get detailed information about a proof by its ID.
478
+ Shows everything: hash, timestamp, file info, OCR results.
479
+
480
+ Args:
481
+ proof_id: Unique proof identifier
482
+
483
+ Returns:
484
+ Complete proof details including:
485
+ - Hash
486
+ - Original timestamp
487
+ - File name and size
488
+ - OCR results (if applicable)
489
+ - Content type
490
+ """
491
+ if not orchestrator:
492
+ raise HTTPException(status_code=503, detail="Service not initialized")
493
+
494
+ logger.info(f"Getting details for proof: {proof_id}")
495
+
496
+ result = orchestrator.get_proof(proof_id)
497
+
498
+ if not result["success"]:
499
+ raise ProofNotFoundError(f"Proof not found: {proof_id}")
500
+
501
+ proof = result["proof"]
502
+
503
+ return {
504
+ "success": True,
505
+ "proof_id": proof.proof_id,
506
+ "hash": proof.content_hash,
507
+ "hash_algorithm": proof.hash_algorithm,
508
+ "timestamp": proof.timestamp,
509
+ "content_type": proof.content_type,
510
+ "file_size": proof.content_size,
511
+ "filename": proof.metadata.get("filename"),
512
+ "ocr_status": proof.ocr_status,
513
+ "extracted_text": proof.extracted_text,
514
+ "message": "Proof details retrieved successfully"
515
+ }
516
+
517
+
518
+ @app.post("/proof/verify/hash")
519
+ async def verify_by_hash(
520
+ proof_id: str = Form(...),
521
+ hash_to_verify: str = Form(...)
522
+ ):
523
+ """
524
+ Verify a proof by comparing hashes directly.
525
+ Useful when you've computed the hash separately.
526
+
527
+ Args:
528
+ proof_id: Unique proof identifier
529
+ hash_to_verify: SHA-256 hash to compare
530
+
531
+ Returns:
532
+ Verification result with timestamp info
533
+ """
534
+ if not orchestrator:
535
+ raise HTTPException(status_code=503, detail="Service not initialized")
536
+
537
+ logger.info(f"Verifying proof {proof_id} with hash: {hash_to_verify[:16]}...")
538
+
539
+ # Get original proof
540
+ result = orchestrator.get_proof(proof_id)
541
+
542
+ if not result["success"]:
543
+ raise ProofNotFoundError(f"Proof not found: {proof_id}")
544
+
545
+ proof = result["proof"]
546
+
547
+ # Compare hashes
548
+ is_valid = proof.content_hash.lower() == hash_to_verify.lower()
549
+
550
+ return {
551
+ "success": True,
552
+ "is_valid": is_valid,
553
+ "proof_id": proof_id,
554
+ "original_hash": proof.content_hash,
555
+ "provided_hash": hash_to_verify,
556
+ "original_timestamp": proof.timestamp,
557
+ "original_filename": proof.metadata.get("filename"),
558
+ "message": "Hash match: proof is valid" if is_valid else "Hash mismatch: content has been modified"
559
+ }
560
+
561
+
562
  # ============================================================================
563
  # AI ASSISTANT ENDPOINTS (OPTIONAL)
564
  # ============================================================================
 
609
  "create_text_proof": "POST /proof/create/text",
610
  "create_file_proof": "POST /proof/create/file",
611
  "get_proof": "GET /proof/{proof_id}",
612
+ "get_proof_details": "GET /proof/{proof_id}/details",
613
  "verify_proof": "POST /proof/verify",
614
+ "verify_proof_file": "POST /proof/verify/file",
615
+ "verify_proof_hash": "POST /proof/verify/hash",
616
  "ask_assistant": "POST /assistant/ask (optional)"
617
  }
618
  }
 
629
  uvicorn.run(
630
  "app:app",
631
  host="0.0.0.0",
632
+ port=8000,
633
  reload=True, # Enable auto-reload in development
634
  log_level="info"
635
  )