162 lines
5.7 KiB
Rust
162 lines
5.7 KiB
Rust
use actix_web::{post, web, HttpResponse};
|
|
use url::Url;
|
|
|
|
use super::types;
|
|
use crate::auth::adapter::out::forge::SupportedForges;
|
|
use crate::auth::application::port::input::ui::{errors::*, login::RequestAuthorizationInterface};
|
|
|
|
pub fn services(cfg: &mut web::ServiceConfig) {
|
|
cfg.service(handler);
|
|
}
|
|
|
|
#[post("/oauth/forgejo/login")]
|
|
#[tracing::instrument(
|
|
name = "login page handler",
|
|
skip(
|
|
forges,
|
|
save_oauth_state_adapter,
|
|
generate_random_string,
|
|
routes,
|
|
settings
|
|
)
|
|
)]
|
|
async fn handler(
|
|
forges: types::WebForgeRepositoryInterface,
|
|
save_oauth_state_adapter: types::WebSaveOauthState,
|
|
generate_random_string: types::WebGenerateRandomStringInterface,
|
|
routes: types::WebRouteRepository,
|
|
settings: types::WebSettings,
|
|
) -> InUIResult<HttpResponse> {
|
|
let oauth_auth_req_uri_adapter = &forges
|
|
.get_forge_factory(&SupportedForges::Forgejo)
|
|
.unwrap()
|
|
.get_oauth_auth_req_uri_adapter();
|
|
|
|
let process_authorization_response_redirect_uri = Url::parse(&format!(
|
|
"{}://{}{}",
|
|
"http",
|
|
&settings.server.domain,
|
|
&routes.process_oauth_authorization_response(&SupportedForges::Forgejo)
|
|
))
|
|
.map_err(|_| InUIError::InternalServerError)?;
|
|
|
|
let web_adapter = super::adapter::RequestAuthorizationHandler::new(
|
|
save_oauth_state_adapter.as_ref().to_owned(),
|
|
oauth_auth_req_uri_adapter.clone(),
|
|
generate_random_string.as_ref().clone(),
|
|
process_authorization_response_redirect_uri,
|
|
);
|
|
|
|
web_adapter
|
|
.request_oauth_authorization(SupportedForges::Forgejo.to_string())
|
|
.await
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use std::sync::Arc;
|
|
|
|
use super::*;
|
|
use actix_web::http::{header, StatusCode};
|
|
use actix_web::{http::header::ContentType, test, App};
|
|
|
|
use crate::auth::adapter::input::web::routes::RoutesRepository;
|
|
use crate::auth::adapter::out::forge::forge_factory::{
|
|
ForgeAdapterFactoryInterface, MockForgeAdapterFactoryInterface,
|
|
};
|
|
use crate::auth::adapter::out::forge::forge_repository::MockForgeRepositoryInterface;
|
|
|
|
use crate::auth::application::port::out::forge::oauth_auth_req_uri::OAuthAuthReqUri;
|
|
use crate::auth::application::port::out::{
|
|
db::save_oauth_state::MockSaveOAuthState, forge::oauth_auth_req_uri::MockOAuthAuthReqUri,
|
|
};
|
|
use crate::utils::random_string::*;
|
|
|
|
#[actix_web::test]
|
|
async fn test_ui_handler_request_oauth_authorization_forgejo() {
|
|
let random_string = "foorand";
|
|
let settings = crate::settings::Settings::new().unwrap();
|
|
|
|
let url = Url::parse("http://test_ui_handler_request_oauth_authorization_forgejo").unwrap();
|
|
let mut redirect_uri = url.clone();
|
|
redirect_uri.set_query(Some(&format!("state={random_string}")));
|
|
|
|
let mock_random_generate_string = {
|
|
let mut mock_random_generate_string = MockGenerateRandomStringInterface::new();
|
|
mock_random_generate_string
|
|
.expect_get_random()
|
|
.times(1)
|
|
.return_const(random_string.to_string());
|
|
WebGenerateRandomStringInterface::new(Arc::new(mock_random_generate_string))
|
|
};
|
|
|
|
let mock_save_oauth_state = {
|
|
let mut mock_save_oauth_state = MockSaveOAuthState::new();
|
|
mock_save_oauth_state
|
|
.expect_save_oauth_state()
|
|
.times(1)
|
|
.returning(|_, _, _| Ok(()));
|
|
types::WebSaveOauthState::new(Arc::new(mock_save_oauth_state))
|
|
};
|
|
|
|
let mock_forges = {
|
|
let mock_oauth_req_uri: Arc<dyn OAuthAuthReqUri> = {
|
|
let r = redirect_uri.clone();
|
|
let mut mock_oauth_req_uri = MockOAuthAuthReqUri::new();
|
|
mock_oauth_req_uri
|
|
.expect_oauth_auth_req_uri()
|
|
.times(1)
|
|
.returning(move |_, _| Ok(r.clone()));
|
|
Arc::new(mock_oauth_req_uri)
|
|
};
|
|
|
|
let mut mock_forge_factory = MockForgeAdapterFactoryInterface::default();
|
|
let a = mock_oauth_req_uri.clone();
|
|
mock_forge_factory
|
|
.expect_get_oauth_auth_req_uri_adapter()
|
|
.times(1)
|
|
.returning(move || a.clone());
|
|
let mock_forge_factory: Arc<dyn ForgeAdapterFactoryInterface> =
|
|
Arc::new(mock_forge_factory);
|
|
|
|
let mut mock_forges = MockForgeRepositoryInterface::default();
|
|
mock_forges
|
|
.expect_get_forge_factory()
|
|
.times(1)
|
|
.returning(move |_| Some(mock_forge_factory.clone()));
|
|
|
|
types::WebForgeRepositoryInterface::new(Arc::new(mock_forges))
|
|
};
|
|
|
|
let routes = RoutesRepository::default();
|
|
|
|
let app = test::init_service(
|
|
App::new()
|
|
.app_data(mock_save_oauth_state)
|
|
.wrap(tracing_actix_web::TracingLogger::default())
|
|
.app_data(mock_random_generate_string)
|
|
.app_data(mock_forges)
|
|
.app_data(web::Data::new(Arc::new(routes.clone())))
|
|
.app_data(web::Data::new(settings.clone()))
|
|
.service(handler),
|
|
)
|
|
.await;
|
|
|
|
let req = test::TestRequest::post()
|
|
.uri("/oauth/forgejo/login")
|
|
.insert_header(ContentType::html())
|
|
.to_request();
|
|
let resp = test::call_service(&app, req).await;
|
|
let status = resp.status();
|
|
assert_eq!(status, StatusCode::FOUND);
|
|
assert_eq!(
|
|
resp.headers()
|
|
.get(header::LOCATION)
|
|
.unwrap()
|
|
.to_str()
|
|
.unwrap(),
|
|
redirect_uri.as_str()
|
|
);
|
|
}
|
|
}
|