1
+ import datetime
1
2
import time
2
-
3
- from fastapi import FastAPI , Request
3
+ from typing import Annotated
4
+ from fastapi import Body , FastAPI , Response , Query
4
5
from fastapi .middleware .cors import CORSMiddleware
5
6
6
7
import api .ollama as ollama
7
8
from data .helper import get_content_list
8
- from data .db_types import Recommendation , Response
9
+ from data .types import Recommendation , Response , Content
9
10
from my_db import Session
10
- from models .models import Finding
11
- from models . models import Recommendation as DBRecommendation
11
+ import models .models as db_models
12
+
12
13
13
- # from data.Findings import Findings
14
+ import data .apischema as apischema
14
15
16
+ from sqlalchemy import Date , cast
15
17
16
18
app = FastAPI ()
17
19
20
+
18
21
app .add_middleware (
19
22
CORSMiddleware ,
20
23
allow_origins = ['*' ],
@@ -47,42 +50,51 @@ def health():
47
50
48
51
49
52
@app .post ('/upload' )
50
- async def upload (request : Request , response : Response ):
53
+ async def upload (data : Annotated [ apischema . StartRecommendationTaskRequest , Body (...)] ):
51
54
"""
52
55
This function takes the string from the request and converts it to a data object.
53
56
:return: 200 OK if the data is valid, 400 BAD REQUEST otherwise.
54
57
"""
55
58
56
- try :
57
- json_data = await request .json ()
58
- except Exception as e :
59
- response .status_code = 400
60
- return 'Invalid JSON data'
61
-
62
- # Check if the JSON data is valid
63
- # TODO: fix required properties for eg cvss_rating_list is not required
64
- # if not validate_json(json_data):
65
- # return 'Invalid JSON data', 400
66
-
67
- # Convert into Response object
68
- response = Response .validate (json_data )
69
-
70
59
# get the content list
71
- content_list = get_content_list (response )
60
+ content_list = get_content_list (data . data )
72
61
73
62
with Session () as s :
74
- for c in content_list :
75
- find = Finding (finding = c .title_list [0 ].element , content = c .json ())
76
- s .add (find )
77
- s .commit ()
63
+ today = datetime .datetime .now ().date ()
64
+ existing_task = s .query (db_models .RecommendationTask ).filter (cast (db_models .RecommendationTask .created_at ,Date )== today ).order_by (db_models .RecommendationTask .created_at ).first ()
65
+ if existing_task and data .force_update is False :
66
+
67
+ return 'Recommendation task already exists for today' , 400
68
+
69
+ if (data .force_update ):
70
+ # Will nuke old task with all its findings.
71
+ if (existing_task .status == db_models .TaskStatus .PENDING ):
72
+ return 'Recommendation task is already processing, cannot exit' , 400
73
+
74
+ s .query (db_models .RecommendationTask ).filter (db_models .RecommendationTask .id == existing_task .id ).delete ()
75
+ s .commit ()
76
+ s .delete (existing_task )
77
+ s .commit ()
78
+
79
+ recommendation_task = db_models .RecommendationTask ()
80
+
81
+ s .add (recommendation_task )
82
+ s .commit ()
83
+ s .flush ()
84
+ s .refresh (recommendation_task )
85
+ for c in content_list :
86
+ find = db_models .Finding ().from_data (c )
87
+ find .recommendation_task_id = recommendation_task .id
88
+ s .add (find )
89
+ s .commit ()
78
90
# start subprocess for processing the data
79
91
# ...
80
92
81
93
return 'Data uploaded successfully'
82
94
83
95
84
96
@app .get ('/recommendations' )
85
- def recommendations ():
97
+ def recommendations (request : Annotated [ apischema . GetRecommendationRequest , Query (...)] ):
86
98
"""
87
99
This function returns the recommendations from the data.
88
100
:return: 200 OK with the recommendations or 204 NO CONTENT if there are no recommendations with retry-after header.
@@ -91,13 +103,20 @@ def recommendations():
91
103
# get the findings
92
104
# ...
93
105
with Session () as s :
94
- recs = s .query (DBRecommendation ).all ()
95
-
96
- recommendations = [Recommendation (recommendation = 'aa' , generic = True ) for r in recs ]
97
- # get the recommendations
98
-
99
- if recommendations :
100
- return recommendations , 200
106
+ total_count = s .query (db_models .Finding ).count ()
107
+ recs = s .query (db_models .Finding ).join (db_models .RecommendationTask ).offset (request .pagination .offset ).limit (request .pagination .limit ).all ()
108
+ findings = apischema .GetRecommendationResponse (
109
+ items = [apischema .GetRecommendationResponseItem (
110
+ description_short = "this is a short description" ,
111
+ description_long = "this is a long description" ,
112
+ finding = 'finding'
113
+
114
+ ) for r in recs ],
115
+ pagination = apischema .Pagination (offset = request .pagination .offset , limit = request .pagination .limit ,total = total_count )
116
+ )
117
+
118
+ if findings :
119
+ return findings , 200
101
120
else :
102
121
return 'No recommendations found' , 204 , {'Retry-After' : 60 }
103
122
0 commit comments