use super::data::*;
use crate::core::CoreClient;
use crate::error::ClientError;
use crate::openid::TokenProvider;
use std::{fmt::Debug, sync::Arc};
use tracing::instrument;
use url::Url;
#[derive(Clone, Debug)]
pub struct Client {
client: reqwest::Client,
api_url: Url,
token_provider: Arc<dyn TokenProvider>,
}
enum AdministrationOperation {
Transfer,
Accept,
Members,
}
type ClientResult<T> = Result<T, ClientError>;
impl CoreClient for Client {
fn client(&self) -> &reqwest::Client {
&self.client
}
fn token_provider(&self) -> &dyn TokenProvider {
self.token_provider.as_ref()
}
}
impl Client {
pub fn new(
client: reqwest::Client,
api_url: Url,
token_provider: impl TokenProvider + 'static,
) -> Self {
Self {
client,
api_url,
token_provider: Arc::new(token_provider),
}
}
fn url(&self, application: &str, operation: AdministrationOperation) -> ClientResult<Url> {
let mut url = self.api_url.clone();
{
let mut path = url
.path_segments_mut()
.map_err(|_| ClientError::Request("Failed to get paths".into()))?;
path.extend(&["api", "admin", "v1alpha1", "apps"]);
if !application.is_empty() {
path.push(application);
}
match operation {
AdministrationOperation::Transfer => path.push("transfer-ownership"),
AdministrationOperation::Accept => path.push("accept-ownership"),
AdministrationOperation::Members => path.push("members"),
};
}
Ok(url)
}
#[instrument]
pub async fn get_members<A>(&self, application: A) -> ClientResult<Option<Members>>
where
A: AsRef<str> + Debug,
{
self.read(self.url(application.as_ref(), AdministrationOperation::Members)?)
.await
}
#[instrument]
pub async fn update_members<A>(&self, application: A, members: Members) -> ClientResult<bool>
where
A: AsRef<str> + Debug,
{
self.update(
self.url(application.as_ref(), AdministrationOperation::Members)?,
Some(members),
)
.await
}
#[instrument]
pub async fn initiate_app_transfer<A, U>(
&self,
application: A,
username: U,
) -> ClientResult<bool>
where
A: AsRef<str> + Debug,
U: AsRef<str> + Debug,
{
let payload = TransferOwnership {
new_user: username.as_ref().to_string(),
};
self.update(
self.url(application.as_ref(), AdministrationOperation::Transfer)?,
Some(payload),
)
.await
}
#[instrument]
pub async fn cancel_app_transfer<A>(&self, application: A) -> ClientResult<bool>
where
A: AsRef<str> + Debug,
{
self.delete(self.url(application.as_ref(), AdministrationOperation::Transfer)?)
.await
}
#[instrument]
pub async fn accept_app_transfer<A>(&self, application: A) -> ClientResult<bool>
where
A: AsRef<str> + Debug,
{
self.update(
self.url(application.as_ref(), AdministrationOperation::Accept)?,
None::<()>,
)
.await
}
#[instrument]
pub async fn read_app_transfer<A>(
&self,
application: A,
) -> ClientResult<Option<TransferOwnership>>
where
A: AsRef<str> + Debug,
{
self.read(self.url(application.as_ref(), AdministrationOperation::Transfer)?)
.await
}
}