use std::collections::HashSet;
use systemprompt_identifiers::UserId;
use super::error::AuthzResult;
use super::parent_chain::{ParentChainIndex, ResolveBase};
use super::repository::AccessControlRepository;
use super::subject::{SubjectAttributes, SubjectDimension};
use super::types::{Decision, EntityKind};
#[derive(Debug, Clone, Copy)]
pub struct BulkKeepQuery<'a> {
pub user_id: &'a UserId,
pub roles: &'a [String],
pub kind: EntityKind,
pub ids: &'a [String],
pub chains: &'a ParentChainIndex,
pub attributes: &'a SubjectAttributes,
pub dimensions: &'a [SubjectDimension],
}
pub async fn allowed_ids(
repo: &AccessControlRepository,
query: BulkKeepQuery<'_>,
) -> AuthzResult<HashSet<String>> {
if query.ids.is_empty() {
return Ok(HashSet::new());
}
let rules = repo.list_rules_bulk(query.kind, query.ids).await?;
let entities = repo.list_entities_bulk(query.kind, query.ids).await?;
let mut keep = HashSet::with_capacity(query.ids.len());
for id in query.ids {
let entity_rules = rules.get(id).map_or(&[][..], Vec::as_slice);
let default_included = entities.get(id).map(|e| e.default_included);
let decision = query.chains.resolve(
query.kind,
id,
ResolveBase {
rules: entity_rules,
user_id: query.user_id,
user_roles: query.roles,
default_included,
attributes: query.attributes,
dimensions: query.dimensions,
},
);
if matches!(decision, Decision::Allow { .. }) {
keep.insert(id.clone());
}
}
Ok(keep)
}