ForgeFlux/src/auth/adapter/input/web/login/adapter.rs

103 lines
3.7 KiB
Rust

use std::sync::Arc;
use actix_web::{http::header, HttpResponse};
use url::Url;
use crate::auth::application::port::input::ui::{errors::*, login::RequestAuthorizationInterface};
use crate::auth::application::port::out::db::save_oauth_state::SaveOAuthState;
use crate::auth::application::port::out::forge::oauth_auth_req_uri::OAuthAuthReqUri;
use crate::auth::application::services::request_authorization::{
command::RequestAuthorizationCommand, service::RequestAuthorizationService,
RequestAuthorizationUserCase,
};
use crate::utils::random_string::GenerateRandomStringInterface;
pub struct RequestAuthorizationHandler {
save_oauth_state_adapter: Arc<dyn SaveOAuthState>,
oauth_auth_req_uri_adapter: Arc<dyn OAuthAuthReqUri>,
generate_random_string: Arc<dyn GenerateRandomStringInterface>,
process_authorization_response_redirect_uri: Url,
}
impl RequestAuthorizationHandler {
pub fn new(
save_oauth_state_adapter: Arc<dyn SaveOAuthState>,
oauth_auth_req_uri_adapter: Arc<dyn OAuthAuthReqUri>,
generate_random_string: Arc<dyn GenerateRandomStringInterface>,
process_authorization_response_redirect_uri: Url,
) -> Self {
Self {
save_oauth_state_adapter,
oauth_auth_req_uri_adapter,
process_authorization_response_redirect_uri,
generate_random_string,
}
}
}
#[async_trait::async_trait]
impl RequestAuthorizationInterface for RequestAuthorizationHandler {
#[tracing::instrument(name = "web adapter request_oauth_authorization", skip(self))]
async fn request_oauth_authorization(&self, forge_name: String) -> InUIResult<HttpResponse> {
let service = RequestAuthorizationService::new(
self.save_oauth_state_adapter.clone(),
self.oauth_auth_req_uri_adapter.clone(),
self.process_authorization_response_redirect_uri.clone(),
self.generate_random_string.clone(),
);
let cmd = RequestAuthorizationCommand::new_command(forge_name)?;
let auth_page = service.request_authorization(cmd).await?;
Ok(HttpResponse::Found()
.insert_header((header::LOCATION, auth_page.as_str()))
.finish())
}
}
#[cfg(test)]
mod tests {
use actix_web::http::{header, StatusCode};
use super::*;
use crate::auth::application::port::out::{
db::save_oauth_state::tests::*, forge::oauth_auth_req_uri::tests::*,
};
use crate::tests::bdd::IS_CALLED_ONLY_ONCE;
use crate::utils::random_string::tests::*;
#[actix_web::test]
async fn test_adapter() {
let random_string = "foorand";
let url = Url::parse("http://test_ui_req_auth_interface_adapter").unwrap();
let oauth_provider = "test_ui_req_auth_interface_adapter";
let mut redirect_uri = url.clone();
redirect_uri.set_query(Some(&format!("state={random_string}")));
let mock_random_generate_string =
mock_generate_random_string(IS_CALLED_ONLY_ONCE, random_string.into());
let mock_oauth_req_uri = mock_oauth_auth_req_uri(IS_CALLED_ONLY_ONCE, redirect_uri.clone());
let mock_save_oauth_state = mock_save_oauth_state(IS_CALLED_ONLY_ONCE);
let adapter = RequestAuthorizationHandler::new(
mock_save_oauth_state,
mock_oauth_req_uri,
mock_random_generate_string,
url.clone(),
);
let res = adapter
.request_oauth_authorization(oauth_provider.into())
.await
.unwrap();
assert_eq!(res.status(), StatusCode::FOUND);
assert_eq!(
res.headers()
.get(header::LOCATION)
.unwrap()
.to_str()
.unwrap(),
redirect_uri.as_str()
);
}
}