diff --git a/server/src/authentication.rs b/server/src/authentication.rs index 568f269..327d213 100644 --- a/server/src/authentication.rs +++ b/server/src/authentication.rs @@ -9,7 +9,7 @@ use uuid::{adapter::Hyphenated, Uuid}; #[cfg(test)] use crate::errors::maybe_fail; -#[derive(Debug, Error)] +#[derive(Debug, Error, PartialEq)] pub enum AuthenticationError { #[error("username already exists")] DuplicateUsername, @@ -162,11 +162,11 @@ pub trait AuthenticationDB: Send + Sync { session: SessionToken, ) -> AppResult<(Username, UserId), AuthenticationError>; - fn get_userid(&self, username: Username) -> AppResult; + fn get_userid(&self, username: &Username) -> AppResult; - fn get_username(&self, userid: UserId) -> AppResult; + fn get_username(&self, userid: &UserId) -> AppResult; - fn list_users(&self) -> AppResult, AuthenticationError>; + fn list_users(&self) -> AppResult, AuthenticationError>; } #[derive(Debug, Default)] @@ -282,7 +282,7 @@ impl AuthenticationDB for MemoryAuth { } } - fn get_userid(&self, username: Username) -> AppResult { + fn get_userid(&self, username: &Username) -> AppResult { Ok(self .users .get(&username) @@ -290,7 +290,7 @@ impl AuthenticationDB for MemoryAuth { .ok_or(AuthenticationError::UserNotFound)) } - fn get_username(&self, userid: UserId) -> AppResult { + fn get_username(&self, userid: &UserId) -> AppResult { Ok(self .inverse_users .get(&userid) @@ -298,10 +298,91 @@ impl AuthenticationDB for MemoryAuth { .ok_or(AuthenticationError::UserNotFound)) } - fn list_users(&self) -> AppResult, AuthenticationError> { - ok(self.users.keys().cloned().collect::>()) + fn list_users(&self) -> AppResult, AuthenticationError> { + ok(self.inverse_users.keys().cloned().collect::>()) } } #[cfg(test)] -mod test {} +mod test { + use super::*; + + fn with_memory_db(test: F) + where + F: Fn(Box), + { + let authdb: Box = Box::new(Default::default()); + test(authdb); + } + + #[test] + fn it_can_create_a_user() { + fn test_case(mut authdb: Box) { + let username = Username::from("shephard"); + let userid = authdb + .create_user(username.clone()) + .expect("no fatal errors") + .expect("creation should succeed"); + assert_eq!(authdb.get_userid(&username).unwrap(), Ok(userid.clone())); + assert_eq!(authdb.get_username(&userid).unwrap(), Ok(username)); + assert!(authdb.list_users().unwrap().unwrap().contains(&userid)); + } + with_memory_db(test_case); + } + + #[test] + fn it_does_not_allow_duplicate_users() { + fn test_case(mut authdb: Box) { + let username = Username::from("shephard"); + let _ = authdb + .create_user(username.clone()) + .expect("no fatal errors") + .expect("creation should succeed"); + assert_eq!( + authdb.create_user(username.clone()).unwrap(), + Err(AuthenticationError::DuplicateUsername) + ); + } + with_memory_db(test_case); + } + + #[test] + fn it_allows_multiple_invitations_per_user() { + unimplemented!() + } + + #[test] + fn it_exchanges_an_invitation_for_a_session() { + unimplemented!() + } + + #[test] + fn it_allows_multiple_sessions_per_user() { + unimplemented!() + } + + #[test] + fn it_disallows_invitation_reuse() { + unimplemented!() + } + + #[test] + fn it_identifies_a_user_by_session() { + unimplemented!() + } + + #[test] + fn it_deletes_a_user_and_invalidates_tokens() { + unimplemented!() + } + + #[test] + fn it_deletes_a_session() { + unimplemented!() + } + + #[test] + fn it_deletes_an_invitation() { + unimplemented!() + } +} diff --git a/server/src/main.rs b/server/src/main.rs index 34820d8..220251f 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -133,6 +133,7 @@ fn authenticate( }) } +/* fn list_users( auth_ctx: Arc>, ) -> impl Filter + Clone { @@ -154,6 +155,7 @@ fn list_users( } }) } +*/ #[tokio::main] pub async fn main() { @@ -180,12 +182,19 @@ pub async fn main() { warp::reply::json(&vec!["authed", param.as_str()]) }); + /* let filter = list_users(auth_ctx.clone()) .or(make_user(auth_ctx.clone())) .or(make_invitation(auth_ctx.clone())) .or(authenticate(auth_ctx.clone())) .or(echo_authenticated) .or(echo_unauthenticated); + */ + let filter = make_user(auth_ctx.clone()) + .or(make_invitation(auth_ctx.clone())) + .or(authenticate(auth_ctx.clone())) + .or(echo_authenticated) + .or(echo_unauthenticated); let server = warp::serve(filter); server