feat: sqlx postgres adapter for oauth domain
This commit is contained in:
parent
c718ae6f4d
commit
9b328a0935
34
src/forge/auth/adapter/out/db/mod.rs
Normal file
34
src/forge/auth/adapter/out/db/mod.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
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;
|
||||
|
||||
pub mod postgres;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DBAdapter {
|
||||
pub save_oauth_state_adapter: Arc<dyn SaveOAuthState>,
|
||||
pg_adapter: postgres::DBOutPostgresAdapter,
|
||||
}
|
||||
|
||||
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 {
|
||||
let pg_adapter = postgres::DBOutPostgresAdapter::new(pool);
|
||||
Self {
|
||||
save_oauth_state_adapter: Arc::new(pg_adapter.clone()),
|
||||
pg_adapter,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn migratable(&self) -> Arc<dyn RunMigrations> {
|
||||
self.pg_adapter.migratable()
|
||||
}
|
||||
}
|
28
src/forge/auth/adapter/out/db/postgres/errors.rs
Normal file
28
src/forge/auth/adapter/out/db/postgres/errors.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use derive_more::Display;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::Error as SqlxError;
|
||||
|
||||
use crate::forge::auth::application::port::out::db::errors::OutDBPortError;
|
||||
|
||||
impl From<SqlxError> for OutDBPortError {
|
||||
fn from(value: SqlxError) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
//impl From<ProcessAuthorizationServiceError> for OutDBPostgresError {
|
||||
// fn from(v: ProcessAuthorizationServiceError) -> Self {
|
||||
// match v {
|
||||
// ProcessAuthorizationServiceError::InteralError => Self::InternalServerError,
|
||||
// ProcessAuthorizationServiceError::BadRequest => Self::BadRequest,
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//impl From<RequestAuthorizationServiceError> for OutDBPostgresError {
|
||||
// fn from(v: RequestAuthorizationServiceError) -> Self {
|
||||
// match v {
|
||||
// RequestAuthorizationServiceError::InteralError => Self::InternalServerError,
|
||||
// }
|
||||
// }
|
||||
//}
|
24
src/forge/auth/adapter/out/db/postgres/mod.rs
Normal file
24
src/forge/auth/adapter/out/db/postgres/mod.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
//use crate::forge::auth::application::port::out::db::save_oauth_state::SaveOAuthState;
|
||||
use std::sync::Arc;
|
||||
|
||||
use sqlx::postgres::PgPool;
|
||||
|
||||
use crate::db::{migrate::RunMigrations, sqlx_postgres::Postgres};
|
||||
|
||||
mod errors;
|
||||
mod save_oauth_state;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DBOutPostgresAdapter {
|
||||
pool: PgPool,
|
||||
}
|
||||
|
||||
impl DBOutPostgresAdapter {
|
||||
pub fn new(pool: PgPool) -> Self {
|
||||
Self { pool }
|
||||
}
|
||||
|
||||
pub fn migratable(&self) -> Arc<dyn RunMigrations> {
|
||||
Arc::new(Postgres::new(self.pool.clone()))
|
||||
}
|
||||
}
|
52
src/forge/auth/adapter/out/db/postgres/save_oauth_state.rs
Normal file
52
src/forge/auth/adapter/out/db/postgres/save_oauth_state.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use url::Url;
|
||||
|
||||
use super::DBOutPostgresAdapter;
|
||||
use crate::forge::auth::application::port::out::db::{
|
||||
errors::OutDBPortResult, save_oauth_state::SaveOAuthState,
|
||||
};
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl SaveOAuthState for DBOutPostgresAdapter {
|
||||
async fn save_oauth_state(
|
||||
&self,
|
||||
state: &str,
|
||||
oauth_provider: &str,
|
||||
redirect_uri: &Url,
|
||||
) -> OutDBPortResult<()> {
|
||||
sqlx::query!(
|
||||
"INSERT INTO oauth_state (state, oauth_provider, redirect_uri) VALUES ($1, $2, $3)",
|
||||
state,
|
||||
oauth_provider,
|
||||
redirect_uri.as_str()
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_postgres_save_oauth_state() {
|
||||
let state = "statetestpostgres";
|
||||
let oauth_provider = "oauthprovitestpostgres";
|
||||
let redirect_uri = Url::parse("https://oauthprovitestpostgres").unwrap();
|
||||
|
||||
let settings = crate::settings::tests::get_settings().await;
|
||||
|
||||
let db = super::DBOutPostgresAdapter::new(
|
||||
sqlx::postgres::PgPool::connect(&settings.database.url)
|
||||
.await
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
db.save_oauth_state(state, oauth_provider, &redirect_uri)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
settings.drop_db().await;
|
||||
}
|
||||
}
|
24
src/forge/auth/adapter/out/forge/forgejo/get_redirect_uri.rs
Normal file
24
src/forge/auth/adapter/out/forge/forgejo/get_redirect_uri.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
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)
|
||||
}
|
||||
}
|
32
src/forge/auth/adapter/out/forge/forgejo/mod.rs
Normal file
32
src/forge/auth/adapter/out/forge/forgejo/mod.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use url::Url;
|
||||
|
||||
mod get_redirect_uri;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Forgejo {
|
||||
url: Url,
|
||||
client_id: String,
|
||||
client_secret: String,
|
||||
}
|
||||
|
||||
impl Forgejo {
|
||||
pub fn new(url: Url, client_id: String, client_secret: String) -> Self {
|
||||
Self {
|
||||
url,
|
||||
client_id,
|
||||
client_secret,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
pub fn client_id(&self) -> &str {
|
||||
&self.client_id
|
||||
}
|
||||
|
||||
pub fn client_secret(&self) -> &str {
|
||||
&self.client_secret
|
||||
}
|
||||
}
|
89
src/forge/auth/adapter/out/forge/mod.rs
Normal file
89
src/forge/auth/adapter/out/forge/mod.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
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 self::forgejo::Forgejo;
|
||||
|
||||
pub mod forgejo;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ForgeAdapter {
|
||||
pub get_redirect_uri_adapter: Arc<dyn GetRedirectUri>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct ForgeRepository {
|
||||
forges: HashMap<SupportedForges, ForgeAdapter>,
|
||||
}
|
||||
|
||||
impl ForgeRepository {
|
||||
fn add_forge(&mut self, name: SupportedForges, forge_factory: ForgeAdapter) {
|
||||
self.forges.insert(name, forge_factory);
|
||||
}
|
||||
|
||||
pub fn get_supported_forge_str(&self) -> Vec<String> {
|
||||
self.forges
|
||||
.clone()
|
||||
.into_keys()
|
||||
.map(|v| v.to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn get_supported_forges(&self) -> Vec<SupportedForges> {
|
||||
self.forges.clone().into_keys().collect()
|
||||
}
|
||||
|
||||
pub fn get_forge(&self, name: &SupportedForges) -> Option<&ForgeAdapter> {
|
||||
self.forges.get(name)
|
||||
}
|
||||
|
||||
pub fn new(forgejo: Forgejo) -> Self {
|
||||
let forgejo_adapter = ForgeAdapter {
|
||||
get_redirect_uri_adapter: Arc::new(forgejo),
|
||||
};
|
||||
let mut s = Self::default();
|
||||
s.add_forge(SupportedForges::Forgejo, forgejo_adapter);
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Clone, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum SupportedForges {
|
||||
#[display(fmt = "forgejo")]
|
||||
Forgejo,
|
||||
}
|
||||
|
||||
impl FromStr for SupportedForges {
|
||||
type Err = SupportedForgesError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.trim() {
|
||||
"forgejo" => Ok(SupportedForges::Forgejo),
|
||||
_ => Err(SupportedForgesError::UnsupportedForge),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Clone, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum SupportedForgesError {
|
||||
UnsupportedForge,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_supported_forges() {
|
||||
assert_eq!(SupportedForges::Forgejo.to_string(), "forgejo");
|
||||
assert_eq!(
|
||||
SupportedForges::from_str("forgejo").unwrap(),
|
||||
SupportedForges::Forgejo
|
||||
);
|
||||
}
|
||||
}
|
2
src/forge/auth/adapter/out/mod.rs
Normal file
2
src/forge/auth/adapter/out/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod db;
|
||||
pub mod forge;
|
Loading…
Reference in a new issue