// Verifies that the `user` is authorized to retrieve the `paths` requested.
Verifies that the `user` is authorized to retrieve the `paths` requested.
Verifies that the ` user ` is authorized to retrieve the ` paths ` requested .
fn verify_paths(
    state_reader: &dyn StateReader<State = ReplicatedState>,
    user: &UserId,
    paths: &[Path],
    targets: &CanisterIdSet,
) -> Result<(), CanonicalError> {
    let state = state_reader.get_latest_state().take();
    let mut num_request_ids = 0;
    // Convert the paths to slices to make it easier to match below.
    let paths: Vec<Vec<&[u8]>> = paths
        .iter()
        .map(|path| path.iter().map(|label| label.as_bytes()).collect())
        .collect();
    for path in paths {
        match path.as_slice() {
            [b"time"] => {}
            [b"canister", _canister_id, b"controller"] => {}
            [b"canister", _canister_id, b"controllers"] => {}
            [b"canister", _canister_id, b"module_hash"] => {}
            [b"canister", canister_id, b"metadata", name] => {
                let name = String::from_utf8(Vec::from(*name)).map_err(|err| {
                    invalid_argument_error(&format!(
                        "Could not parse the custom section name: {}.",
                        err
                    ))
                })?;
                match CanisterId::try_from(*canister_id) {
                    Ok(canister_id) => {
                        can_read_canister_metadata(user, &canister_id, &name, &state)?
                    }
                    Err(err) => {
                        return Err(invalid_argument_error(&format!(
                            "Could not parse Canister ID: {}.",
                            err
                        )))
                    }
                }
            }
            [b"subnet", _subnet_id, b"public_key"] => {}
            [b"subnet", _subnet_id, b"canister_ranges"] => {}
            [b"request_status", request_id] | [b"request_status", request_id, ..] => {
                num_request_ids += 1;
                if num_request_ids > MAX_READ_STATE_REQUEST_IDS {
                    return Err(resource_exhausted_error(&format!(
                        "Can only request up to {} request IDs.",
                        MAX_READ_STATE_REQUEST_IDS
                    )));
                }
                // Verify that the request was signed by the same user.
                if let Ok(message_id) = MessageId::try_from(*request_id) {
                    let ingress_status = state.get_ingress_status(&message_id);
                    if let Some(ingress_user_id) = ingress_status.user_id() {
                        if let Some(receiver) = ingress_status.receiver() {
                            if ingress_user_id != *user || !targets.contains(&receiver) {
                                return Err(permission_denied_error(
                                    "Request IDs must be for requests signed by the caller.",
                                ));
                            }
                        }
                    }
                } else {
                    return Err(invalid_argument_error(&format!(
                        "Request IDs must be {} bytes in length.",
                        EXPECTED_MESSAGE_ID_LENGTH
                    )));
                }
            }
            _ => {
                // All other paths are unsupported.
                return Err(not_found_error("Invalid path requested."));
            }
        }
    }
    Ok(())
}
fn verify_paths ( state_reader : & dyn StateReader < State = ReplicatedState > , user : & UserId , paths : & [ Path ] , targets : & CanisterIdSet , ) -> Result < ( ) , CanonicalError > { let state = state_reader . get_latest_state ( ) . take ( ) ; let mut num_request_ids = 0 ; // Convert the paths to slices to make it easier to match below. let paths : Vec < Vec < & [ u8 ] > > = paths . iter ( ) . map ( | path | path . iter ( ) . map ( | label | label . as_bytes ( ) ) . collect ( ) ) . collect ( ) ; for path in paths { match path . as_slice ( ) { [ b" " ] => { } [ b" " , _canister_id , b" " ] => { } [ b" " , _canister_id , b" " ] => { } [ b" " , _canister_id , b" " ] => { } [ b" " , canister_id , b" " , name ] => { let name = String :: from_utf8 ( Vec :: from ( * name ) ) . map_err ( | err | { invalid_argument_error ( & format ! ( " " err ) ) } ) ? ; match CanisterId :: try_from ( * canister_id ) { Ok ( canister_id ) => { can_read_canister_metadata ( user , & canister_id , & name , & state ) ? } Err ( err ) => { return Err ( invalid_argument_error ( & format ! ( " " err ) ) ) } } } [ b" " , _subnet_id , b" " ] => { } [ b" " , _subnet_id , b" " ] => { } [ b" " , request_id ] | [ b" " , request_id , .. ] => { num_request_ids += 1 ; if num_request_ids > MAX_READ_STATE_REQUEST_IDS { return Err ( resource_exhausted_error ( & format ! ( " " MAX_READ_STATE_REQUEST_IDS ) ) ) ; } // Verify that the request was signed by the same user. if let Ok ( message_id ) = MessageId :: try_from ( * request_id ) { let ingress_status = state . get_ingress_status ( & message_id ) ; if let Some ( ingress_user_id ) = ingress_status . user_id ( ) { if let Some ( receiver ) = ingress_status . receiver ( ) { if ingress_user_id != * user || ! targets . contains ( & receiver ) { return Err ( permission_denied_error ( " " , ) ) ; } } } } else { return Err ( invalid_argument_error ( & format ! ( " " EXPECTED_MESSAGE_ID_LENGTH ) ) ) ; } } _ => { // All other paths are unsupported. return Err ( not_found_error ( " " ) ) ; } } } Ok ( ( ) ) }
Verifies that the `user` is authorized to retrieve the `paths` requested.
Verifies that the ` user ` is authorized to retrieve the ` paths ` requested .
state_reader
&dyn StateReader<State = ReplicatedState>
user
&UserId
paths
&[Path]
targets
&CanisterIdSet