From 333647d88ddcb271a072162d138993542e8349df Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Mon, 21 Sep 2026 12:54:54 -0400 Subject: [PATCH] feat: route for delphi to look up file based on file id --- ...c03a7444a882da3364be924c2c220e8402b8f.json | 46 ++++++++++++++ .../src/routes/internal/delphi/mod.rs | 63 +++++++++++++++++-- apps/labrinth/src/routes/internal/mod.rs | 1 + 3 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 apps/labrinth/.sqlx/query-f07c8b1dc869c8c7836d769efe2c03a7444a882da3364be924c2c220e8402b8f.json diff --git a/apps/labrinth/.sqlx/query-f07c8b1dc869c8c7836d769efe2c03a7444a882da3364be924c2c220e8402b8f.json b/apps/labrinth/.sqlx/query-f07c8b1dc869c8c7836d769efe2c03a7444a882da3364be924c2c220e8402b8f.json new file mode 100644 index 00000000000..436f92af95c --- /dev/null +++ b/apps/labrinth/.sqlx/query-f07c8b1dc869c8c7836d769efe2c03a7444a882da3364be924c2c220e8402b8f.json @@ -0,0 +1,46 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n files.url,\n files.filename,\n files.size,\n files.version_id AS \"version_id: DBVersionId\",\n versions.mod_id AS \"project_id: DBProjectId\"\n FROM files INNER JOIN versions ON files.version_id = versions.id\n WHERE files.id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "url", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "filename", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "size", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "version_id: DBVersionId", + "type_info": "Int8" + }, + { + "ordinal": 4, + "name": "project_id: DBProjectId", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false + ] + }, + "hash": "f07c8b1dc869c8c7836d769efe2c03a7444a882da3364be924c2c220e8402b8f" +} diff --git a/apps/labrinth/src/routes/internal/delphi/mod.rs b/apps/labrinth/src/routes/internal/delphi/mod.rs index 29656d1fdcf..e6e68f5f93c 100644 --- a/apps/labrinth/src/routes/internal/delphi/mod.rs +++ b/apps/labrinth/src/routes/internal/delphi/mod.rs @@ -7,7 +7,7 @@ use crate::{database::PgPool, util::http::HttpClient}; use actix_web::{HttpRequest, HttpResponse, get, post, web}; use chrono::{DateTime, Utc}; use eyre::eyre; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use tokio::sync::Mutex; use tracing::info; use uuid::Uuid; @@ -17,8 +17,8 @@ use crate::{ database::{ advisory_lock::AdvisoryLock, models::{ - DBFileId, DBProjectId, DelphiReportId, DelphiReportIssueDetailsId, - DelphiReportIssueId, + DBFileId, DBProjectId, DBVersionId, DelphiReportId, + DelphiReportIssueDetailsId, DelphiReportIssueId, delphi_report_item::{ DBDelphiReport, DBDelphiReportIssue, DelphiSeverity, DelphiStatus, ReportIssueDetail, @@ -26,7 +26,7 @@ use crate::{ }, }, models::{ - ids::{ProjectId, VersionId}, + ids::{FileId, ProjectId, VersionId}, pats::Scopes, }, queue::session::AuthQueue, @@ -42,6 +42,7 @@ pub fn config(cfg: &mut actix_web::web::ServiceConfig) { web::scope("/delphi") .service(ingest_report) .service(_run) + .service(get_file) .service(version) .service(issue_type_schema), ); @@ -405,6 +406,60 @@ pub async fn _run( Ok(HttpResponse::NoContent().finish()) } +#[derive(Debug, Serialize, utoipa::ToSchema)] +pub struct DelphiFile { + pub id: FileId, + pub url: String, + pub file_name: String, + pub size: i32, + pub version_id: VersionId, + pub project_id: ProjectId, +} + +/// Resolve a file ID to the file it refers to. +#[utoipa::path( + context_path = "/delphi", + tag = "delphi", + params(("file_id" = FileId, Path)), + responses( + (status = OK, body = DelphiFile), + (status = NOT_FOUND), + ) +)] +#[get("/file/{file_id}", guard = "admin_key_guard")] +pub async fn get_file( + pool: web::Data, + path: web::Path, +) -> Result, ApiError> { + let file_id = path.into_inner(); + let file = sqlx::query!( + r#" + SELECT + files.url, + files.filename, + files.size, + files.version_id AS "version_id: DBVersionId", + versions.mod_id AS "project_id: DBProjectId" + FROM files INNER JOIN versions ON files.version_id = versions.id + WHERE files.id = $1 + "#, + DBFileId::from(file_id) as DBFileId, + ) + .fetch_optional(&**pool) + .await + .wrap_internal_err("fetching file from database")? + .wrap_not_found_err("file not found")?; + + Ok(web::Json(DelphiFile { + id: file_id, + url: file.url, + file_name: file.filename, + size: file.size, + version_id: file.version_id.into(), + project_id: file.project_id.into(), + })) +} + /// Get the Delphi version. #[utoipa::path( context_path = "/delphi", diff --git a/apps/labrinth/src/routes/internal/mod.rs b/apps/labrinth/src/routes/internal/mod.rs index c3852ec0474..cf6301f11f1 100644 --- a/apps/labrinth/src/routes/internal/mod.rs +++ b/apps/labrinth/src/routes/internal/mod.rs @@ -178,6 +178,7 @@ pub fn config(cfg: &mut web::ServiceConfig) { billing::credit, delphi::ingest_report, delphi::_run, + delphi::get_file, delphi::version, delphi::issue_type_schema, external_notifications::create,