libsignal_service/push_service/
account.rs

1use std::fmt;
2
3use chrono::{DateTime, Utc};
4use phonenumber::PhoneNumber;
5use reqwest::Method;
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9use super::{
10    response::ReqwestExt, HttpAuthOverride, PushService, ServiceError,
11};
12use crate::{
13    configuration::Endpoint,
14    utils::{serde_optional_base64, serde_phone_number},
15};
16
17#[derive(Debug, Serialize, Deserialize, Clone)]
18pub struct ServiceIds {
19    #[serde(rename = "uuid")]
20    pub aci: Uuid,
21    #[serde(default)] // nil when not present (yet)
22    pub pni: Uuid,
23}
24
25impl ServiceIds {
26    pub fn aci(&self) -> libsignal_protocol::Aci {
27        libsignal_protocol::Aci::from_uuid_bytes(self.aci.into_bytes())
28    }
29
30    pub fn pni(&self) -> libsignal_protocol::Pni {
31        libsignal_protocol::Pni::from_uuid_bytes(self.pni.into_bytes())
32    }
33}
34
35impl fmt::Display for ServiceIds {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        write!(f, "aci={} pni={}", self.aci, self.pni)
38    }
39}
40
41#[derive(Debug, Serialize, Deserialize)]
42#[serde(rename_all = "camelCase")]
43pub struct DeviceId {
44    pub device_id: u32,
45}
46
47#[derive(Debug, Serialize, Deserialize)]
48#[serde(rename_all = "camelCase")]
49pub struct DeviceInfo {
50    pub id: i64,
51    pub name: Option<String>,
52    #[serde(with = "chrono::serde::ts_milliseconds")]
53    pub created: DateTime<Utc>,
54    #[serde(with = "chrono::serde::ts_milliseconds")]
55    pub last_seen: DateTime<Utc>,
56}
57
58#[derive(Debug, Serialize, Deserialize)]
59#[serde(rename_all = "camelCase")]
60pub struct AccountAttributes {
61    #[serde(default, with = "serde_optional_base64")]
62    pub signaling_key: Option<Vec<u8>>,
63    pub registration_id: u32,
64    pub pni_registration_id: u32,
65    pub voice: bool,
66    pub video: bool,
67    pub fetches_messages: bool,
68    pub pin: Option<String>,
69    pub registration_lock: Option<String>,
70    #[serde(default, with = "serde_optional_base64")]
71    pub unidentified_access_key: Option<Vec<u8>>,
72    pub unrestricted_unidentified_access: bool,
73    pub discoverable_by_phone_number: bool,
74    pub capabilities: DeviceCapabilities,
75    pub name: Option<String>,
76}
77
78#[derive(Debug, Serialize, Deserialize, Default, Eq, PartialEq, Clone)]
79#[serde(rename_all = "camelCase")]
80pub struct DeviceCapabilities {
81    #[serde(default)]
82    pub storage: bool,
83    #[serde(default)]
84    pub sender_key: bool,
85    #[serde(default)]
86    pub announcement_group: bool,
87    #[serde(default)]
88    pub change_number: bool,
89    #[serde(default)]
90    pub stories: bool,
91    #[serde(default)]
92    pub gift_badges: bool,
93    #[serde(default)]
94    pub pni: bool,
95    #[serde(default)]
96    pub payment_activation: bool,
97}
98
99#[derive(Debug, Deserialize)]
100#[serde(rename_all = "camelCase")]
101pub struct WhoAmIResponse {
102    #[serde(rename = "uuid")]
103    pub aci: Uuid,
104    #[serde(default)] // nil when not present (yet)
105    pub pni: Uuid,
106    #[serde(with = "serde_phone_number")]
107    pub number: PhoneNumber,
108}
109
110impl PushService {
111    /// Method used to check our own UUID
112    pub async fn whoami(&mut self) -> Result<WhoAmIResponse, ServiceError> {
113        self.request(
114            Method::GET,
115            Endpoint::service("/v1/accounts/whoami"),
116            HttpAuthOverride::NoOverride,
117        )?
118        .send()
119        .await?
120        .service_error_for_status()
121        .await?
122        .json()
123        .await
124        .map_err(Into::into)
125    }
126
127    /// Fetches a list of all devices tied to the authenticated account.
128    ///
129    /// This list include the device that sends the request.
130    pub async fn devices(&mut self) -> Result<Vec<DeviceInfo>, ServiceError> {
131        #[derive(serde::Deserialize)]
132        struct DeviceInfoList {
133            devices: Vec<DeviceInfo>,
134        }
135
136        let devices: DeviceInfoList = self
137            .request(
138                Method::GET,
139                Endpoint::service("/v1/devices/"),
140                HttpAuthOverride::NoOverride,
141            )?
142            .send()
143            .await?
144            .service_error_for_status()
145            .await?
146            .json()
147            .await?;
148
149        Ok(devices.devices)
150    }
151
152    pub async fn set_account_attributes(
153        &mut self,
154        attributes: AccountAttributes,
155    ) -> Result<(), ServiceError> {
156        assert!(
157            attributes.pin.is_none() || attributes.registration_lock.is_none(),
158            "only one of PIN and registration lock can be set."
159        );
160
161        self.request(
162            Method::PUT,
163            Endpoint::service("/v1/accounts/attributes/"),
164            HttpAuthOverride::NoOverride,
165        )?
166        .json(&attributes)
167        .send()
168        .await?
169        .service_error_for_status()
170        .await?
171        .json()
172        .await
173        .map_err(Into::into)
174    }
175}