Skip to content

Commit 0ca69ed

Browse files
committed
refactore the structure of the backend services - dto - routes - models
1 parent 6444051 commit 0ca69ed

40 files changed

+2497
-1930
lines changed

backend/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
.env
2+
*/__pycache__/
3+
*.pyc
4+
*.log

backend/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ flask_wtf
55
flask_cors
66
pytz
77
requests
8+
pydantic
89
python-dotenv
910
psycopg2-binary
1011
GitPython

backend/routes/History.py

Lines changed: 14 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,22 @@
11
from flask import Blueprint, request, jsonify
2-
from routes.checkov import logger
3-
from utils.db import db
4-
from models.scan_history import ScanHistory
5-
from models.file_content import FileContent
2+
from services.history_service import get_scan_history
3+
from schemas.history_dto import ScanHistoryResponse, HistoryErrorResponse
4+
import logging
65

7-
history_bp = Blueprint('history', __name__)
6+
history_bp = Blueprint("history", __name__)
7+
logger = logging.getLogger(__name__)
88

99
@history_bp.route("/history", methods=["GET"])
10-
def get_scan_history():
10+
def get_scan_history_route():
1111
user_id = request.headers.get("X-User-ID")
12-
if not user_id:
13-
return jsonify({"error": "user_id is required"}), 400
14-
1512
scan_type = request.args.get("scan_type")
1613

1714
try:
18-
# Base query
19-
query = ScanHistory.query.filter_by(user_id=user_id)
20-
21-
# Add scan_type filter if provided
22-
if scan_type:
23-
query = query.filter_by(scan_type=scan_type)
24-
25-
# Order by created_at DESC
26-
query = query.order_by(ScanHistory.created_at.desc())
27-
28-
history = []
29-
for scan in query.all():
30-
item_name = None
31-
if scan.input_type:
32-
file_content = FileContent.query.filter_by(scan_id=scan.id).first()
33-
if file_content:
34-
item_name = f"{file_content.file_path} {file_content.id}"
35-
logger.debug(f"Item name for scan_id {scan.id}: {item_name}")
36-
37-
element = {
38-
"id": scan.id,
39-
"repo_id": scan.repo_id,
40-
"scan_result": scan.scan_result,
41-
"repo_url": scan.repo_url,
42-
"item_name": item_name,
43-
"status": scan.status,
44-
"score": scan.score,
45-
"compliant": scan.compliant,
46-
"created_at": scan.created_at.isoformat(),
47-
"input_type": scan.input_type,
48-
"scan_type": scan.scan_type
49-
}
50-
history.append(element)
51-
52-
return jsonify(history)
53-
except Exception as e:
54-
logger.error(f"Failed to fetch scan history for user_id {user_id}: {str(e)}")
55-
db.session.rollback()
56-
return jsonify({"error": "Failed to fetch scan history"}), 500
15+
history = get_scan_history(user_id, scan_type)
16+
return jsonify([ScanHistoryResponse(**item).dict() for item in history]), 200
17+
except ValueError as e:
18+
logger.error(f"Invalid input for scan history: {str(e)}")
19+
return jsonify(HistoryErrorResponse(error=str(e)).dict()), 400
20+
except RuntimeError as e:
21+
logger.error(f"Error fetching scan history: {str(e)}")
22+
return jsonify(HistoryErrorResponse(error=str(e)).dict()), 500

backend/routes/admin.py

Lines changed: 14 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,23 @@
11
from flask import Blueprint, jsonify
22
from flask_jwt_extended import jwt_required, get_jwt_identity
3-
from utils.db import db
4-
from models.user import User
5-
from models.scan_history import ScanHistory
6-
from sqlalchemy import func
3+
from services.admin_service import get_admin_stats
4+
from schemas.admin_dto import AdminStatsResponse
5+
from pydantic import ValidationError
76

87
admin_bp = Blueprint("admin", __name__)
98

109
@admin_bp.route("/api/admin-stats", methods=["GET"])
1110
@jwt_required()
12-
def get_admin_stats():
13-
user_id = get_jwt_identity()
14-
11+
def get_admin_stats_route():
1512
try:
16-
# Verify user is admin
17-
user = User.query.filter_by(id=user_id).first()
18-
if not user or user.role != "admin":
19-
return jsonify({"error": "Access denied: Admin role required"}), 403
20-
21-
# Get total users (with role 'user')
22-
total_users = User.query.filter_by(role="user").count()
23-
24-
# Get total scans
25-
total_scans = ScanHistory.query.count()
26-
27-
# Get user data with scan counts
28-
users = (
29-
db.session.query(
30-
User.id,
31-
User.name,
32-
User.email,
33-
User.role,
34-
User.created_at,
35-
func.count(ScanHistory.id).label("scan_count")
36-
)
37-
.outerjoin(ScanHistory, User.id == ScanHistory.user_id)
38-
.filter(User.role == "user")
39-
.group_by(User.id, User.name, User.email, User.role, User.created_at)
40-
.order_by(User.created_at.desc())
41-
.all()
42-
)
43-
44-
# Format users data for response
45-
users_data = [
46-
{
47-
"id": user.id,
48-
"name": user.name,
49-
"email": user.email,
50-
"role": user.role,
51-
"created_at": user.created_at.isoformat(),
52-
"scan_count": user.scan_count
53-
}
54-
for user in users
55-
]
56-
57-
return jsonify({
58-
"totalUsers": total_users,
59-
"totalScans": total_scans,
60-
"users": users_data
61-
})
62-
13+
user_id = get_jwt_identity()
14+
stats = get_admin_stats(user_id)
15+
return jsonify(AdminStatsResponse(**stats).dict()), 200
16+
except ValidationError as e:
17+
return jsonify({"error": e.errors()}), 400
18+
except ValueError as e:
19+
return jsonify({"error": str(e)}), 403
20+
except RuntimeError as e:
21+
return jsonify({"error": str(e)}), 500
6322
except Exception as e:
64-
print(f"❌ Error fetching admin stats: {e}")
65-
db.session.rollback()
66-
return jsonify({"error": "Internal server error"}), 500
23+
return jsonify({"error": f"Internal server error: {str(e)}"}), 500

0 commit comments

Comments
 (0)