mirror of
https://github.com/modrinth/code.git
synced 2026-09-04 22:10:15 +00:00
refactor: Adjust API to return project ids instead of direct count
This commit is contained in:
@@ -1680,22 +1680,23 @@ pub async fn delete_all_locks(
|
|||||||
Ok(web::Json(DeleteAllLocksResponse { deleted_count }))
|
Ok(web::Json(DeleteAllLocksResponse { deleted_count }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get counts of each `ProjectStatus` across a user's projects. Only
|
/// Get project id's for a given user with them grouped by their `ProjectStatus`.
|
||||||
/// statuses with at least one project are present in the map.
|
///
|
||||||
|
/// Only statuses with at least one project are present in the map.
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
context_path = "/moderation",
|
context_path = "/moderation",
|
||||||
tag = "moderation",
|
tag = "moderation",
|
||||||
security(("bearer_auth" = [])),
|
security(("bearer_auth" = [])),
|
||||||
responses((status = OK, body = HashMap<ProjectStatus, u32>))
|
responses((status = OK, body = HashMap<ProjectStatus, Vec<ProjectId>>))
|
||||||
)]
|
)]
|
||||||
#[get("/user/{user_id}/project-status-counts")]
|
#[get("/user/{user_id}/all-projects-grouped")]
|
||||||
pub async fn get_user_project_status_counts(
|
pub async fn get_user_project_grouped(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
info: web::Path<(String,)>,
|
info: web::Path<(String,)>,
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
redis: web::Data<RedisPool>,
|
redis: web::Data<RedisPool>,
|
||||||
session_queue: web::Data<AuthQueue>,
|
session_queue: web::Data<AuthQueue>,
|
||||||
) -> Result<web::Json<HashMap<ProjectStatus, u32>>, ApiError> {
|
) -> Result<web::Json<HashMap<ProjectStatus, Vec<ProjectId>>>, ApiError> {
|
||||||
check_is_moderator_from_headers(
|
check_is_moderator_from_headers(
|
||||||
&req,
|
&req,
|
||||||
&**pool,
|
&**pool,
|
||||||
@@ -1713,17 +1714,13 @@ pub async fn get_user_project_status_counts(
|
|||||||
.wrap_not_found_err("resource not found")?;
|
.wrap_not_found_err("resource not found")?;
|
||||||
|
|
||||||
let counts =
|
let counts =
|
||||||
user_project_status_counts(target_user.id, &**pool, &redis).await?;
|
user_projects_status_grouped(target_user.id, &**pool, &redis).await?;
|
||||||
|
|
||||||
Ok(web::Json(counts))
|
Ok(web::Json(counts))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
/// Get project id's for a list of user's with them grouped by their `ProjectStatus`.
|
||||||
pub struct ProjectStatusCountsUserIds {
|
///
|
||||||
pub ids: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get counts of each `ProjectStatus` across multiple users' projects.
|
|
||||||
/// Users that don't exist are silently omitted from the response; users
|
/// Users that don't exist are silently omitted from the response; users
|
||||||
/// that exist but have no projects are included with an empty map.
|
/// that exist but have no projects are included with an empty map.
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
@@ -1731,16 +1728,16 @@ pub struct ProjectStatusCountsUserIds {
|
|||||||
tag = "moderation",
|
tag = "moderation",
|
||||||
security(("bearer_auth" = [])),
|
security(("bearer_auth" = [])),
|
||||||
params(("ids" = String, Query)),
|
params(("ids" = String, Query)),
|
||||||
responses((status = OK, body = HashMap<UserId, HashMap<ProjectStatus, u32>>))
|
responses((status = OK, body = HashMap<UserId, HashMap<ProjectStatus, Vec<ProjectId>>>))
|
||||||
)]
|
)]
|
||||||
#[get("/users/project-status-counts")]
|
#[get("/users/all-projects-grouped")]
|
||||||
pub async fn get_users_project_status_counts(
|
pub async fn get_users_project_grouped(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
ids: web::Query<ProjectStatusCountsUserIds>,
|
ids: web::Query<UserIds>,
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
redis: web::Data<RedisPool>,
|
redis: web::Data<RedisPool>,
|
||||||
session_queue: web::Data<AuthQueue>,
|
session_queue: web::Data<AuthQueue>,
|
||||||
) -> Result<web::Json<HashMap<UserId, HashMap<ProjectStatus, u32>>>, ApiError>
|
) -> Result<web::Json<HashMap<UserId, HashMap<ProjectStatus, Vec<ProjectId>>>>, ApiError>
|
||||||
{
|
{
|
||||||
check_is_moderator_from_headers(
|
check_is_moderator_from_headers(
|
||||||
&req,
|
&req,
|
||||||
@@ -1767,9 +1764,9 @@ pub async fn get_users_project_status_counts(
|
|||||||
let pool_ref = &**pool;
|
let pool_ref = &**pool;
|
||||||
let redis_ref = &*redis;
|
let redis_ref = &*redis;
|
||||||
|
|
||||||
let counts_by_user = try_join_all(target_users.into_iter().map(
|
let grouped_projects_by_user = try_join_all(target_users.into_iter().map(
|
||||||
|target_user| async move {
|
|target_user| async move {
|
||||||
let counts = user_project_status_counts(
|
let counts = user_projects_status_grouped(
|
||||||
target_user.id,
|
target_user.id,
|
||||||
pool_ref,
|
pool_ref,
|
||||||
redis_ref,
|
redis_ref,
|
||||||
@@ -1783,25 +1780,26 @@ pub async fn get_users_project_status_counts(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
Ok(web::Json(counts_by_user))
|
Ok(web::Json(grouped_projects_by_user))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get counts of each `ProjectStatus` across an organization's projects.
|
/// Get project id's for a given organization with them grouped by their `ProjectStatus`.
|
||||||
|
///
|
||||||
/// Only statuses with at least one project are present in the map.
|
/// Only statuses with at least one project are present in the map.
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
context_path = "/moderation",
|
context_path = "/moderation",
|
||||||
tag = "moderation",
|
tag = "moderation",
|
||||||
security(("bearer_auth" = [])),
|
security(("bearer_auth" = [])),
|
||||||
responses((status = OK, body = HashMap<ProjectStatus, u32>))
|
responses((status = OK, body = HashMap<ProjectStatus, Vec<ProjectId>>))
|
||||||
)]
|
)]
|
||||||
#[get("/organization/{organization_id}/project-status-counts")]
|
#[get("/organization/{organization_id}/all-projects-grouped")]
|
||||||
pub async fn get_organization_project_status_counts(
|
pub async fn get_organization_project_grouped(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
info: web::Path<(String,)>,
|
info: web::Path<(String,)>,
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
redis: web::Data<RedisPool>,
|
redis: web::Data<RedisPool>,
|
||||||
session_queue: web::Data<AuthQueue>,
|
session_queue: web::Data<AuthQueue>,
|
||||||
) -> Result<web::Json<HashMap<ProjectStatus, u32>>, ApiError> {
|
) -> Result<web::Json<HashMap<ProjectStatus, Vec<ProjectId>>>, ApiError> {
|
||||||
check_is_moderator_from_headers(
|
check_is_moderator_from_headers(
|
||||||
&req,
|
&req,
|
||||||
&**pool,
|
&**pool,
|
||||||
@@ -1821,18 +1819,19 @@ pub async fn get_organization_project_status_counts(
|
|||||||
.wrap_internal_err("fetching organization from database")?
|
.wrap_internal_err("fetching organization from database")?
|
||||||
.wrap_not_found_err("resource not found")?;
|
.wrap_not_found_err("resource not found")?;
|
||||||
|
|
||||||
let counts = organization_project_status_counts(
|
let grouped_projects = organization_projects_status_grouped(
|
||||||
target_org.id,
|
target_org.id,
|
||||||
&**pool,
|
&**pool,
|
||||||
&redis,
|
&redis,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(web::Json(counts))
|
Ok(web::Json(grouped_projects))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get counts of each `ProjectStatus` across multiple organizations'
|
/// Get project id's for a list of organization's with them grouped by their `ProjectStatus`.
|
||||||
/// projects. Organizations that don't exist are silently omitted from the
|
///
|
||||||
|
/// Organizations that don't exist are silently omitted from the
|
||||||
/// response; organizations that exist but have no projects are included
|
/// response; organizations that exist but have no projects are included
|
||||||
/// with an empty map.
|
/// with an empty map.
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
@@ -1840,17 +1839,17 @@ pub async fn get_organization_project_status_counts(
|
|||||||
tag = "moderation",
|
tag = "moderation",
|
||||||
security(("bearer_auth" = [])),
|
security(("bearer_auth" = [])),
|
||||||
params(("ids" = String, Query)),
|
params(("ids" = String, Query)),
|
||||||
responses((status = OK, body = HashMap<OrganizationId, HashMap<ProjectStatus, u32>>))
|
responses((status = OK, body = HashMap<OrganizationId, HashMap<ProjectStatus, Vec<ProjectId>>>))
|
||||||
)]
|
)]
|
||||||
#[get("/organizations/project-status-counts")]
|
#[get("/organizations/all-projects-grouped")]
|
||||||
pub async fn get_organizations_project_status_counts(
|
pub async fn get_organizations_project_grouped(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
ids: web::Query<OrganizationIds>,
|
ids: web::Query<OrganizationIds>,
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
redis: web::Data<RedisPool>,
|
redis: web::Data<RedisPool>,
|
||||||
session_queue: web::Data<AuthQueue>,
|
session_queue: web::Data<AuthQueue>,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
web::Json<HashMap<OrganizationId, HashMap<ProjectStatus, u32>>>,
|
web::Json<HashMap<OrganizationId, HashMap<ProjectStatus, Vec<ProjectId>>>>,
|
||||||
ApiError,
|
ApiError,
|
||||||
> {
|
> {
|
||||||
check_is_moderator_from_headers(
|
check_is_moderator_from_headers(
|
||||||
@@ -1881,9 +1880,9 @@ pub async fn get_organizations_project_status_counts(
|
|||||||
let pool_ref = &**pool;
|
let pool_ref = &**pool;
|
||||||
let redis_ref = &*redis;
|
let redis_ref = &*redis;
|
||||||
|
|
||||||
let counts_by_org = try_join_all(target_orgs.into_iter().map(
|
let grouped_projects_by_org = try_join_all(target_orgs.into_iter().map(
|
||||||
|target_org| async move {
|
|target_org| async move {
|
||||||
let counts = organization_project_status_counts(
|
let counts = organization_projects_status_grouped(
|
||||||
target_org.id,
|
target_org.id,
|
||||||
pool_ref,
|
pool_ref,
|
||||||
redis_ref,
|
redis_ref,
|
||||||
@@ -1897,37 +1896,35 @@ pub async fn get_organizations_project_status_counts(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
Ok(web::Json(counts_by_org))
|
Ok(web::Json(grouped_projects_by_org))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tallies a single user's projects by `ProjectStatus`. Shared by the
|
/// Groups the given User projects by their `ProjectStatus`.
|
||||||
/// single- and multi-user project-status-count endpoints.
|
async fn user_projects_status_grouped<'a, E>(
|
||||||
async fn user_project_status_counts<'a, E>(
|
|
||||||
user_id: database::models::DBUserId,
|
user_id: database::models::DBUserId,
|
||||||
pool: E,
|
pool: E,
|
||||||
redis: &RedisPool,
|
redis: &RedisPool,
|
||||||
) -> Result<HashMap<ProjectStatus, u32>, ApiError>
|
) -> Result<HashMap<ProjectStatus, Vec<ProjectId>>, ApiError>
|
||||||
where
|
where
|
||||||
E: database::Executor<'a, Database = sqlx::Postgres>
|
E: database::Executor<'a, Database = sqlx::Postgres>
|
||||||
+ database::Acquire<'a, Database = sqlx::Postgres>
|
+ database::Acquire<'a, Database = sqlx::Postgres>
|
||||||
+ Copy,
|
+ Copy,
|
||||||
{
|
{
|
||||||
let project_ids =
|
let project_ids =
|
||||||
models::DBUser::get_projects(user_id, pool, redis)
|
database::models::DBUser::get_projects(user_id, pool, redis)
|
||||||
.await
|
.await
|
||||||
.wrap_internal_err("fetching user's projects from database")?;
|
.wrap_internal_err("fetching user's projects from database")?;
|
||||||
|
|
||||||
project_status_counts_for(&project_ids, pool, redis).await
|
grouped_projects_for(&project_ids, pool, redis).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Tallies a single organization's projects by `ProjectStatus`. Shared by
|
/// Groups the given Organization projects by their `ProjectStatus`.
|
||||||
/// the single- and multi-organization project-status-count endpoints.
|
async fn organization_projects_status_grouped<'a, E>(
|
||||||
async fn organization_project_status_counts<'a, E>(
|
|
||||||
organization_id: DBOrganizationId,
|
organization_id: DBOrganizationId,
|
||||||
pool: E,
|
pool: E,
|
||||||
redis: &RedisPool,
|
redis: &RedisPool,
|
||||||
) -> Result<HashMap<ProjectStatus, u32>, ApiError>
|
) -> Result<HashMap<ProjectStatus, Vec<ProjectId>>, ApiError>
|
||||||
where
|
where
|
||||||
E: database::Executor<'a, Database = sqlx::Postgres>
|
E: database::Executor<'a, Database = sqlx::Postgres>
|
||||||
+ database::Acquire<'a, Database = sqlx::Postgres>
|
+ database::Acquire<'a, Database = sqlx::Postgres>
|
||||||
@@ -1937,16 +1934,15 @@ where
|
|||||||
.await
|
.await
|
||||||
.wrap_internal_err("fetching project IDs from database")?;
|
.wrap_internal_err("fetching project IDs from database")?;
|
||||||
|
|
||||||
project_status_counts_for(&project_ids, pool, redis).await
|
grouped_projects_for(&project_ids, pool, redis).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tallies `ProjectStatus` counts across the given projects. Shared by the
|
/// Groups the given input Projects by their `ProjectStatus`.
|
||||||
/// user- and organization-scoped project-status-count helpers above.
|
async fn grouped_projects_for<'a, E>(
|
||||||
async fn project_status_counts_for<'a, E>(
|
|
||||||
project_ids: &[DBProjectId],
|
project_ids: &[DBProjectId],
|
||||||
pool: E,
|
pool: E,
|
||||||
redis: &RedisPool,
|
redis: &RedisPool,
|
||||||
) -> Result<HashMap<ProjectStatus, u32>, ApiError>
|
) -> Result<HashMap<ProjectStatus, Vec<ProjectId>>, ApiError>
|
||||||
where
|
where
|
||||||
E: database::Executor<'a, Database = sqlx::Postgres>
|
E: database::Executor<'a, Database = sqlx::Postgres>
|
||||||
+ database::Acquire<'a, Database = sqlx::Postgres>
|
+ database::Acquire<'a, Database = sqlx::Postgres>
|
||||||
@@ -1961,10 +1957,10 @@ where
|
|||||||
.await
|
.await
|
||||||
.wrap_internal_err("fetching projects from database")?;
|
.wrap_internal_err("fetching projects from database")?;
|
||||||
|
|
||||||
let mut counts = HashMap::new();
|
let mut grouped_projects = HashMap::new();
|
||||||
for project in &projects {
|
for project in &projects {
|
||||||
*counts.entry(project.inner.status).or_insert(0u32) += 1;
|
*grouped_projects.entry(project.inner.status).or_default().push(project.inner.id.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(counts)
|
Ok(grouped_projects)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user