Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions receipt-scanner-app/receipt-scanner-backend/.env
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ DATABASE_URL=sqlite:///./receipts.db

# オプション: セキュリティ設定
SECRET_KEY=dev-secret-key-change-in-production
DISABLE_AUTH=true

# オプション: レート制限設定
RATE_LIMIT_REQUESTS=10
Expand Down
3 changes: 3 additions & 0 deletions receipt-scanner-app/receipt-scanner-backend/RAILWAY_ENV.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ Railwayのダッシュボードで以下の環境変数を設定してくださ
```
OPENAI_API_KEY=sk-your-actual-api-key
ENVIRONMENT=production
DISABLE_AUTH=true
```

**注意**: `DISABLE_AUTH=true`は一時的な設定です。本格運用時は認証機能を有効にしてください。

## 重要な環境変数(CORS設定)

```
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
30 changes: 29 additions & 1 deletion receipt-scanner-app/receipt-scanner-backend/app/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@

# HTTP Bearer scheme
security = HTTPBearer()
optional_security = HTTPBearer(auto_error=False)

def create_fake_test_user() -> User:
"""Create a fake test user for development purposes."""
return User(
id=9999,
username="test_user",
email="test@example.com",
is_active=True,
hashed_password=get_password_hash("test_password")
)

def verify_password(plain_password: str, hashed_password: str) -> bool:
"""Verify a password against its hash."""
Expand Down Expand Up @@ -124,4 +135,21 @@ async def get_current_active_user(current_user: User = Depends(get_current_user)
"""Get the current active user."""
if not current_user.is_active:
raise HTTPException(status_code=400, detail="Inactive user")
return current_user
return current_user

async def get_current_active_user_optional(
credentials: Optional[HTTPAuthorizationCredentials] = Depends(optional_security),
db: Session = Depends(get_db)
) -> User:
"""
Get current active user with optional authentication.
If DISABLE_AUTH is true, returns a fake test user.
"""
# Check if auth is disabled
if settings.disable_auth:
logger.warning("Authentication is disabled - using test user")
return create_fake_test_user()

# If auth is enabled, use normal authentication
return await get_current_active_user(credentials, db)

3 changes: 3 additions & 0 deletions receipt-scanner-app/receipt-scanner-backend/app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ def __init__(self):
# JWT configuration
self.jwt_expire_minutes = int(os.getenv("JWT_EXPIRE_MINUTES", "30"))

# Authentication bypass for development
self.disable_auth = os.getenv("DISABLE_AUTH", "false").lower() == "true"

# Validate configuration
self._validate_config()

Expand Down
20 changes: 10 additions & 10 deletions receipt-scanner-app/receipt-scanner-backend/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from app.receipt_processor import ReceiptProcessor
from app.database import get_db, engine, Base
from app.db_models import Receipt as ReceiptDB, User
from app.auth import get_current_active_user
from app.auth import get_current_active_user, get_current_active_user_optional
from app.auth_routes import router as auth_router

# Configure logging
Expand Down Expand Up @@ -222,7 +222,7 @@ async def upload_receipt(
file: UploadFile = File(...),
processing_mode: Optional[str] = Query(None, description="Processing mode: 'ai', 'ocr', 'vision', or 'auto'"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user)
current_user: User = Depends(get_current_active_user_optional)
):
"""
Upload and process a receipt image.
Expand Down Expand Up @@ -391,7 +391,7 @@ async def analyze_receipt(
request: Request,
file: UploadFile = File(...),
detailed: bool = Query(False, description="Return detailed analysis"),
current_user: User = Depends(get_current_active_user)
current_user: User = Depends(get_current_active_user_optional)
):
"""
Analyze receipt image and return detailed information without saving.
Expand Down Expand Up @@ -478,7 +478,7 @@ async def get_receipts(
skip: int = Query(0, ge=0, description="Number of receipts to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum number of receipts to return"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user)
current_user: User = Depends(get_current_active_user_optional)
):
"""Get receipts with pagination support."""
try:
Expand Down Expand Up @@ -512,7 +512,7 @@ async def get_receipts(
async def get_receipt(
receipt_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user)
current_user: User = Depends(get_current_active_user_optional)
):
"""Get a specific receipt by ID."""
try:
Expand All @@ -537,7 +537,7 @@ async def update_receipt(
receipt_id: int,
receipt_data: ReceiptData,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user)
current_user: User = Depends(get_current_active_user_optional)
):
"""Update a specific receipt."""
try:
Expand Down Expand Up @@ -576,7 +576,7 @@ async def update_receipt(
async def delete_receipt(
receipt_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user)
current_user: User = Depends(get_current_active_user_optional)
):
"""Delete a specific receipt."""
try:
Expand Down Expand Up @@ -614,7 +614,7 @@ async def delete_receipt(
@app.get("/api/receipts/export/csv")
async def export_receipts_csv(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user)
current_user: User = Depends(get_current_active_user_optional)
):
"""Export receipts as CSV."""
try:
Expand Down Expand Up @@ -700,7 +700,7 @@ async def export_receipts_csv(
@app.get("/api/stats")
async def get_statistics(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user)
current_user: User = Depends(get_current_active_user_optional)
):
"""Get enhanced receipt statistics."""
try:
Expand Down Expand Up @@ -773,7 +773,7 @@ async def get_statistics(
async def get_receipt_image(
receipt_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user)
current_user: User = Depends(get_current_active_user_optional)
):
"""Get the original image for a receipt."""
try:
Expand Down
30 changes: 18 additions & 12 deletions receipt-scanner-app/receipt-scanner-frontend/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,19 +228,25 @@ export async function updateReceipt(receiptId: number, data: any): Promise<ApiRe
}

export async function exportReceipts(): Promise<string> {
const response = await apiRequest<ExportResponse>(`${API_URL}/api/receipts/export`);

// Properly access csv_data from the response
if (response.data && 'csv_data' in response.data) {
return response.data.csv_data;
}

// Fallback for backward compatibility
if (response.data && typeof response.data === 'string') {
return response.data;
try {
const response = await fetch(`${API_URL}/api/receipts/export/csv`, {
method: 'GET',
headers: {
'Accept': 'text/csv',
},
});

if (!response.ok) {
throw new Error(`Export failed: ${response.status}`);
}

// Get the CSV content directly from the response
const csvContent = await response.text();
return csvContent;
} catch (error) {
console.error('Export error:', error);
throw error;
}

return '';
}

export async function testUploadReceipt(): Promise<ApiResponse> {
Expand Down
Loading