libsignal_service/push_service/
linking.rs1use libsignal_core::DeviceId;
2use reqwest::Method;
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6use crate::{
7 configuration::Endpoint, utils::serde_device_id,
8 websocket::registration::DeviceActivationRequest,
9};
10
11use super::response::{
12 device_limit_reached, error_mapper, SignalServiceResponse,
13};
14use super::{HttpAuth, HttpAuthOverride, PushService, ServiceError};
15
16#[derive(Debug, Serialize)]
17#[serde(rename_all = "camelCase")]
18pub struct LinkAccountAttributes {
19 pub fetches_messages: bool,
20 pub name: String,
21 pub registration_id: u32,
22 pub pni_registration_id: u32,
23 pub capabilities: LinkCapabilities,
24}
25
26#[derive(Debug, Serialize)]
27#[serde(rename_all = "camelCase")]
28pub struct LinkCapabilities {
30 pub attachment_backfill: bool,
31 pub spqr: bool,
36 pub username_change_sync_message: bool,
37}
38
39impl Default for LinkCapabilities {
41 fn default() -> Self {
42 Self {
43 attachment_backfill: false,
44 spqr: true,
45 username_change_sync_message: true,
46 }
47 }
48}
49
50#[derive(Debug, Deserialize)]
51#[serde(rename_all = "camelCase")]
52pub struct LinkResponse {
53 #[serde(rename = "uuid")]
54 pub aci: Uuid,
55 pub pni: Uuid,
56 #[serde(with = "serde_device_id")]
57 pub device_id: DeviceId,
58}
59
60#[derive(Debug, Serialize)]
61#[serde(rename_all = "camelCase")]
62pub struct LinkRequest {
63 pub verification_code: String,
64 pub account_attributes: LinkAccountAttributes,
65 #[serde(flatten)]
66 pub device_activation_request: DeviceActivationRequest,
67}
68
69error_mapper! {
72 link_device_errors:
73 FORBIDDEN => InvalidDeviceVerificationCode,
75 CONFLICT => DeviceCapabilityDowngrade,
77 LENGTH_REQUIRED => fn device_limit_reached,
79}
80
81impl PushService {
82 pub async fn link_device(
83 &mut self,
84 link_request: &LinkRequest,
85 http_auth: HttpAuth,
86 ) -> Result<LinkResponse, ServiceError> {
87 self.request(
88 Method::PUT,
89 Endpoint::service("/v1/devices/link"),
90 HttpAuthOverride::Identified(http_auth),
91 )?
92 .json(&link_request)
93 .send()
94 .await?
95 .service_error_for_status_with(link_device_errors)
96 .await?
97 .json()
98 .await
99 .map_err(Into::into)
100 }
101}