use http::StatusCode;
use crate::api::codespaces::CodespacesSecretRepositoriesHandler;
use crate::models::codespaces::{Codespace, OrgCodespacesAccess, OrgCodespacesAccessVisibility};
use crate::models::orgs::secrets::{
CreateOrganizationSecret, CreateOrganizationSecretResponse, OrganizationSecret,
};
use crate::models::PublicKey;
use crate::{Octocrab, Page, Result};
pub struct OrgCodespacesHandler<'octo> {
crab: &'octo Octocrab,
owner: String,
}
impl<'octo> OrgCodespacesHandler<'octo> {
pub(crate) fn new(crab: &'octo Octocrab, owner: impl Into<String>) -> Self {
Self {
crab,
owner: owner.into(),
}
}
pub fn list(&self) -> ListOrgCodespacesBuilder<'octo, '_> {
ListOrgCodespacesBuilder::new(self)
}
pub async fn access(&self) -> Result<OrgCodespacesAccess> {
let route = format!("/orgs/{}/codespaces/access", self.owner);
self.crab.get(route, None::<&()>).await
}
pub async fn update_access(
&self,
visibility: OrgCodespacesAccessVisibility,
selected_usernames: Option<&[impl AsRef<str>]>,
) -> Result<()> {
let route = format!("/orgs/{}/codespaces/access", self.owner);
#[derive(serde::Serialize)]
struct Body<'a> {
visibility: OrgCodespacesAccessVisibility,
#[serde(skip_serializing_if = "Option::is_none")]
selected_usernames: Option<Vec<&'a str>>,
}
let body = Body {
visibility,
selected_usernames: selected_usernames
.map(|users| users.iter().map(AsRef::as_ref).collect()),
};
let resp = self.crab._put(route, Some(&body)).await?;
crate::map_github_error(resp).await?;
Ok(())
}
pub async fn add_selected_users(&self, selected_usernames: &[impl AsRef<str>]) -> Result<()> {
let route = format!("/orgs/{}/codespaces/access/selected_users", self.owner);
let body = serde_json::json!({
"selected_usernames": selected_usernames.iter().map(AsRef::as_ref).collect::<Vec<_>>()
});
let resp = self.crab._post(route, Some(&body)).await?;
crate::map_github_error(resp).await?;
Ok(())
}
pub async fn remove_selected_users(
&self,
selected_usernames: &[impl AsRef<str>],
) -> Result<()> {
let route = format!("/orgs/{}/codespaces/access/selected_users", self.owner);
let body = serde_json::json!({
"selected_usernames": selected_usernames.iter().map(AsRef::as_ref).collect::<Vec<_>>()
});
let resp = self.crab._delete(route, Some(&body)).await?;
crate::map_github_error(resp).await?;
Ok(())
}
pub fn list_for_user(
&self,
username: impl Into<String>,
) -> ListUserOrgCodespacesBuilder<'octo, '_> {
ListUserOrgCodespacesBuilder::new(self, username.into())
}
pub async fn delete_for_user(
&self,
username: impl AsRef<str>,
codespace_name: impl AsRef<str>,
) -> Result<()> {
let route = format!(
"/orgs/{}/members/{}/codespaces/{}",
self.owner,
username.as_ref(),
codespace_name.as_ref()
);
let resp = self.crab._delete(route, None::<&()>).await?;
crate::map_github_error(resp).await?;
Ok(())
}
pub async fn stop_for_user(
&self,
username: impl AsRef<str>,
codespace_name: impl AsRef<str>,
) -> Result<Codespace> {
let route = format!(
"/orgs/{}/members/{}/codespaces/{}/stop",
self.owner,
username.as_ref(),
codespace_name.as_ref()
);
self.crab.post(route, None::<&()>).await
}
pub fn secrets(&self) -> OrgCodespacesSecretsHandler<'octo> {
OrgCodespacesSecretsHandler::new(self.crab, self.owner.clone())
}
}
#[derive(serde::Serialize)]
pub struct ListOrgCodespacesBuilder<'octo, 'r> {
#[serde(skip)]
handler: &'r OrgCodespacesHandler<'octo>,
#[serde(skip_serializing_if = "Option::is_none")]
per_page: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
page: Option<u32>,
}
impl<'octo, 'r> ListOrgCodespacesBuilder<'octo, 'r> {
pub(crate) fn new(handler: &'r OrgCodespacesHandler<'octo>) -> Self {
Self {
handler,
per_page: None,
page: None,
}
}
pub fn per_page(mut self, per_page: impl Into<u8>) -> Self {
self.per_page = Some(per_page.into());
self
}
pub fn page(mut self, page: impl Into<u32>) -> Self {
self.page = Some(page.into());
self
}
pub async fn send(self) -> Result<Page<Codespace>> {
let route = format!("/orgs/{}/codespaces", self.handler.owner);
self.handler.crab.get(route, Some(&self)).await
}
}
#[derive(serde::Serialize)]
pub struct ListUserOrgCodespacesBuilder<'octo, 'r> {
#[serde(skip)]
handler: &'r OrgCodespacesHandler<'octo>,
#[serde(skip)]
username: String,
#[serde(skip_serializing_if = "Option::is_none")]
per_page: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
page: Option<u32>,
}
impl<'octo, 'r> ListUserOrgCodespacesBuilder<'octo, 'r> {
pub(crate) fn new(handler: &'r OrgCodespacesHandler<'octo>, username: String) -> Self {
Self {
handler,
username,
per_page: None,
page: None,
}
}
pub fn per_page(mut self, per_page: impl Into<u8>) -> Self {
self.per_page = Some(per_page.into());
self
}
pub fn page(mut self, page: impl Into<u32>) -> Self {
self.page = Some(page.into());
self
}
pub async fn send(self) -> Result<Page<Codespace>> {
let route = format!(
"/orgs/{}/members/{}/codespaces",
self.handler.owner, self.username
);
self.handler.crab.get(route, Some(&self)).await
}
}
pub struct OrgCodespacesSecretsHandler<'octo> {
crab: &'octo Octocrab,
owner: String,
}
impl<'octo> OrgCodespacesSecretsHandler<'octo> {
pub(crate) fn new(crab: &'octo Octocrab, owner: impl Into<String>) -> Self {
Self {
crab,
owner: owner.into(),
}
}
pub fn list(&self) -> ListOrgCodespacesSecretsBuilder<'octo, '_> {
ListOrgCodespacesSecretsBuilder::new(self)
}
pub async fn get_public_key(&self) -> Result<PublicKey> {
let route = format!("/orgs/{}/codespaces/secrets/public-key", self.owner);
self.crab.get(route, None::<&()>).await
}
pub async fn get(&self, secret_name: impl AsRef<str>) -> Result<OrganizationSecret> {
let route = format!(
"/orgs/{}/codespaces/secrets/{}",
self.owner,
secret_name.as_ref()
);
self.crab.get(route, None::<&()>).await
}
pub async fn create_or_update(
&self,
secret_name: impl AsRef<str>,
secret: &CreateOrganizationSecret<'_>,
) -> Result<CreateOrganizationSecretResponse> {
let route = format!(
"/orgs/{}/codespaces/secrets/{}",
self.owner,
secret_name.as_ref()
);
let resp = self.crab._put(route, Some(secret)).await?;
let resp = crate::map_github_error(resp).await?;
match resp.status() {
StatusCode::CREATED => Ok(CreateOrganizationSecretResponse::Created),
StatusCode::NO_CONTENT => Ok(CreateOrganizationSecretResponse::Updated),
status => Err(crate::Error::Other {
source: format!("Unexpected status code from request: {}", status.as_str()).into(),
backtrace: snafu::Backtrace::capture(),
}),
}
}
pub async fn delete(&self, secret_name: impl AsRef<str>) -> Result<()> {
let route = format!(
"/orgs/{}/codespaces/secrets/{}",
self.owner,
secret_name.as_ref()
);
let resp = self.crab._delete(route, None::<&()>).await?;
crate::map_github_error(resp).await?;
Ok(())
}
pub fn repositories(
&self,
secret_name: impl AsRef<str>,
) -> CodespacesSecretRepositoriesHandler<'octo> {
CodespacesSecretRepositoriesHandler::new(
self.crab,
format!(
"/orgs/{}/codespaces/secrets/{}",
self.owner,
secret_name.as_ref()
),
)
}
}
#[derive(serde::Serialize)]
pub struct ListOrgCodespacesSecretsBuilder<'octo, 'r> {
#[serde(skip)]
handler: &'r OrgCodespacesSecretsHandler<'octo>,
#[serde(skip_serializing_if = "Option::is_none")]
per_page: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
page: Option<u32>,
}
impl<'octo, 'r> ListOrgCodespacesSecretsBuilder<'octo, 'r> {
pub(crate) fn new(handler: &'r OrgCodespacesSecretsHandler<'octo>) -> Self {
Self {
handler,
per_page: None,
page: None,
}
}
pub fn per_page(mut self, per_page: impl Into<u8>) -> Self {
self.per_page = Some(per_page.into());
self
}
pub fn page(mut self, page: impl Into<u32>) -> Self {
self.page = Some(page.into());
self
}
pub async fn send(self) -> Result<Page<OrganizationSecret>> {
let route = format!("/orgs/{}/codespaces/secrets", self.handler.owner);
self.handler.crab.get(route, Some(&self)).await
}
}