use std::collections::HashMap;
use crate::{
User,
common::{Result, address::Address},
connection::server_connection::ServerConnection,
error::ConnectionError,
};
#[derive(Debug)]
pub struct UserManager {
server_connections: HashMap<Address, ServerConnection>,
}
impl UserManager {
pub(crate) fn new(server_connections: HashMap<Address, ServerConnection>) -> Self {
Self { server_connections }
}
#[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
pub async fn get_current_user(&self) -> Result<Option<User>> {
let (_, connection) = self
.server_connections
.iter()
.next()
.expect("Unexpected condition: the server connection collection is empty");
self.get(connection.username()).await
}
#[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
pub async fn contains(&self, username: impl Into<String>) -> Result<bool> {
let username = username.into();
let mut error_buffer = Vec::with_capacity(self.server_connections.len());
for (server_id, server_connection) in self.server_connections.iter() {
match server_connection.contains_user(username.clone()).await {
Ok(res) => return Ok(res),
Err(err) => error_buffer.push(format!("- {}: {}", server_id, err)),
}
}
Err(ConnectionError::ServerConnectionFailedWithError { error: error_buffer.join("\n") })?
}
#[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
pub async fn get(&self, username: impl Into<String>) -> Result<Option<User>> {
let uname = username.into();
let mut error_buffer = Vec::with_capacity(self.server_connections.len());
for (server_id, server_connection) in self.server_connections.iter() {
match server_connection.get_user(uname.clone()).await {
Ok(res) => {
return Ok(res.map(|u_info| User {
name: u_info.name,
password: u_info.password,
server_connections: self.server_connections.clone(),
}));
}
Err(err) => error_buffer.push(format!("- {}: {}", server_id, err)),
}
}
Err(ConnectionError::ServerConnectionFailedWithError { error: error_buffer.join("\n") })?
}
#[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
pub async fn all(&self) -> Result<Vec<User>> {
let mut error_buffer = Vec::with_capacity(self.server_connections.len());
for (server_id, server_connection) in self.server_connections.iter() {
match server_connection.all_users().await {
Ok(res) => {
return Ok(res
.iter()
.map(|u_info| User {
name: u_info.name.clone(),
password: u_info.password.clone(),
server_connections: self.server_connections.clone(),
})
.collect());
}
Err(err) => error_buffer.push(format!("- {}: {}", server_id, err)),
}
}
Err(ConnectionError::ServerConnectionFailedWithError { error: error_buffer.join("\n") })?
}
#[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
pub async fn create(&self, username: impl Into<String>, password: impl Into<String>) -> Result {
let uname = username.into();
let passwd = password.into();
let mut error_buffer = Vec::with_capacity(self.server_connections.len());
for (server_id, server_connection) in self.server_connections.iter() {
match server_connection.create_user(uname.clone(), passwd.clone()).await {
Ok(res) => return Ok(res),
Err(err) => error_buffer.push(format!("- {}: {}", server_id, err)),
}
}
Err(ConnectionError::ServerConnectionFailedWithError { error: error_buffer.join("\n") })?
}
}