1use crate::auth::{CredentialChain, OidcAuthProvider, TokenSource, token_endpoint};
4use crate::resources::applications::{
5 Application as ApplicationInfo, ApplicationConfiguration, ApplicationsClient,
6 Installation as InstallationInfo, InstallationDetails, InstallationStatusChange,
7 InstallationSummary, InstallationsClient, ListApplicationsRequest,
8};
9use crate::{Client, Error, List, Page, Project};
10
11#[derive(Clone)]
17pub struct Application {
18 client: ApplicationsClient,
19}
20
21#[derive(Clone)]
23pub struct ApplicationRegistration {
24 client: ApplicationsClient,
25 id: String,
26}
27
28#[derive(Clone)]
34pub struct ApplicationInstallation {
35 client: ApplicationsClient,
36 id: String,
37}
38
39#[derive(Clone)]
41pub struct Installation {
42 client: InstallationsClient,
43}
44
45#[derive(Clone)]
47pub struct InstallationRegistration {
48 client: InstallationsClient,
49 id: String,
50}
51
52impl Client {
53 pub fn application(&self, id: impl Into<String>) -> ApplicationRegistration {
55 self.applications().application(id)
56 }
57 pub fn installation(&self, id: impl Into<String>) -> InstallationRegistration {
59 self.installations().installation(id)
60 }
61}
62impl Application {
63 pub(crate) fn new(client: ApplicationsClient) -> Self {
64 Self { client }
65 }
66 pub async fn get(&self) -> Result<ApplicationInfo, Error> {
68 Ok(self.client.service.client.get_self().await?)
69 }
70 pub fn installations(&self) -> List<'_, ApplicationInstallation> {
72 List::new(move |options| {
73 Box::pin(async move {
74 let page = self
75 .client
76 .service
77 .client
78 .list_self_installations(ListApplicationsRequest {
79 page_size: options.size,
80 page_token: options.token,
81 })
82 .await?;
83 Ok(Page {
84 items: page
85 .installations
86 .into_iter()
87 .map(|info| self.installation(info.id))
88 .collect(),
89 next_page_token: page.next_page_token,
90 })
91 })
92 })
93 }
94 pub fn installation(&self, id: impl Into<String>) -> ApplicationInstallation {
96 ApplicationInstallation {
97 client: self.client.clone(),
98 id: id.into(),
99 }
100 }
101}
102impl ApplicationInstallation {
103 pub fn id(&self) -> &str {
105 &self.id
106 }
107 pub async fn get(&self) -> Result<InstallationDetails, Error> {
109 Ok(self
110 .client
111 .service
112 .client
113 .get_self_installation(self.id.clone())
114 .await?)
115 }
116 pub async fn authenticate(&self) -> Result<Installation, Error> {
122 let service = &self.client.service;
123 let source = service.auth.clone().ok_or(Error::CredentialsNotFound)?;
124 let provider = TokenSource::from(CredentialChain::new(vec![
125 OidcAuthProvider::new(
126 service.http.clone(),
127 token_endpoint(&service.auth_url)?,
128 self.id.clone(),
129 )
130 .with_assertion_provider(source)
131 .into(),
132 ]));
133 let client = service.connection(Some(provider))?;
134 client.access_token().await?;
136 Ok(client.installations().current())
137 }
138}
139impl ApplicationRegistration {
140 pub(crate) fn new(client: ApplicationsClient, id: String) -> Self {
141 Self { client, id }
142 }
143 pub fn id(&self) -> &str {
145 &self.id
146 }
147 pub async fn get(&self) -> Result<ApplicationInfo, Error> {
149 Ok(self
150 .client
151 .service
152 .client
153 .get_application(self.id.clone())
154 .await?)
155 }
156 pub async fn update(
158 &self,
159 configuration: ApplicationConfiguration,
160 ) -> Result<ApplicationInfo, Error> {
161 Ok(self
162 .client
163 .service
164 .client
165 .put_application(self.id.clone(), configuration)
166 .await?)
167 }
168 pub async fn delete(&self) -> Result<ApplicationInfo, Error> {
170 Ok(self
171 .client
172 .service
173 .client
174 .delete_application(self.id.clone())
175 .await?)
176 }
177 pub fn installations(&self) -> List<'_, InstallationInfo> {
179 self.client
180 .service
181 .client
182 .list_application_installations_list(self.id.clone(), Default::default())
183 }
184}
185impl Installation {
186 pub(crate) fn current(client: InstallationsClient) -> Self {
187 Self { client }
188 }
189 pub async fn get(&self) -> Result<InstallationDetails, Error> {
191 Ok(self
192 .client
193 .service
194 .client
195 .get_current_installation()
196 .await?)
197 }
198 pub fn projects(&self) -> List<'_, Project> {
200 List::new(move |options| {
201 Box::pin(async move {
202 let service = &self.client.service;
203 let page = service
204 .client
205 .list_installation_projects(ListApplicationsRequest {
206 page_size: options.size,
207 page_token: options.token,
208 })
209 .await?;
210 let client = &self.client.connection;
211 Ok(Page {
212 items: page
213 .projects
214 .into_iter()
215 .map(|info| client.project(info.id))
216 .collect::<Result<_, _>>()?,
217 next_page_token: page.next_page_token,
218 })
219 })
220 })
221 }
222 pub fn project(&self, id: impl AsRef<str>) -> Result<Project, Error> {
225 self.client.connection.project(id)
226 }
227}
228impl InstallationRegistration {
229 pub(crate) fn new(client: InstallationsClient, id: String) -> Self {
230 Self { client, id }
231 }
232 pub fn id(&self) -> &str {
234 &self.id
235 }
236 pub async fn get(&self) -> Result<InstallationInfo, Error> {
238 Ok(self
239 .client
240 .service
241 .client
242 .get_installation(self.id.clone())
243 .await?)
244 }
245 pub async fn approve(&self) -> Result<InstallationInfo, Error> {
247 Ok(self
248 .client
249 .service
250 .client
251 .approve_installation(self.id.clone())
252 .await?)
253 }
254 pub async fn suspend(&self) -> Result<InstallationInfo, Error> {
256 Ok(self
257 .client
258 .service
259 .client
260 .set_installation_status(self.id.clone(), InstallationStatusChange { enabled: false })
261 .await?)
262 }
263 pub async fn resume(&self) -> Result<InstallationInfo, Error> {
265 Ok(self
266 .client
267 .service
268 .client
269 .set_installation_status(self.id.clone(), InstallationStatusChange { enabled: true })
270 .await?)
271 }
272 pub async fn uninstall(&self) -> Result<InstallationInfo, Error> {
274 Ok(self
275 .client
276 .service
277 .client
278 .uninstall(self.id.clone())
279 .await?)
280 }
281}
282
283#[derive(Clone)]
289pub struct UserInstallation {
290 client: InstallationsClient,
291 info: InstallationSummary,
292}
293impl UserInstallation {
294 pub(crate) fn new(client: InstallationsClient, info: InstallationSummary) -> Self {
295 Self { client, info }
296 }
297 pub fn id(&self) -> &str {
299 &self.info.id
300 }
301 pub fn info(&self) -> &InstallationSummary {
303 &self.info
304 }
305 pub async fn get(&self) -> Result<InstallationSummary, Error> {
307 let service = &self.client.service;
308 service
309 .client
310 .get_user_installation()
311 .await?
312 .installation
313 .filter(|info| info.id == self.info.id)
314 .ok_or_else(|| Error::NotFound(self.info.id.clone()))
315 }
316 pub fn projects(&self) -> List<'_, Project> {
318 List::new(move |options| {
319 Box::pin(async move {
320 let service = &self.client.service;
321 let page = service
322 .client
323 .list_user_installation_projects(
324 self.info.id.clone(),
325 ListApplicationsRequest {
326 page_size: options.size,
327 page_token: options.token,
328 },
329 )
330 .await?;
331 Ok(Page {
332 items: page
333 .projects
334 .into_iter()
335 .map(|info| self.project(info.id))
336 .collect::<Result<_, _>>()?,
337 next_page_token: page.next_page_token,
338 })
339 })
340 })
341 }
342 pub fn project(&self, id: impl AsRef<str>) -> Result<Project, Error> {
345 self.client.connection.project(id)
346 }
347}