From a5d9f049a9c76c84d2cbd78c0b6ead15a3f958f6 Mon Sep 17 00:00:00 2001 From: fef Date: Tue, 6 Dec 2022 00:29:24 +0100 Subject: [PATCH] add repository stuff --- src/data/account.rs | 21 +++++++++++++++++---- src/model/account.rs | 11 +++++++++-- src/repo/account.rs | 31 +++++++++++++++++++++++++++++++ src/repo/mod.rs | 19 +++++++++++++++++++ src/route/api/v1/accounts.rs | 13 +++++++------ src/state.rs | 8 ++++++-- 6 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 src/repo/account.rs create mode 100644 src/repo/mod.rs diff --git a/src/data/account.rs b/src/data/account.rs index fb971c4..1c1992c 100644 --- a/src/data/account.rs +++ b/src/data/account.rs @@ -1,9 +1,8 @@ -use log::*; use serde; use sqlx::{Executor, PgPool}; -use crate::core::{Id, Result}; -use crate::model::account::Account; +use crate::core::*; +use crate::model::account::{Account, NewAccount}; pub struct PgAccountDataSource { pool: PgPool, @@ -19,11 +18,25 @@ impl PgAccountDataSource { I: Into + Send, { let id: Id = id.into(); - debug!(target: "db", "Query accounts by id {}", id); let account: Account = sqlx::query_as("SELECT * FROM accounts WHERE id = $1") .bind(id) .fetch_one(&self.pool) .await?; Ok(account) } + + pub async fn create(&self, new: T) -> Result + where + T: Into + Send, + { + let new = new.into(); + let account: Account = + sqlx::query_as("INSERT INTO accounts (name, domain, display_name) VALUES ($1, $2, $3)") + .bind(new.name) + .bind(new.domain) + .bind(new.display_name) + .fetch_one(&self.pool) + .await?; + Ok(account) + } } diff --git a/src/model/account.rs b/src/model/account.rs index 5277b03..0e5c89b 100644 --- a/src/model/account.rs +++ b/src/model/account.rs @@ -8,9 +8,16 @@ use crate::core::Id; pub struct Account { pub id: Id, pub name: String, + pub domain: String, + pub display_name: Option, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, +} + +pub struct NewAccount { + pub name: String, + pub domain: String, pub display_name: Option, - pub created_at: DateTime, - pub updated_at: DateTime, } impl Into for Account { diff --git a/src/repo/account.rs b/src/repo/account.rs new file mode 100644 index 0000000..78f3315 --- /dev/null +++ b/src/repo/account.rs @@ -0,0 +1,31 @@ +use sqlx::PgPool; + +use crate::core::*; +use crate::data::account::PgAccountDataSource; +use crate::model::account::{Account, NewAccount}; + +pub struct AccountRepo { + db: PgAccountDataSource, +} + +impl AccountRepo { + pub fn new(db_pool: PgPool) -> AccountRepo { + AccountRepo { + db: PgAccountDataSource::new(db_pool), + } + } + + pub async fn by_id(&self, id: I) -> Result + where + I: Into + Send, + { + self.db.by_id(id).await + } + + pub async fn create(&self, new: T) -> Result + where + T: Into + Send, + { + self.db.create(new).await + } +} diff --git a/src/repo/mod.rs b/src/repo/mod.rs new file mode 100644 index 0000000..dc8013d --- /dev/null +++ b/src/repo/mod.rs @@ -0,0 +1,19 @@ +use sqlx::PgPool; + +pub mod account; +use account::AccountRepo; + +/// The central collection of all data accessible to the app. +/// This is included in `AppState` so it is accessible everywhere. +/// All interactions with resident data must happen through this interface. +pub struct AppRepo { + pub accounts: AccountRepo, +} + +impl AppRepo { + pub fn new(db_pool: PgPool) -> AppRepo { + AppRepo { + accounts: AccountRepo::new(db_pool), + } + } +} diff --git a/src/route/api/v1/accounts.rs b/src/route/api/v1/accounts.rs index c6e831a..0049735 100644 --- a/src/route/api/v1/accounts.rs +++ b/src/route/api/v1/accounts.rs @@ -1,13 +1,14 @@ -use crate::state::AppState; use actix_web::{get, web, HttpRequest, HttpResponse, Responder}; +use crate::core::*; +use crate::model::account::Account; +use crate::state::AppState; + #[get("/{id}")] -async fn get_by_id(path: web::Path, state: AppState) -> impl Responder { +async fn get_by_id(path: web::Path, state: AppState) -> Result { let id = path.into_inner(); - HttpResponse::Ok().body(format!( - "hello uid {}, listening on port {}", - id, state.config.bind_port - )) + let account = state.repo.accounts.by_id(id).await?; + Ok(HttpResponse::Ok().json(account)) } pub fn configure(cfg: &mut web::ServiceConfig) { diff --git a/src/state.rs b/src/state.rs index 8ae6079..bb71351 100644 --- a/src/state.rs +++ b/src/state.rs @@ -3,15 +3,19 @@ use sqlx::PgPool; use std::sync::Arc; use crate::conf::Config; +use crate::repo::AppRepo; pub struct State { pub config: Config, - pub db_pool: PgPool, + pub repo: AppRepo, } pub type AppStateRaw = Arc; pub type AppState = web::Data; pub fn new(config: Config, db_pool: PgPool) -> AppState { - web::Data::new(Arc::new(State { config, db_pool })) + web::Data::new(Arc::new(State { + config, + repo: AppRepo::new(db_pool), + })) }