feat: Chat request implementation #14

Manually merged
awiteb merged 55 commits from awiteb/chat-request-and-response into master 2024-07-18 14:21:39 +02:00 AGit
Showing only changes of commit 927a345802 - Show all commits

View file

@ -21,6 +21,7 @@ use errors::{WsError, WsResult};
use futures::{channel::mpsc, FutureExt, StreamExt, TryStreamExt}; use futures::{channel::mpsc, FutureExt, StreamExt, TryStreamExt};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use oxidetalis_core::{cipher::K256Secret, types::PublicKey}; use oxidetalis_core::{cipher::K256Secret, types::PublicKey};
use oxidetalis_entities::prelude::*;
use salvo::{ use salvo::{
handler, handler,
http::StatusError, http::StatusError,
@ -30,15 +31,18 @@ use salvo::{
Response, Response,
Router, Router,
}; };
use sea_orm::DatabaseConnection;
use tokio::{sync::RwLock, task::spawn as tokio_spawn, time::sleep as tokio_sleep}; use tokio::{sync::RwLock, task::spawn as tokio_spawn, time::sleep as tokio_sleep};
mod errors; pub mod errors;
mod events; mod events;
mod handlers;
pub use events::*; pub use events::*;
use uuid::Uuid; use uuid::Uuid;
use crate::{ use crate::{
database::UserTableExt,
extensions::{DepotExt, OnlineUsersExt}, extensions::{DepotExt, OnlineUsersExt},
middlewares, middlewares,
nonce::NonceCache, nonce::NonceCache,
@ -92,6 +96,7 @@ pub async fn user_connected(
depot: &Depot, depot: &Depot,
) -> Result<(), StatusError> { ) -> Result<(), StatusError> {
let nonce_cache = depot.nonce_cache(); let nonce_cache = depot.nonce_cache();
let db_conn = depot.db_conn();
let public_key = let public_key =
utils::extract_public_key(req).expect("The public key was checked in the middleware"); utils::extract_public_key(req).expect("The public key was checked in the middleware");
// FIXME: The config should hold `K256Secret` not `PrivateKey` // FIXME: The config should hold `K256Secret` not `PrivateKey`
@ -100,7 +105,7 @@ pub async fn user_connected(
WebSocketUpgrade::new() WebSocketUpgrade::new()
.upgrade(req, res, move |ws| { .upgrade(req, res, move |ws| {
handle_socket(ws, nonce_cache, public_key, shared_secret) handle_socket(ws, db_conn, nonce_cache, public_key, shared_secret)
}) })
.await .await
} }
@ -108,6 +113,7 @@ pub async fn user_connected(
/// Handle the websocket connection /// Handle the websocket connection
async fn handle_socket( async fn handle_socket(
ws: WebSocket, ws: WebSocket,
db_conn: Arc<DatabaseConnection>,
nonce_cache: Arc<NonceCache>, nonce_cache: Arc<NonceCache>,
user_public_key: PublicKey, user_public_key: PublicKey,
user_shared_secret: [u8; 32], user_shared_secret: [u8; 32],
@ -123,15 +129,31 @@ async fn handle_socket(
}); });
tokio_spawn(fut); tokio_spawn(fut);
let conn_id = Uuid::new_v4(); let conn_id = Uuid::new_v4();
let user = SocketUserData::new(user_public_key, user_shared_secret, sender.clone()); let Ok(user) = db_conn.get_user_by_pubk(&user_public_key).await else {
ONLINE_USERS.add_user(&conn_id, user).await; let _ = sender.unbounded_send(Ok(ServerEvent::from(WsError::InternalServerError)
.sign(&user_shared_secret)
.as_ref()
.into()));
return;
};
ONLINE_USERS
.add_user(
&conn_id,
SocketUserData::new(user_public_key, user_shared_secret, sender.clone()),
)
.await;
log::info!("New user connected: ConnId(={conn_id}) PublicKey(={user_public_key})"); log::info!("New user connected: ConnId(={conn_id}) PublicKey(={user_public_key})");
// TODO: Send the incoming chat request to the user, while they are offline.
// This after adding last_login col to the user table
let fut = async move { let fut = async move {
while let Some(Ok(msg)) = user_ws_receiver.next().await { while let Some(Ok(msg)) = user_ws_receiver.next().await {
match handle_ws_msg(msg, &nonce_cache, &user_shared_secret).await { match handle_ws_msg(msg, &nonce_cache, &user_shared_secret).await {
Ok(event) => { Ok(event) => {
if let Some(server_event) = handle_events(event, &conn_id).await { if let Some(server_event) =
handle_events(event, &db_conn, &conn_id, user.as_ref()).await
{
if let Err(err) = sender.unbounded_send(Ok(server_event if let Err(err) = sender.unbounded_send(Ok(server_event
.sign(&user_shared_secret) .sign(&user_shared_secret)
.as_ref() .as_ref()
@ -182,13 +204,21 @@ async fn handle_ws_msg(
} }
/// Handle user events, and return the server event if needed /// Handle user events, and return the server event if needed
async fn handle_events(event: ClientEvent, conn_id: &Uuid) -> Option<ServerEvent<Unsigned>> { async fn handle_events(
event: ClientEvent,
db: &DatabaseConnection,
conn_id: &Uuid,
user: Option<&UserModel>,
) -> Option<ServerEvent<Unsigned>> {
match &event.event { match &event.event {
ClientEventType::Ping { .. } => Some(ServerEvent::pong()), ClientEventType::Ping { .. } => Some(ServerEvent::pong()),
ClientEventType::Pong { .. } => { ClientEventType::Pong { .. } => {
ONLINE_USERS.update_pong(conn_id).await; ONLINE_USERS.update_pong(conn_id).await;
None None
} }
ClientEventType::ChatRequest { to } => {
Some(handlers::handle_chat_request(db, user, to).await)
}
} }
} }