libsignal_service/websocket/
account.rs1use chrono::{DateTime, Utc};
2use reqwest::Method;
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6use crate::{
7 content::ServiceError,
8 proto::DeviceName,
9 push_service::response::SignalServiceResponse,
10 utils::{
11 serde_device_id, serde_e164, serde_optional_base64,
12 serde_optional_base64_url_safe_no_pad, serde_optional_prost_base64,
13 },
14 websocket,
15};
16
17use super::SignalWebSocket;
18
19#[derive(Debug, Serialize, Deserialize)]
20#[serde(rename_all = "camelCase")]
21pub struct DeviceId {
22 #[serde(with = "serde_device_id")]
23 pub device_id: libsignal_core::DeviceId,
24}
25
26#[derive(Debug, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct DeviceInfo {
29 #[serde(with = "serde_device_id")]
30 pub id: libsignal_core::DeviceId,
31 pub registration_id: i32,
32 pub name: Option<String>,
33 #[serde(with = "chrono::serde::ts_milliseconds")]
34 pub created_at: DateTime<Utc>,
35 #[serde(with = "chrono::serde::ts_milliseconds")]
36 pub last_seen: DateTime<Utc>,
37}
38
39#[derive(Debug, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub(crate) struct DeviceInfoEncrypted {
42 #[serde(with = "serde_device_id")]
43 pub id: libsignal_core::DeviceId,
44 pub name: Option<String>,
45 pub registration_id: i32,
46 pub created_at_ciphertext: String,
47 #[serde(with = "chrono::serde::ts_milliseconds")]
48 pub last_seen: DateTime<Utc>,
49}
50
51#[derive(Debug, Serialize, Deserialize)]
52#[serde(rename_all = "camelCase")]
53pub struct AccountAttributes {
55 pub registration_id: u32,
56 pub voice: bool,
57 pub video: bool,
58 pub fetches_messages: bool,
59 #[serde(default, skip_serializing_if = "Option::is_none")]
60 pub registration_lock: Option<String>,
61 #[serde(default, with = "serde_optional_base64")]
62 pub unidentified_access_key: Option<Vec<u8>>,
63 pub unrestricted_unidentified_access: bool,
64 pub discoverable_by_phone_number: bool,
65 #[serde(default, skip_serializing_if = "Option::is_none")]
66 pub capabilities: Option<DeviceCapabilities>,
67 #[serde(default, with = "serde_optional_prost_base64")]
68 pub name: Option<DeviceName>,
69 pub pni_registration_id: u32,
70 #[serde(
71 default,
72 with = "serde_optional_base64",
73 skip_serializing_if = "Option::is_none"
74 )]
75 pub recovery_password: Option<Vec<u8>>,
76}
77
78#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
81#[serde(rename_all = "camelCase")]
82pub struct DeviceCapabilities {
83 #[serde(default)]
84 pub storage: bool,
85 #[serde(default)]
86 pub transfer: bool,
87 #[serde(default)]
88 pub attachment_backfill: bool,
89 #[serde(default)]
90 pub spqr: bool,
91 #[serde(default, rename = "profiles_v2")]
93 pub profiles_v2: bool,
94 #[serde(default)]
95 pub username_change_sync_message: bool,
96}
97
98impl Default for DeviceCapabilities {
99 fn default() -> Self {
100 DeviceCapabilities {
101 storage: false,
102 transfer: false,
103 attachment_backfill: false,
104 spqr: true,
105 profiles_v2: false,
106 username_change_sync_message: false,
107 }
108 }
109}
110
111#[cfg(test)]
112mod test {
113 #[test]
114 fn device_capabilities_serialization_weird_casing() {
115 let capabilities = super::DeviceCapabilities::default();
116 let json = serde_json::to_string(&capabilities)
117 .expect("Serialize capabilities");
118 assert!(json.contains("usernameChangeSyncMessage"));
119 assert!(json.contains("profiles_v2"));
120 }
121}
122
123#[derive(Debug, Deserialize)]
124#[serde(rename_all = "camelCase")]
125pub struct WhoAmIResponse {
126 #[serde(rename = "uuid")]
127 pub aci: Uuid,
128 #[serde(default)] pub pni: Uuid,
130 #[serde(with = "serde_e164")]
131 pub number: libsignal_core::E164,
132 #[serde(default, with = "serde_optional_base64_url_safe_no_pad")]
134 pub username_hash: Option<Vec<u8>>,
135 #[serde(default)]
140 pub username_link_handle: Option<Uuid>,
141}
142
143impl SignalWebSocket<websocket::Identified> {
144 pub async fn whoami(&mut self) -> Result<WhoAmIResponse, ServiceError> {
146 self.http_request(Method::GET, "/v1/accounts/whoami")?
147 .send()
148 .await?
149 .service_error_for_status()
150 .await?
151 .json()
152 .await
153 }
154
155 pub(crate) async fn devices(
159 &mut self,
160 ) -> Result<Vec<DeviceInfoEncrypted>, ServiceError> {
161 #[derive(serde::Deserialize)]
162 struct DeviceInfoList {
163 devices: Vec<DeviceInfoEncrypted>,
164 }
165
166 let devices: DeviceInfoList = self
167 .http_request(Method::GET, "/v1/devices")?
168 .send()
169 .await?
170 .service_error_for_status()
171 .await?
172 .json()
173 .await?;
174
175 Ok(devices.devices)
176 }
177
178 pub async fn set_account_attributes(
179 &mut self,
180 attributes: AccountAttributes,
181 ) -> Result<(), ServiceError> {
182 self.http_request(Method::PUT, "/v1/accounts/attributes")?
183 .send_json(&attributes)
184 .await?
185 .service_error_for_status()
186 .await?;
187
188 Ok(())
189 }
190
191 pub async fn unregister_account(&mut self) -> Result<(), ServiceError> {
198 self.http_request(Method::DELETE, "/v1/accounts/me")?
199 .send()
200 .await?
201 .service_error_for_status()
202 .await?;
203
204 Ok(())
205 }
206}