1use serde::{Deserialize, Serialize};
2use reqwest::Client;
3use anyhow::{anyhow, Result};
4
5
6const BASE_URL: &str = "https://api.dev.amit.public.norman-ai.com/v0";
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct Account {
12 pub id: String,
13 pub creation_time: String,
14 pub name: String,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct AccountAuthenticationFactors {
20 pub account_id: String,
21 pub api_key_count: u32,
22 pub password_count: u32,
23 pub verified_email_count: u32,
24}
25
26impl AccountAuthenticationFactors {
27 pub fn has_authentication_factor(&self) -> bool {
28 self.api_key_count > 0 || self.password_count > 0 || self.verified_email_count > 0
29 }
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct LoginResponse {
35 pub account: Account,
36 pub access_token: String,
37 pub id_token: String,
38}
39
40pub struct AccountService {
42 client: Client,
43}
44
45impl AccountService {
46 pub fn new() -> Self {
47 Self {
48 client: Client::new(),
49 }
50 }
51
52 pub async fn get_account_by_id(&self, account_id: &str) -> Result<Account> {
54 let payload = serde_json::json!({
55 "table": "Accounts",
56 "filters": { "id": account_id }
57 });
58
59 let resp = self.client
60 .post(format!("{BASE_URL}/authenticate/accounts/get"))
61 .json(&payload)
62 .send()
63 .await?;
64
65 let map: serde_json::Value = resp.json().await?;
66 if let Some(obj) = map.as_object().and_then(|o| o.values().next()) {
67 Ok(serde_json::from_value(obj.clone())?)
68 } else {
69 Err(anyhow!("No account found for id: {account_id}"))
70 }
71 }
72
73 pub async fn get_accounts(
75 &self,
76 filters: Option<serde_json::Value>,
77 ) -> Result<Vec<Account>, reqwest::Error> {
78 let payload = if let Some(f) = filters {
79 serde_json::json!({ "filters": f })
80 } else {
81 serde_json::json!({})
82 };
83
84 let resp = self.client
85 .post(format!("{BASE_URL}/authenticate/accounts/get"))
86 .json(&payload)
87 .send()
88 .await?;
89
90 let map: serde_json::Value = resp.json().await?;
91 let mut accounts = vec![];
92 if let Some(obj) = map.as_object() {
93 for v in obj.values() {
94 if let Ok(a) = serde_json::from_value::<Account>(v.clone()) {
95 accounts.push(a);
96 }
97 }
98 }
99 Ok(accounts)
100 }
101
102 pub async fn get_authentication_factors(
104 &self,
105 account_id: &str,
106 ) -> Result<AccountAuthenticationFactors, reqwest::Error> {
107 let url = format!("{BASE_URL}/authenticate/register/get/authentication/factors/{account_id}");
108 let resp = self.client.get(url).send().await?;
109 let data = resp.json::<AccountAuthenticationFactors>().await?;
110 Ok(data)
111 }
112
113 pub async fn update_account_name(
115 &self,
116 account_id: &str,
117 name: &str,
118 ) -> Result<(), reqwest::Error> {
119 let payload = serde_json::json!({
120 "account": { "name": name },
121 "filters": { "id": account_id }
122 });
123
124 self.client
125 .patch(format!("{BASE_URL}/authenticate/accounts"))
126 .json(&payload)
127 .send()
128 .await?
129 .error_for_status()?;
130
131 Ok(())
132 }
133}