sdp_request_client/
lib.rs1use chrono::Duration;
37use reqwest::{
38 Url,
39 header::{HeaderMap, HeaderName, HeaderValue},
40};
41use serde::{Deserialize, Serialize};
42
43mod auth;
44mod builders;
45mod client;
46mod error;
47
48pub use crate::auth::Credentials;
49pub use builders::{
50 NoteBuilder, TicketClient, TicketCreateBuilder, TicketSearchBuilder, TicketStatus,
51 TicketsClient,
52};
53pub use client::{
54 Attachment, Condition, CreateTicketData, Criteria, DetailedTicket, EditTicketData, LogicalOp,
55 NameWrapper, Note, NoteData, NoteResponse, Priority, Resolution, SizeInfo, Status, TicketData,
56 TicketResponse, TimeEntry, UserInfo,
57};
58pub use error::{Error, SdpErrorCode};
59
60#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Hash, Default)]
62pub struct UserID(pub String);
63
64#[derive(Clone, Debug)]
66pub struct TicketID(pub u64);
67
68#[derive(Clone, Debug)]
70pub struct NoteID(pub u64);
71
72impl From<u64> for NoteID {
73 fn from(value: u64) -> Self {
74 NoteID(value)
75 }
76}
77
78impl From<NoteID> for u64 {
79 fn from(value: NoteID) -> Self {
80 value.0
81 }
82}
83
84impl std::fmt::Display for NoteID {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 write!(f, "{}", self.0)
87 }
88}
89
90impl From<u64> for TicketID {
91 fn from(value: u64) -> Self {
92 TicketID(value)
93 }
94}
95
96impl From<TicketID> for u64 {
97 fn from(value: TicketID) -> Self {
98 value.0
99 }
100}
101
102impl From<&TicketID> for u64 {
103 fn from(value: &TicketID) -> Self {
104 value.0
105 }
106}
107
108impl From<&UserID> for String {
109 fn from(value: &UserID) -> Self {
110 value.0.clone()
111 }
112}
113
114impl From<String> for UserID {
115 fn from(value: String) -> Self {
116 UserID(value)
117 }
118}
119
120impl From<&str> for UserID {
121 fn from(value: &str) -> Self {
122 UserID(value.to_string())
123 }
124}
125
126impl From<u32> for UserID {
127 fn from(value: u32) -> Self {
128 UserID(value.to_string())
129 }
130}
131
132impl From<UserID> for u32 {
133 fn from(value: UserID) -> Self {
134 value.0.parse().unwrap_or_default()
135 }
136}
137
138impl std::fmt::Display for TicketID {
139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 write!(f, "{}", self.0)
141 }
142}
143
144impl std::fmt::Display for UserID {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 write!(f, "{}", self.0)
147 }
148}
149
150#[derive(Clone)]
155pub struct ServiceDesk {
156 pub base_url: Url,
157 pub credentials: Credentials,
158 inner: reqwest::Client,
159}
160
161#[derive(Clone, Debug)]
164pub enum Security {
165 Unsafe,
166 NativeTlS,
167}
168
169#[derive(Clone, Debug)]
171pub struct ServiceDeskOptions {
172 user_agent: Option<String>,
173 timeout: Option<Duration>,
175 security: Option<Security>,
176 default_headers: Option<HeaderMap>,
177}
178
179static SDP_HEADER: (HeaderName, HeaderValue) = (
180 HeaderName::from_static("accept"),
181 HeaderValue::from_static("application/vnd.manageengine.sdp.v3+json"),
182);
183
184impl Default for ServiceDeskOptions {
185 fn default() -> Self {
186 ServiceDeskOptions {
187 user_agent: Some(String::from("servicedesk-rs/0.1.0")),
188 timeout: Some(Duration::seconds(5)),
189 security: Some(Security::Unsafe),
190 default_headers: Some(HeaderMap::from_iter(vec![SDP_HEADER.clone()])),
191 }
192 }
193}
194
195impl ServiceDesk {
196 pub fn new(base_url: Url, credentials: Credentials, options: ServiceDeskOptions) -> Self {
198 let mut headers = options.default_headers.unwrap_or_default();
199
200 #[allow(clippy::single_match)]
201 match credentials {
202 Credentials::Token { ref token } => {
203 headers.insert("authtoken", HeaderValue::from_str(token).unwrap());
204 }
205 _ => {}
206 }
207 let mut inner = reqwest::ClientBuilder::new()
208 .default_headers(headers)
209 .user_agent(options.user_agent.unwrap_or_default())
210 .timeout(options.timeout.unwrap_or_default().to_std().unwrap());
211
212 if let Some(security) = options.security {
213 match security {
214 Security::Unsafe => {
215 inner = inner.danger_accept_invalid_certs(true);
216 }
217 Security::NativeTlS => {
218 }
220 }
221 };
222
223 let inner = inner.build().expect("failed to build sdp client");
224
225 ServiceDesk {
226 base_url,
227 credentials,
228 inner,
229 }
230 }
231}
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236
237 #[test]
238 fn service_desk_options_default() {
239 let opts = ServiceDeskOptions::default();
240 assert_eq!(opts.user_agent, Some("servicedesk-rs/0.1.0".to_string()));
241 assert_eq!(opts.timeout, Some(Duration::seconds(5)));
242 assert!(matches!(opts.security, Some(Security::Unsafe)));
243 assert!(opts.default_headers.is_some());
244 }
245}