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

106 lines
3.7 KiB
Rust

use std::sync::Arc;
use actix_web::http::header::ContentType;
use actix_web::{get, post, web, HttpResponse};
use url::Url;
use crate::auth::adapter::input::web::routes::RoutesRepository;
use crate::auth::adapter::out::forge::SupportedForges;
use crate::auth::application::port::input::ui::{errors::*, login::RequestAuthorizationInterface};
use crate::auth::application::port::out::db::save_oauth_state::SaveOAuthState;
use crate::utils::random_string::GenerateRandomStringInterface;
use crate::ForgeRepository;
use super::template::{LoginCtxFactory, LoginPageInterface};
#[get("/login")]
#[tracing::instrument(name = "login page handler", skip(forges, routes, template))]
async fn login_page(
forges: web::Data<Arc<ForgeRepository>>,
routes: web::Data<Arc<RoutesRepository>>,
template: web::Data<Arc<dyn LoginPageInterface>>,
) -> InUIResult<HttpResponse> {
let template_ctx = LoginCtxFactory::get_ctx(forges.get_supported_forges(), &routes);
let page = template.get_login_page(template_ctx).unwrap();
Ok(HttpResponse::Ok()
.insert_header(ContentType::html())
.body(page))
}
#[post("/oauth/forgejo/login")]
async fn request_oauth_authorization_forgejo(
forges: web::Data<Arc<ForgeRepository>>,
save_oauth_state_adapter: web::Data<Arc<dyn SaveOAuthState>>,
routes: web::Data<Arc<RoutesRepository>>,
generate_random_string: web::Data<Arc<dyn GenerateRandomStringInterface>>,
settings: web::Data<crate::settings::Settings>,
) -> InUIResult<HttpResponse> {
let oauth_auth_req_uri_adapter = &forges
.get_forge(&SupportedForges::Forgejo)
.unwrap()
.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
}
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(login_page);
cfg.service(request_oauth_authorization_forgejo);
}
#[cfg(test)]
mod tests {
use super::*;
use actix_web::{http::header::ContentType, test, App};
use crate::auth::adapter::input::web::login::template::load_templates;
use crate::auth::adapter::out::forge::forgejo::Forgejo;
#[actix_web::test]
async fn test_get_login_page() {
let settings = crate::settings::Settings::new().unwrap();
let forgejo = Forgejo::new(
settings.forges.forgejo.url.clone(),
settings.forges.forgejo.client_id.clone(),
settings.forges.forgejo.client_secret.clone(),
);
let forges = ForgeRepository::new(forgejo);
let routes = RoutesRepository::default();
let app = test::init_service(
App::new()
.app_data(web::Data::new(Arc::new(forges.clone())))
.app_data(web::Data::new(Arc::new(routes.clone())))
.configure(load_templates)
.service(login_page),
)
.await;
let req = test::TestRequest::get()
.uri("/login")
.insert_header(ContentType::html())
.to_request();
let resp = test::call_service(&app, req).await;
println!("{}", resp.status());
assert!(resp.status().is_success());
}
}