ephemeris_forge_github/api/http/
security.rs1use ephemeris_forge::{RepoRef, encode};
2use reqwest::Method;
3
4use crate::api::HttpApi;
5use crate::api::error::ForgeError;
6use crate::api::model::{CodeScanning, EnabledResponse};
7use crate::api::operations::SecurityApi;
8use crate::api::request::{AnalysisBody, AnalysisPatch, CodeScanningPatch};
9
10impl HttpApi {
11 pub(super) async fn put_switch(
12 &self,
13 repository: &RepoRef,
14 name: &str,
15 enabled: bool,
16 ) -> Result<(), ForgeError> {
17 let method = if enabled { Method::PUT } else { Method::DELETE };
18 self.empty(method, &switch_path(repository, name), None)
19 .await
20 }
21}
22
23impl SecurityApi for HttpApi {
24 async fn automated_security_fixes(
25 &self,
26 repository: &RepoRef,
27 ) -> Result<Option<bool>, ForgeError> {
28 let setting: Option<EnabledResponse> = self
29 .optional(&switch_path(repository, "automated-security-fixes"))
30 .await?;
31 Ok(Some(setting.is_some_and(|setting| setting.enabled)))
32 }
33
34 async fn code_scanning_default_setup(
35 &self,
36 repository: &RepoRef,
37 ) -> Result<Option<CodeScanning>, ForgeError> {
38 match self
39 .optional(&repository.path("code-scanning/default-setup"))
40 .await
41 {
42 Err(error) if error.status() == Some(403) => Ok(None),
44 result => result,
45 }
46 }
47
48 async fn patch_code_scanning_default_setup(
49 &self,
50 repository: &RepoRef,
51 patch: &CodeScanningPatch,
52 ) -> Result<(), ForgeError> {
53 self.empty(
54 Method::PATCH,
55 &repository.path("code-scanning/default-setup"),
56 Some(encode(patch)),
57 )
58 .await
59 }
60
61 async fn patch_security_analysis(
62 &self,
63 repository: &RepoRef,
64 patch: &AnalysisPatch,
65 ) -> Result<(), ForgeError> {
66 self.empty(
67 Method::PATCH,
68 &repository.path(""),
69 Some(encode(&AnalysisBody {
70 security_and_analysis: patch.clone(),
71 })),
72 )
73 .await
74 }
75
76 async fn private_vulnerability_reporting(
77 &self,
78 repository: &RepoRef,
79 ) -> Result<Option<bool>, ForgeError> {
80 let setting: Option<EnabledResponse> = self
81 .optional(&switch_path(repository, "private-vulnerability-reporting"))
82 .await?;
83 Ok(setting.map(|setting| setting.enabled))
84 }
85
86 async fn set_automated_security_fixes(
87 &self,
88 repository: &RepoRef,
89 enabled: bool,
90 ) -> Result<(), ForgeError> {
91 self.put_switch(repository, "automated-security-fixes", enabled)
92 .await
93 }
94
95 async fn set_private_vulnerability_reporting(
96 &self,
97 repository: &RepoRef,
98 enabled: bool,
99 ) -> Result<(), ForgeError> {
100 self.put_switch(repository, "private-vulnerability-reporting", enabled)
101 .await
102 }
103
104 async fn set_vulnerability_alerts(
105 &self,
106 repository: &RepoRef,
107 enabled: bool,
108 ) -> Result<(), ForgeError> {
109 self.put_switch(repository, "vulnerability-alerts", enabled)
110 .await
111 }
112
113 async fn vulnerability_alerts(&self, repository: &RepoRef) -> Result<Option<bool>, ForgeError> {
114 match self
115 .empty(
116 Method::GET,
117 &switch_path(repository, "vulnerability-alerts"),
118 None,
119 )
120 .await
121 {
122 Ok(()) => Ok(Some(true)),
123 Err(error) if error.status() == Some(404) => Ok(Some(false)),
124 Err(error) => Err(error),
125 }
126 }
127}
128
129fn switch_path(repository: &RepoRef, name: &str) -> String {
130 repository.path(name)
131}