feat: rewrite user model using diesel

image-uploads
Jef Roosens 2025-01-13 13:43:09 +01:00
parent 18a321853a
commit 77995ebec9
No known key found for this signature in database
GPG Key ID: 21FD3D77D56BAF49
10 changed files with 97 additions and 17 deletions

1
Cargo.lock generated
View File

@ -579,6 +579,7 @@ checksum = "ccf1bedf64cdb9643204a36dd15b19a6ce8e7aa7f7b105868e9f1fad5ffa7d12"
dependencies = [
"diesel_derives",
"libsqlite3-sys",
"r2d2",
"time",
]

View File

@ -13,7 +13,7 @@ axum = { version = "0.8.0", features = ["macros"] }
axum-extra = { version = "0.10.0", features = ["cookie"] }
chrono = { version = "0.4.39", features = ["serde"] }
clap = { version = "4.5.26", features = ["derive", "env"] }
diesel = { version = "2.2.6", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] }
diesel = { version = "2.2.6", features = ["sqlite", "returning_clauses_for_sqlite_3_35", "r2d2"] }
r2d2 = "0.8.10"
r2d2_sqlite = "0.25.0"
rand = "0.8.5"

View File

@ -1,5 +1,5 @@
create table plants (
id integer primary key not null,
id bigint primary key not null,
name text not null,
species text not null,
description text not null

View File

@ -1,5 +1,7 @@
create table comments (
id integer primary key not null,
plant_id integer references plants (id),
id bigint primary key not null,
plant_id bigint not null
references plants (id)
on delete cascade,
comment text not null
);

View File

@ -1,6 +1,6 @@
create table events (
id integer primary key not null,
plant_id integer not null
id bigint primary key not null,
plant_id bigint not null
references plants (id)
on delete cascade,
event_type text not null,

View File

@ -1,13 +1,13 @@
create table users (
id integer primary key not null,
id bigint primary key not null,
username text unique not null,
password_hash text not null,
admin boolean not null
);
create table sessions (
id integer primary key not null,
user_id integer not null
id bigint primary key not null,
user_id bigint not null
references users (id)
on delete cascade,
unique (id, user_id)

View File

@ -1,5 +1,6 @@
mod comment;
mod event;
mod models;
mod plant;
mod schema;
mod session;

View File

@ -0,0 +1 @@
mod user;

View File

@ -0,0 +1,75 @@
use argon2::{
password_hash::{rand_core::OsRng, SaltString},
Argon2, PasswordHash, PasswordHasher, PasswordVerifier,
};
use diesel::prelude::*;
use serde::{Deserialize, Serialize};
use crate::db::schema::*;
#[derive(Serialize, Deserialize, Clone, Queryable, Selectable)]
#[diesel(table_name = users)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct User {
pub id: i64,
pub username: String,
pub password_hash: String,
pub admin: bool,
}
#[derive(Deserialize, Insertable)]
#[diesel(table_name = users)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct NewUser {
pub username: String,
pub password_hash: String,
pub admin: bool,
}
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 new(username: String, password: String, admin: bool) -> Self {
Self {
username,
password_hash: hash_password(&password),
admin,
}
}
pub fn insert(self, conn: &mut SqliteConnection) -> QueryResult<User> {
diesel::insert_into(users::table)
.values(self)
.returning(User::as_returning())
.get_result(conn)
}
}
impl User {
pub fn by_username(
conn: &mut SqliteConnection,
username: impl AsRef<str>,
) -> QueryResult<Option<Self>> {
users::dsl::users
.select(User::as_select())
.filter(users::username.eq(username.as_ref()))
.first(conn)
.optional()
}
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()
}
}

View File

@ -2,16 +2,16 @@
diesel::table! {
comments (id) {
id -> Integer,
plant_id -> Nullable<Integer>,
id -> BigInt,
plant_id -> BigInt,
comment -> Text,
}
}
diesel::table! {
events (id) {
id -> Integer,
plant_id -> Integer,
id -> BigInt,
plant_id -> BigInt,
event_type -> Text,
date -> Text,
description -> Text,
@ -20,7 +20,7 @@ diesel::table! {
diesel::table! {
plants (id) {
id -> Integer,
id -> BigInt,
name -> Text,
species -> Text,
description -> Text,
@ -29,14 +29,14 @@ diesel::table! {
diesel::table! {
sessions (id) {
id -> Integer,
user_id -> Integer,
id -> BigInt,
user_id -> BigInt,
}
}
diesel::table! {
users (id) {
id -> Integer,
id -> BigInt,
username -> Text,
password_hash -> Text,
admin -> Bool,