State implementation and initial db work

State system is fully implemented and passing tests. I added in a
handful of unit tests to test most of the available operations.

Other work has involved getting the interface between client and server
right and starting on the actual message handler. This involves starting
work on the db as well
This commit is contained in:
2026-05-24 22:53:52 -07:00
parent c92ee309a9
commit eaeb293915
8 changed files with 1639 additions and 242 deletions
+66
View File
@@ -1,2 +1,68 @@
use diesel::prelude::*;
pub mod models;
pub mod schema;
use bcrypt::{DEFAULT_COST, hash, verify};
use diesel_async::AsyncPgConnection;
use diesel_async::RunQueryDsl;//, AsyncConnection};
use diesel_async::pooled_connection::deadpool::Object;
use fedichat::client::{ServerMessage,ServerError};
use tracing::{instrument,warn};
#[instrument(skip_all)]
pub async fn maybe_create_user(mut connection: Object<AsyncPgConnection>, username: &str, password: &str) -> Result<ServerMessage,ServerError> {
let password = match hash(password,DEFAULT_COST) {
Ok(val) => val,
Err(e) => {
warn!("Error encountered while generating password hash");
warn!("{e}");
return Err(ServerError::Generic)
}
};
let username = username.to_string();
let user = models::NewUser{ username, password};
let result = diesel::insert_into(schema::users::table)
.values(&user)
.execute(&mut *connection)
.await;
match result {
// TODO: might need to check this? I don't know what it means
Ok(_) => Ok(ServerMessage::Ok),
// TODO: Probably actually check the error
Err(_e) => Err(ServerError::UserAlreadyExists)
}
}
/// Try to authenticate a user against information in the database
#[instrument(skip_all)]
pub async fn verify_user(mut connection: Object<AsyncPgConnection>, user: &str, pass: &str) -> Result<bool,ServerError> {
use schema::users::dsl::*;
let result = users
.filter(username.eq(user))
.select(models::User::as_select())
.first(&mut *connection)
.await;
match result {
// If we have more than 0 rows then authentication is successful
Ok(user) => match verify(pass,&user.password) {
Ok(val) => Ok(val),
Err(e) => {
warn!("Error encountered while generating password hash");
warn!("{e}");
return Err(ServerError::Generic)
}
},
// TODO: Probably actually check the error
_ => Err(ServerError::AuthenticationFailed)
}
}
+7
View File
@@ -55,6 +55,13 @@ pub struct User {
pub password: String,
}
#[derive(Insertable)]
#[diesel(table_name = crate::db::schema::users)]
pub struct NewUser {
pub username: String,
pub password: String,
}
#[derive(Queryable, Selectable)]
#[diesel(table_name = crate::db::schema::messages)]
pub struct Messages {