mirror of
https://github.com/modrinth/code.git
synced 2026-07-31 21:26:40 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d760c173a4 |
Generated
+34
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT DISTINCT d.mod_dependency_id as \"mod_dependency_id!\", dependent_version.mod_id dependent_project_id, d.dependency_type\n FROM dependencies d\n INNER JOIN versions dependent_version ON dependent_version.id = d.dependent_id\n WHERE d.mod_dependency_id = ANY($1)\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "mod_dependency_id!",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "dependent_project_id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "dependency_type",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8Array"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "7279d76dedd38306cba783844c84ff763aabf70eb8091a40c4ec9535b0d44a0c"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE INDEX dependencies_mod_dependency_id
|
||||
ON dependencies (mod_dependency_id);
|
||||
@@ -928,7 +928,15 @@ impl VersionType {
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, utoipa::ToSchema,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Hash,
|
||||
utoipa::ToSchema,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum DependencyType {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::any::type_name;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::auth::checks::{filter_visible_versions, is_visible_project};
|
||||
@@ -55,7 +55,8 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
pub fn utoipa_config(
|
||||
cfg: &mut utoipa_actix_web::service_config::ServiceConfig,
|
||||
) {
|
||||
cfg.service(project_get)
|
||||
cfg.service(project_dependents_get)
|
||||
.service(project_get)
|
||||
.service(project_get_check)
|
||||
.service(project_delete)
|
||||
.service(project_edit)
|
||||
@@ -1260,6 +1261,138 @@ pub struct DependencyInfo {
|
||||
pub versions: Vec<models::projects::Version>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct ProjectDependentsRequest {
|
||||
pub ids: Vec<ProjectId>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct ProjectDependentsResponse {
|
||||
pub dependents: HashMap<ProjectId, HashSet<DependentInfo>>,
|
||||
pub projects: HashMap<ProjectId, Project>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, utoipa::ToSchema, PartialEq, Eq, Hash)]
|
||||
pub struct DependentInfo {
|
||||
pub dependent_project_id: ProjectId,
|
||||
pub dependency_type: models::projects::DependencyType,
|
||||
}
|
||||
|
||||
#[utoipa::path]
|
||||
#[post("/dependents")]
|
||||
pub async fn project_dependents_get(
|
||||
req: HttpRequest,
|
||||
web::Json(projects): web::Json<ProjectDependentsRequest>,
|
||||
pool: web::Data<PgPool>,
|
||||
redis: web::Data<RedisPool>,
|
||||
session_queue: web::Data<AuthQueue>,
|
||||
) -> Result<web::Json<ProjectDependentsResponse>, ApiError> {
|
||||
let user_option = get_user_from_headers(
|
||||
&req,
|
||||
&**pool,
|
||||
&redis,
|
||||
&session_queue,
|
||||
Scopes::PROJECT_READ,
|
||||
)
|
||||
.await
|
||||
.map(|x| x.1)
|
||||
.ok();
|
||||
|
||||
let requested_project_ids = projects
|
||||
.ids
|
||||
.iter()
|
||||
.copied()
|
||||
.map(db_ids::DBProjectId::from)
|
||||
.collect::<Vec<_>>();
|
||||
let requested_projects = db_models::DBProject::get_many_ids(
|
||||
&requested_project_ids,
|
||||
&**pool,
|
||||
&redis,
|
||||
)
|
||||
.await
|
||||
.wrap_internal_err("failed to fetch requested projects")?;
|
||||
let visible_requested_projects =
|
||||
filter_visible_projects(requested_projects, &user_option, &pool, false)
|
||||
.await
|
||||
.wrap_internal_err("failed to filter requested projects")?;
|
||||
let project_ids = visible_requested_projects
|
||||
.iter()
|
||||
.map(|project| db_ids::DBProjectId::from(project.id).0)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let rows = sqlx::query!(
|
||||
r#"
|
||||
SELECT DISTINCT d.mod_dependency_id as "mod_dependency_id!", dependent_version.mod_id dependent_project_id, d.dependency_type
|
||||
FROM dependencies d
|
||||
INNER JOIN versions dependent_version ON dependent_version.id = d.dependent_id
|
||||
WHERE d.mod_dependency_id = ANY($1)
|
||||
"#,
|
||||
&project_ids,
|
||||
)
|
||||
.fetch(&**pool)
|
||||
.try_collect::<Vec<_>>()
|
||||
.await
|
||||
.wrap_internal_err("failed to fetch project dependents")?;
|
||||
|
||||
let dependent_project_ids = rows
|
||||
.iter()
|
||||
.map(|row| db_ids::DBProjectId(row.dependent_project_id))
|
||||
.unique()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let dependent_projects = db_models::DBProject::get_many_ids(
|
||||
&dependent_project_ids,
|
||||
&**pool,
|
||||
&redis,
|
||||
)
|
||||
.await
|
||||
.wrap_internal_err("failed to fetch dependent projects")?;
|
||||
let visible_projects =
|
||||
filter_visible_projects(dependent_projects, &user_option, &pool, false)
|
||||
.await
|
||||
.wrap_internal_err("failed to filter dependent projects")?;
|
||||
|
||||
let visible_project_ids = visible_projects
|
||||
.iter()
|
||||
.map(|project| db_ids::DBProjectId::from(project.id))
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
let mut dependents = visible_requested_projects
|
||||
.iter()
|
||||
.map(|project| project.id)
|
||||
.map(|project_id| (project_id, HashSet::new()))
|
||||
.collect::<HashMap<_, _>>();
|
||||
for row in rows {
|
||||
let dependent_project_id =
|
||||
db_ids::DBProjectId(row.dependent_project_id);
|
||||
|
||||
if visible_project_ids.contains(&dependent_project_id) {
|
||||
dependents
|
||||
.entry(ProjectId::from(db_ids::DBProjectId(
|
||||
row.mod_dependency_id,
|
||||
)))
|
||||
.or_default()
|
||||
.insert(DependentInfo {
|
||||
dependent_project_id: ProjectId::from(dependent_project_id),
|
||||
dependency_type:
|
||||
models::projects::DependencyType::from_string(
|
||||
&row.dependency_type,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let projects = visible_projects
|
||||
.into_iter()
|
||||
.map(|project| (project.id, project))
|
||||
.collect();
|
||||
|
||||
Ok(web::Json(ProjectDependentsResponse {
|
||||
dependents,
|
||||
projects,
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path]
|
||||
#[get("/{project_id}/dependencies")]
|
||||
pub async fn dependency_list(
|
||||
|
||||
Reference in New Issue
Block a user