use crate::usimp; use crate::usimp::*; use crate::database; use serde_json::{Value, from_value, to_value}; use serde::{Serialize, Deserialize}; use rand::Rng; #[derive(Serialize, Deserialize, Clone)] struct Input { name: String, password: String, } #[derive(Serialize, Deserialize, Clone)] struct Output { session_id: String, token: String, } pub async fn handle(input: &InputEnvelope, session: Option) -> Result { Ok(to_value(authenticate(from_value(input.data.clone())?, session).await?)?) } async fn authenticate(input: Input, _session: Option) -> Result { let backend = database::client().await?; let token; let session_id; match backend { database::Client::Postgres(client) => { let res = client.query( "SELECT account_id, domain_id \ FROM accounts \ WHERE account_name = $1", &[&input.name] ).await?; if res.len() == 0 { return Err(Error::new(ErrorKind::AuthenticationError, ErrorClass::ClientError, None)); } let row = &res[0]; let account_id: String = row.get(0); let domain_id: String = row.get(1); // TODO password check if !input.password.eq("MichaelScott") { return Err(Error::new(ErrorKind::AuthenticationError, ErrorClass::ClientError, None)); } session_id = usimp::get_id(&[domain_id.as_str(), account_id.as_str()]); token = rand::thread_rng() .sample_iter(&rand::distributions::Alphanumeric) .take(256) .map(char::from) .collect(); client.execute( "INSERT INTO sessions (account_id, session_nr, session_id, session_token) \ VALUES ($1, COALESCE((SELECT MAX(session_nr) + 1 \ FROM sessions \ WHERE account_id = $1), 1), $2, $3);", &[&account_id, &session_id, &token], ).await?; } } Ok(Output { session_id, token, }) }