Skip to content

Commit

Permalink
feat: ログイン状態でAPIにアクセスした場合に、UUIDと名前をDBに保存するように
Browse files Browse the repository at this point in the history
  • Loading branch information
rito528 committed Oct 13, 2023
1 parent 0e67db5 commit ac157a1
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 13 deletions.
3 changes: 3 additions & 0 deletions server/domain/src/repository.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
pub mod form_repository;
pub mod user_repository;

pub trait Repositories: Send + Sync {
type ConcreteFormRepository: form_repository::FormRepository;
type ConcreteUserRepository: user_repository::UserRepository;

fn form_repository(&self) -> &Self::ConcreteFormRepository;
fn user_repository(&self) -> &Self::ConcreteUserRepository;
}
10 changes: 10 additions & 0 deletions server/domain/src/repository/user_repository.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::user::models::User;
use async_trait::async_trait;
use errors::Error;
use mockall::automock;

#[automock]
#[async_trait]
pub trait UserRepository: Send + Sync + 'static {
async fn upsert_user(&self, user: &User) -> Result<(), Error>;
}
5 changes: 4 additions & 1 deletion server/entrypoint/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ async fn main() -> anyhow::Result<()> {
.with_state(shared_repository.to_owned())
.route("/health", get(health_check))
.layer(layer)
.route_layer(middleware::from_fn(auth))
.route_layer(middleware::from_fn_with_state(
shared_repository.to_owned(),
auth,
))
.layer(
CorsLayer::new()
.allow_methods([Method::GET, Method::POST, Method::DELETE, Method::PATCH])
Expand Down
1 change: 1 addition & 0 deletions server/infra/resource/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pub mod components;
pub mod config;
pub mod connection;
pub mod form;
pub mod user;
8 changes: 8 additions & 0 deletions server/infra/resource/src/database/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ use crate::dto::{FormDto, PostedAnswersDto};
#[async_trait]
pub trait DatabaseComponents: Send + Sync {
type ConcreteFormDatabase: FormDatabase;
type ConcreteUserDatabase: UserDatabase;
type TransactionAcrossComponents: Send + Sync;

async fn begin_transaction(&self) -> anyhow::Result<Self::TransactionAcrossComponents>;
fn form(&self) -> &Self::ConcreteFormDatabase;
fn user(&self) -> &Self::ConcreteUserDatabase;
}

#[automock]
Expand All @@ -42,3 +44,9 @@ pub trait FormDatabase: Send + Sync {
async fn create_questions(&self, questions: FormQuestionUpdateSchema)
-> Result<(), InfraError>;
}

#[automock]
#[async_trait]
pub trait UserDatabase: Send + Sync {
async fn upsert_user(&self, user: &User) -> Result<(), InfraError>;
}
5 changes: 5 additions & 0 deletions server/infra/resource/src/database/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ impl ConnectionPool {
#[async_trait]
impl DatabaseComponents for ConnectionPool {
type ConcreteFormDatabase = Self;
type ConcreteUserDatabase = Self;
type TransactionAcrossComponents = DatabaseTransaction;

async fn begin_transaction(&self) -> anyhow::Result<Self::TransactionAcrossComponents> {
Expand All @@ -51,4 +52,8 @@ impl DatabaseComponents for ConnectionPool {
fn form(&self) -> &Self::ConcreteFormDatabase {
self
}

fn user(&self) -> &Self::ConcreteUserDatabase {
self
}
}
23 changes: 23 additions & 0 deletions server/infra/resource/src/database/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::database::components::UserDatabase;
use crate::database::connection::ConnectionPool;
use async_trait::async_trait;
use domain::user::models::User;
use errors::infra::InfraError;
use sea_orm::{ConnectionTrait, DatabaseBackend, Statement};

#[async_trait]
impl UserDatabase for ConnectionPool {
async fn upsert_user(&self, user: &User) -> Result<(), InfraError> {
self.pool
.execute(Statement::from_sql_and_values(
DatabaseBackend::MySql,
"INSERT INTO users (uuid, name) VALUES (UUID_TO_BIN(?), ?)
ON DUPLICATE KEY UPDATE
name = VALUES(name)",
[user.id.to_string().into(), user.name.to_owned().into()],
))
.await?;

Ok(())
}
}
6 changes: 6 additions & 0 deletions server/infra/resource/src/repository.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod form_repository_impl;
mod user_repository_impl;

use std::sync::Arc;

Expand Down Expand Up @@ -27,8 +28,13 @@ impl<Client: DatabaseComponents + 'static> Repository<Client> {

impl<Client: DatabaseComponents + 'static> Repositories for SharedRepository<Client> {
type ConcreteFormRepository = Repository<Client>;
type ConcreteUserRepository = Repository<Client>;

fn form_repository(&self) -> &Self::ConcreteFormRepository {
&self.0
}

fn user_repository(&self) -> &Self::ConcreteUserRepository {
&self.0
}
}
17 changes: 17 additions & 0 deletions server/infra/resource/src/repository/user_repository_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::database::components::UserDatabase;
use crate::{database::components::DatabaseComponents, repository::Repository};
use async_trait::async_trait;
use domain::repository::user_repository::UserRepository;
use domain::user::models::User;
use errors::Error;

#[async_trait]
impl<Client: DatabaseComponents + 'static> UserRepository for Repository<Client> {
async fn upsert_user(&self, user: &User) -> Result<(), Error> {
self.client
.user()
.upsert_user(user)
.await
.map_err(Into::into)
}
}
7 changes: 6 additions & 1 deletion server/migration/src/m20231008_135425_create_user_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ impl MigrationTrait for Migration {
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(UsersTable::Uuid).uuid().not_null())
.col(
ColumnDef::new(UsersTable::Uuid)
.uuid()
.unique_key()
.not_null(),
)
.col(ColumnDef::new(UsersTable::Name).string().not_null())
.to_owned(),
)
Expand Down
37 changes: 26 additions & 11 deletions server/presentation/src/auth.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use axum::extract::State;
use axum::{
extract::TypedHeader,
headers::authorization::{Authorization, Bearer},
Expand All @@ -6,25 +7,27 @@ use axum::{
response::Response,
};
use common::config::ENV;
use domain::repository::user_repository::UserRepository;
use domain::repository::Repositories;
use domain::user::models::User;
use reqwest::header::{ACCEPT, CONTENT_TYPE};
use resource::repository::RealInfrastructureRepository;
use usecase::user::UserUseCase;
use uuid::uuid;

pub async fn auth<B>(
State(repository): State<RealInfrastructureRepository>,
TypedHeader(auth): TypedHeader<Authorization<Bearer>>,
mut request: Request<B>,
next: Next<B>,
) -> Result<Response, StatusCode> {
let token = auth.token();

if ENV.name == "local" && token == "debug_user" {
let user = User {
let user = if ENV.name == "local" && token == "debug_user" {
User {
name: "test_user".to_string(),
id: uuid!("478911be-3356-46c1-936e-fb14b71bf282"),
};
request.extensions_mut().insert(user);
let response = next.run(request).await;
Ok(response)
}
} else {
let client = reqwest::Client::new();

Expand All @@ -37,17 +40,29 @@ pub async fn auth<B>(
.await
.map_err(|_| StatusCode::UNAUTHORIZED)?;

let user = serde_json::from_str::<User>(
serde_json::from_str::<User>(
response
.text()
.await
.map_err(|_| StatusCode::UNAUTHORIZED)?
.as_str(),
)
.map_err(|_| StatusCode::UNAUTHORIZED)?;
.map_err(|_| StatusCode::UNAUTHORIZED)?
};

request.extensions_mut().insert(user);
let response = next.run(request).await;
Ok(response)
let user_use_case = UserUseCase {
repository: repository.user_repository(),
};

match user_use_case.repository.upsert_user(&user).await {
Ok(_) => {
request.extensions_mut().insert(user);
let response = next.run(request).await;
Ok(response)
}
Err(err) => {
tracing::error!("{}", err);
Err(StatusCode::INTERNAL_SERVER_ERROR)
}
}
}
1 change: 1 addition & 0 deletions server/usecase/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod form;
pub mod user;
13 changes: 13 additions & 0 deletions server/usecase/src/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use domain::repository::user_repository::UserRepository;
use domain::user::models::User;
use errors::Error;

pub struct UserUseCase<'a, UserRepo: UserRepository> {
pub repository: &'a UserRepo,
}

impl<R: UserRepository> UserUseCase<'_, R> {
pub async fn upsert_user(&self, user: &User) -> Result<(), Error> {
self.repository.upsert_user(user).await
}
}

0 comments on commit ac157a1

Please sign in to comment.