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