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