mod db; mod id; mod password; use std::fmt; use db::AuthDatabase; pub use id::RandomId; use password::{IntoHashedPassword, PasswordVerifier}; use somethings::{ DatabaseError, DatabaseHandle, auth::{AsUserId, Session, SessionId, User, UserId}, }; pub async fn create_table(db: &DatabaseHandle) -> Result<(), Error> { db.auth_create_tables().await?; Ok(()) } pub async fn user_register( db: &DatabaseHandle, name: &str, plaintext_password: String, ) -> Result { let id = UserId::rand(); let hash = plaintext_password.hash_password(); db.insert_user(&id, name, hash).await?; Ok(User::new(id, name.to_owned())) } pub async fn user_login( db: &DatabaseHandle, name: &str, plaintext_password: String, ) -> Result { let userauth = db.get_userauth_by_name(name).await?; userauth.hash().verify_password(plaintext_password)?; let session_id = SessionId::rand(); db.insert_session(&session_id, userauth.user().userid()) .await?; Ok(Session::new(session_id, userauth.into())) } pub async fn get_session(db: &DatabaseHandle, sid_str: &str) -> Result { let sid = sid_str.parse().map_err(|_| Error::InvalidSessionId)?; db.get_session_by_id(&sid).await } pub async fn remove_session(db: &DatabaseHandle, sid_str: &str) -> Result<(), Error> { let sid = sid_str.parse().map_err(|_| Error::InvalidSessionId)?; db.delete_session_by_id(&sid).await } #[derive(Debug)] pub enum Error { AuthenticationFailed, InvalidSessionId, UserIsAnonymous, UserIsRegistered, DatabaseError(DatabaseError), } impl std::error::Error for Error {} impl From for Error { fn from(dbe: DatabaseError) -> Self { Self::DatabaseError(dbe) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::AuthenticationFailed => write!(f, "failed to authenticate user"), Self::InvalidSessionId => write!(f, "SessionId invalid"), Self::UserIsAnonymous => { write!(f, "expected a registered user, but UserId is anonymous") } Self::UserIsRegistered => { write!(f, "expected an anonymous user, but UserId is registered") } Self::DatabaseError(dbe) => write!(f, "{dbe}"), } } }