diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/artist.rs | 6 | ||||
| -rw-r--r-- | src/artwork.rs | 14 | ||||
| -rw-r--r-- | src/build.rs | 8 | ||||
| -rw-r--r-- | src/comment.rs | 12 | ||||
| -rw-r--r-- | src/config.rs | 43 | ||||
| -rw-r--r-- | src/db/artworks.rs | 1 | ||||
| -rw-r--r-- | src/db/mod.rs | 20 | ||||
| -rw-r--r-- | src/error.rs | 30 | ||||
| -rw-r--r-- | src/file.rs | 7 | ||||
| -rw-r--r-- | src/lib.rs | 28 | ||||
| -rw-r--r-- | src/main.rs | 49 | ||||
| -rw-r--r-- | src/routes/admin.rs | 11 | ||||
| -rw-r--r-- | src/routes/artists.rs | 21 | ||||
| -rw-r--r-- | src/routes/artworks.rs | 23 | ||||
| -rw-r--r-- | src/routes/artworks/comments.rs | 11 | ||||
| -rw-r--r-- | src/routes/mod.rs | 3 | ||||
| -rw-r--r-- | src/ructe_poem.rs | 27 | 
17 files changed, 314 insertions, 0 deletions
| diff --git a/src/artist.rs b/src/artist.rs new file mode 100644 index 0000000..06b90e7 --- /dev/null +++ b/src/artist.rs @@ -0,0 +1,6 @@ +pub struct Artist { +    id: Option<usize>, +    name: String, +    bio: Option<String>, +    site: Option<String>, +} diff --git a/src/artwork.rs b/src/artwork.rs new file mode 100644 index 0000000..78b39af --- /dev/null +++ b/src/artwork.rs @@ -0,0 +1,14 @@ +pub struct Artwork { +    /// artwork id +    id: Option<usize>, +    /// name of the artwork +    title: Option<String>, +    /// description of the artwork +    description: Option<String>, +    /// source url of the artwork +    url_source: Option<String>, +    /// id of the artist +    artist_id: usize, +    /// ids of files +    files: Vec<usize>, +} diff --git a/src/build.rs b/src/build.rs new file mode 100644 index 0000000..16c887c --- /dev/null +++ b/src/build.rs @@ -0,0 +1,8 @@ +use ructe::{Result, Ructe}; + +fn main() -> Result<()> { +    let mut ructe = Ructe::from_env()?; +    ructe.statics()?.add_files("./static")?; +    // .add_sass_file("./style.scss")?; +    ructe.compile_templates("templates") +} diff --git a/src/comment.rs b/src/comment.rs new file mode 100644 index 0000000..77b0fc0 --- /dev/null +++ b/src/comment.rs @@ -0,0 +1,12 @@ +pub struct Comment { +    /// id of the comment in the thread +    id: Option<usize>, +    /// text of the comment +    text: String, +    /// thread comment is in +    thread: usize, +    /// comments that are mentioned by the comment +    in_reply_to: Vec<usize>, +    /// comments that mention the comment +    mentioned_by: Vec<usize>, +} diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..eee2fc2 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,43 @@ +use std::{ +    fs::File, +    io::Read, +    path::{Path, PathBuf}, +}; + +use serde::Deserialize; + +use crate::Result; + +#[derive(Deserialize, Clone)] +pub struct Config { +    admin_password: String, +    site_password: Option<String>, +    files_dir: std::path::PathBuf, +    database_connection: String, +} + +impl Config { +    pub fn from_file(path: &str) -> Result<Self> { +        let path = PathBuf::from(path); +        let mut config = String::new(); +        File::open(path)?.read_to_string(&mut config)?; +        let config: Config = toml::from_str(&config)?; +        Ok(config) +    } + +    pub fn admin_password(&self) -> &str { +        &self.admin_password +    } + +    pub fn site_password(&self) -> Option<&str> { +        self.site_password.as_deref() +    } + +    pub fn files_dir(&self) -> &Path { +        self.files_dir.as_path() +    } + +    pub fn database_connection(&self) -> &str { +        &self.database_connection +    } +} diff --git a/src/db/artworks.rs b/src/db/artworks.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/db/artworks.rs @@ -0,0 +1 @@ + diff --git a/src/db/mod.rs b/src/db/mod.rs new file mode 100644 index 0000000..97a5b25 --- /dev/null +++ b/src/db/mod.rs @@ -0,0 +1,20 @@ +use sqlx::{postgres::PgPoolOptions, Pool, Postgres}; + +mod artworks; + +#[derive(Clone)] +pub struct Database(Pool<Postgres>); + +impl Database { +    pub async fn new(connection_string: &str) -> Self { +        let pool = PgPoolOptions::new() +            .max_connections(5) +            .connect(connection_string) +            .await +            .unwrap(); + +        sqlx::migrate!("./migrations").run(&pool).await.unwrap(); + +        Self(pool) +    } +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..03cad93 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,30 @@ +use std::fmt::Display; + +#[derive(Debug)] +pub enum Error { +    IOError(std::io::Error), +    TOMLError(toml::de::Error), +} + +impl Display for Error { +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +        match self { +            Error::IOError(error) => write!(f, "IO Error: {}", error), +            Error::TOMLError(error) => write!(f, "TOML deserialization error: {}", error), +        } +    } +} + +impl std::error::Error for Error {} + +impl From<std::io::Error> for Error { +    fn from(e: std::io::Error) -> Self { +        Self::IOError(e) +    } +} + +impl From<toml::de::Error> for Error { +    fn from(e: toml::de::Error) -> Self { +        Self::TOMLError(e) +    } +} diff --git a/src/file.rs b/src/file.rs new file mode 100644 index 0000000..8a49839 --- /dev/null +++ b/src/file.rs @@ -0,0 +1,7 @@ +use uuid::Uuid; + +#[derive(sqlx::FromRow)] +pub struct File { +    id: Option<Uuid>, +    artwork: usize, +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..fc2ab75 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,28 @@ +use config::Config; +use db::Database; + +mod artist; +mod artwork; +mod comment; +pub mod config; +mod db; +mod error; +mod file; +pub mod routes; +mod ructe_poem; + +pub type Result<T> = std::result::Result<T, error::Error>; + +#[derive(Clone)] +pub struct Critch { +    db: Database, +    config: Config, +} + +impl Critch { +    pub async fn new(config: Config) -> Self { +        let db = Database::new(config.database_connection()).await; + +        Self { db, config } +    } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..639ba2d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,49 @@ +use poem::{delete, post, put, EndpointExt}; +use poem::{get, listener::TcpListener, Route, Server}; + +use critch::config::Config; +use critch::routes; +use critch::Critch; + +#[tokio::main] +async fn main() -> Result<(), std::io::Error> { +    let config = Config::from_file("./critch.toml").unwrap(); +    let state = Critch::new(config).await; + +    let app = Route::new() +        .at( +            "/admin", +            post(routes::admin::login).get(routes::admin::get_login_form), +        ) +        .at("/", get(routes::artworks::get)) +        .at( +            "/artworks", +            get(routes::artworks::get).post(routes::artworks::post), +        ) +        .at( +            "/artworks/:artwork", +            get(routes::artworks::get) +                .put(routes::artworks::put) +                .delete(routes::artworks::delete), +        ) +        .at( +            "/artists", +            get(routes::artists::get).post(routes::artists::post), +        ) +        .at( +            "/artists/:artist", +            get(routes::artists::get) +                .put(routes::artists::put) +                .delete(routes::artists::delete), +        ) +        .at( +            "/artworks/:artwork/comments", +            post(routes::artworks::comments::post).delete(routes::artworks::comments::delete), +        ) +        .data(state); + +    Server::new(TcpListener::bind("0.0.0.0:3000")) +        .run(app) +        .await?; +    Ok(()) +} diff --git a/src/routes/admin.rs b/src/routes/admin.rs new file mode 100644 index 0000000..98cb954 --- /dev/null +++ b/src/routes/admin.rs @@ -0,0 +1,11 @@ +use poem::handler; + +#[handler] +pub async fn login() { +    todo!() +} + +#[handler] +pub async fn get_login_form() { +    todo!() +} diff --git a/src/routes/artists.rs b/src/routes/artists.rs new file mode 100644 index 0000000..79a2ab1 --- /dev/null +++ b/src/routes/artists.rs @@ -0,0 +1,21 @@ +use poem::handler; + +#[handler] +pub async fn post() { +    todo!() +} + +#[handler] +pub async fn get() { +    todo!() +} + +#[handler] +pub async fn put() { +    todo!() +} + +#[handler] +pub async fn delete() { +    todo!() +} diff --git a/src/routes/artworks.rs b/src/routes/artworks.rs new file mode 100644 index 0000000..556265f --- /dev/null +++ b/src/routes/artworks.rs @@ -0,0 +1,23 @@ +use poem::{handler, web::Path}; + +pub mod comments; + +#[handler] +pub async fn post() { +    todo!() +} + +#[handler] +pub async fn get() { +    todo!() +} + +#[handler] +pub async fn put() { +    todo!() +} + +#[handler] +pub async fn delete() { +    todo!() +} diff --git a/src/routes/artworks/comments.rs b/src/routes/artworks/comments.rs new file mode 100644 index 0000000..dfac733 --- /dev/null +++ b/src/routes/artworks/comments.rs @@ -0,0 +1,11 @@ +use poem::handler; + +#[handler] +pub async fn post() { +    todo!() +} + +#[handler] +pub async fn delete() { +    todo!() +} diff --git a/src/routes/mod.rs b/src/routes/mod.rs new file mode 100644 index 0000000..fe8e0d1 --- /dev/null +++ b/src/routes/mod.rs @@ -0,0 +1,3 @@ +pub mod admin; +pub mod artists; +pub mod artworks; diff --git a/src/ructe_poem.rs b/src/ructe_poem.rs new file mode 100644 index 0000000..fc14048 --- /dev/null +++ b/src/ructe_poem.rs @@ -0,0 +1,27 @@ +use poem::{http::StatusCode, Body, IntoResponse}; + +macro_rules! render { +    ($template:path) => {{ +        use $crate::axum_ructe::Render; +        Render(|o| $template(o)) +    }}; +    ($template:path, $($arg:expr),* $(,)*) => {{ +        use $crate::axum_ructe::Render; +        Render(move |o| $template(o, $($arg),*)) +    }} +} + +pub struct Render<T: FnOnce(&mut Vec<u8>) -> std::io::Result<()> + Send>(pub T); + +impl<T: FnOnce(&mut Vec<u8>) -> std::io::Result<()> + Send> IntoResponse for Render<T> { +    fn into_response(self) -> poem::Response { +        let mut buf = Vec::new(); +        match self.0(&mut buf) { +            Ok(()) => Body::from_vec(buf).into_response(), +            Err(_e) => { +                // TODO: logging +                (StatusCode::INTERNAL_SERVER_ERROR, "Render failed").into_response() +            } +        } +    } +} | 
