use crate::redirect::{AuthorizationCode, RedirectListener};
use async_trait::async_trait;
use origin_domain::{AppError, Result};
#[derive(Debug)]
pub struct FakeRedirectListener {
redirect_uri: String,
outcome: Outcome,
}
#[derive(Debug)]
enum Outcome {
Code(String),
WrongState(String),
Denied,
}
impl FakeRedirectListener {
pub fn returning(code: impl Into<String>) -> Self {
Self {
redirect_uri: "http://127.0.0.1:1/callback".to_owned(),
outcome: Outcome::Code(code.into()),
}
}
pub fn with_state(state: impl Into<String>) -> Self {
Self {
redirect_uri: "http://127.0.0.1:1/callback".to_owned(),
outcome: Outcome::WrongState(state.into()),
}
}
pub fn denied() -> Self {
Self {
redirect_uri: "http://127.0.0.1:1/callback".to_owned(),
outcome: Outcome::Denied,
}
}
}
#[async_trait]
impl RedirectListener for FakeRedirectListener {
fn redirect_uri(&self) -> String {
self.redirect_uri.clone()
}
async fn wait(&self, expected_state: &str) -> Result<AuthorizationCode> {
match &self.outcome {
Outcome::Code(code) => Ok(AuthorizationCode::new(code)),
Outcome::WrongState(state) => Err(AppError::Authentication(format!(
"unexpected state in redirect: got {state}, expected {expected_state}"
))),
Outcome::Denied => Err(AppError::Authentication(
"authorization was denied: access_denied".to_owned(),
)),
}
}
}