1use std::fmt;
4
5use ap_noise::Psk;
6use ap_proxy_protocol::IdentityFingerprint;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub enum CredentialQuery {
13 Domain(String),
15 Id(String),
17 Search(String),
19}
20
21impl CredentialQuery {
22 pub fn search_string(&self) -> &str {
24 match self {
25 Self::Domain(d) => d.as_str(),
26 Self::Id(id) => id.as_str(),
27 Self::Search(s) => s.as_str(),
28 }
29 }
30}
31
32impl fmt::Display for CredentialQuery {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 match self {
35 CredentialQuery::Domain(d) => write!(f, "domain: {d}"),
36 CredentialQuery::Id(id) => write!(f, "id: {id}"),
37 CredentialQuery::Search(s) => write!(f, "search: {s}"),
38 }
39 }
40}
41
42#[derive(Debug, Clone)]
44pub enum ConnectionMode {
45 New { rendezvous_code: String },
47 NewPsk {
49 psk: Psk,
50 remote_fingerprint: IdentityFingerprint,
51 },
52 Existing {
54 remote_fingerprint: IdentityFingerprint,
55 },
56}
57
58pub enum ClientAction {
59 Accept,
60}
61
62#[derive(Debug, Clone)]
64pub enum RemoteClientResponse {
65 VerifyFingerprint {
67 approved: bool,
69 },
70}
71
72#[derive(Debug, Clone)]
74pub enum RemoteClientEvent {
75 Connecting {
77 proxy_url: String,
79 },
80 Connected {
82 fingerprint: IdentityFingerprint,
84 },
85 ReconnectingToSession {
87 fingerprint: IdentityFingerprint,
89 },
90 RendevouzResolving {
92 code: String,
94 },
95 RendevouzResolved {
97 fingerprint: IdentityFingerprint,
99 },
100 PskMode {
102 fingerprint: IdentityFingerprint,
104 },
105 HandshakeStart,
107 HandshakeProgress {
109 message: String,
111 },
112 HandshakeComplete,
114 HandshakeFingerprint {
116 fingerprint: String,
118 },
119 FingerprintVerified,
121 FingerprintRejected {
123 reason: String,
125 },
126 Ready {
128 can_request_credentials: bool,
130 },
131 CredentialRequestSent {
133 query: CredentialQuery,
135 },
136 CredentialReceived {
138 credential: CredentialData,
140 },
141 Error {
143 message: String,
145 context: Option<String>,
147 },
148 Disconnected {
150 reason: Option<String>,
152 },
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157#[serde(rename_all = "camelCase")]
158pub struct CredentialData {
159 #[serde(skip_serializing_if = "Option::is_none")]
161 pub username: Option<String>,
162 #[serde(skip_serializing_if = "Option::is_none")]
164 pub password: Option<String>,
165 #[serde(skip_serializing_if = "Option::is_none")]
167 pub totp: Option<String>,
168 #[serde(skip_serializing_if = "Option::is_none")]
170 pub uri: Option<String>,
171 #[serde(skip_serializing_if = "Option::is_none")]
173 pub notes: Option<String>,
174 #[serde(skip_serializing_if = "Option::is_none")]
176 pub credential_id: Option<String>,
177 #[serde(default)]
179 #[serde(skip_serializing_if = "Option::is_none")]
180 pub domain: Option<String>,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
185#[serde(tag = "type", rename_all = "kebab-case")]
186pub(crate) enum ProtocolMessage {
187 #[serde(rename = "handshake-init")]
189 HandshakeInit { data: String, ciphersuite: String },
190 #[serde(rename = "handshake-response")]
192 HandshakeResponse { data: String, ciphersuite: String },
193 CredentialRequest { encrypted: String },
195 CredentialResponse { encrypted: String },
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
201pub(crate) struct CredentialRequestPayload {
202 #[serde(rename = "type")]
203 pub request_type: String,
204 pub query: CredentialQuery,
205 pub timestamp: u64,
206 #[serde(rename = "requestId")]
207 pub request_id: String,
208}
209
210#[derive(Debug, Clone, Serialize, Deserialize)]
212pub(crate) struct CredentialResponsePayload {
213 #[serde(skip_serializing_if = "Option::is_none")]
214 pub credential: Option<CredentialData>,
215 #[serde(skip_serializing_if = "Option::is_none")]
216 pub error: Option<String>,
217 #[serde(rename = "requestId")]
218 #[serde(skip_serializing_if = "Option::is_none")]
219 pub request_id: Option<String>,
220}