Add ban check and reason retrieval for user authentication
- Introduced `check_ban` and `get_ban_reason` functions in `db::users` - Updated client handler to enforce ban checks during login - Added detailed logging for ban status and reasons
This commit is contained in:
parent
b98a890738
commit
d06a15771a
4 changed files with 103 additions and 1 deletions
BIN
db.sqlite
BIN
db.sqlite
Binary file not shown.
Binary file not shown.
|
@ -4,7 +4,9 @@ pub(crate) mod handlers {
|
||||||
Aes256Gcm, Key, Nonce,
|
Aes256Gcm, Key, Nonce,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::db::users::{check_for_account, create_user, hash_password, verify_password};
|
use crate::db::users::{
|
||||||
|
check_ban, check_for_account, create_user, get_ban_reason, hash_password, verify_password,
|
||||||
|
};
|
||||||
use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};
|
use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -89,6 +91,38 @@ pub(crate) mod handlers {
|
||||||
|
|
||||||
// Check if the user already exists in the database
|
// Check if the user already exists in the database
|
||||||
if check_for_account(&username).await? {
|
if check_for_account(&username).await? {
|
||||||
|
// Check if the user is banned
|
||||||
|
if check_ban(&username).await? == true {
|
||||||
|
let ban_reason_result = get_ban_reason(&username).await;
|
||||||
|
|
||||||
|
let message: String = match ban_reason_result {
|
||||||
|
Ok(Some(reason)) => {
|
||||||
|
info!("User {} is banned, Reason: {}", username, reason);
|
||||||
|
format!("User {} is banned, Reason: {}", username, reason).to_string()
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
info!("User {} is banned, but no reason provided", username);
|
||||||
|
format!("User {} is banned, but no reason provided", username).to_string()
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Error fetching ban reason: {}", e);
|
||||||
|
format!("You are banned").to_string();
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let encrypted = match cipher_writer.encrypt(&nonce_writer, message.as_bytes()) {
|
||||||
|
Ok(encrypted) => encrypted,
|
||||||
|
Err(e) => {
|
||||||
|
error!("Encryption error: {}", e);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let message = format!("{}\n", BASE64.encode(&encrypted));
|
||||||
|
writer.write_all(message.as_bytes()).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
info!("User {} already exists", username);
|
info!("User {} already exists", username);
|
||||||
// Send a message to the client
|
// Send a message to the client
|
||||||
let message = format!("User {} is registered, input your password", username);
|
let message = format!("User {} is registered, input your password", username);
|
||||||
|
|
|
@ -93,6 +93,74 @@ pub(crate) mod users {
|
||||||
password_hash.to_string()
|
password_hash.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn check_ban(username: &str) -> Result<bool, sqlx::Error> {
|
||||||
|
let pool = create_db_pool().await?;
|
||||||
|
|
||||||
|
let is_banned = sqlx::query(
|
||||||
|
r#"
|
||||||
|
SELECT EXISTS(
|
||||||
|
SELECT 1
|
||||||
|
FROM users
|
||||||
|
WHERE username = ?
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(username)
|
||||||
|
.fetch_one(&pool)
|
||||||
|
.await?
|
||||||
|
.get::<i64, _>(0);
|
||||||
|
|
||||||
|
// Check if the user is banned
|
||||||
|
if is_banned == 1 {
|
||||||
|
info!("User {} is banned", username);
|
||||||
|
} else {
|
||||||
|
info!("User {} is not banned", username);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(is_banned == 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_ban_reason(username: &str) -> Result<Option<String>, sqlx::Error> {
|
||||||
|
let pool = create_db_pool().await?;
|
||||||
|
info!("Attempting to fetch ban reason for user: {}", username);
|
||||||
|
|
||||||
|
let row_option = sqlx::query(
|
||||||
|
r#"
|
||||||
|
SELECT ban_reason
|
||||||
|
FROM users
|
||||||
|
WHERE username = ?
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(username)
|
||||||
|
.fetch_optional(&pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// Process the result
|
||||||
|
match row_option {
|
||||||
|
Some(row) => {
|
||||||
|
// Row found, now get the ban_reason (which might be NULL)
|
||||||
|
let reason: Option<String> = row.get(0); // Type annotation clarifies intent
|
||||||
|
if let Some(ref r) = reason {
|
||||||
|
info!("User {} found. Ban reason: {}", username, r);
|
||||||
|
} else {
|
||||||
|
// User exists, but ban_reason is NULL in the database
|
||||||
|
info!(
|
||||||
|
"User {} found, but ban_reason is NULL (not banned)",
|
||||||
|
username
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(reason)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// No row found for the username
|
||||||
|
info!("User {} not found in the database", username);
|
||||||
|
// Return Ok(None) as per the function signature, indicating no ban reason found
|
||||||
|
// because the user doesn't exist.
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn verify_password(
|
pub async fn verify_password(
|
||||||
// Use clearer argument names
|
// Use clearer argument names
|
||||||
username: &str,
|
username: &str,
|
||||||
|
|
Loading…
Add table
Reference in a new issue