use super::RepoHandler;
use crate::models::repos::secret_scanning_alert::{
BulkCreatedCustomPatterns, CreateSecretScanningCustomPattern,
DeleteSecretScanningCustomPattern, PushProtectionBypass, PushProtectionBypassReason,
SecretScanningAlert, SecretScanningCustomPattern, SecretScanningScanHistory,
SecretsScanningAlertLocation, UpdateSecretScanningAlert, UpdateSecretScanningCustomPattern,
};
pub struct RepoSecretScanningAlertsHandler<'octo> {
handler: &'octo RepoHandler<'octo>,
params: Params,
}
pub(crate) fn serialize_comma_separated<S>(
val: &Option<Vec<String>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match val {
Some(v) => serializer.serialize_str(&v.join(",")),
None => serializer.serialize_none(),
}
}
#[derive(serde::Serialize, Default, Clone)]
pub(crate) struct Params {
#[serde(skip_serializing_if = "Option::is_none")]
pub per_page: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub push_protection: Option<String>,
#[serde(
skip_serializing_if = "Option::is_none",
serialize_with = "serialize_comma_separated"
)]
pub resolution: Option<Vec<String>>,
#[serde(
skip_serializing_if = "Option::is_none",
serialize_with = "serialize_comma_separated"
)]
pub validity: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sort: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub direction: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub secret_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub exclude_secret_types: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub providers: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub exclude_providers: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assignee: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub before: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub after: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_publicly_leaked: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_multi_repo: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hide_secret: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_bypassed: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub included_metadata: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub owner_email_hash: Option<String>,
}
impl<'octo> RepoSecretScanningAlertsHandler<'octo> {
pub(crate) fn new(repo: &'octo RepoHandler<'octo>) -> Self {
Self {
handler: repo,
params: Params::default(),
}
}
pub async fn get_alerts(&self) -> crate::Result<crate::Page<SecretScanningAlert>> {
let route = format!("/{}/secret-scanning/alerts", self.handler.repo);
self.handler.crab.get(route, Some(&self.params)).await
}
pub fn per_page(mut self, per_page: impl Into<u8>) -> Self {
self.params.per_page = Some(per_page.into());
self
}
pub fn page(mut self, page: impl Into<u32>) -> Self {
self.params.page = Some(page.into());
self
}
pub fn state(mut self, state: impl Into<String>) -> Self {
self.params.state = Some(state.into());
self
}
pub fn push_protection(mut self, push_protection: impl Into<String>) -> Self {
self.params.push_protection = Some(push_protection.into());
self
}
pub fn resolution(mut self, resolution: impl Into<Vec<String>>) -> Self {
self.params.resolution = Some(resolution.into());
self
}
pub fn validity(mut self, validity: impl Into<Vec<String>>) -> Self {
self.params.validity = Some(validity.into());
self
}
pub fn secret_type(mut self, secret_type: impl Into<String>) -> Self {
self.params.secret_type = Some(secret_type.into());
self
}
pub fn exclude_secret_types(mut self, exclude_secret_types: impl Into<String>) -> Self {
self.params.exclude_secret_types = Some(exclude_secret_types.into());
self
}
pub fn providers(mut self, providers: impl Into<String>) -> Self {
self.params.providers = Some(providers.into());
self
}
pub fn exclude_providers(mut self, exclude_providers: impl Into<String>) -> Self {
self.params.exclude_providers = Some(exclude_providers.into());
self
}
pub fn assignee(mut self, assignee: impl Into<String>) -> Self {
self.params.assignee = Some(assignee.into());
self
}
pub fn hide_secret(mut self, hide_secret: impl Into<bool>) -> Self {
self.params.hide_secret = Some(hide_secret.into());
self
}
pub fn is_bypassed(mut self, is_bypassed: impl Into<bool>) -> Self {
self.params.is_bypassed = Some(is_bypassed.into());
self
}
pub fn included_metadata(mut self, included_metadata: impl Into<String>) -> Self {
self.params.included_metadata = Some(included_metadata.into());
self
}
pub fn owner_email_hash(mut self, owner_email_hash: impl Into<String>) -> Self {
self.params.owner_email_hash = Some(owner_email_hash.into());
self
}
pub fn is_multi_repo(mut self, is_multi_repo: impl Into<bool>) -> Self {
self.params.is_multi_repo = Some(is_multi_repo.into());
self
}
pub fn is_publicly_leaked(mut self, is_publicly_leaked: impl Into<bool>) -> Self {
self.params.is_publicly_leaked = Some(is_publicly_leaked.into());
self
}
pub fn after(mut self, after: impl Into<String>) -> Self {
self.params.after = Some(after.into());
self
}
pub fn before(mut self, before: impl Into<String>) -> Self {
self.params.before = Some(before.into());
self
}
pub fn sort(mut self, sort: impl Into<String>) -> Self {
self.params.sort = Some(sort.into());
self
}
pub fn direction(mut self, direction: impl Into<String>) -> Self {
self.params.direction = Some(direction.into());
self
}
pub async fn get_alert(&self, alert_number: u32) -> crate::Result<SecretScanningAlert> {
let route = format!(
"/{}/secret-scanning/alerts/{}",
self.handler.repo, alert_number
);
self.handler.crab.get(route, None::<&()>).await
}
pub async fn update_alert(
&self,
alert_number: u32,
alert_update: Option<&UpdateSecretScanningAlert<'_>>,
) -> crate::Result<SecretScanningAlert> {
let route = format!(
"/{}/secret-scanning/alerts/{}",
self.handler.repo, alert_number
);
self.handler.crab.patch(route, alert_update).await
}
pub async fn get_alert_locations(
&self,
alert_number: u32,
) -> crate::Result<crate::Page<SecretsScanningAlertLocation>> {
let route = format!(
"/{}/secret-scanning/alerts/{}/locations",
self.handler.repo, alert_number
);
self.handler.crab.get(route, None::<&()>).await
}
pub async fn list_custom_patterns(
&self,
) -> crate::Result<crate::Page<SecretScanningCustomPattern>> {
let route = format!("/{}/secret-scanning/custom-patterns", self.handler.repo);
self.handler.crab.get(route, Some(&self.params)).await
}
pub async fn create_custom_patterns(
&self,
patterns: &[CreateSecretScanningCustomPattern],
) -> crate::Result<BulkCreatedCustomPatterns> {
let route = format!("/{}/secret-scanning/custom-patterns", self.handler.repo);
let body = serde_json::json!({ "patterns": patterns });
self.handler.crab.post(route, Some(&body)).await
}
pub async fn delete_custom_patterns(
&self,
patterns: &[DeleteSecretScanningCustomPattern],
post_delete_action: Option<&str>,
) -> crate::Result<()> {
let route = format!("/{}/secret-scanning/custom-patterns", self.handler.repo);
let body = match post_delete_action {
Some(action) => serde_json::json!({
"patterns": patterns,
"post_delete_action": action,
}),
None => serde_json::json!({
"patterns": patterns,
}),
};
let response = self.handler.crab._delete(route, Some(&body)).await?;
crate::map_github_error(response).await.map(drop)
}
pub async fn update_custom_pattern(
&self,
pattern_id: u64,
update: &UpdateSecretScanningCustomPattern,
) -> crate::Result<SecretScanningCustomPattern> {
let route = format!(
"/{}/secret-scanning/custom-patterns/{pattern_id}",
self.handler.repo
);
self.handler.crab.patch(route, Some(update)).await
}
pub async fn create_push_protection_bypass(
&self,
reason: PushProtectionBypassReason,
placeholder_id: impl Into<String>,
) -> crate::Result<PushProtectionBypass> {
let route = format!(
"/{}/secret-scanning/push-protection-bypasses",
self.handler.repo
);
let body = serde_json::json!({
"reason": reason,
"placeholder_id": placeholder_id.into(),
});
self.handler.crab.post(route, Some(&body)).await
}
pub async fn get_scan_history(&self) -> crate::Result<SecretScanningScanHistory> {
let route = format!("/{}/secret-scanning/scan-history", self.handler.repo);
self.handler.crab.get(route, None::<&()>).await
}
}