use crate::database; use crate::usimp; use crate::usimp::*; use rand::Rng; use serde::{Deserialize, Serialize}; use serde_json::{from_value, to_value, Value}; use uuid::Uuid; #[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: String; let session_id; match backend { database::Client::Postgres(client) => { let res = client .query( "SELECT account_id, domain_id \ FROM account \ 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: Uuid = row.get(0); let domain_id: Uuid = row.get(1); // TODO password check if !input.password.eq("MichaelScott") { return Err(Error::new( ErrorKind::AuthenticationError, ErrorClass::ClientError, None, )); } session_id = Uuid::new_v4(); token = rand::thread_rng() .sample_iter(&rand::distributions::Alphanumeric) .take(256) .map(char::from) .collect(); client .execute( "INSERT INTO session (account_id, session_nr, session_id, session_token) \ VALUES ($1, COALESCE((SELECT MAX(session_nr) + 1 \ FROM session \ WHERE account_id = $1), 1), $2, $3);", &[&account_id, &session_id, &token], ) .await?; } } Ok(Output { session_id: session_id.to_string(), token }) }