Add attachment deletion route and automatic cleanup on record deletion
Co-authored-by: aiulian25 <17886483+aiulian25@users.noreply.github.com>
This commit is contained in:
parent
0eb54dfd30
commit
90143f7dc0
2 changed files with 76 additions and 0 deletions
|
|
@ -85,6 +85,41 @@ Download or view an attachment.
|
|||
|
||||
---
|
||||
|
||||
### Delete Attachment
|
||||
Delete an attachment file.
|
||||
|
||||
**Endpoint:** `DELETE /api/attachments/delete`
|
||||
|
||||
**Authentication:** Required
|
||||
|
||||
**Query Parameters:**
|
||||
- `path` (required): Relative path to the attachment (e.g., `attachments/filename.pdf`)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Attachment deleted successfully"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses:**
|
||||
- 400: No file path provided
|
||||
- 403: Invalid file path (security violation)
|
||||
- 404: File not found
|
||||
- 500: Server error during deletion
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
await fetch(`/api/attachments/delete?path=${encodeURIComponent(filePath)}`, {
|
||||
method: 'DELETE',
|
||||
credentials: 'include'
|
||||
});
|
||||
```
|
||||
|
||||
**Note:** When deleting a fuel record, service record, or recurring expense, the associated attachment is automatically deleted.
|
||||
|
||||
---
|
||||
|
||||
## Data Models
|
||||
|
||||
### FuelRecord
|
||||
|
|
|
|||
|
|
@ -418,6 +418,29 @@ def download_attachment():
|
|||
|
||||
return send_from_directory(directory, filename, as_attachment=True)
|
||||
|
||||
@app.route('/api/attachments/delete', methods=['DELETE'])
|
||||
@login_required
|
||||
def delete_attachment():
|
||||
"""Delete an attachment file. Only the file owner can delete it."""
|
||||
file_path = request.args.get('path')
|
||||
|
||||
if not file_path:
|
||||
return jsonify({'error': 'No file path provided'}), 400
|
||||
|
||||
full_path = os.path.join('/app/uploads', file_path)
|
||||
|
||||
if not full_path.startswith('/app/uploads'):
|
||||
return jsonify({'error': 'Invalid file path'}), 403
|
||||
|
||||
if not os.path.exists(full_path):
|
||||
return jsonify({'error': 'File not found'}), 404
|
||||
|
||||
try:
|
||||
os.remove(full_path)
|
||||
return jsonify({'message': 'Attachment deleted successfully'}), 200
|
||||
except Exception as e:
|
||||
return jsonify({'error': f'Failed to delete attachment: {str(e)}'}), 500
|
||||
|
||||
@app.route('/api/vehicles/<int:vehicle_id>', methods=['GET', 'PUT', 'DELETE'])
|
||||
@login_required
|
||||
def vehicle_detail(vehicle_id):
|
||||
|
|
@ -827,6 +850,15 @@ def service_record_operations(vehicle_id, record_id):
|
|||
return jsonify({'message': 'Service record updated successfully'})
|
||||
|
||||
elif request.method == 'DELETE':
|
||||
# Clean up attachment if it exists
|
||||
if record.document_path:
|
||||
try:
|
||||
full_path = os.path.join('/app/uploads', record.document_path)
|
||||
if os.path.exists(full_path):
|
||||
os.remove(full_path)
|
||||
except Exception as e:
|
||||
print(f"Failed to delete attachment: {e}")
|
||||
|
||||
db.session.delete(record)
|
||||
db.session.commit()
|
||||
return jsonify({'message': 'Service record deleted successfully'})
|
||||
|
|
@ -861,6 +893,15 @@ def fuel_record_operations(vehicle_id, record_id):
|
|||
return jsonify({'message': 'Fuel record updated successfully'})
|
||||
|
||||
elif request.method == 'DELETE':
|
||||
# Clean up attachment if it exists
|
||||
if record.document_path:
|
||||
try:
|
||||
full_path = os.path.join('/app/uploads', record.document_path)
|
||||
if os.path.exists(full_path):
|
||||
os.remove(full_path)
|
||||
except Exception as e:
|
||||
print(f"Failed to delete attachment: {e}")
|
||||
|
||||
db.session.delete(record)
|
||||
db.session.commit()
|
||||
return jsonify({'message': 'Fuel record deleted successfully'})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue