redmine_api/api/
attachments.rs1use derive_builder::Builder;
10use reqwest::Method;
11use std::borrow::Cow;
12
13use crate::api::users::UserEssentials;
14use crate::api::{Endpoint, NoPagination, ReturnsJsonResponse};
15
16#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
20pub struct Attachment {
21 pub id: u64,
23 pub filename: String,
25 pub filesize: u64,
27 pub content_type: Option<String>,
29 #[serde(default)]
31 pub description: Option<String>,
32 pub content_url: String,
34 pub author: UserEssentials,
36 #[serde(
38 serialize_with = "crate::api::serialize_rfc3339",
39 deserialize_with = "crate::api::deserialize_rfc3339"
40 )]
41 pub created_on: time::OffsetDateTime,
42}
43
44#[derive(Debug, Clone, Builder)]
46#[builder(setter(strip_option))]
47pub struct GetAttachment {
48 id: u64,
50}
51
52impl ReturnsJsonResponse for GetAttachment {}
53impl NoPagination for GetAttachment {}
54
55impl GetAttachment {
56 #[must_use]
58 pub fn builder() -> GetAttachmentBuilder {
59 GetAttachmentBuilder::default()
60 }
61}
62
63impl Endpoint for GetAttachment {
64 fn method(&self) -> Method {
65 Method::GET
66 }
67
68 fn endpoint(&self) -> Cow<'static, str> {
69 format!("attachments/{}.json", &self.id).into()
70 }
71}
72
73#[derive(Debug, Clone, Builder)]
75#[builder(setter(strip_option))]
76pub struct DeleteAttachment {
77 id: u64,
79}
80
81impl DeleteAttachment {
82 #[must_use]
84 pub fn builder() -> DeleteAttachmentBuilder {
85 DeleteAttachmentBuilder::default()
86 }
87}
88
89impl Endpoint for DeleteAttachment {
90 fn method(&self) -> Method {
91 Method::DELETE
92 }
93
94 fn endpoint(&self) -> Cow<'static, str> {
95 format!("attachments/{}.json", &self.id).into()
96 }
97}
98
99#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
101pub struct AttachmentWrapper<T> {
102 pub attachment: T,
104}
105
106#[cfg(test)]
107mod test {
108 use super::*;
109 use pretty_assertions::assert_eq;
110 use std::error::Error;
111 use tracing_test::traced_test;
112
113 #[traced_test]
114 #[test]
115 fn test_get_attachment() -> Result<(), Box<dyn Error>> {
116 dotenvy::dotenv()?;
117 let redmine = crate::api::Redmine::from_env(
118 reqwest::blocking::Client::builder()
119 .use_rustls_tls()
120 .build()?,
121 )?;
122 let endpoint = GetAttachment::builder().id(38468).build()?;
123 redmine.json_response_body::<_, AttachmentWrapper<Attachment>>(&endpoint)?;
124 Ok(())
125 }
126
127 #[traced_test]
132 #[test]
133 fn test_completeness_attachment_type() -> Result<(), Box<dyn Error>> {
134 dotenvy::dotenv()?;
135 let redmine = crate::api::Redmine::from_env(
136 reqwest::blocking::Client::builder()
137 .use_rustls_tls()
138 .build()?,
139 )?;
140 let endpoint = GetAttachment::builder().id(38468).build()?;
141 let AttachmentWrapper { attachment: value } =
142 redmine.json_response_body::<_, AttachmentWrapper<serde_json::Value>>(&endpoint)?;
143 let o: Attachment = serde_json::from_value(value.clone())?;
144 let reserialized = serde_json::to_value(o)?;
145 assert_eq!(value, reserialized);
146 Ok(())
147 }
148}