drogue_client/admin/v1/
client.rs1use super::data::*;
2use crate::core::CoreClient;
3use crate::error::ClientError;
4use crate::openid::TokenProvider;
5use std::{fmt::Debug, sync::Arc};
6use tracing::instrument;
7use url::Url;
8
9#[derive(Clone, Debug)]
11pub struct Client {
12 client: reqwest::Client,
13 api_url: Url,
14 token_provider: Arc<dyn TokenProvider>,
15}
16
17enum AdministrationOperation {
18 Transfer,
19 Accept,
20 Members,
21}
22
23type ClientResult<T> = Result<T, ClientError>;
24
25impl CoreClient for Client {
26 fn client(&self) -> &reqwest::Client {
27 &self.client
28 }
29
30 fn token_provider(&self) -> &dyn TokenProvider {
31 self.token_provider.as_ref()
32 }
33}
34
35impl Client {
36 pub fn new(
38 client: reqwest::Client,
39 api_url: Url,
40 token_provider: impl TokenProvider + 'static,
41 ) -> Self {
42 Self {
43 client,
44 api_url,
45 token_provider: Arc::new(token_provider),
46 }
47 }
48
49 fn url(&self, application: &str, operation: AdministrationOperation) -> ClientResult<Url> {
50 let mut url = self.api_url.clone();
51
52 {
53 let mut path = url
54 .path_segments_mut()
55 .map_err(|_| ClientError::Request("Failed to get paths".into()))?;
56
57 path.extend(&["api", "admin", "v1alpha1", "apps"]);
58 if !application.is_empty() {
59 path.push(application);
60 }
61 match operation {
62 AdministrationOperation::Transfer => path.push("transfer-ownership"),
63 AdministrationOperation::Accept => path.push("accept-ownership"),
64 AdministrationOperation::Members => path.push("members"),
65 };
66 }
67
68 Ok(url)
69 }
70
71 #[instrument]
73 pub async fn get_members<A>(&self, application: A) -> ClientResult<Option<Members>>
74 where
75 A: AsRef<str> + Debug,
76 {
77 self.read(self.url(application.as_ref(), AdministrationOperation::Members)?)
78 .await
79 }
80
81 #[instrument]
83 pub async fn update_members<A>(&self, application: A, members: Members) -> ClientResult<bool>
84 where
85 A: AsRef<str> + Debug,
86 {
87 self.update(
88 self.url(application.as_ref(), AdministrationOperation::Members)?,
89 Some(members),
90 )
91 .await
92 }
93
94 #[instrument]
96 pub async fn initiate_app_transfer<A, U>(
97 &self,
98 application: A,
99 username: U,
100 ) -> ClientResult<bool>
101 where
102 A: AsRef<str> + Debug,
103 U: AsRef<str> + Debug,
104 {
105 let payload = TransferOwnership {
106 new_user: username.as_ref().to_string(),
107 };
108
109 self.update(
110 self.url(application.as_ref(), AdministrationOperation::Transfer)?,
111 Some(payload),
112 )
113 .await
114 }
115
116 #[instrument]
118 pub async fn cancel_app_transfer<A>(&self, application: A) -> ClientResult<bool>
119 where
120 A: AsRef<str> + Debug,
121 {
122 self.delete(self.url(application.as_ref(), AdministrationOperation::Transfer)?)
123 .await
124 }
125
126 #[instrument]
128 pub async fn accept_app_transfer<A>(&self, application: A) -> ClientResult<bool>
129 where
130 A: AsRef<str> + Debug,
131 {
132 self.update(
133 self.url(application.as_ref(), AdministrationOperation::Accept)?,
134 None::<()>,
135 )
136 .await
137 }
138
139 #[instrument]
141 pub async fn read_app_transfer<A>(
142 &self,
143 application: A,
144 ) -> ClientResult<Option<TransferOwnership>>
145 where
146 A: AsRef<str> + Debug,
147 {
148 self.read(self.url(application.as_ref(), AdministrationOperation::Transfer)?)
149 .await
150 }
151}