Compare commits
5 Commits
3640774c6a
...
60885319f7
Author | SHA1 | Date |
---|---|---|
Aravinth Manivannan | 60885319f7 | |
Aravinth Manivannan | 316d1c7e21 | |
Aravinth Manivannan | 807cbf4920 | |
Aravinth Manivannan | 2ac557d48b | |
Aravinth Manivannan | aba028fdd8 |
|
@ -5,13 +5,19 @@ use super::migrate::RunMigrations;
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct Postgres {
|
||||
pool: PgPool,
|
||||
pub pool: PgPool,
|
||||
}
|
||||
|
||||
impl Postgres {
|
||||
pub fn new(pool: PgPool) -> Self {
|
||||
Self { pool }
|
||||
}
|
||||
|
||||
pub async fn init(database_url: &str) -> Self {
|
||||
let pool = PgPool::connect(database_url).await.unwrap();
|
||||
|
||||
Self::new(pool)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use actix_web::{get, http::header, post, web, HttpResponse};
|
||||
|
||||
use crate::forge::auth::adapter::out::forge::SupportedForges;
|
||||
use crate::forge::auth::application::port::input::ui::{
|
||||
errors::*, login::RequestAuthorizationInterface,
|
||||
};
|
||||
use crate::forge::auth::application::services::request_authorization::command::RequestAuthorizationCommand;
|
||||
|
||||
use super::{templates::login::LoginCtxFactory, ServiceFactory, WebCtx};
|
||||
use crate::ActixCtx;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl RequestAuthorizationInterface for WebCtx {
|
||||
#[tracing::instrument(name = "web adapter request_oauth_authorization", skip(self))]
|
||||
async fn request_oauth_authorization(&self, forge_name: String) -> InUIResult<HttpResponse> {
|
||||
let service = ServiceFactory::request_authorization(
|
||||
SupportedForges::from_str(&forge_name).map_err(|_| InUIError::BadRequest)?,
|
||||
self,
|
||||
)?;
|
||||
|
||||
log::info!("service found");
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/login")]
|
||||
async fn login_page(ctx: ActixCtx) -> InUIResult<HttpResponse> {
|
||||
let template_ctx =
|
||||
LoginCtxFactory::get_ctx(ctx.adapters.forges.get_supported_forges(), &ctx.routes);
|
||||
let page = ctx
|
||||
.templates
|
||||
.login_page
|
||||
.get_login_page(template_ctx)
|
||||
.unwrap();
|
||||
Ok(HttpResponse::Ok()
|
||||
.append_header((header::CONTENT_TYPE, "text/html; charset=UTF-8"))
|
||||
.body(page))
|
||||
}
|
||||
|
||||
#[post("/oauth/{forge}/login")]
|
||||
#[tracing::instrument(name = "web handler request_oauth_authorization", skip(ctx))]
|
||||
async fn request_oauth_authorization(
|
||||
ctx: ActixCtx,
|
||||
forge_name: web::Path<String>,
|
||||
) -> InUIResult<HttpResponse> {
|
||||
ctx.request_oauth_authorization(forge_name.into_inner())
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(login_page);
|
||||
cfg.service(request_oauth_authorization);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use actix_web::{http::header, HttpResponse};
|
||||
use url::Url;
|
||||
|
||||
use crate::forge::auth::application::port::input::ui::{
|
||||
errors::*, login::RequestAuthorizationInterface,
|
||||
};
|
||||
use crate::forge::auth::application::port::out::db::save_oauth_state::SaveOAuthState;
|
||||
use crate::forge::auth::application::port::out::forge::oauth_auth_req_uri::OAuthAuthReqUri;
|
||||
use crate::forge::auth::application::services::request_authorization::{
|
||||
command::RequestAuthorizationCommand, service::RequestAuthorizationService,
|
||||
RequestAuthorizationUserCase,
|
||||
};
|
||||
//use crate::forge::auth::application::services::request_authorization::command::RequestAuthorizationCommand;
|
||||
|
||||
pub struct RequestAuthorizationHandler {
|
||||
save_oauth_state_adapter: Arc<dyn SaveOAuthState>,
|
||||
oauth_auth_req_uri_adapter: Arc<dyn OAuthAuthReqUri>,
|
||||
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>,
|
||||
process_authorization_response_redirect_uri: Url,
|
||||
) -> Self {
|
||||
Self {
|
||||
save_oauth_state_adapter,
|
||||
oauth_auth_req_uri_adapter,
|
||||
process_authorization_response_redirect_uri,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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(),
|
||||
);
|
||||
|
||||
log::info!("service found");
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use actix_web::{get, http::header, post, web, HttpResponse};
|
||||
use url::Url;
|
||||
|
||||
use crate::forge::auth::adapter::input::web::routes::RoutesRepository;
|
||||
use crate::forge::auth::adapter::out::forge::SupportedForges;
|
||||
use crate::forge::auth::application::port::input::ui::{
|
||||
errors::*, login::RequestAuthorizationInterface,
|
||||
};
|
||||
use crate::forge::auth::application::port::out::db::save_oauth_state::SaveOAuthState;
|
||||
|
||||
use super::template::{LoginCtxFactory, LoginPageInterface};
|
||||
use crate::ForgeRepository;
|
||||
|
||||
#[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()
|
||||
.append_header((header::CONTENT_TYPE, "text/html; charset=UTF-8"))
|
||||
.body(page))
|
||||
}
|
||||
|
||||
#[post("/oauth/forgejo/login")]
|
||||
async fn request_oauth_authorization_forgejo(
|
||||
forge_name: web::Path<String>,
|
||||
forges: web::Data<Arc<ForgeRepository>>,
|
||||
save_oauth_state_adapter: web::Data<Arc<dyn SaveOAuthState>>,
|
||||
routes: web::Data<Arc<RoutesRepository>>,
|
||||
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(),
|
||||
process_authorization_response_redirect_uri,
|
||||
);
|
||||
|
||||
web_adapter
|
||||
.request_oauth_authorization(forge_name.into_inner())
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(login_page);
|
||||
cfg.service(request_oauth_authorization_forgejo);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
use actix_web::web;
|
||||
|
||||
mod adapter;
|
||||
mod handler;
|
||||
mod template;
|
||||
|
||||
pub use template::register_templates;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
template::load_templates(cfg);
|
||||
handler::services(cfg);
|
||||
}
|
|
@ -1,36 +1,44 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use actix_web::web;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::forge::auth::adapter::input::web::routes::RoutesRepository;
|
||||
use crate::forge::auth::adapter::out::forge::SupportedForges;
|
||||
|
||||
use super::{tera_context, TEMPLATES};
|
||||
use crate::forge::auth::adapter::input::web::template::{tera_context, TemplateFile, TEMPLATES};
|
||||
|
||||
pub trait LoginPageInterface: Send + Sync {
|
||||
fn get_login_page(&self, ctx: LoginCtx) -> Result<String, Box<dyn std::error::Error>>;
|
||||
}
|
||||
|
||||
use super::TemplateFile;
|
||||
const LOGIN_TEMPLATE: TemplateFile = TemplateFile::new("login", "login/page.html");
|
||||
|
||||
pub const LOGIN_TEMPLATE: TemplateFile = TemplateFile::new("login", "login.html");
|
||||
pub fn register_templates(t: &mut tera::Tera) {
|
||||
println!("registering login template");
|
||||
LOGIN_TEMPLATE.register(t).expect(LOGIN_TEMPLATE.name);
|
||||
}
|
||||
|
||||
pub fn load_templates(cfg: &mut web::ServiceConfig) {
|
||||
let t: Arc<dyn LoginPageInterface> = Arc::new(LoginPageTemplate);
|
||||
cfg.app_data(web::Data::new(t));
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Forge {
|
||||
struct Forge {
|
||||
name: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
impl Forge {
|
||||
pub fn new(name: String, path: String) -> Self {
|
||||
fn new(name: String, path: String) -> Self {
|
||||
Self { name, path }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct LoginCtx {
|
||||
pub forges: Vec<Forge>,
|
||||
forges: Vec<Forge>,
|
||||
}
|
||||
|
||||
pub struct LoginCtxFactory;
|
||||
|
@ -47,7 +55,7 @@ impl LoginCtxFactory {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct LoginPageTemplate;
|
||||
struct LoginPageTemplate;
|
||||
|
||||
impl LoginPageInterface for LoginPageTemplate {
|
||||
fn get_login_page(&self, ctx: LoginCtx) -> Result<String, Box<dyn std::error::Error>> {
|
|
@ -1,81 +1,20 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use actix_web::web::{self, Data};
|
||||
use url::Url;
|
||||
|
||||
use crate::forge::auth::adapter::out::db::DBAdapter;
|
||||
use crate::forge::auth::adapter::out::forge::{ForgeRepository, SupportedForges};
|
||||
use crate::forge::auth::application::port::input::ui::errors::{InUIError, InUIResult};
|
||||
use crate::forge::auth::application::services::request_authorization::service::RequestAuthorizationService;
|
||||
use crate::forge::auth::application::services::request_authorization::RequestAuthorizationUserCase;
|
||||
use crate::settings::Settings;
|
||||
use actix_web::web;
|
||||
|
||||
pub mod login;
|
||||
mod routes;
|
||||
mod templates;
|
||||
mod template;
|
||||
|
||||
use routes::RoutesRepository;
|
||||
|
||||
pub type ArcCtx = Arc<WebCtx>;
|
||||
pub type ActixCtx = Data<ArcCtx>;
|
||||
pub fn load_ctx() -> impl FnOnce(&mut web::ServiceConfig) {
|
||||
let routes = web::Data::new(Arc::new(RoutesRepository::default()));
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WebCtx {
|
||||
pub routes: Arc<RoutesRepository>,
|
||||
pub adapters: Adapters,
|
||||
pub templates: templates::Templates,
|
||||
pub settings: Settings,
|
||||
}
|
||||
|
||||
impl WebCtx {
|
||||
pub fn new_actix_ctx(forges: ForgeRepository, db: DBAdapter, settings: Settings) -> ActixCtx {
|
||||
let routes = Arc::new(RoutesRepository::default());
|
||||
Data::new(Arc::new(Self {
|
||||
routes: routes.clone(),
|
||||
adapters: Adapters::new(forges, db),
|
||||
templates: templates::Templates::default(),
|
||||
settings,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Adapters {
|
||||
pub forges: ForgeRepository,
|
||||
pub db: DBAdapter,
|
||||
}
|
||||
|
||||
impl Adapters {
|
||||
pub fn new(forges: ForgeRepository, db: DBAdapter) -> Self {
|
||||
Self { forges, db }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ServiceFactory;
|
||||
|
||||
impl ServiceFactory {
|
||||
pub fn request_authorization(
|
||||
forge_name: SupportedForges,
|
||||
ctx: &WebCtx,
|
||||
) -> InUIResult<Arc<dyn RequestAuthorizationUserCase>> {
|
||||
if let Some(forge) = ctx.adapters.forges.get_forge(&forge_name) {
|
||||
Ok(Arc::new(RequestAuthorizationService::new(
|
||||
ctx.adapters.db.save_oauth_state_adapter.clone(),
|
||||
forge.get_redirect_uri_adapter.clone(),
|
||||
Url::parse(&format!(
|
||||
"{}://{}{}",
|
||||
"http",
|
||||
&ctx.settings.server.domain,
|
||||
&ctx.routes.process_oauth_authorization_response(&forge_name)
|
||||
))
|
||||
.map_err(|_| InUIError::InternalServerError)?,
|
||||
)))
|
||||
} else {
|
||||
Err(InUIError::BadRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.configure(login::services);
|
||||
let f = move |cfg: &mut web::ServiceConfig| {
|
||||
cfg.app_data(routes);
|
||||
cfg.configure(login::services);
|
||||
};
|
||||
|
||||
Box::new(f)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use lazy_static::lazy_static;
|
||||
use rust_embed::RustEmbed;
|
||||
use std::cell::RefCell;
|
||||
use tera::*;
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
pub struct TemplateFile {
|
||||
pub name: &'static str,
|
||||
pub path: &'static str,
|
||||
|
@ -16,12 +19,12 @@ impl TemplateFile {
|
|||
t.add_raw_template(self.name, &Templates::get_template(self).expect(self.name))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)]
|
||||
pub fn register_from_file(&self, t: &mut Tera) -> std::result::Result<(), tera::Error> {
|
||||
use std::path::Path;
|
||||
t.add_template_file(Path::new("templates/").join(self.path), Some(self.name))
|
||||
}
|
||||
// #[cfg(test)]
|
||||
// #[allow(dead_code)]
|
||||
// pub fn register_from_file(&self, t: &mut Tera) -> std::result::Result<(), tera::Error> {
|
||||
// use std::path::Path;
|
||||
// t.add_template_file(Path::new("./").join(self.path), Some(self.name))
|
||||
// }
|
||||
}
|
||||
|
||||
pub const PAYLOAD_KEY: &str = "payload";
|
||||
|
@ -40,14 +43,12 @@ lazy_static! {
|
|||
// errors::register_templates(&mut tera);
|
||||
tera.autoescape_on(vec![".html", ".sql"]);
|
||||
super::login::register_templates(&mut tera);
|
||||
// auth::register_templates(&mut tera);
|
||||
// gists::register_templates(&mut tera);
|
||||
tera
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "src/forge/auth/adapter/input/web/templates/"]
|
||||
#[folder = "src/forge/auth/adapter/input/web/"]
|
||||
#[include = "*.html"]
|
||||
#[exclude = "*.rs"]
|
||||
struct Templates;
|
||||
|
@ -60,3 +61,9 @@ impl Templates {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tera_context<T: Serialize>(s: &T) -> RefCell<Context> {
|
||||
let c = RefCell::new(Context::new());
|
||||
c.borrow_mut().insert(PAYLOAD_KEY, s);
|
||||
c
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
pub mod login;
|
||||
pub mod setup;
|
||||
mod utils;
|
||||
|
||||
use login::{LoginPageInterface, LoginPageTemplate};
|
||||
|
||||
pub use setup::{TemplateFile, PAYLOAD_KEY, TEMPLATES};
|
||||
pub use utils::tera_context;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Templates {
|
||||
pub login_page: Arc<dyn LoginPageInterface>,
|
||||
}
|
||||
|
||||
impl Default for Templates {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
login_page: Arc::new(LoginPageTemplate),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
use std::cell::RefCell;
|
||||
|
||||
use super::PAYLOAD_KEY;
|
||||
use serde::Serialize;
|
||||
use tera::Context;
|
||||
|
||||
pub fn tera_context<T: Serialize>(s: &T) -> RefCell<Context> {
|
||||
let c = RefCell::new(Context::new());
|
||||
c.borrow_mut().insert(PAYLOAD_KEY, s);
|
||||
c
|
||||
}
|
|
@ -1,2 +1,31 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use actix_web::web;
|
||||
use sqlx::postgres::PgPool;
|
||||
|
||||
pub mod input;
|
||||
pub mod out;
|
||||
|
||||
use crate::settings;
|
||||
use out::db::DBAdapter;
|
||||
use out::forge::{forgejo::Forgejo, ForgeRepository};
|
||||
|
||||
pub fn load_adapters(
|
||||
pool: PgPool,
|
||||
settings: &settings::Settings,
|
||||
) -> impl FnOnce(&mut web::ServiceConfig) {
|
||||
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 f = move |cfg: &mut web::ServiceConfig| {
|
||||
cfg.app_data(web::Data::new(Arc::new(DBAdapter::new(pool))));
|
||||
cfg.app_data(web::Data::new(Arc::new(forges.clone())));
|
||||
cfg.configure(input::web::load_ctx());
|
||||
};
|
||||
|
||||
Box::new(f)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use sqlx::PgPool;
|
||||
use url::Url;
|
||||
|
||||
use crate::db::migrate::RunMigrations;
|
||||
use crate::forge::auth::application::port::out::db::save_oauth_state::SaveOAuthState;
|
||||
|
@ -15,12 +14,7 @@ pub struct DBAdapter {
|
|||
}
|
||||
|
||||
impl DBAdapter {
|
||||
pub async fn init(database_url: &str) -> Self {
|
||||
let pool = PgPool::connect(database_url).await.unwrap();
|
||||
|
||||
Self::new(pool)
|
||||
}
|
||||
fn new(pool: PgPool) -> Self {
|
||||
pub fn new(pool: PgPool) -> Self {
|
||||
let pg_adapter = postgres::DBOutPostgresAdapter::new(pool);
|
||||
Self {
|
||||
save_oauth_state_adapter: Arc::new(pg_adapter.clone()),
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
use url::Url;
|
||||
|
||||
use super::Forgejo;
|
||||
use crate::forge::auth::application::port::out::forge::{
|
||||
errors::OutForgePortResult, get_redirect_uri::GetRedirectUri,
|
||||
};
|
||||
|
||||
impl GetRedirectUri for Forgejo {
|
||||
fn get_redirect_uri(
|
||||
&self,
|
||||
state: &str,
|
||||
process_authorization_response_uri: &Url,
|
||||
) -> OutForgePortResult<Url> {
|
||||
let mut u = self.url().to_owned();
|
||||
u.set_path("/login/oauth/authorize");
|
||||
u.set_query(Some(&format!(
|
||||
"client_id={}&redirect_uri={}&response_type=code&state={state}",
|
||||
self.client_id(),
|
||||
process_authorization_response_uri.as_str()
|
||||
)));
|
||||
|
||||
Ok(u)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use url::Url;
|
||||
|
||||
mod get_redirect_uri;
|
||||
pub mod oauth_auth_req_uri;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Forgejo {
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
use url::Url;
|
||||
|
||||
use super::Forgejo;
|
||||
use crate::forge::auth::application::port::out::forge::{
|
||||
errors::OutForgePortResult, oauth_auth_req_uri::OAuthAuthReqUri,
|
||||
};
|
||||
|
||||
impl OAuthAuthReqUri for Forgejo {
|
||||
fn oauth_auth_req_uri(
|
||||
&self,
|
||||
state: &str,
|
||||
process_authorization_response_uri: &Url,
|
||||
) -> OutForgePortResult<Url> {
|
||||
let mut u = self.url().to_owned();
|
||||
u.set_path("/login/oauth/authorize/");
|
||||
u.set_query(Some(&format!(
|
||||
"client_id={}&redirect_uri={}&response_type=code&state={state}",
|
||||
self.client_id(),
|
||||
process_authorization_response_uri.as_str()
|
||||
)));
|
||||
|
||||
Ok(u)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_forgejo_oauth_auth_req_uri() {
|
||||
let u = Url::parse("https://forgejo").unwrap();
|
||||
let client_id = "id";
|
||||
let client_secret = "sec";
|
||||
let state = "st";
|
||||
let process_authorization_response_uri = Url::parse("https://forgeflux").unwrap();
|
||||
|
||||
let f = Forgejo::new(u.clone(), client_id.into(), client_secret.into());
|
||||
let oauth_auth_req_uri = f
|
||||
.oauth_auth_req_uri(state, &process_authorization_response_uri)
|
||||
.unwrap();
|
||||
|
||||
let path = "/login/oauth/authorize";
|
||||
let q = format!(
|
||||
"client_id={}&redirect_uri={}&response_type=code&state={state}",
|
||||
client_id,
|
||||
process_authorization_response_uri.as_str()
|
||||
);
|
||||
assert_eq!(
|
||||
oauth_auth_req_uri.to_string(),
|
||||
format!("https://forgejo{path}/?{q}")
|
||||
);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ use std::sync::Arc;
|
|||
use derive_more::Display;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::forge::auth::application::port::out::forge::get_redirect_uri::GetRedirectUri;
|
||||
use crate::forge::auth::application::port::out::forge::oauth_auth_req_uri::OAuthAuthReqUri;
|
||||
|
||||
use self::forgejo::Forgejo;
|
||||
|
||||
|
@ -13,7 +13,7 @@ pub mod forgejo;
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct ForgeAdapter {
|
||||
pub get_redirect_uri_adapter: Arc<dyn GetRedirectUri>,
|
||||
pub oauth_auth_req_uri_adapter: Arc<dyn OAuthAuthReqUri>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
|
@ -44,7 +44,7 @@ impl ForgeRepository {
|
|||
|
||||
pub fn new(forgejo: Forgejo) -> Self {
|
||||
let forgejo_adapter = ForgeAdapter {
|
||||
get_redirect_uri_adapter: Arc::new(forgejo),
|
||||
oauth_auth_req_uri_adapter: Arc::new(forgejo),
|
||||
};
|
||||
let mut s = Self::default();
|
||||
s.add_forge(SupportedForges::Forgejo, forgejo_adapter);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
pub mod errors;
|
||||
pub mod get_redirect_uri;
|
||||
pub mod oauth_auth_req_uri;
|
||||
pub mod refresh_access_token;
|
||||
pub mod request_access_token;
|
||||
|
||||
|
@ -10,14 +10,14 @@ pub mod tests {
|
|||
use super::*;
|
||||
|
||||
use errors::*;
|
||||
use get_redirect_uri::GetRedirectUri;
|
||||
use oauth_auth_req_uri::OAuthAuthReqUri;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct MockForge; // {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl GetRedirectUri for MockForge {
|
||||
fn get_redirect_uri(
|
||||
impl OAuthAuthReqUri for MockForge {
|
||||
fn oauth_auth_req_uri(
|
||||
&self,
|
||||
state: &str,
|
||||
process_authorization_response_uri: &Url,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use super::errors::*;
|
||||
use url::Url;
|
||||
|
||||
pub trait GetRedirectUri: Send + Sync {
|
||||
fn get_redirect_uri(
|
||||
pub trait OAuthAuthReqUri: Send + Sync {
|
||||
fn oauth_auth_req_uri(
|
||||
&self,
|
||||
state: &str,
|
||||
process_authorization_response_uri: &Url,
|
|
@ -4,7 +4,7 @@ use url::Url;
|
|||
|
||||
use crate::forge::auth::application::port::out::db::errors::OutDBPortError;
|
||||
use crate::forge::auth::application::port::out::db::save_oauth_state::SaveOAuthState;
|
||||
use crate::forge::auth::application::port::out::forge::get_redirect_uri::GetRedirectUri;
|
||||
use crate::forge::auth::application::port::out::forge::oauth_auth_req_uri::OAuthAuthReqUri;
|
||||
use crate::utils;
|
||||
|
||||
use super::{errors::*, RequestAuthorizationUserCase};
|
||||
|
@ -14,19 +14,19 @@ const STATE_LEN: usize = 8;
|
|||
#[derive(Clone)]
|
||||
pub struct RequestAuthorizationService {
|
||||
save_oauth_state_adapter: Arc<dyn SaveOAuthState>,
|
||||
get_redirect_uri_adapter: Arc<dyn GetRedirectUri>,
|
||||
oauth_auth_req_uri_adapter: Arc<dyn OAuthAuthReqUri>,
|
||||
process_authorization_response_redirect_uri: Url,
|
||||
}
|
||||
|
||||
impl RequestAuthorizationService {
|
||||
pub fn new(
|
||||
save_oauth_state_adapter: Arc<dyn SaveOAuthState>,
|
||||
get_redirect_uri_adapter: Arc<dyn GetRedirectUri>,
|
||||
oauth_auth_req_uri_adapter: Arc<dyn OAuthAuthReqUri>,
|
||||
process_authorization_response_redirect_uri: Url,
|
||||
) -> Self {
|
||||
Self {
|
||||
save_oauth_state_adapter,
|
||||
get_redirect_uri_adapter,
|
||||
oauth_auth_req_uri_adapter,
|
||||
process_authorization_response_redirect_uri,
|
||||
}
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ impl RequestAuthorizationUserCase for RequestAuthorizationService {
|
|||
}
|
||||
}
|
||||
let redirect = self
|
||||
.get_redirect_uri_adapter
|
||||
.get_redirect_uri(&state, &self.process_authorization_response_redirect_uri)?;
|
||||
.oauth_auth_req_uri_adapter
|
||||
.oauth_auth_req_uri(&state, &self.process_authorization_response_redirect_uri)?;
|
||||
Ok(redirect)
|
||||
}
|
||||
}
|
||||
|
@ -78,13 +78,13 @@ mod tests {
|
|||
#[actix_rt::test]
|
||||
async fn test_service() {
|
||||
let save_oauth_state = MockDB::default();
|
||||
let get_redirect_uri = MockForge::default();
|
||||
let oauth_auth_req_uri = MockForge;
|
||||
let url = Url::parse("http://test_service_request_auth").unwrap();
|
||||
let oauth_provider = "test_service_request_auth_oauth_provider";
|
||||
|
||||
let s = RequestAuthorizationService::new(
|
||||
Arc::new(save_oauth_state.clone()),
|
||||
Arc::new(get_redirect_uri),
|
||||
Arc::new(oauth_auth_req_uri),
|
||||
url.clone(),
|
||||
);
|
||||
let cmd = RequestAuthorizationCommand::new_command(oauth_provider.to_owned()).unwrap();
|
||||
|
@ -92,7 +92,7 @@ mod tests {
|
|||
let res = s.request_authorization(cmd).await.unwrap().to_string();
|
||||
{
|
||||
let save_oauth_state_ctx = save_oauth_state.calls.read().unwrap();
|
||||
let call = save_oauth_state_ctx.get(0).unwrap();
|
||||
let call = save_oauth_state_ctx.first().unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
format!("http://test_service_request_auth/?state={}", &call.state)
|
||||
|
|
20
src/main.rs
20
src/main.rs
|
@ -1,13 +1,13 @@
|
|||
use std::env;
|
||||
|
||||
use actix_web::{middleware, App, HttpServer};
|
||||
use db::migrate::RunMigrations;
|
||||
|
||||
mod db;
|
||||
mod forge;
|
||||
mod settings;
|
||||
mod utils;
|
||||
|
||||
pub use crate::forge::auth::adapter::input::web::{services, ActixCtx, WebCtx};
|
||||
pub use crate::forge::auth::adapter::out::{
|
||||
db::DBAdapter,
|
||||
forge::{forgejo::Forgejo, ForgeRepository},
|
||||
|
@ -27,26 +27,22 @@ async fn main() {
|
|||
|
||||
pretty_env_logger::init();
|
||||
|
||||
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 db = DBAdapter::init(&settings.database.url).await;
|
||||
db.migratable().migrate().await;
|
||||
let ctx = WebCtx::new_actix_ctx(forges, db, settings.clone());
|
||||
let db = db::sqlx_postgres::Postgres::init(&settings.database.url).await;
|
||||
db.migrate().await;
|
||||
|
||||
let socket_addr = settings.server.get_ip();
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.wrap(tracing_actix_web::TracingLogger::default())
|
||||
.wrap(middleware::Compress::default())
|
||||
.app_data(ctx.clone())
|
||||
.app_data(actix_web::web::Data::new(settings.clone()))
|
||||
.wrap(
|
||||
middleware::DefaultHeaders::new().add(("Permissions-Policy", "interest-cohort=()")),
|
||||
)
|
||||
.configure(services)
|
||||
.configure(forge::auth::adapter::load_adapters(
|
||||
db.pool.clone(),
|
||||
&settings,
|
||||
))
|
||||
})
|
||||
.bind(&socket_addr)
|
||||
.unwrap()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use config::{builder::DefaultState, ConfigBuilder};
|
||||
use serde::Deserialize;
|
||||
use std::env;
|
||||
|
||||
pub mod forgejo;
|
||||
|
||||
|
@ -12,7 +11,7 @@ pub struct Forges {
|
|||
}
|
||||
|
||||
impl Forges {
|
||||
pub fn env_override(mut s: ConfigBuilder<DefaultState>) -> ConfigBuilder<DefaultState> {
|
||||
pub fn env_override(s: ConfigBuilder<DefaultState>) -> ConfigBuilder<DefaultState> {
|
||||
Forgejo::env_override(s)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ pub mod tests {
|
|||
println!("Setting env var {} to {} for test", $env, $val);
|
||||
env::set_var($env, $val);
|
||||
{
|
||||
let new_settings = crate::settings::Settings::new().unwrap();
|
||||
let new_settings = $crate::settings::Settings::new().unwrap();
|
||||
assert_eq!(new_settings.$($param).+, $val_typed, "should match");
|
||||
assert_ne!(new_settings.$($param).+, $init_settings.$($param).+);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue