chris/client/
base.rs

1use super::access::{Access, RoAccess};
2use super::filebrowser::FileBrowser;
3use crate::errors::{check, CubeError};
4use crate::search::*;
5use crate::types::{CubeUrl, FeedId, PipelineId, PluginId, PluginInstanceId};
6use crate::{FeedResponse, LinkedModel, PipelineResponse, PluginInstanceResponse, PluginResponse};
7use async_trait::async_trait;
8use reqwest_middleware::ClientWithMiddleware;
9use serde::de::DeserializeOwned;
10use std::fmt::Display;
11
12/// APIs you can interact with without having to log in.
13#[async_trait]
14pub trait BaseChrisClient<A: Access> {
15    /// Get a filebrowser API client.
16    fn filebrowser(&self) -> FileBrowser;
17
18    /// Get the CUBE API URL.
19    fn url(&self) -> &CubeUrl;
20
21    /// Search for ChRIS plugins.
22    fn plugin(&self) -> PluginSearchBuilder<A>;
23
24    /// Search for pipeines.
25    fn pipeline(&self) -> PipelineSearchBuilder<A>;
26
27    /// Search for public feeds.
28    fn public_feeds(&self) -> FeedSearchBuilder<RoAccess>;
29
30    // Note: get_feed and get_plugin_instance must be implemented manually,
31    // whereas we can use a SearchBuilder for get_plugin and get_pipeline because
32    // feeds and plugin instances are affected by the feature incompleteness of
33    // public feeds.
34    // See https://github.com/FNNDSC/ChRIS_ultron_backEnd/issues/530
35
36    /// Get a feed (directly).
37    async fn get_feed(&self, id: FeedId) -> Result<LinkedModel<FeedResponse, A>, CubeError>;
38
39    /// Get a plugin instance (directly).
40    async fn get_plugin_instance(
41        &self,
42        id: PluginInstanceId,
43    ) -> Result<LinkedModel<PluginInstanceResponse, A>, CubeError>;
44
45    /// Get a plugin by ID
46    async fn get_plugin(
47        &self,
48        id: PluginId,
49    ) -> Result<LinkedModel<PluginResponse, A>, GetOnlyError> {
50        self.plugin()
51            .id(id)
52            .search()
53            .page_limit(1)
54            .max_items(1)
55            .get_only()
56            .await
57    }
58
59    /// Get a pipeline by ID
60    async fn get_pipeline(
61        &self,
62        id: PipelineId,
63    ) -> Result<LinkedModel<PipelineResponse, A>, GetOnlyError> {
64        self.pipeline()
65            .id(id)
66            .search()
67            .page_limit(1)
68            .max_items(1)
69            .get_only()
70            .await
71    }
72}
73
74pub(crate) async fn fetch_id<A: Access, T: DeserializeOwned>(
75    client: &ClientWithMiddleware,
76    url: impl Display,
77    id: u32,
78) -> Result<LinkedModel<T, A>, CubeError> {
79    let url = format!("{}{}/", url, id);
80    let res = client.get(url).send().await?;
81    let data = check(res).await?.json().await?;
82    Ok(LinkedModel {
83        client: client.clone(),
84        object: data,
85        phantom: Default::default(),
86    })
87}