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
|
## Data Models
|
||||||
|
|
||||||
### FuelRecord
|
### FuelRecord
|
||||||
|
|
|
||||||
|
|
@ -418,6 +418,29 @@ def download_attachment():
|
||||||
|
|
||||||
return send_from_directory(directory, filename, as_attachment=True)
|
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'])
|
@app.route('/api/vehicles/<int:vehicle_id>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
@login_required
|
@login_required
|
||||||
def vehicle_detail(vehicle_id):
|
def vehicle_detail(vehicle_id):
|
||||||
|
|
@ -827,6 +850,15 @@ def service_record_operations(vehicle_id, record_id):
|
||||||
return jsonify({'message': 'Service record updated successfully'})
|
return jsonify({'message': 'Service record updated successfully'})
|
||||||
|
|
||||||
elif request.method == 'DELETE':
|
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.delete(record)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return jsonify({'message': 'Service record deleted successfully'})
|
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'})
|
return jsonify({'message': 'Fuel record updated successfully'})
|
||||||
|
|
||||||
elif request.method == 'DELETE':
|
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.delete(record)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return jsonify({'message': 'Fuel record deleted successfully'})
|
return jsonify({'message': 'Fuel record deleted successfully'})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue