canic-core 0.55.4

Canic — a canister orchestration and management toolkit for the Internet Computer
Documentation
use super::{AccessContext, AppPredicate, BuiltinPredicate, CallerPredicate, EnvironmentPredicate};
use crate::{
    access::{self, AccessError, metrics::DelegatedAuthMetrics},
    ids::AccessMetricKind,
};

pub(super) const fn name(pred: &BuiltinPredicate) -> &'static str {
    match pred {
        BuiltinPredicate::App(AppPredicate::AllowsUpdates) => "app_allows_updates",
        BuiltinPredicate::App(AppPredicate::IsQueryable) => "app_is_queryable",
        BuiltinPredicate::Caller(CallerPredicate::IsController) => "caller_is_controller",
        BuiltinPredicate::Caller(CallerPredicate::IsParent) => "caller_is_parent",
        BuiltinPredicate::Caller(CallerPredicate::IsChild) => "caller_is_child",
        BuiltinPredicate::Caller(CallerPredicate::IsRoot) => "caller_is_root",
        BuiltinPredicate::Caller(CallerPredicate::IsSameCanister) => "caller_is_same_canister",
        BuiltinPredicate::Caller(CallerPredicate::IsRegisteredToSubnet) => {
            "caller_is_registered_to_subnet"
        }
        BuiltinPredicate::Caller(CallerPredicate::IsWhitelisted) => "caller_is_whitelisted",
        BuiltinPredicate::Environment(EnvironmentPredicate::SelfIsPrimeSubnet) => {
            "self_is_prime_subnet"
        }
        BuiltinPredicate::Environment(EnvironmentPredicate::SelfIsPrimeRoot) => {
            "self_is_prime_root"
        }
        BuiltinPredicate::Environment(EnvironmentPredicate::BuildIcOnly) => "build_ic_only",
        BuiltinPredicate::Environment(EnvironmentPredicate::BuildLocalOnly) => "build_local_only",
        BuiltinPredicate::Authenticated { .. } => "authenticated",
    }
}

pub(super) const fn metric_kind(pred: &BuiltinPredicate) -> AccessMetricKind {
    match pred {
        BuiltinPredicate::App(_) => AccessMetricKind::Guard,
        BuiltinPredicate::Caller(_) | BuiltinPredicate::Authenticated { .. } => {
            AccessMetricKind::Auth
        }
        BuiltinPredicate::Environment(
            EnvironmentPredicate::SelfIsPrimeSubnet | EnvironmentPredicate::SelfIsPrimeRoot,
        ) => AccessMetricKind::Env,
        BuiltinPredicate::Environment(
            EnvironmentPredicate::BuildIcOnly | EnvironmentPredicate::BuildLocalOnly,
        ) => AccessMetricKind::Rule,
    }
}

pub(super) async fn evaluate(
    pred: &BuiltinPredicate,
    ctx: &AccessContext,
) -> Result<(), AccessError> {
    match pred {
        BuiltinPredicate::App(AppPredicate::AllowsUpdates) => access::app::guard_app_update(),
        BuiltinPredicate::App(AppPredicate::IsQueryable) => access::app::guard_app_query(),
        BuiltinPredicate::Caller(CallerPredicate::IsController) => {
            access::auth::is_controller(ctx.caller).await
        }
        BuiltinPredicate::Caller(CallerPredicate::IsParent) => {
            access::auth::is_parent(ctx.caller).await
        }
        BuiltinPredicate::Caller(CallerPredicate::IsChild) => {
            access::auth::is_child(ctx.caller).await
        }
        BuiltinPredicate::Caller(CallerPredicate::IsRoot) => {
            access::auth::is_root(ctx.caller).await
        }
        BuiltinPredicate::Caller(CallerPredicate::IsSameCanister) => {
            access::auth::is_same_canister(ctx.caller).await
        }
        BuiltinPredicate::Caller(CallerPredicate::IsRegisteredToSubnet) => {
            access::auth::is_registered_to_subnet(ctx.caller).await
        }
        BuiltinPredicate::Caller(CallerPredicate::IsWhitelisted) => {
            access::auth::is_whitelisted(ctx.caller).await
        }
        BuiltinPredicate::Environment(EnvironmentPredicate::SelfIsPrimeSubnet) => {
            access::env::is_prime_subnet()
        }
        BuiltinPredicate::Environment(EnvironmentPredicate::SelfIsPrimeRoot) => {
            access::env::is_prime_root()
        }
        BuiltinPredicate::Environment(EnvironmentPredicate::BuildIcOnly) => {
            access::env::build_network_ic()
        }
        BuiltinPredicate::Environment(EnvironmentPredicate::BuildLocalOnly) => {
            access::env::build_network_local()
        }
        BuiltinPredicate::Authenticated { required_scope } => {
            let issuer_shard_pid = access::auth::delegated_token_verified(
                ctx.authenticated_caller,
                *required_scope,
                ctx.call.kind,
            )?;
            DelegatedAuthMetrics::record_authority(issuer_shard_pid);
            Ok(())
        }
    }
}