diff --git a/backend/.env b/backend/.env index 42ab709..9a606a3 100644 --- a/backend/.env +++ b/backend/.env @@ -1 +1,2 @@ DATABASE_URL=postgres://user:password@localhost/db +API_KEY=helloworld diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 488c82a..f3b9dde 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -8,7 +8,7 @@ rocket = { version = "0.5.1", features = ["json"] } serde = { version = "1.0.228", features = ["derive"] } dotenv = "0.15.0" uuid = { version = "1.18.1", features = ["v4", "serde"] } -diesel = { version = "2.3.2", features = ["postgres", "uuid", "chrono"] } +diesel = { version = "2.3.2", features = ["postgres", "uuid", "chrono", "r2d2"] } chrono = "0.4.42" log = "0.4.28" fern = "0.7.1" diff --git a/backend/src/api/action.rs b/backend/src/api/action.rs new file mode 100644 index 0000000..9b841c3 --- /dev/null +++ b/backend/src/api/action.rs @@ -0,0 +1,34 @@ +use crate::auth::Authenticated; +use crate::dtos::action::ActionDTO; +use crate::models::action::Action; +use crate::models::{AppState, DEFAULT_QUERY_LIMIT}; +use crate::schema::actions::dsl::actions; +use diesel::{QueryDsl, RunQueryDsl, SelectableHelper}; +use rocket::State; +use rocket::http::Status; +use rocket::serde::json::Json; + +#[get("/?&")] +pub fn index( + offset: Option, + limit: Option, + _auth: Authenticated, + state: &State, +) -> Result>, Status> { + let mut db = state.db.get().unwrap(); + + let offset = offset.unwrap_or(0); + let limit = limit.unwrap_or(DEFAULT_QUERY_LIMIT); + + let results = actions + .offset(offset) + .limit(limit) + .select(Action::as_select()) + .load(&mut db) + .ok(); + + match results { + Some(results) => Ok(Json(results.iter().map(ActionDTO::from).collect())), + None => Err(Status::InternalServerError), + } +} diff --git a/backend/src/api/mod.rs b/backend/src/api/mod.rs new file mode 100644 index 0000000..e9a6726 --- /dev/null +++ b/backend/src/api/mod.rs @@ -0,0 +1 @@ +pub mod action; diff --git a/backend/src/dtos/action.rs b/backend/src/dtos/action.rs new file mode 100644 index 0000000..d0041d7 --- /dev/null +++ b/backend/src/dtos/action.rs @@ -0,0 +1,23 @@ +use crate::models::action::Action; +use serde::Serialize; + +#[derive(Serialize)] +pub struct ActionDTO { + pub id: String, + pub name: String, + pub source: String, + pub created_at: String, + pub updated_at: String, +} + +impl ActionDTO { + pub fn from(action: &Action) -> Self { + Self { + id: action.id.to_string(), + name: action.name.clone(), + source: action.source.clone(), + created_at: action.created_at.to_string(), + updated_at: action.updated_at.to_string(), + } + } +} diff --git a/backend/src/dtos/mod.rs b/backend/src/dtos/mod.rs new file mode 100644 index 0000000..e9a6726 --- /dev/null +++ b/backend/src/dtos/mod.rs @@ -0,0 +1 @@ +pub mod action; diff --git a/backend/src/main.rs b/backend/src/main.rs index ddb3dc7..ef37107 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -1,15 +1,18 @@ +extern crate fern; +extern crate log; +#[macro_use] +extern crate rocket; +mod api; mod auth; +mod dtos; mod models; mod schema; -#[macro_use] -extern crate rocket; -extern crate fern; -extern crate log; - +use crate::api::action; use auth::CORS; use chrono::Local; -use diesel::{Connection, PgConnection}; +use diesel::PgConnection; +use diesel::r2d2::{ConnectionManager, Pool}; use models::AppState; use rocket::State; use std::env; @@ -42,7 +45,7 @@ fn setup_logging(log_file: Option) -> Result<(), fern::InitError> { } #[get("/")] -fn index(state: &State) -> String { +fn index(_state: &State) -> String { "Hello world!".to_string() } @@ -54,12 +57,15 @@ fn rocket() -> _ { setup_logging(log_file).expect("Failed to setup logging"); let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); - let db = PgConnection::establish(&database_url) - .expect(&format!("Error connecting to {}", database_url)); + let manager = ConnectionManager::::new(database_url); + let pool = Pool::builder() + .build(manager) + .expect("Failed to create pool"); - let app_data = AppState::new(db); + let app_data = AppState::new(pool); rocket::build() .manage(app_data) .attach(CORS {}) .mount("/", routes![index]) + .mount("/action", routes![action::index]) } diff --git a/backend/src/models/mod.rs b/backend/src/models/mod.rs index 51bb773..f67694a 100644 --- a/backend/src/models/mod.rs +++ b/backend/src/models/mod.rs @@ -1,16 +1,16 @@ +use diesel::r2d2::{ConnectionManager, Pool}; use diesel::PgConnection; -use std::sync::{Arc, Mutex}; -mod action; +pub const DEFAULT_QUERY_LIMIT: i64 = 100; + +pub mod action; pub struct AppState { - pub db: Arc>, + pub db: Pool>, } impl AppState { - pub fn new(db: PgConnection) -> Self { - Self { - db: Arc::new(Mutex::new(db)), - } + pub fn new(pool: Pool>) -> Self { + Self { db: pool } } }