Complete the test suite for the authentication DB
This commit is contained in:
parent
2c1c19690f
commit
45df1233e5
|
@ -144,7 +144,7 @@ impl FromSql for Username {
|
|||
pub trait AuthenticationDB: Send + Sync {
|
||||
fn create_user(&mut self, username: Username) -> AppResult<UserId, AuthenticationError>;
|
||||
|
||||
fn create_invitation(&mut self, user: UserId) -> AppResult<Invitation, AuthenticationError>;
|
||||
fn create_invitation(&mut self, user: &UserId) -> AppResult<Invitation, AuthenticationError>;
|
||||
|
||||
fn authenticate(
|
||||
&mut self,
|
||||
|
@ -182,6 +182,10 @@ impl AuthenticationDB for MemoryAuth {
|
|||
#[cfg(test)]
|
||||
let _ = maybe_fail::<AuthenticationError>(vec![])?;
|
||||
|
||||
if self.users.contains_key(&username) {
|
||||
return Ok(Err(AuthenticationError::DuplicateUsername));
|
||||
}
|
||||
|
||||
let userid = UserId::from(format!("{}", Hyphenated::from_uuid(Uuid::new_v4())).as_str());
|
||||
self.users.insert(username.clone(), userid.clone());
|
||||
self.inverse_users.insert(userid.clone(), username);
|
||||
|
@ -189,7 +193,7 @@ impl AuthenticationDB for MemoryAuth {
|
|||
ok(userid)
|
||||
}
|
||||
|
||||
fn create_invitation(&mut self, user: UserId) -> AppResult<Invitation, AuthenticationError> {
|
||||
fn create_invitation(&mut self, user: &UserId) -> AppResult<Invitation, AuthenticationError> {
|
||||
#[cfg(test)]
|
||||
let _ = maybe_fail::<AuthenticationError>(vec![])?;
|
||||
|
||||
|
@ -199,7 +203,7 @@ impl AuthenticationDB for MemoryAuth {
|
|||
|
||||
let invitation =
|
||||
Invitation::from(format!("{}", Hyphenated::from_uuid(Uuid::new_v4())).as_str());
|
||||
self.invitations.insert(invitation.clone(), user);
|
||||
self.invitations.insert(invitation.clone(), user.clone());
|
||||
ok(invitation)
|
||||
}
|
||||
|
||||
|
@ -346,43 +350,197 @@ mod test {
|
|||
with_memory_db(test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_allows_multiple_invitations_per_user() {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_exchanges_an_invitation_for_a_session() {
|
||||
unimplemented!()
|
||||
fn test_case(mut authdb: Box<dyn AuthenticationDB>) {
|
||||
let username = Username::from("shephard");
|
||||
let userid = authdb
|
||||
.create_user(username.clone())
|
||||
.expect("no fatal errors")
|
||||
.expect("user to be created");
|
||||
let invitation = authdb
|
||||
.create_invitation(&userid)
|
||||
.expect("no fatal errors")
|
||||
.expect("invitation to be created");
|
||||
let _ = authdb
|
||||
.authenticate(invitation)
|
||||
.expect("no fatal errors")
|
||||
.expect("to receive a session token");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_allows_multiple_sessions_per_user() {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_disallows_invitation_reuse() {
|
||||
unimplemented!()
|
||||
with_memory_db(test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_identifies_a_user_by_session() {
|
||||
unimplemented!()
|
||||
fn test_case(mut authdb: Box<dyn AuthenticationDB>) {
|
||||
let shephard = Username::from("shephard");
|
||||
let garrus = Username::from("garrus");
|
||||
|
||||
let (shephard_session, shephard_id) = {
|
||||
let userid = authdb.create_user(shephard.clone()).unwrap().unwrap();
|
||||
let invitation = authdb.create_invitation(&userid).unwrap().unwrap();
|
||||
(authdb.authenticate(invitation).unwrap().unwrap(), userid)
|
||||
};
|
||||
|
||||
let (garrus_session, garrus_id) = {
|
||||
let userid = authdb.create_user(garrus.clone()).unwrap().unwrap();
|
||||
let invitation = authdb.create_invitation(&userid).unwrap().unwrap();
|
||||
(authdb.authenticate(invitation).unwrap().unwrap(), userid)
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
authdb.validate_session(shephard_session).unwrap().unwrap(),
|
||||
(shephard, shephard_id)
|
||||
);
|
||||
assert_eq!(
|
||||
authdb.validate_session(garrus_session).unwrap().unwrap(),
|
||||
(garrus, garrus_id)
|
||||
);
|
||||
}
|
||||
with_memory_db(test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_allows_multiple_invitations_per_user() {
|
||||
fn test_case(mut authdb: Box<dyn AuthenticationDB>) {
|
||||
let username = Username::from("shephard");
|
||||
let userid = authdb.create_user(username).unwrap().unwrap();
|
||||
let invite1 = authdb.create_invitation(&userid).unwrap().unwrap();
|
||||
let invite2 = authdb.create_invitation(&userid).unwrap().unwrap();
|
||||
|
||||
assert_ne!(invite1, invite2);
|
||||
|
||||
authdb.authenticate(invite1).unwrap().unwrap();
|
||||
authdb.authenticate(invite2).unwrap().unwrap();
|
||||
}
|
||||
with_memory_db(test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_allows_multiple_sessions_per_user() {
|
||||
fn test_case(mut authdb: Box<dyn AuthenticationDB>) {
|
||||
let username = Username::from("shephard");
|
||||
let userid = authdb.create_user(username.clone()).unwrap().unwrap();
|
||||
let invite1 = authdb.create_invitation(&userid).unwrap().unwrap();
|
||||
let invite2 = authdb.create_invitation(&userid).unwrap().unwrap();
|
||||
|
||||
assert_ne!(invite1, invite2);
|
||||
|
||||
let session1 = authdb.authenticate(invite1).unwrap().unwrap();
|
||||
let session2 = authdb.authenticate(invite2).unwrap().unwrap();
|
||||
|
||||
assert_ne!(session1, session2);
|
||||
assert_eq!(
|
||||
authdb.validate_session(session1).unwrap().unwrap(),
|
||||
(username.clone(), userid.clone())
|
||||
);
|
||||
assert_eq!(
|
||||
authdb.validate_session(session2).unwrap().unwrap(),
|
||||
(username, userid)
|
||||
);
|
||||
}
|
||||
with_memory_db(test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_disallows_invitation_reuse() {
|
||||
fn test_case(mut authdb: Box<dyn AuthenticationDB>) {
|
||||
let username = Username::from("shephard");
|
||||
let userid = authdb
|
||||
.create_user(username.clone())
|
||||
.expect("no fatal errors")
|
||||
.expect("user to be created");
|
||||
let invitation = authdb
|
||||
.create_invitation(&userid)
|
||||
.expect("no fatal errors")
|
||||
.expect("invitation to be created");
|
||||
let _ = authdb
|
||||
.authenticate(invitation.clone())
|
||||
.expect("no fatal errors")
|
||||
.expect("to receive a session token");
|
||||
let reuse_result = authdb.authenticate(invitation).expect("no fatal errors");
|
||||
assert_eq!(reuse_result, Err(AuthenticationError::InvalidInvitation));
|
||||
}
|
||||
with_memory_db(test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_deletes_a_user_and_invalidates_tokens() {
|
||||
unimplemented!()
|
||||
fn test_case(mut authdb: Box<dyn AuthenticationDB>) {
|
||||
let shephard = Username::from("shephard");
|
||||
let garrus = Username::from("garrus");
|
||||
|
||||
let (shephard_session, shephard_id) = {
|
||||
let userid = authdb.create_user(shephard.clone()).unwrap().unwrap();
|
||||
let invitation = authdb.create_invitation(&userid).unwrap().unwrap();
|
||||
(authdb.authenticate(invitation).unwrap().unwrap(), userid)
|
||||
};
|
||||
|
||||
let (garrus_invitation, garrus_id) = {
|
||||
let userid = authdb.create_user(garrus.clone()).unwrap().unwrap();
|
||||
(authdb.create_invitation(&userid).unwrap().unwrap(), userid)
|
||||
};
|
||||
|
||||
authdb.delete_user(shephard_id).unwrap().unwrap();
|
||||
assert_eq!(
|
||||
authdb.validate_session(shephard_session).unwrap(),
|
||||
Err(AuthenticationError::InvalidSession)
|
||||
);
|
||||
|
||||
authdb.delete_user(garrus_id).unwrap().unwrap();
|
||||
assert_eq!(
|
||||
authdb.authenticate(garrus_invitation).unwrap(),
|
||||
Err(AuthenticationError::InvalidInvitation)
|
||||
);
|
||||
}
|
||||
with_memory_db(test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_deletes_a_session() {
|
||||
unimplemented!()
|
||||
fn test_case(mut authdb: Box<dyn AuthenticationDB>) {
|
||||
let username = Username::from("shephard");
|
||||
let userid = authdb
|
||||
.create_user(username.clone())
|
||||
.expect("no fatal errors")
|
||||
.expect("user to be created");
|
||||
let invitation = authdb
|
||||
.create_invitation(&userid)
|
||||
.expect("no fatal errors")
|
||||
.expect("invitation to be created");
|
||||
let session = authdb.authenticate(invitation).unwrap().unwrap();
|
||||
|
||||
authdb.delete_session(session.clone()).unwrap().unwrap();
|
||||
assert_eq!(
|
||||
authdb.validate_session(session).unwrap(),
|
||||
Err(AuthenticationError::InvalidSession)
|
||||
);
|
||||
}
|
||||
with_memory_db(test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_deletes_an_invitation() {
|
||||
unimplemented!()
|
||||
fn test_case(mut authdb: Box<dyn AuthenticationDB>) {
|
||||
let username = Username::from("shephard");
|
||||
let userid = authdb
|
||||
.create_user(username.clone())
|
||||
.expect("no fatal errors")
|
||||
.expect("user to be created");
|
||||
let invitation = authdb
|
||||
.create_invitation(&userid)
|
||||
.expect("no fatal errors")
|
||||
.expect("invitation to be created");
|
||||
|
||||
authdb
|
||||
.delete_invitation(invitation.clone())
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
authdb.authenticate(invitation).unwrap(),
|
||||
Err(AuthenticationError::InvalidInvitation)
|
||||
);
|
||||
}
|
||||
with_memory_db(test_case);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ struct MakeInvitationResponse {
|
|||
invitation: Invitation,
|
||||
}
|
||||
|
||||
/*
|
||||
fn make_invitation(
|
||||
auth_ctx: Arc<RwLock<impl AuthenticationDB>>,
|
||||
) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
|
||||
|
@ -104,6 +105,7 @@ fn make_invitation(
|
|||
}
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct AuthenticateParams {
|
||||
|
@ -191,7 +193,6 @@ pub async fn main() {
|
|||
.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);
|
||||
|
|
Loading…
Reference in New Issue