better-auth-api 1.0.0-alpha.5

Plugin implementations for better-auth
use super::*;
use better_auth_core::{AuthError, HttpMethod};

struct ResponsePlugin {
    replace: bool,
    fail: bool,
}

#[async_trait::async_trait]
impl<S: AuthSchema> AuthPlugin<S> for ResponsePlugin {
    fn name(&self) -> &'static str {
        "response-delegation"
    }
    fn routes(&self) -> Vec<AuthRoute> {
        Vec::new()
    }
    async fn on_request(
        &self,
        _: &AuthRequest,
        _: &AuthContext<S>,
    ) -> AuthResult<Option<AuthResponse>> {
        Ok(None)
    }
    async fn on_http_response(
        &self,
        request: &AuthRequest,
        response: &mut AuthResponse,
        _: &AuthContext<S>,
    ) -> AuthResult<Option<AuthResponse>> {
        if self.fail {
            return Err(AuthError::bad_request("response hook rejected"));
        }
        let _ = response
            .headers
            .insert("x-request-path".to_owned(), request.path().to_owned());
        Ok(self.replace.then(|| AuthResponse::text(202, "replacement")))
    }
}

#[tokio::test]
async fn callback_wrapper_preserves_http_response_mutations_replacement_and_errors() {
    let context = crate::plugins::test_helpers::create_test_context().await;
    let request = AuthRequest::new(HttpMethod::Get, "/response-probe/");
    for (replace, fail) in [(false, false), (true, false), (false, true)] {
        let plugin = WithCallbacks {
            plugin: ResponsePlugin { replace, fail },
            callbacks: Arc::new(()),
        };
        let mut response = AuthResponse::new(200);
        let result = plugin
            .on_http_response(&request, &mut response, &context)
            .await;
        if fail {
            assert_eq!(result.unwrap_err().status_code().unwrap(), 400);
            assert!(response.headers.get("x-request-path").is_none());
        } else {
            assert_eq!(
                response.headers.get("x-request-path"),
                Some(&"/response-probe/".to_owned())
            );
            let replacement = result.unwrap();
            assert_eq!(
                replacement.as_ref().map(|response| response.status),
                replace.then_some(202)
            );
            if let Some(replacement) = replacement {
                assert_eq!(replacement.body.bytes().unwrap().as_ref(), b"replacement");
            }
        }
    }
}