1
1
use crate :: auth:: validate:: get_user_record_from_bearer_token;
2
+ use crate :: database:: models:: thread_item:: ThreadMessageBuilder ;
2
3
use crate :: database:: redis:: RedisPool ;
3
4
use crate :: models:: analytics:: Download ;
4
5
use crate :: models:: ids:: ProjectId ;
5
6
use crate :: models:: pats:: Scopes ;
7
+ use crate :: models:: threads:: MessageBody ;
6
8
use crate :: queue:: analytics:: AnalyticsQueue ;
7
9
use crate :: queue:: maxmind:: MaxMindIndexer ;
10
+ use crate :: queue:: moderation:: AUTOMOD_ID ;
8
11
use crate :: queue:: payouts:: PayoutsQueue ;
9
12
use crate :: queue:: session:: AuthQueue ;
10
13
use crate :: routes:: ApiError ;
@@ -17,13 +20,15 @@ use sqlx::PgPool;
17
20
use std:: collections:: HashMap ;
18
21
use std:: net:: Ipv4Addr ;
19
22
use std:: sync:: Arc ;
23
+ use log:: info;
20
24
21
25
pub fn config ( cfg : & mut web:: ServiceConfig ) {
22
26
cfg. service (
23
27
web:: scope ( "admin" )
24
28
. service ( count_download)
25
29
. service ( force_reindex)
26
- . service ( get_balances) ,
30
+ . service ( get_balances)
31
+ . service ( delphi_result_ingest) ,
27
32
) ;
28
33
}
29
34
@@ -178,3 +183,75 @@ pub async fn get_balances(
178
183
"tremendous" : tremendous,
179
184
} ) ) )
180
185
}
186
+
187
+ #[ derive( Deserialize ) ]
188
+ pub struct DelphiIngest {
189
+ pub url : String ,
190
+ pub project_id : crate :: models:: ids:: ProjectId ,
191
+ pub version_id : crate :: models:: ids:: VersionId ,
192
+ pub issues : Vec < String > ,
193
+ }
194
+
195
+ #[ post( "/_delphi" , guard = "admin_key_guard" ) ]
196
+ pub async fn delphi_result_ingest (
197
+ pool : web:: Data < PgPool > ,
198
+ redis : web:: Data < RedisPool > ,
199
+ body : web:: Json < DelphiIngest > ,
200
+ ) -> Result < HttpResponse , ApiError > {
201
+ if body. issues . is_empty ( ) {
202
+ info ! ( "No issues found for file {}" , body. url) ;
203
+ return Ok ( HttpResponse :: NoContent ( ) . finish ( ) ) ;
204
+ }
205
+
206
+ let webhook_url = dotenvy:: var ( "DELPHI_SLACK_WEBHOOK" ) ?;
207
+
208
+ let project = crate :: database:: models:: Project :: get_id (
209
+ body. project_id . into ( ) ,
210
+ & * * pool,
211
+ & redis,
212
+ )
213
+ . await ?
214
+ . ok_or_else ( || {
215
+ ApiError :: InvalidInput ( format ! (
216
+ "Project {} does not exist" ,
217
+ body. project_id
218
+ ) )
219
+ } ) ?;
220
+
221
+ crate :: util:: webhook:: send_slack_webhook (
222
+ body. project_id ,
223
+ & pool,
224
+ & redis,
225
+ webhook_url,
226
+ Some ( format ! (
227
+ "Suspicious traces found at {}. Traces: {}" ,
228
+ body. url,
229
+ body. issues. join( ", " )
230
+ ) ) ,
231
+ )
232
+ . await
233
+ . ok ( ) ;
234
+
235
+ let mut transaction = pool. begin ( ) . await ?;
236
+ ThreadMessageBuilder {
237
+ author_id : Some ( crate :: database:: models:: UserId ( AUTOMOD_ID ) ) ,
238
+ body : MessageBody :: Text {
239
+ body : format ! (
240
+ "WSR; Suspicious traces found for version_id {}. Traces: {}" ,
241
+ body. version_id,
242
+ body. issues. join( ", " )
243
+ ) ,
244
+ private : true ,
245
+ replying_to : None ,
246
+ associated_images : vec ! [ ] ,
247
+ } ,
248
+ thread_id : project. thread_id ,
249
+ hide_identity : false ,
250
+ }
251
+ . insert ( & mut transaction)
252
+ . await ?;
253
+
254
+ transaction. commit ( ) . await ?;
255
+
256
+ Ok ( HttpResponse :: NoContent ( ) . finish ( ) )
257
+ }
0 commit comments