fix(admin): search archives across both subject types (#2542)

This commit is contained in:
Hampus
2026-09-06 18:42:33 +02:00
committed by GitHub
parent 8dcd00a8fe
commit a2ca24eeb4
2 changed files with 40 additions and 22 deletions
+26 -11
View File
@@ -2,7 +2,7 @@
use crate::api::generated::types as generated_types;
use super::client::{AdminApiClient, ApiResult};
use super::client::{AdminApiClient, ApiError, ApiResult};
use super::types::{Archive, ArchiveDownloadUrlResponse, ListArchivesResponse};
impl AdminApiClient {
@@ -45,16 +45,31 @@ impl AdminApiClient {
include_expired: bool,
requested_by: Option<&str>,
) -> ApiResult<ListArchivesResponse> {
let query_params = [
("subject_type", subject_type),
("subject_id", subject_id.unwrap_or_default()),
("requested_by", requested_by.unwrap_or_default()),
(
"include_expired",
if include_expired { "true" } else { "false" },
),
];
self.get("/admin/archives", Some(&query_params)).await
let subject_id = subject_id.filter(|id| !id.is_empty());
let search_every_subject_type = subject_type == "all" && subject_id.is_some();
let subject_types: &[&str] = if search_every_subject_type {
&["user", "guild"]
} else {
std::slice::from_ref(&subject_type)
};
let mut archives = Vec::new();
for &subject_type in subject_types {
let query_params = [
("subject_type", subject_type),
("subject_id", subject_id.unwrap_or_default()),
("requested_by", requested_by.unwrap_or_default()),
(
"include_expired",
if include_expired { "true" } else { "false" },
),
];
match self.get("/admin/archives", Some(&query_params)).await {
Ok(ListArchivesResponse { archives: page }) => archives.extend(page),
Err(ApiError::Http { status: 403, .. }) if search_every_subject_type => {}
Err(error) => return Err(error),
}
}
Ok(ListArchivesResponse { archives })
}
pub async fn get_archive_download_url(
@@ -30,6 +30,19 @@ function requireArchiveSubjectAccess(adminAcls: Set<string>, subjectType: 'user'
throw new MissingACLError(subjectType === 'user' ? AdminACLs.ARCHIVE_TRIGGER_USER : AdminACLs.ARCHIVE_TRIGGER_GUILD);
}
function resolveListSubjectType(adminAcls: Set<string>, requested: 'all' | 'user' | 'guild'): 'all' | 'user' | 'guild' {
if (requested !== 'all') {
requireArchiveSubjectAccess(adminAcls, requested);
return requested;
}
const viewUser = canViewArchive(adminAcls, 'user');
const viewGuild = canViewArchive(adminAcls, 'guild');
if (viewUser && viewGuild) return 'all';
if (viewUser) return 'user';
if (viewGuild) return 'guild';
throw new MissingACLError(AdminACLs.ARCHIVE_VIEW_ALL);
}
export function ArchiveAdminController(app: HonoApp) {
app.post(
'/admin/users/:user_id/archives',
@@ -104,18 +117,8 @@ export function ArchiveAdminController(app: HonoApp) {
const adminArchiveService = ctx.get('adminArchiveService');
const adminAcls = ctx.get('adminUserAcls');
const query = ctx.req.valid('query');
if (
query.subject_type === 'all' &&
!adminAcls.has(AdminACLs.ARCHIVE_VIEW_ALL) &&
!adminAcls.has(AdminACLs.WILDCARD)
) {
throw new MissingACLError(AdminACLs.ARCHIVE_VIEW_ALL);
}
if (query.subject_type !== 'all') {
requireArchiveSubjectAccess(adminAcls, query.subject_type);
}
const result = await adminArchiveService.listArchives({
subjectType: query.subject_type,
subjectType: resolveListSubjectType(adminAcls, query.subject_type),
subjectId: query.subject_id ?? undefined,
requestedBy: query.requested_by ?? undefined,
limit: query.limit,