1 use std::fmt; 2 use std::str::FromStr; 3 4 use serde::Serialize; 5 6 use crate::{ 7 commons::{ 8 api::{ 9 AllCertAuthIssues, AspaDefinitionList, CaCommandDetails, CaRepoDetails, CertAuthInfo, CertAuthIssues, 10 CertAuthList, ChildCaInfo, ChildrenConnectionStats, CommandHistory, ParentCaContact, ParentStatuses, 11 PublisherDetails, PublisherList, RepoStatus, RoaDefinitions, RtaList, RtaPrepResponse, ServerInfo, 12 }, 13 bgp::{BgpAnalysisAdvice, BgpAnalysisReport, BgpAnalysisSuggestion}, 14 remote::{api::ClientInfos, rfc8183}, 15 }, 16 daemon::ca::ResourceTaggedAttestation, 17 pubd::RepoStats, 18 }; 19 20 //------------ ApiResponse --------------------------------------------------- 21 22 /// This type defines all supported responses for the api 23 #[derive(Clone, Debug, Eq, PartialEq)] 24 #[allow(clippy::large_enum_variant)] 25 pub enum ApiResponse { 26 Health, 27 Info(ServerInfo), 28 29 CertAuthInfo(CertAuthInfo), 30 CertAuthHistory(CommandHistory), 31 CertAuthAction(CaCommandDetails), 32 CertAuths(CertAuthList), 33 34 // ROA related 35 RouteAuthorizations(RoaDefinitions), 36 BgpAnalysisAdvice(BgpAnalysisAdvice), 37 BgpAnalysisFull(BgpAnalysisReport), 38 BgpAnalysisSuggestions(BgpAnalysisSuggestion), 39 40 // ASPA related 41 AspaDefinitions(AspaDefinitionList), 42 43 ParentCaContact(ParentCaContact), 44 ParentStatuses(ParentStatuses), 45 46 ChildInfo(ChildCaInfo), 47 ChildrenStats(ChildrenConnectionStats), 48 49 PublisherDetails(PublisherDetails), 50 PublisherList(PublisherList), 51 RepoStats(RepoStats), 52 53 Rfc8181ClientList(ClientInfos), 54 Rfc8183RepositoryResponse(rfc8183::RepositoryResponse), 55 Rfc8183ChildRequest(rfc8183::ChildRequest), 56 Rfc8183PublisherRequest(rfc8183::PublisherRequest), 57 58 RepoDetails(CaRepoDetails), 59 RepoStatus(RepoStatus), 60 61 CertAuthIssues(CertAuthIssues), 62 AllCertAuthIssues(AllCertAuthIssues), 63 64 RtaList(RtaList), 65 RtaMultiPrep(RtaPrepResponse), 66 Rta(ResourceTaggedAttestation), 67 68 Empty, // Typically a successful post just gets an empty 200 response 69 GenericBody(String), // For when the server echos Json to a successful post 70 } 71 72 impl ApiResponse { report(&self, fmt: ReportFormat) -> Result<Option<String>, ReportError>73 pub fn report(&self, fmt: ReportFormat) -> Result<Option<String>, ReportError> { 74 if fmt == ReportFormat::None { 75 Ok(None) 76 } else { 77 match self { 78 ApiResponse::Health => Ok(None), 79 ApiResponse::Info(info) => Ok(Some(info.report(fmt)?)), 80 ApiResponse::CertAuths(list) => Ok(Some(list.report(fmt)?)), 81 ApiResponse::CertAuthInfo(info) => Ok(Some(info.report(fmt)?)), 82 ApiResponse::CertAuthHistory(history) => Ok(Some(history.report(fmt)?)), 83 ApiResponse::CertAuthAction(details) => Ok(Some(details.report(fmt)?)), 84 ApiResponse::CertAuthIssues(issues) => Ok(Some(issues.report(fmt)?)), 85 ApiResponse::AllCertAuthIssues(issues) => Ok(Some(issues.report(fmt)?)), 86 ApiResponse::RouteAuthorizations(definitions) => Ok(Some(definitions.report(fmt)?)), 87 ApiResponse::BgpAnalysisAdvice(analysis) => Ok(Some(analysis.report(fmt)?)), 88 ApiResponse::BgpAnalysisFull(table) => Ok(Some(table.report(fmt)?)), 89 ApiResponse::BgpAnalysisSuggestions(suggestions) => Ok(Some(suggestions.report(fmt)?)), 90 ApiResponse::AspaDefinitions(definitions) => Ok(Some(definitions.report(fmt)?)), 91 ApiResponse::ParentCaContact(contact) => Ok(Some(contact.report(fmt)?)), 92 ApiResponse::ParentStatuses(statuses) => Ok(Some(statuses.report(fmt)?)), 93 ApiResponse::ChildInfo(info) => Ok(Some(info.report(fmt)?)), 94 ApiResponse::ChildrenStats(stats) => Ok(Some(stats.report(fmt)?)), 95 ApiResponse::PublisherList(list) => Ok(Some(list.report(fmt)?)), 96 ApiResponse::PublisherDetails(details) => Ok(Some(details.report(fmt)?)), 97 ApiResponse::RepoStats(stats) => Ok(Some(stats.report(fmt)?)), 98 ApiResponse::Rfc8181ClientList(list) => Ok(Some(list.report(fmt)?)), 99 ApiResponse::Rfc8183ChildRequest(req) => Ok(Some(req.report(fmt)?)), 100 ApiResponse::Rfc8183PublisherRequest(req) => Ok(Some(req.report(fmt)?)), 101 ApiResponse::Rfc8183RepositoryResponse(res) => Ok(Some(res.report(fmt)?)), 102 ApiResponse::RepoDetails(details) => Ok(Some(details.report(fmt)?)), 103 ApiResponse::RepoStatus(status) => Ok(Some(status.report(fmt)?)), 104 ApiResponse::Rta(rta) => Ok(Some(rta.report(fmt)?)), 105 ApiResponse::RtaList(list) => Ok(Some(list.report(fmt)?)), 106 ApiResponse::RtaMultiPrep(res) => Ok(Some(res.report(fmt)?)), 107 ApiResponse::GenericBody(body) => Ok(Some(body.clone())), 108 ApiResponse::Empty => Ok(None), 109 } 110 } 111 } 112 } 113 114 //------------ ReportFormat -------------------------------------------------- 115 116 /// This type defines the format to use when representing the api response 117 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 118 pub enum ReportFormat { 119 None, 120 Json, 121 Text, 122 } 123 124 impl FromStr for ReportFormat { 125 type Err = ReportError; 126 from_str(s: &str) -> Result<Self, ReportError>127 fn from_str(s: &str) -> Result<Self, ReportError> { 128 match s { 129 "none" => Ok(ReportFormat::None), 130 "json" => Ok(ReportFormat::Json), 131 "text" => Ok(ReportFormat::Text), 132 _ => Err(ReportError::UnrecognizedFormat(s.to_string())), 133 } 134 } 135 } 136 137 //------------ ReportError --------------------------------------------------- 138 139 /// This type defines possible Errors for KeyStore 140 #[derive(Debug)] 141 pub enum ReportError { 142 UnsupportedFormat, 143 UnrecognizedFormat(String), 144 } 145 146 impl fmt::Display for ReportError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result147 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 148 match self { 149 ReportError::UnsupportedFormat => write!(f, "This report format is not supported for this data"), 150 ReportError::UnrecognizedFormat(s) => write!(f, "This report format is not recognized: {}", s), 151 } 152 } 153 } 154 155 //------------ Report -------------------------------------------------------- 156 157 /// This trait should be implemented by all api responses, so that the 158 /// response can be formatted for users. 159 trait Report: Serialize + ToString { text(&self) -> Result<String, ReportError>160 fn text(&self) -> Result<String, ReportError> { 161 Ok(self.to_string()) 162 } 163 json(&self) -> String164 fn json(&self) -> String { 165 serde_json::to_string_pretty(self).unwrap() 166 } 167 report(&self, format: ReportFormat) -> Result<String, ReportError>168 fn report(&self, format: ReportFormat) -> Result<String, ReportError> { 169 match format { 170 ReportFormat::None => Ok("".to_string()), 171 ReportFormat::Json => Ok(self.json()), 172 ReportFormat::Text => self.text(), 173 } 174 } 175 } 176 177 impl Report for CertAuthList {} 178 impl Report for CertAuthInfo {} 179 180 impl Report for ChildCaInfo {} 181 182 impl Report for ParentCaContact {} 183 impl Report for ParentStatuses {} 184 185 impl Report for CommandHistory {} 186 impl Report for CaCommandDetails {} 187 188 impl Report for PublisherList {} 189 190 impl Report for RepoStats {} 191 impl Report for ChildrenConnectionStats {} 192 193 impl Report for PublisherDetails {} 194 195 impl Report for ClientInfos {} 196 197 impl Report for rfc8183::RepositoryResponse {} 198 impl Report for rfc8183::ChildRequest {} 199 impl Report for rfc8183::PublisherRequest {} 200 201 impl Report for RoaDefinitions {} 202 203 impl Report for BgpAnalysisAdvice {} 204 impl Report for BgpAnalysisReport {} 205 impl Report for BgpAnalysisSuggestion {} 206 207 impl Report for AspaDefinitionList {} 208 209 impl Report for CaRepoDetails {} 210 impl Report for RepoStatus {} 211 212 impl Report for CertAuthIssues {} 213 214 impl Report for AllCertAuthIssues {} 215 216 impl Report for ServerInfo {} 217 218 impl Report for ResourceTaggedAttestation {} 219 impl Report for RtaList {} 220 impl Report for RtaPrepResponse {} 221