chore: remove unused files and imports
							parent
							
								
									c7dc68926b
								
							
						
					
					
						commit
						3568365c6f
					
				
							
								
								
									
										112
									
								
								src/db/event.rs
								
								
								
								
							
							
						
						
									
										112
									
								
								src/db/event.rs
								
								
								
								
							|  | @ -1,112 +0,0 @@ | |||
| use std::{fmt::Display, str::FromStr}; | ||||
| 
 | ||||
| use chrono::NaiveDate; | ||||
| use r2d2_sqlite::rusqlite::{ | ||||
|     self, | ||||
|     types::{FromSql, FromSqlError}, | ||||
|     Row, ToSql, | ||||
| }; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use super::{DbError, DbPool}; | ||||
| 
 | ||||
| pub const EVENT_TYPES: [&str; 1] = ["Watering"]; | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize)] | ||||
| pub enum EventType { | ||||
|     Watering, | ||||
| } | ||||
| 
 | ||||
| impl ToString for EventType { | ||||
|     fn to_string(&self) -> String { | ||||
|         String::from(match self { | ||||
|             Self::Watering => "watering", | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct ParseEventTypeErr; | ||||
| 
 | ||||
| impl Display for ParseEventTypeErr { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "invalid name") | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl std::error::Error for ParseEventTypeErr {} | ||||
| 
 | ||||
| impl FromStr for EventType { | ||||
|     type Err = ParseEventTypeErr; | ||||
| 
 | ||||
|     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||
|         match s { | ||||
|             "watering" => Ok(Self::Watering), | ||||
|             _ => Err(ParseEventTypeErr), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ToSql for EventType { | ||||
|     fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> { | ||||
|         Ok(self.to_string().into()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromSql for EventType { | ||||
|     fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> { | ||||
|         value | ||||
|             .as_str()? | ||||
|             .parse() | ||||
|             .map_err(|e| FromSqlError::Other(Box::new(e))) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Serialize)] | ||||
| pub struct Event { | ||||
|     id: i64, | ||||
|     plant_id: i64, | ||||
|     event_type: EventType, | ||||
|     date: NaiveDate, | ||||
|     description: String, | ||||
| } | ||||
| 
 | ||||
| impl Event { | ||||
|     pub fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> { | ||||
|         Ok(Self { | ||||
|             id: row.get("id")?, | ||||
|             plant_id: row.get("plant_id")?, | ||||
|             event_type: row.get("event_type")?, | ||||
|             date: row.get("date")?, | ||||
|             description: row.get("description")?, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Deserialize)] | ||||
| pub struct NewEvent { | ||||
|     plant_id: i64, | ||||
|     event_type: EventType, | ||||
|     date: NaiveDate, | ||||
|     description: String, | ||||
| } | ||||
| 
 | ||||
| impl NewEvent { | ||||
|     pub fn insert(self, pool: &DbPool) -> Result<Event, DbError> { | ||||
|         let conn = pool.get()?; | ||||
| 
 | ||||
|         let mut stmt = conn.prepare( | ||||
|             "insert into events (plant_id, event_type, date, description) values ($1, $2, $3, $4) returning *", | ||||
|         )?; | ||||
| 
 | ||||
|         Ok(stmt.query_row( | ||||
|             ( | ||||
|                 &self.plant_id, | ||||
|                 &self.event_type, | ||||
|                 &self.date, | ||||
|                 &self.description, | ||||
|             ), | ||||
|             Event::from_row, | ||||
|         )?) | ||||
|     } | ||||
| } | ||||
|  | @ -2,21 +2,19 @@ mod models; | |||
| mod schema; | ||||
| 
 | ||||
| use diesel::{ | ||||
|     prelude::*, | ||||
|     r2d2::{ConnectionManager, Pool, PooledConnection}, | ||||
|     r2d2::{ConnectionManager, Pool}, | ||||
|     SqliteConnection, | ||||
| }; | ||||
| use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; | ||||
| 
 | ||||
| use std::{error::Error, fmt, path::Path}; | ||||
| 
 | ||||
| pub use models::event::{Event, EventType, NewEvent, EVENT_TYPES}; | ||||
| pub use models::event::{Event, NewEvent, EVENT_TYPES}; | ||||
| pub use models::plant::{NewPlant, Plant}; | ||||
| pub use models::session::Session; | ||||
| pub use models::user::{NewUser, User}; | ||||
| 
 | ||||
| pub type DbPool = Pool<ConnectionManager<SqliteConnection>>; | ||||
| pub type DbConn = PooledConnection<ConnectionManager<SqliteConnection>>; | ||||
| pub type DbResult<T> = Result<T, DbError>; | ||||
| 
 | ||||
| pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations"); | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ use argon2::{ | |||
| use diesel::prelude::*; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use crate::db::{schema::*, DbConn, DbPool, DbResult}; | ||||
| use crate::db::{schema::*, DbPool, DbResult}; | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize, Clone, Queryable, Selectable)] | ||||
| #[diesel(table_name = users)] | ||||
|  |  | |||
|  | @ -1,73 +0,0 @@ | |||
| use r2d2_sqlite::rusqlite::{self, Row}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use super::{DbError, DbPool, Event}; | ||||
| 
 | ||||
| #[derive(Serialize)] | ||||
| pub struct Plant { | ||||
|     id: i64, | ||||
|     name: String, | ||||
|     species: String, | ||||
|     description: String, | ||||
| } | ||||
| 
 | ||||
| #[derive(Deserialize)] | ||||
| pub struct NewPlant { | ||||
|     name: String, | ||||
|     species: String, | ||||
|     description: String, | ||||
| } | ||||
| 
 | ||||
| impl Plant { | ||||
|     pub fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> { | ||||
|         Ok(Self { | ||||
|             id: row.get(0)?, | ||||
|             name: row.get(1)?, | ||||
|             species: row.get(2)?, | ||||
|             description: row.get(3)?, | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn all(pool: &DbPool) -> Result<Vec<Self>, DbError> { | ||||
|         let conn = pool.get()?; | ||||
| 
 | ||||
|         let mut stmt = conn.prepare("select * from plants")?; | ||||
|         let plants: Result<Vec<_>, _> = stmt.query_map((), Self::from_row)?.collect(); | ||||
| 
 | ||||
|         Ok(plants?) | ||||
|     } | ||||
| 
 | ||||
|     pub fn by_id(pool: &DbPool, id: i64) -> Result<Option<Self>, DbError> { | ||||
|         let conn = pool.get()?; | ||||
| 
 | ||||
|         let mut stmt = conn.prepare("select * from plants where id = $1")?; | ||||
|         match stmt.query_row((id,), |row| Plant::from_row(row)) { | ||||
|             Ok(plant) => Ok(Some(plant)), | ||||
|             Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None), | ||||
|             Err(err) => Err(DbError::Db(err)), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn events(&self, pool: &DbPool) -> Result<Vec<Event>, DbError> { | ||||
|         let conn = pool.get()?; | ||||
|         let mut stmt = conn.prepare("select * from events where plant_id = $1")?; | ||||
| 
 | ||||
|         let events: Result<Vec<_>, _> = stmt.query_map((self.id,), Event::from_row)?.collect(); | ||||
|         Ok(events?) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl NewPlant { | ||||
|     pub fn insert(self, pool: &DbPool) -> Result<Plant, DbError> { | ||||
|         let conn = pool.get()?; | ||||
| 
 | ||||
|         let mut stmt = conn.prepare( | ||||
|             "insert into plants (name, species, description) values ($1, $2, $3) returning *", | ||||
|         )?; | ||||
| 
 | ||||
|         Ok(stmt.query_row( | ||||
|             (&self.name, &self.species, &self.description), | ||||
|             Plant::from_row, | ||||
|         )?) | ||||
|     } | ||||
| } | ||||
|  | @ -1,39 +0,0 @@ | |||
| use rand::Rng; | ||||
| use rusqlite::Row; | ||||
| 
 | ||||
| use super::{DbError, DbPool, User}; | ||||
| 
 | ||||
| pub struct Session { | ||||
|     pub id: i64, | ||||
|     pub user_id: i32, | ||||
| } | ||||
| 
 | ||||
| impl Session { | ||||
|     pub fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> { | ||||
|         Ok(Self { | ||||
|             id: row.get("id")?, | ||||
|             user_id: row.get("user_id")?, | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn user_from_id(pool: &DbPool, id: i64) -> Result<Option<super::User>, DbError> { | ||||
|         let conn = pool.get()?; | ||||
| 
 | ||||
|         let mut stmt = conn.prepare("select users.* from sessions inner join users on sessions.user_id = users.id where sessions.id = $1")?; | ||||
|         match stmt.query_row((id,), User::from_row) { | ||||
|             Ok(user) => Ok(Some(user)), | ||||
|             Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None), | ||||
|             Err(err) => Err(DbError::Db(err)), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn new_for_user(pool: &DbPool, user_id: i64) -> Result<Self, DbError> { | ||||
|         let id: i64 = rand::thread_rng().gen(); | ||||
| 
 | ||||
|         let conn = pool.get()?; | ||||
|         let mut stmt = | ||||
|             conn.prepare("insert into sessions (id, user_id) values ($1, $2) returning *")?; | ||||
| 
 | ||||
|         Ok(stmt.query_row((&id, &user_id), Self::from_row)?) | ||||
|     } | ||||
| } | ||||
|  | @ -1,94 +0,0 @@ | |||
| use argon2::{ | ||||
|     password_hash::{rand_core::OsRng, SaltString}, | ||||
|     Argon2, PasswordHash, PasswordHasher, PasswordVerifier, | ||||
| }; | ||||
| use rusqlite::Row; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use super::{DbError, DbPool}; | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize, Clone)] | ||||
| pub struct User { | ||||
|     pub id: i64, | ||||
|     pub username: String, | ||||
|     pub password_hash: String, | ||||
|     pub admin: bool, | ||||
| } | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize)] | ||||
| pub struct NewUser { | ||||
|     pub username: String, | ||||
|     pub password: String, | ||||
|     pub admin: bool, | ||||
| } | ||||
| 
 | ||||
| impl User { | ||||
|     pub fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> { | ||||
|         Ok(Self { | ||||
|             id: row.get("id")?, | ||||
|             username: row.get("username")?, | ||||
|             password_hash: row.get("password_hash")?, | ||||
|             admin: row.get("admin")?, | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn by_username(pool: &DbPool, username: impl AsRef<str>) -> Result<Option<Self>, DbError> { | ||||
|         let conn = pool.get()?; | ||||
| 
 | ||||
|         let mut stmt = conn.prepare("select * from users where username = $1")?; | ||||
| 
 | ||||
|         match stmt.query_row((username.as_ref(),), User::from_row) { | ||||
|             Ok(user) => Ok(Some(user)), | ||||
|             Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None), | ||||
|             Err(err) => Err(DbError::Db(err)), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn verify_password(&self, password: impl AsRef<str>) -> bool { | ||||
|         let password_hash = PasswordHash::new(&self.password_hash).unwrap(); | ||||
| 
 | ||||
|         Argon2::default() | ||||
|             .verify_password(password.as_ref().as_bytes(), &password_hash) | ||||
|             .is_ok() | ||||
|     } | ||||
| 
 | ||||
|     pub fn all(pool: &DbPool) -> Result<Vec<Self>, DbError> { | ||||
|         let conn = pool.get()?; | ||||
| 
 | ||||
|         let mut stmt = conn.prepare("select * from users")?; | ||||
|         let users: Result<Vec<_>, _> = stmt.query_map((), Self::from_row)?.collect(); | ||||
| 
 | ||||
|         Ok(users?) | ||||
|     } | ||||
| 
 | ||||
|     pub fn remove_by_username(pool: &DbPool, username: impl AsRef<str>) -> Result<bool, DbError> { | ||||
|         let conn = pool.get()?; | ||||
|         let mut stmt = conn.prepare("delete from users where username = $1")?; | ||||
| 
 | ||||
|         Ok(stmt.execute((username.as_ref(),))? > 0) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn hash_password(password: impl AsRef<str>) -> String { | ||||
|     let salt = SaltString::generate(&mut OsRng); | ||||
|     let argon2 = Argon2::default(); | ||||
| 
 | ||||
|     argon2 | ||||
|         .hash_password(password.as_ref().as_bytes(), &salt) | ||||
|         .unwrap() | ||||
|         .to_string() | ||||
| } | ||||
| 
 | ||||
| impl NewUser { | ||||
|     pub fn insert(self, pool: &DbPool) -> Result<User, DbError> { | ||||
|         let conn = pool.get()?; | ||||
| 
 | ||||
|         let password_hash = hash_password(&self.password); | ||||
| 
 | ||||
|         let mut stmt = conn.prepare( | ||||
|             "insert into users (username, password_hash, admin) values ($1, $2, $3) returning *", | ||||
|         )?; | ||||
| 
 | ||||
|         Ok(stmt.query_row((&self.username, password_hash, &self.admin), User::from_row)?) | ||||
|     } | ||||
| } | ||||
|  | @ -5,7 +5,6 @@ mod server; | |||
| use std::{fs, path::Path, sync::Arc}; | ||||
| 
 | ||||
| use clap::Parser; | ||||
| use diesel_migrations::{embed_migrations, EmbeddedMigrations}; | ||||
| use tera::Tera; | ||||
| use tower_http::compression::CompressionLayer; | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ use axum::{ | |||
|     http::{HeaderMap, StatusCode}, | ||||
|     middleware::Next, | ||||
|     response::{Html, IntoResponse, Response}, | ||||
|     routing::{get, post}, | ||||
|     routing::post, | ||||
|     Form, Router, | ||||
| }; | ||||
| use axum_extra::extract::{ | ||||
|  | @ -11,11 +11,10 @@ use axum_extra::extract::{ | |||
|     CookieJar, | ||||
| }; | ||||
| use serde::Deserialize; | ||||
| use tera::Context; | ||||
| 
 | ||||
| use crate::db::{DbError, DbPool, Session, User}; | ||||
| 
 | ||||
| use super::{error::AppError, render_view}; | ||||
| use super::error::AppError; | ||||
| 
 | ||||
| pub fn logged_in_user(pool: &DbPool, headers: &HeaderMap) -> Result<Option<User>, DbError> { | ||||
|     let jar = CookieJar::from_headers(headers); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue