ddnet_account_client/
account_token.rs1use ddnet_accounts_shared::{
2 account_server::{account_token::AccountTokenError, errors::AccountServerRequestError},
3 client::account_token::{
4 AccountTokenEmailRequest, AccountTokenOperation, AccountTokenSteamRequest, SecretKey,
5 },
6};
7
8use anyhow::anyhow;
9use thiserror::Error;
10
11use crate::{
12 errors::{FsLikeError, HttpLikeError},
13 interface::Io,
14 safe_interface::{IoSafe, SafeIo},
15};
16
17#[derive(Error, Debug)]
19pub enum AccountTokenResult {
20 #[error("{0}")]
22 HttpLikeError(HttpLikeError),
23 #[error("{0}")]
25 FsLikeError(FsLikeError),
26 #[error("{0}")]
27 AccountServerRequstError(AccountServerRequestError<AccountTokenError>),
29 #[error("Account failed: {0}")]
31 Other(anyhow::Error),
32}
33
34impl From<HttpLikeError> for AccountTokenResult {
35 fn from(value: HttpLikeError) -> Self {
36 Self::HttpLikeError(value)
37 }
38}
39
40impl From<FsLikeError> for AccountTokenResult {
41 fn from(value: FsLikeError) -> Self {
42 Self::FsLikeError(value)
43 }
44}
45
46fn get_secret_key(
47 secret_key_hex: Option<String>,
48) -> anyhow::Result<Option<SecretKey>, AccountTokenResult> {
49 secret_key_hex
50 .map(hex::decode)
51 .transpose()
52 .map_err(|err| AccountTokenResult::Other(err.into()))?
53 .map(|secret_key| secret_key.try_into())
54 .transpose()
55 .map_err(|_| {
56 AccountTokenResult::Other(anyhow!(
57 "secret key had an invalid length. make sure you copied it correctly."
58 ))
59 })
60}
61
62pub async fn account_token_email(
64 email: email_address::EmailAddress,
65 op: AccountTokenOperation,
66 secret_key_hex: Option<String>,
67 io: &dyn Io,
68) -> anyhow::Result<(), AccountTokenResult> {
69 account_token_email_impl(email, op, secret_key_hex, io.into()).await
70}
71
72async fn account_token_email_impl(
73 email: email_address::EmailAddress,
74 op: AccountTokenOperation,
75 secret_key_hex: Option<String>,
76 io: IoSafe<'_>,
77) -> anyhow::Result<(), AccountTokenResult> {
78 if secret_key_hex.is_some() {
79 io.request_account_token_email_secret(AccountTokenEmailRequest {
80 email,
81 secret_key: get_secret_key(secret_key_hex)?,
82 op,
83 })
84 .await
85 } else {
86 io.request_account_token_email(AccountTokenEmailRequest {
87 email,
88 secret_key: get_secret_key(secret_key_hex)?,
89 op,
90 })
91 .await
92 }?
93 .map_err(AccountTokenResult::AccountServerRequstError)?;
94
95 Ok(())
96}
97
98pub async fn account_token_steam(
101 steam_ticket: Vec<u8>,
102 op: AccountTokenOperation,
103 secret_key_hex: Option<String>,
104 io: &dyn Io,
105) -> anyhow::Result<String, AccountTokenResult> {
106 account_token_steam_impl(steam_ticket, op, secret_key_hex, io.into()).await
107}
108
109async fn account_token_steam_impl(
110 steam_ticket: Vec<u8>,
111 op: AccountTokenOperation,
112 secret_key_hex: Option<String>,
113 io: IoSafe<'_>,
114) -> anyhow::Result<String, AccountTokenResult> {
115 let account_token_hex = if secret_key_hex.is_some() {
116 io.request_account_token_steam_secret(AccountTokenSteamRequest {
117 steam_ticket,
118 secret_key: get_secret_key(secret_key_hex)?,
119 op,
120 })
121 .await
122 } else {
123 io.request_account_token_steam(AccountTokenSteamRequest {
124 steam_ticket,
125 secret_key: get_secret_key(secret_key_hex)?,
126 op,
127 })
128 .await
129 }?
130 .map_err(AccountTokenResult::AccountServerRequstError)?;
131
132 Ok(account_token_hex)
133}