fix: scan logic file whitelist + rescan route (#6585)

* explicitly only scan jar/zip/disabled files for attributions

* add route to force scan file

* prepare
This commit is contained in:
aecsocket
2026-07-02 16:33:16 +00:00
committed by GitHub
parent a5ebc85356
commit eb28121c0a
14 changed files with 405 additions and 10 deletions
@@ -3,17 +3,18 @@ use chrono::{DateTime, Utc};
use eyre::eyre;
use serde::{Deserialize, Serialize};
use crate::auth::get_user_from_headers;
use crate::auth::{check_is_moderator_from_headers, get_user_from_headers};
use crate::database::PgPool;
use crate::database::models::{
DBOrganization, DBTeamMember, DBVersion,
DBFileId, DBOrganization, DBTeamMember, DBVersion,
ids::{
DBAttributionGroupId, DBProjectId, DBVersionId,
generate_attribution_group_id,
},
};
use crate::database::redis::RedisPool;
use crate::models::ids::{ProjectId, VersionId};
use crate::file_hosting::FileHost;
use crate::models::ids::{FileId, ProjectId, VersionId};
use crate::models::pats::Scopes;
use crate::models::projects::{
AttributionModerationStatusKind, AttributionResolution,
@@ -21,6 +22,7 @@ use crate::models::projects::{
};
use crate::models::teams::ProjectPermissions;
use crate::models::users::User;
use crate::queue::file_scan::{FileScanSummary, scan_file};
use crate::queue::moderation::ApprovalType;
use crate::queue::session::AuthQueue;
use crate::routes::ApiError;
@@ -30,6 +32,7 @@ pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) {
cfg.service(list)
.service(update_group)
.service(scan)
.service(force_scan_file)
.service(assign)
.service(split);
}
@@ -201,6 +204,80 @@ async fn scan(
}))
}
#[utoipa::path]
#[post("/file/{file_id}/scan")]
async fn force_scan_file(
req: HttpRequest,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
file_host: web::Data<dyn FileHost>,
path: web::Path<FileId>,
) -> Result<web::Json<FileScanSummary>, ApiError> {
check_is_moderator_from_headers(
&req,
&**pool,
&redis,
&session_queue,
Scopes::PROJECT_READ,
)
.await?;
let file_id: DBFileId = path.into_inner().into();
let file = sqlx::query!(
r#"
select
f.url,
f.version_id as "version_id: DBVersionId",
v.mod_id as "project_id: DBProjectId"
from files f
inner join versions v on v.id = f.version_id
where f.id = $1
"#,
file_id as DBFileId,
)
.fetch_optional(pool.as_ref())
.await
.wrap_internal_err("failed to fetch attribution scan file")?
.ok_or(ApiError::NotFound)?;
let mut transaction = pool.begin().await.wrap_internal_err(
"failed to begin attribution file scan transaction",
)?;
sqlx::query!(
r#"
delete from attributions_exemptions
where version_id = $1
"#,
file.version_id as DBVersionId,
)
.execute(&mut transaction)
.await
.wrap_internal_err("failed to remove attribution scan exemption")?;
let scan_summary = scan_file(
&mut transaction,
redis.as_ref(),
&**file_host,
file.project_id,
file_id,
&file.url,
)
.await
.wrap_internal_err("failed to scan file for attributions")?;
transaction.commit().await.wrap_internal_err(
"failed to commit attribution file scan transaction",
)?;
DBVersion::clear_cache_ids(&[file.version_id], redis.as_ref())
.await
.wrap_internal_err("failed to clear version cache")?;
Ok(web::Json(scan_summary))
}
#[utoipa::path]
#[get("/{project_id}")]
async fn list(