use super::builder::ResourceLimits;
use super::errors::{JwtSourceError, LimitKind, MetricsErrorKind};
use super::metrics::MetricsRecorder;
use crate::bundle::jwt::JwtBundleSet;
pub(super) fn validate_limits(
bundle_set: &JwtBundleSet,
limits: ResourceLimits,
) -> Result<(), JwtSourceError> {
if let Some(max_bundles) = limits.max_bundles {
let actual = bundle_set.len();
if actual > max_bundles {
return Err(JwtSourceError::ResourceLimitExceeded {
kind: LimitKind::MaxBundles,
limit: max_bundles,
actual,
});
}
}
if let Some(max_bundle_jwks_bytes) = limits.max_bundle_jwks_bytes {
for (_, bundle) in bundle_set.iter() {
let actual: usize = bundle
.jwt_authorities()
.map(|auth| auth.jwk_json().len())
.sum();
if actual > max_bundle_jwks_bytes {
return Err(JwtSourceError::ResourceLimitExceeded {
kind: LimitKind::MaxBundleJwksBytes,
limit: max_bundle_jwks_bytes,
actual,
});
}
}
}
Ok(())
}
pub(super) fn validate_limits_and_record_metric(
bundle_set: &JwtBundleSet,
limits: ResourceLimits,
metrics: Option<&dyn MetricsRecorder>,
) -> Result<(), JwtSourceError> {
if let Err(e) = validate_limits(bundle_set, limits) {
if let JwtSourceError::ResourceLimitExceeded { kind, .. } = &e {
if let Some(m) = metrics {
m.record_error(metric_kind_for_limit(*kind));
}
}
return Err(e);
}
Ok(())
}
pub(super) const fn metric_kind_for_limit(kind: LimitKind) -> MetricsErrorKind {
match kind {
LimitKind::MaxBundles => MetricsErrorKind::LimitMaxBundles,
LimitKind::MaxBundleJwksBytes => MetricsErrorKind::LimitMaxBundleJwksBytes,
}
}
pub(super) fn validate_bundle_set(
bundle_set: &JwtBundleSet,
limits: ResourceLimits,
metrics: Option<&dyn MetricsRecorder>,
) -> Result<(), JwtSourceError> {
validate_limits_and_record_metric(bundle_set, limits, metrics)?;
Ok(())
}