Skip to content

Commit

Permalink
feat: add driver example
Browse files Browse the repository at this point in the history
  • Loading branch information
azzamsa committed Jul 20, 2023
1 parent eb2737e commit e76f8c0
Show file tree
Hide file tree
Showing 24 changed files with 103 additions and 49 deletions.
2 changes: 2 additions & 0 deletions db/migrations/20230720201940_add_email_to_user.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- Add migration script here
alter table user_ add column email text not null;
1 change: 1 addition & 0 deletions src/domain/user/entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct User {
pub created_at: Time,
pub updated_at: Time,
pub name: String,
pub email: String,
pub full_name: Option<String>,
}

Expand Down
4 changes: 4 additions & 0 deletions src/domain/user/model/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use crate::scalar::Id;
pub struct CreateUserInput {
/// The name for the User.
pub name: String,
/// The email for the User.
pub email: String,
/// The full name for the User.
pub full_name: Option<String>,
}
Expand All @@ -15,6 +17,8 @@ pub struct CreateUserInput {
pub struct UpdateUserInput {
/// The ID of the User to modify.
pub id: Id,
/// The email for the User.
pub email: String,
/// The name for the User.
pub name: String,
/// The full name for the User.
Expand Down
2 changes: 2 additions & 0 deletions src/domain/user/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub struct User {
pub id: Id,
pub created_at: Time,

/// The email for the User.
pub email: String,
/// The name for the User.
pub name: String,
/// The full name for the User.
Expand Down
3 changes: 2 additions & 1 deletion src/domain/user/repository/create_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ impl Repository {
user: &entities::User,
) -> Result<entities::User, crate::Error> {
const QUERY: &str = "insert into user_ (id, created_at, updated_at,
name, full_name) values ($1, $2, $3, $4, $5) returning *";
name, email, full_name) values ($1, $2, $3, $4, $5, $6) returning *";

match sqlx::query_as::<_, entities::User>(QUERY)
.bind(user.id)
.bind(user.created_at)
.bind(user.updated_at)
//
.bind(&user.name)
.bind(&user.email)
.bind(&user.full_name)
.fetch_one(db)
.await
Expand Down
4 changes: 3 additions & 1 deletion src/domain/user/repository/update_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ impl Repository {
const QUERY: &str = "update user_ set
updated_at = $2,
name = $3,
full_name = COALESCE($4, full_name)
email = $4,
full_name = COALESCE($5, full_name)
where id = $1 returning *";

match sqlx::query_as::<_, entities::User>(QUERY)
.bind(user.id)
.bind(user.updated_at)
//
.bind(&user.name)
.bind(&user.email)
.bind(&user.full_name)
.fetch_one(db)
.await
Expand Down
2 changes: 2 additions & 0 deletions src/domain/user/service/create_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ impl Service {
let user_input = entities::User {
id: Ulid::new().into(),
name: input.name,
email: input.email,
full_name: input.full_name,
created_at: Utc::now(),
updated_at: Utc::now(),
};

let user = self.repo.create_user(&self.db, &user_input).await?;
self.notify_user(&user.email).await?;

Ok(user)
}
Expand Down
10 changes: 7 additions & 3 deletions src/domain/user/service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,40 @@ mod create_user;
mod delete_user;
mod find_user;
mod find_users;
mod notify_user;
mod update_user;

use frunk::LabelledGeneric;
use uuid::Uuid;

use super::repository::Repository;
use crate::db::DB;
use crate::{db::DB, drivers::Mailer};

#[derive(Debug)]
pub struct Service {
repo: Repository,
pub db: DB,
mailer: Mailer,
}

impl Service {
pub fn new(db: DB) -> Self {
pub fn new(db: DB, mailer: Mailer) -> Self {
let repo = Repository::new();
Self { db, repo }
Self { db, repo, mailer }
}
}

#[derive(Debug, LabelledGeneric)]
pub struct CreateUserInput {
pub name: String,
pub email: String,
pub full_name: Option<String>,
}

#[derive(Debug, LabelledGeneric)]
pub struct UpdateUserInput {
pub id: Uuid,
pub name: String,
pub email: String,
pub full_name: Option<String>,
}
8 changes: 8 additions & 0 deletions src/domain/user/service/notify_user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use super::Service;

impl Service {
pub async fn notify_user(&self, email: &str) -> Result<(), crate::Error> {
self.mailer.send(email).await?;
Ok(())
}
}
1 change: 1 addition & 0 deletions src/domain/user/service/update_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ impl Service {
let user_input = entities::User {
id: input.id,
name: input.name,
email: input.email,
full_name: input.full_name,
updated_at: Utc::now(),
// FIXME
Expand Down
17 changes: 17 additions & 0 deletions src/drivers/mailer/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#[derive(Debug)]
pub struct Mailer {}

impl Default for Mailer {
fn default() -> Self {
Self::new()
}
}

impl Mailer {
pub fn new() -> Self {
Self {}
}
pub async fn send(&self, _email: &str) -> Result<(), crate::Error> {
Ok(())
}
}
3 changes: 3 additions & 0 deletions src/drivers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod mailer;

pub use mailer::Mailer;
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod config;
pub mod context;
pub mod db;
pub mod domain;
pub mod drivers;
mod errors;
pub mod logger;
pub mod relay;
Expand Down
6 changes: 4 additions & 2 deletions src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::{
context::ServerContext,
db,
domain::{health, meta, user},
drivers::mailer::Mailer,
routes,
schema::{AppSchema, Mutation, Query},
Error,
Expand All @@ -38,9 +39,10 @@ pub async fn app() -> Result<Router, Error> {
let db = db::connect(&config.database).await?;
db::migrate(&db).await?;

let user_service = Arc::new(user::Service::new(db.clone()));
let meta_service = Arc::new(meta::Service::new());
let health_service = Arc::new(health::Service::new());
let meta_service = Arc::new(meta::Service::new());
let mailer_service = Mailer::new();
let user_service = Arc::new(user::Service::new(db.clone(), mailer_service));

let server_context = Arc::new(ServerContext {
user_service,
Expand Down
12 changes: 12 additions & 0 deletions tests/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ input CreateUserInput {
"""
name: String!
"""
The email for the User.
"""
email: String!
"""
The full name for the User.
"""
fullName: String
Expand Down Expand Up @@ -68,6 +72,10 @@ input UpdateUserInput {
"""
id: UUID!
"""
The email for the User.
"""
email: String!
"""
The name for the User.
"""
name: String!
Expand All @@ -84,6 +92,10 @@ type User {
id: UUID!
createdAt: DateTime!
"""
The email for the User.
"""
email: String!
"""
The name for the User.
"""
name: String!
Expand Down
8 changes: 2 additions & 6 deletions tests/user/create_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,14 @@ use serde_json::{from_slice, to_string};
use tin::routes::app;
use tower::util::ServiceExt;

use super::teardown;
use super::{fake_user, teardown};
use super::{graphql::add, schema::CreateUserResponse};

#[tokio::test]
async fn create_user() -> Result<()> {
let app = app().await?;

let args = add::CreateUserInput {
name: "khawa".to_string(),
full_name: Some("Abu Musa Al-Khawarizmi".to_string()),
};
let query = add::UserMutation::build(args);
let query = add::UserMutation::build(fake_user());

let request = Request::builder()
.method(http::Method::POST)
Expand Down
1 change: 1 addition & 0 deletions tests/user/create_user_without_full_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ async fn create_user_without_full_name() -> Result<()> {

let args = add::CreateUserInput {
name: "khawa".to_string(),
email: "khawa@email.com".to_string(),
full_name: None,
};
let query = add::UserMutation::build(args);
Expand Down
9 changes: 2 additions & 7 deletions tests/user/delete_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use serde_json::{from_slice, to_string, Value};
use tin::routes::app;
use tower::{util::ServiceExt, Service};

use super::teardown;
use super::{fake_user, teardown};
use super::{
graphql::{
add, delete, queries,
Expand All @@ -24,12 +24,7 @@ async fn delete_user() -> Result<()> {
//
// Create User
//

let args = add::CreateUserInput {
name: "khawa".to_string(),
full_name: Some("Abu Musa Al-Khawarizmi".to_string()),
};
let query = add::UserMutation::build(args);
let query = add::UserMutation::build(fake_user());

let request = Request::builder()
.method(http::Method::POST)
Expand Down
25 changes: 7 additions & 18 deletions tests/user/duplicate_username.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,16 @@ use serde_json::{from_slice, to_string, Value};
use tin::routes::app;
use tower::{util::ServiceExt, Service};

use super::{fake_user, graphql::update, teardown};
use super::{graphql::add, schema::CreateUserResponse};
use super::{graphql::update, teardown};

#[tokio::test]
async fn duplicate_username_create() -> Result<()> {
let mut app = app().await?;
//
// Create User
//

let args = add::CreateUserInput {
name: "khawa".to_string(),
full_name: Some("Abu Musa Al-Khawarizmi".to_string()),
};
let query = add::UserMutation::build(args);
let query = add::UserMutation::build(fake_user());

let request = Request::builder()
.method(http::Method::POST)
Expand All @@ -36,11 +31,7 @@ async fn duplicate_username_create() -> Result<()> {
// Create next user with the same name
//

let args = add::CreateUserInput {
name: "khawa".to_string(),
full_name: None,
};
let query = add::UserMutation::build(args);
let query = add::UserMutation::build(fake_user());

let request = Request::builder()
.method(http::Method::POST)
Expand All @@ -66,11 +57,7 @@ async fn duplicate_username_update() -> Result<()> {
// Create User
//

let args = add::CreateUserInput {
name: "khawa".to_string(),
full_name: Some("Abu Musa Al-Khawarizmi".to_string()),
};
let query = add::UserMutation::build(args);
let query = add::UserMutation::build(fake_user());

let request = Request::builder()
.method(http::Method::POST)
Expand All @@ -87,7 +74,8 @@ async fn duplicate_username_update() -> Result<()> {

let args = add::CreateUserInput {
name: "khawa1".to_string(),
full_name: Some("Abu Musa Al-Khawarizmi".to_string()),
email: "khawa1@email.com".to_string(),
full_name: None,
};
let query = add::UserMutation::build(args);

Expand All @@ -112,6 +100,7 @@ async fn duplicate_username_update() -> Result<()> {
let args = update::UpdateUserInput {
id: user_id,
name: "khawa".to_string(),
email: "haitam@email.com".to_string(),
full_name: None,
};
let query = update::UserMutation::build(args);
Expand Down
Loading

0 comments on commit e76f8c0

Please sign in to comment.