updates
This commit is contained in:
@@ -24,6 +24,14 @@ router = APIRouter(prefix='/invoices', tags=['invoices'])
|
||||
@router.get('/')
|
||||
async def get_invoices(request: Request, booking_id: Optional[int]=Query(None), status_filter: Optional[str]=Query(None, alias='status'), page: int=Query(1, ge=1), limit: int=Query(10, ge=1, le=100), current_user: User=Depends(get_current_user), db: Session=Depends(get_db)):
|
||||
try:
|
||||
# SECURITY: Verify booking ownership when booking_id is provided
|
||||
if booking_id and not can_access_all_invoices(current_user, db):
|
||||
booking = db.query(Booking).filter(Booking.id == booking_id).first()
|
||||
if not booking:
|
||||
raise HTTPException(status_code=404, detail='Booking not found')
|
||||
if booking.user_id != current_user.id:
|
||||
raise HTTPException(status_code=403, detail='Forbidden: You do not have permission to access invoices for this booking')
|
||||
|
||||
user_id = None if can_access_all_invoices(current_user, db) else current_user.id
|
||||
result = InvoiceService.get_invoices(db=db, user_id=user_id, booking_id=booking_id, status=status_filter, page=page, limit=limit)
|
||||
return success_response(data=result)
|
||||
@@ -38,8 +46,10 @@ async def get_invoice_by_id(id: int, current_user: User=Depends(get_current_user
|
||||
invoice = InvoiceService.get_invoice(id, db)
|
||||
if not invoice:
|
||||
raise HTTPException(status_code=404, detail='Invoice not found')
|
||||
if not can_access_all_invoices(current_user, db) and invoice['user_id'] != current_user.id:
|
||||
raise HTTPException(status_code=403, detail='Forbidden')
|
||||
# SECURITY: Verify invoice ownership for non-admin/accountant users
|
||||
if not can_access_all_invoices(current_user, db):
|
||||
if 'user_id' not in invoice or invoice['user_id'] != current_user.id:
|
||||
raise HTTPException(status_code=403, detail='Forbidden: You do not have permission to access this invoice')
|
||||
return success_response(data={'invoice': invoice})
|
||||
except HTTPException:
|
||||
raise
|
||||
@@ -48,9 +58,10 @@ async def get_invoice_by_id(id: int, current_user: User=Depends(get_current_user
|
||||
logger.error(f'Error fetching invoice by id: {str(e)}', exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.post('/')
|
||||
async def create_invoice(request: Request, invoice_data: CreateInvoiceRequest, current_user: User=Depends(get_current_user), db: Session=Depends(get_db)):
|
||||
@router.post('/', dependencies=[Depends(authorize_roles('admin', 'staff', 'accountant'))])
|
||||
async def create_invoice(request: Request, invoice_data: CreateInvoiceRequest, current_user: User=Depends(authorize_roles('admin', 'staff', 'accountant')), db: Session=Depends(get_db)):
|
||||
try:
|
||||
# Defense in depth: Additional business logic check (authorize_roles already verified)
|
||||
if not can_create_invoices(current_user, db):
|
||||
raise HTTPException(status_code=403, detail='Forbidden')
|
||||
booking_id = invoice_data.booking_id
|
||||
@@ -137,13 +148,46 @@ async def mark_invoice_as_paid(request: Request, id: int, payment_data: MarkInvo
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.delete('/{id}')
|
||||
async def delete_invoice(id: int, current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)):
|
||||
async def delete_invoice(id: int, request: Request, current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)):
|
||||
client_ip = request.client.host if request.client else None
|
||||
user_agent = request.headers.get('User-Agent')
|
||||
request_id = get_request_id(request)
|
||||
|
||||
try:
|
||||
invoice = db.query(Invoice).filter(Invoice.id == id).first()
|
||||
if not invoice:
|
||||
raise HTTPException(status_code=404, detail='Invoice not found')
|
||||
|
||||
# Capture invoice info before deletion for audit
|
||||
deleted_invoice_info = {
|
||||
'invoice_id': invoice.id,
|
||||
'invoice_number': invoice.invoice_number,
|
||||
'user_id': invoice.user_id,
|
||||
'booking_id': invoice.booking_id,
|
||||
'total_amount': float(invoice.total_amount) if invoice.total_amount else 0.0,
|
||||
'status': invoice.status.value if hasattr(invoice.status, 'value') else str(invoice.status),
|
||||
}
|
||||
|
||||
db.delete(invoice)
|
||||
db.commit()
|
||||
|
||||
# SECURITY: Log invoice deletion for audit trail
|
||||
try:
|
||||
await audit_service.log_action(
|
||||
db=db,
|
||||
action='invoice_deleted',
|
||||
resource_type='invoice',
|
||||
user_id=current_user.id,
|
||||
resource_id=id,
|
||||
ip_address=client_ip,
|
||||
user_agent=user_agent,
|
||||
request_id=request_id,
|
||||
details=deleted_invoice_info,
|
||||
status='success'
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f'Failed to log invoice deletion audit: {e}')
|
||||
|
||||
return success_response(message='Invoice deleted successfully')
|
||||
except HTTPException:
|
||||
raise
|
||||
|
||||
Reference in New Issue
Block a user