1use crate::client::Parse;
3use crate::error::ParseError;
4use crate::object::{CreateObjectResponse, UpdateObjectResponse};
5use crate::types::common::EmptyResponse;
6use crate::ParseACL;
7use reqwest::Method;
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10use std::collections::HashMap;
11
12#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
14#[serde(rename_all = "lowercase")]
15pub enum DeviceType {
16 #[default]
17 Js, Ios,
19 Android,
20 Winphone, Macos,
22 Windows,
23 Linux,
24 Embedded, Other(String), }
27
28#[derive(Serialize, Debug, Clone, Default)]
30#[serde(rename_all = "camelCase")]
31pub struct NewParseInstallation {
32 pub device_type: DeviceType,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub device_token: Option<String>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub installation_id: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
38 pub app_name: Option<String>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub app_version: Option<String>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub app_identifier: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
44 pub parse_version: Option<String>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub badge: Option<i64>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub time_zone: Option<String>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub channels: Option<Vec<String>>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub locale_identifier: Option<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub push_type: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
56 pub gcm_sender_id: Option<String>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub acl: Option<ParseACL>,
59 #[serde(flatten, skip_serializing_if = "Option::is_none")]
61 pub custom_fields: Option<HashMap<String, Value>>,
62}
63
64impl NewParseInstallation {
65 pub fn new(device_type: DeviceType) -> Self {
66 Self {
67 device_type,
68 ..Default::default()
69 }
70 }
71}
72
73#[derive(Deserialize, Debug, Clone)]
75#[serde(rename_all = "camelCase")]
76pub struct RetrievedParseInstallation {
77 #[serde(rename = "objectId")]
78 pub object_id: String,
79 #[serde(rename = "createdAt")]
80 pub created_at: String, #[serde(rename = "updatedAt")]
82 pub updated_at: String, pub device_type: DeviceType,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub device_token: Option<String>,
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub installation_id: Option<String>,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub app_name: Option<String>,
90 #[serde(skip_serializing_if = "Option::is_none")]
91 pub app_version: Option<String>,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub app_identifier: Option<String>,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 pub parse_version: Option<String>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub badge: Option<i64>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub time_zone: Option<String>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub channels: Option<Vec<String>>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub locale_identifier: Option<String>,
104 #[serde(skip_serializing_if = "Option::is_none")]
105 pub push_type: Option<String>,
106 #[serde(skip_serializing_if = "Option::is_none")]
107 pub gcm_sender_id: Option<String>,
108 #[serde(skip_serializing_if = "Option::is_none")]
109 pub acl: Option<ParseACL>,
110 #[serde(flatten)]
112 pub custom_fields: HashMap<String, Value>,
113}
114
115#[derive(Serialize, Debug, Clone, Default, PartialEq)]
118#[serde(rename_all = "camelCase")]
119pub struct UpdateParseInstallation {
120 #[serde(skip_serializing_if = "Option::is_none")]
121 pub device_type: Option<DeviceType>,
122 #[serde(skip_serializing_if = "Option::is_none")]
123 pub device_token: Option<String>,
124 #[serde(skip_serializing_if = "Option::is_none")]
125 pub installation_id: Option<String>,
126 #[serde(skip_serializing_if = "Option::is_none")]
127 pub app_name: Option<String>,
128 #[serde(skip_serializing_if = "Option::is_none")]
129 pub app_version: Option<String>,
130 #[serde(skip_serializing_if = "Option::is_none")]
131 pub app_identifier: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
133 pub time_zone: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
135 pub locale_identifier: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
137 pub badge: Option<i32>,
138 #[serde(skip_serializing_if = "Option::is_none")]
139 pub channels: Option<Vec<String>>,
140 #[serde(skip_serializing_if = "Option::is_none")]
141 pub push_type: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
143 pub gcm_sender_id: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
145 pub acl: Option<ParseACL>,
146 #[serde(flatten, skip_serializing_if = "HashMap::is_empty")]
149 pub custom_fields: HashMap<String, Value>,
150}
151
152impl UpdateParseInstallation {
153 pub fn new() -> Self {
154 Self::default()
155 }
156}
157
158impl Parse {
159 pub async fn create_installation(
167 &self,
168 installation_data: &NewParseInstallation,
169 ) -> Result<CreateObjectResponse, ParseError> {
170 let use_master_key = self.master_key.is_some();
173 let session_token_to_use = None;
174
175 self._request(
176 Method::POST,
177 "installations",
178 Some(installation_data),
179 use_master_key,
180 session_token_to_use,
181 )
182 .await
183 }
184
185 pub async fn get_installation(
193 &self,
194 object_id: &str,
195 ) -> Result<RetrievedParseInstallation, ParseError> {
196 if object_id.is_empty() {
197 return Err(ParseError::InvalidInput(
198 "Object ID cannot be empty.".to_string(),
199 ));
200 }
201 let endpoint = format!("installations/{}", object_id);
202 let use_master_key = self.master_key.is_some();
205 let session_token_to_use = None;
206
207 self._request(
208 Method::GET,
209 &endpoint,
210 None::<Value>.as_ref(), use_master_key,
212 session_token_to_use,
213 )
214 .await
215 }
216
217 pub async fn update_installation(
226 &self,
227 object_id: &str,
228 update_data: &UpdateParseInstallation,
229 ) -> Result<UpdateObjectResponse, ParseError> {
230 if object_id.is_empty() {
231 return Err(ParseError::InvalidInput(
232 "Object ID cannot be empty.".to_string(),
233 ));
234 }
235 let endpoint = format!("installations/{}", object_id);
236 let use_master_key = self.master_key.is_some();
238 let session_token_to_use = None;
239
240 self._request(
241 Method::PUT,
242 &endpoint,
243 Some(update_data),
244 use_master_key,
245 session_token_to_use,
246 )
247 .await
248 }
249
250 pub async fn delete_installation(&self, object_id: &str) -> Result<EmptyResponse, ParseError> {
258 if object_id.is_empty() {
259 return Err(ParseError::InvalidInput(
260 "Object ID cannot be empty.".to_string(),
261 ));
262 }
263 let endpoint = format!("installations/{}", object_id);
264 let use_master_key = self.master_key.is_some();
266 if !use_master_key {
267 log::warn!("Attempting to delete an installation without the master key. This might be restricted by server ACLs/CLPs.");
269 }
270 let session_token_to_use = None;
271
272 self._request(
273 Method::DELETE,
274 &endpoint,
275 None::<Value>.as_ref(), use_master_key,
277 session_token_to_use,
278 )
279 .await
280 }
281}
282
283