canic_core/access/
env.rs

1use crate::{
2    Error, ThisError, access::AccessError, cdk::api::canister_self, ops::runtime::env::EnvOps,
3};
4
5///
6/// EnvAccessError
7///
8
9#[derive(Debug, ThisError)]
10pub enum EnvAccessError {
11    #[error("this endpoint is only available on the prime subnet")]
12    NotPrimeSubnet,
13
14    #[error("this endpoint is only available on prime root")]
15    NotPrimeRoot,
16
17    #[error("operation must be called from the root canister")]
18    NotRoot,
19
20    #[error("operation cannot be called from the root canister")]
21    IsRoot,
22}
23
24impl From<EnvAccessError> for Error {
25    fn from(err: EnvAccessError) -> Self {
26        AccessError::Env(err).into()
27    }
28}
29
30///
31/// Env Checks
32///
33
34#[allow(clippy::unused_async)]
35pub async fn is_prime_root() -> Result<(), AccessError> {
36    if EnvOps::is_prime_root() {
37        Ok(())
38    } else {
39        Err(EnvAccessError::NotPrimeRoot.into())
40    }
41}
42
43#[allow(clippy::unused_async)]
44pub async fn is_prime_subnet() -> Result<(), AccessError> {
45    if EnvOps::is_prime_subnet() {
46        Ok(())
47    } else {
48        Err(EnvAccessError::NotPrimeSubnet.into())
49    }
50}
51
52/// Ensure the caller is the root canister.
53pub(crate) fn require_root() -> Result<(), Error> {
54    let root_pid = EnvOps::root_pid()?;
55
56    if root_pid == canister_self() {
57        Ok(())
58    } else {
59        Err(EnvAccessError::NotRoot.into())
60    }
61}
62
63/// Ensure the caller is not the root canister.
64pub(crate) fn deny_root() -> Result<(), Error> {
65    let root_pid = EnvOps::root_pid()?;
66
67    if root_pid == canister_self() {
68        Err(EnvAccessError::IsRoot.into())
69    } else {
70        Ok(())
71    }
72}