Add SQLite database support and user management functionality
This commit is contained in:
parent
6ebdef9a64
commit
8df02b7a5a
8 changed files with 1362 additions and 9 deletions
1277
Cargo.lock
generated
1277
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -18,3 +18,4 @@ toml = "0.8.19"
|
|||
ratatui = "0.29.0"
|
||||
crossterm = "0.28.1"
|
||||
chrono = "0.4.39"
|
||||
sqlx = { version = "0.8", features = [ "sqlite", "runtime-tokio", "tls-native-tls" ] }
|
25
README.md
Normal file
25
README.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# SRC (Simple Rust Chat)
|
||||
|
||||
Simple Rust Chat è una chat Client/Server che permette di fare le seguenti azioni:
|
||||
- Chattare con altri utenti in canali per topic
|
||||
- Chattare con una persona sola (DMs)
|
||||
- Inviare i file tra utenti
|
||||
- Possibilità di amministrare la chat con comandi di /kick o /ban
|
||||
|
||||
La chat è basata molto sull'idea di una chat IRC (inizialmente il progetto aveva come scopo la creazione di un server IRC da utilizzare con dei clienti IRC come Halloy o mIRC)
|
||||
|
||||
## Protocolli utilizzati
|
||||
|
||||
Il server utilizza TCP/IP come protocollo per la trasmissione dei dati in rete. I pacchetti sono composti da un pacchetto prestabilito
|
||||
|
||||
```
|
||||
/*
|
||||
Specifications of the packet
|
||||
32 bytes - Command name
|
||||
512 bytes - Command argument
|
||||
if command is empty then it is a message
|
||||
*/
|
||||
```
|
||||
|
||||
La chat è sicura usando x25519-dalek e AES-128 per criptare i messaggi e i dati dei file che vengono inviati. Lo scambio di chiavi viene effettuato con Diffie Hellman
|
||||
|
BIN
db.sqlite
Normal file
BIN
db.sqlite
Normal file
Binary file not shown.
9
migrations/001_create_users_table.sql
Normal file
9
migrations/001_create_users_table.sql
Normal file
|
@ -0,0 +1,9 @@
|
|||
-- Create the users table
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT, -- Unique ID for each user
|
||||
username TEXT NOT NULL UNIQUE, -- Username, must be unique
|
||||
password_hash TEXT NOT NULL -- Hashed password for security
|
||||
);
|
||||
|
||||
-- Create an index on the username and email columns for faster lookups
|
||||
CREATE INDEX IF NOT EXISTS idx_users_username ON users (username);
|
|
@ -7,11 +7,13 @@ pub(crate) mod handlers {
|
|||
use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};
|
||||
use log::{debug, error, info};
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::broadcast;
|
||||
use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||
|
||||
use crate::db::users::create_user;
|
||||
/*
|
||||
Specifications of the packet
|
||||
32 bytes - Command name
|
||||
|
@ -81,9 +83,11 @@ pub(crate) mod handlers {
|
|||
let decrypted = cipher_reader
|
||||
.decrypt(&nonce_reader, decoded.as_ref())
|
||||
.unwrap();
|
||||
let username = String::from_utf8(decrypted)?;
|
||||
let username_read = username.clone(); // Clone for read task
|
||||
let mut username_write = username.clone(); // Clone for write task
|
||||
let username = Arc::new(String::from_utf8(decrypted)?);
|
||||
let username_read = Arc::clone(&username); // Clone the Arc for read task
|
||||
let username_write = Arc::clone(&username); // Clone the Arc for write task
|
||||
|
||||
create_user(&username, "1234").await?;
|
||||
|
||||
// Read task for receiving messages from the client
|
||||
let read_task = tokio::spawn(async move {
|
||||
|
@ -160,12 +164,20 @@ pub(crate) mod handlers {
|
|||
}
|
||||
let new_nickname = &parsed_message.argument[0];
|
||||
info!("Changing nickname to: {}", new_nickname);
|
||||
username_write = new_nickname.clone();
|
||||
// Here implement your nickname change logic
|
||||
}
|
||||
|
||||
_ => {
|
||||
error!("Unknown command: {}", parsed_message.command[0]);
|
||||
match tx.send("Error! Unknown command".to_string()) {
|
||||
Ok(_) => {
|
||||
info!("Error message sent to client {}", username_write)
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to send error message: {:?}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
30
src/db/mod.rs
Normal file
30
src/db/mod.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
pub(crate) mod users {
|
||||
use sqlx::sqlite::SqlitePool;
|
||||
|
||||
pub async fn connect_to_db() -> Result<SqlitePool, sqlx::Error> {
|
||||
let pool = SqlitePool::connect("sqlite:./db.sqlite").await?;
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
pub async fn create_db_pool() -> Result<SqlitePool, sqlx::Error> {
|
||||
let pool = connect_to_db().await?;
|
||||
sqlx::migrate!("./migrations").run(&pool).await?;
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
pub async fn create_user(username: &str, password_hash: &str) -> Result<(), sqlx::Error> {
|
||||
let pool = create_db_pool().await?;
|
||||
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO users (username, password_hash)
|
||||
VALUES (?, ?)
|
||||
"#,
|
||||
)
|
||||
.bind(username)
|
||||
.bind(password_hash)
|
||||
.execute(&pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
mod client;
|
||||
mod tui; // Add this new module
|
||||
mod db;
|
||||
|
||||
use client::handlers::handle_client;
|
||||
use db::users::create_db_pool;
|
||||
use log::{error, info, Level, Log, Metadata, Record};
|
||||
use serde::Deserialize;
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use std::{process::exit, sync::mpsc};
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::sync::broadcast;
|
||||
use tui::{run_app, LogEntry};
|
||||
|
@ -43,6 +45,8 @@ impl Log for CustomLogger {
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
create_db_pool().await.unwrap();
|
||||
|
||||
// Create a channel for logging
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
|
@ -56,6 +60,9 @@ async fn main() {
|
|||
if let Err(e) = run_app(rx) {
|
||||
eprintln!("Error running TUI: {:?}", e);
|
||||
}
|
||||
|
||||
// Exit the process when the TUI closes
|
||||
exit(0);
|
||||
});
|
||||
|
||||
// Load the configuration from config file
|
||||
|
|
Loading…
Add table
Reference in a new issue