From 4bb478a20a15a48c2f0d2d71b9f82209ebfc195a Mon Sep 17 00:00:00 2001 From: Brandon Konkle Date: Tue, 3 Sep 2024 18:33:00 -0600 Subject: [PATCH 1/5] Feature: Flexible, Generic WebSocket Sessions --- CHANGELOG.md | 6 ++ Cargo.toml | 8 ++ examples/async-graphql/Cargo.toml | 13 +-- examples/async-graphql/src/events/handler.rs | 11 +- examples/async-graphql/src/events/mod.rs | 3 + examples/async-graphql/src/events/session.rs | 29 +++++ examples/cqrs-es/Cargo.toml | 11 +- examples/simple-warp/Cargo.toml | 9 +- examples/simple/Cargo.toml | 9 +- nakago/Cargo.toml | 10 +- nakago_async_graphql/Cargo.toml | 12 +-- nakago_axum/Cargo.toml | 12 +-- nakago_derive/Cargo.toml | 12 +-- nakago_figment/Cargo.toml | 12 +-- nakago_sea_orm/Cargo.toml | 12 +-- nakago_warp/Cargo.toml | 12 +-- nakago_ws/Cargo.toml | 14 +-- nakago_ws/src/connections.rs | 106 ++++++++----------- nakago_ws/src/controller.rs | 27 ++--- 19 files changed, 182 insertions(+), 146 deletions(-) create mode 100644 examples/async-graphql/src/events/session.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e1d4f32..acd1f493 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Removed + +- `nakago-ws` - Removed `Session` in favor of a generic type parameter for the `Connections` struct. + ## [0.23.0] Major pivot! Until now, Nakago has been aimed at growing into a full-scale API server framework. However, I've realized that the core value of Nakago is the Dependency Injection system, and that it can be used in a wide variety of contexts. This release is a pivot to focus on the DI system itself, and to make it more flexible and easier to use in a variety of contexts. diff --git a/Cargo.toml b/Cargo.toml index f391845d..d3705077 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,14 @@ default-members = [ "nakago_ws", ] +[workspace.package] +version = "0.24.0" +license = "MIT" +edition = "2021" +authors = ["Brandon Konkle "] +homepage = "https://github.com/bkonkle/nakago" +repository = "https://github.com/bkonkle/nakago" + [patch.crates-io] nakago = { path = "./nakago" } nakago-async-graphql = { path = "./nakago_async_graphql" } diff --git a/examples/async-graphql/Cargo.toml b/examples/async-graphql/Cargo.toml index 2b8edf72..4c8a3a50 100644 --- a/examples/async-graphql/Cargo.toml +++ b/examples/async-graphql/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "nakago-examples-async-graphql" -version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" +version = "0.24.0" description = "A lightweight Rust toolkit for sharp dependency injection 😎" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true publish = false @@ -38,7 +39,7 @@ nakago-axum = "0.23" nakago-derive = "0.23" nakago-figment = "0.23" nakago-sea-orm = "0.23" -nakago-ws = "0.23" +nakago-ws = "0.24" nakago = "0.23" oso = "0.27" pico-args = "0.5.0" diff --git a/examples/async-graphql/src/events/handler.rs b/examples/async-graphql/src/events/handler.rs index d7711ad1..f6db35bd 100644 --- a/examples/async-graphql/src/events/handler.rs +++ b/examples/async-graphql/src/events/handler.rs @@ -9,18 +9,21 @@ use nakago_ws::connections::Connections; use crate::domains::users::{self, model::User}; -use super::messages::{IncomingMessage, OutgoingMessage}; +use super::{ + messages::{IncomingMessage, OutgoingMessage}, + session::Session, +}; /// Message Handler #[derive(Clone)] pub struct Handler { - connections: Arc>, + connections: Arc>, users: Arc>, } #[async_trait] impl nakago_ws::Handler for Handler { - async fn get_user(&self, sub: Subject) -> Option { + async fn get_session(&self, sub: Subject) -> Option { if let Subject(Some(ref username)) = sub { self.users .get_by_username(username, &true) @@ -63,7 +66,7 @@ impl Provider>> for Provide { self: Arc, i: nakago::Inject, ) -> provider::Result>>> { - let connections = i.get::>().await?; + let connections = i.get::>().await?; let users = i.get::>().await?; Ok(Arc::new(Box::new(Handler { connections, users }))) diff --git a/examples/async-graphql/src/events/mod.rs b/examples/async-graphql/src/events/mod.rs index bb5b2242..5cb46c1e 100644 --- a/examples/async-graphql/src/events/mod.rs +++ b/examples/async-graphql/src/events/mod.rs @@ -3,3 +3,6 @@ pub mod handler; /// WebSocket message types pub mod messages; + +/// WebSocket sessions +pub mod session; diff --git a/examples/async-graphql/src/events/session.rs b/examples/async-graphql/src/events/session.rs new file mode 100644 index 00000000..ee8bbcb7 --- /dev/null +++ b/examples/async-graphql/src/events/session.rs @@ -0,0 +1,29 @@ +use serde::{Deserialize, Serialize}; + +use crate::domains::users::model::User; + +/// A Session tracking details about this particular connection +#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)] +#[serde(tag = "type")] +pub enum Session { + /// A session that is not associated with a User + #[default] + Anonymous, + + /// A session that is associated with a User + User { + /// The User instance + user: User, + }, +} + +impl Session { + /// Get the User associated with this session, if any + #[allow(dead_code)] + pub fn get_user(&self) -> Option<&User> { + match self { + Session::Anonymous => None, + Session::User { user, .. } => Some(user), + } + } +} diff --git a/examples/cqrs-es/Cargo.toml b/examples/cqrs-es/Cargo.toml index 2b9348a6..827d7671 100644 --- a/examples/cqrs-es/Cargo.toml +++ b/examples/cqrs-es/Cargo.toml @@ -1,13 +1,12 @@ [package] name = "nakago-examples-cqrs-es" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "A lightweight Rust toolkit for sharp dependency injection 😎" -documentation = "https://docs.rs/nakago/" -homepage = "https://github.com/bkonkle/nakago" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true publish = false # diff --git a/examples/simple-warp/Cargo.toml b/examples/simple-warp/Cargo.toml index e0d140c5..b80c0516 100644 --- a/examples/simple-warp/Cargo.toml +++ b/examples/simple-warp/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "nakago-examples-simple-warp" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "A lightweight Rust toolkit for sharp dependency injection 😎" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true publish = false diff --git a/examples/simple/Cargo.toml b/examples/simple/Cargo.toml index d26cee4b..2455ed98 100644 --- a/examples/simple/Cargo.toml +++ b/examples/simple/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "nakago-examples-simple" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "A lightweight Rust toolkit for sharp dependency injection 😎" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true publish = false diff --git a/nakago/Cargo.toml b/nakago/Cargo.toml index 76b510e9..3ec55bb3 100644 --- a/nakago/Cargo.toml +++ b/nakago/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nakago" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "A lightweight Rust toolkit for sharp dependency injection 😎" documentation = "https://docs.rs/nakago/" -homepage = "https://github.com/bkonkle/nakago" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true [dependencies] anyhow = "1.0" diff --git a/nakago_async_graphql/Cargo.toml b/nakago_async_graphql/Cargo.toml index e636031c..8a0e5abc 100644 --- a/nakago_async_graphql/Cargo.toml +++ b/nakago_async_graphql/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nakago-async-graphql" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "An Async-GraphQL integration for Nakago" -documentation = "https://docs.rs/nakago/" -homepage = "https://github.com/bkonkle/nakago" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +documentation = "https://docs.rs/nakago-async-graphql/" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true [dependencies] anyhow = "1.0" diff --git a/nakago_axum/Cargo.toml b/nakago_axum/Cargo.toml index 2f394f01..7627c429 100644 --- a/nakago_axum/Cargo.toml +++ b/nakago_axum/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nakago-axum" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "An Axum HTTP routes integration for Nakago" -documentation = "https://docs.rs/nakago/" -homepage = "https://github.com/bkonkle/nakago" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +documentation = "https://docs.rs/nakago-axum/" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true [dependencies] anyhow = "1.0" diff --git a/nakago_derive/Cargo.toml b/nakago_derive/Cargo.toml index ae69f42c..083337ce 100644 --- a/nakago_derive/Cargo.toml +++ b/nakago_derive/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nakago-derive" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "Macros for nakago" -documentation = "https://docs.rs/nakago/" -homepage = "https://github.com/bkonkle/nakago" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +documentation = "https://docs.rs/nakago-derive/" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true [lib] proc-macro = true diff --git a/nakago_figment/Cargo.toml b/nakago_figment/Cargo.toml index 7c33566a..7494a890 100644 --- a/nakago_figment/Cargo.toml +++ b/nakago_figment/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nakago-figment" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "Figment config loading utils for Nakago" -documentation = "https://docs.rs/nakago/" -homepage = "https://github.com/bkonkle/nakago" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +documentation = "https://docs.rs/nakago-figment/" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true [dependencies] anyhow = "1.0" diff --git a/nakago_sea_orm/Cargo.toml b/nakago_sea_orm/Cargo.toml index c5c22889..78176816 100644 --- a/nakago_sea_orm/Cargo.toml +++ b/nakago_sea_orm/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nakago-sea-orm" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "A SeaORM integration for Nakago" -documentation = "https://docs.rs/nakago/" -homepage = "https://github.com/bkonkle/nakago" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +documentation = "https://docs.rs/nakago-sea-orm/" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true [dependencies] anyhow = "1.0" diff --git a/nakago_warp/Cargo.toml b/nakago_warp/Cargo.toml index 2f49b36b..b30d073f 100644 --- a/nakago_warp/Cargo.toml +++ b/nakago_warp/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nakago-warp" version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" description = "A Warp HTTP routes integration for Nakago" -documentation = "https://docs.rs/nakago/" -homepage = "https://github.com/bkonkle/nakago" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +documentation = "https://docs.rs/nakago-warp/" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true [dependencies] anyhow = "1.0" diff --git a/nakago_ws/Cargo.toml b/nakago_ws/Cargo.toml index 46b3bbd3..370aabb7 100644 --- a/nakago_ws/Cargo.toml +++ b/nakago_ws/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nakago-ws" -version = "0.23.0" -authors = ["Brandon Konkle "] -edition = "2021" +version = "0.24.0" description = "Websocket utils for Nakago" -documentation = "https://docs.rs/nakago/" -homepage = "https://github.com/bkonkle/nakago" -repository = "https://github.com/bkonkle/nakago" -license = "MIT" +documentation = "https://docs.rs/nakago-ws/" +license.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true [dependencies] anyhow = "1.0" diff --git a/nakago_ws/src/connections.rs b/nakago_ws/src/connections.rs index 23ef55c5..9a0b9d25 100644 --- a/nakago_ws/src/connections.rs +++ b/nakago_ws/src/connections.rs @@ -6,7 +6,6 @@ use axum::extract::ws::Message; use derive_new::new; use nakago::{provider, Inject, Provider}; use nakago_derive::Provider; -use serde::{Deserialize, Serialize}; use tokio::sync::{ mpsc::{self, UnboundedSender}, RwLock, @@ -15,11 +14,11 @@ use ulid::Ulid; /// User Connection for WebSocket connections #[derive(Debug, Clone, new)] -pub struct Connection { +pub struct Connection { tx: mpsc::UnboundedSender, #[allow(dead_code)] - session: Session, + session: Session, } impl Connection { @@ -38,12 +37,12 @@ impl Connection { /// - Key is their connection id /// - Value is a sender of `axum::extract::ws::Message` #[derive(Default, new)] -pub struct Connections(Arc>>>); +pub struct Connections(Arc>>>); -impl Connections { +impl Connections { /// Get a copy of the Session associated with the given connection ID #[allow(dead_code)] - pub async fn get_session(&self, conn_id: &str) -> Session { + pub async fn get_session(&self, conn_id: &str) -> Session { self.0 .write() .await @@ -54,7 +53,7 @@ impl Connections { /// Set the Session associated with the given connection ID, if it exists #[allow(dead_code)] - pub async fn set_session(&self, conn_id: &str, session: Session) { + pub async fn set_session(&self, conn_id: &str, session: Session) { if let Some(connection) = self.0.write().await.get_mut(conn_id) { connection.session = session; } @@ -70,7 +69,7 @@ impl Connections { } ///. Inserts a connection into the hash map, and returns the id - pub async fn insert(&self, tx: UnboundedSender, session: Session) -> String { + pub async fn insert(&self, tx: UnboundedSender, session: Session) -> String { let conn_id = Ulid::new().to_string(); self.0 @@ -87,40 +86,6 @@ impl Connections { } } -/// A Session tracking details about this particular connection -#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)] -#[serde(tag = "type")] -pub enum Session { - /// A session that is not associated with a User - #[default] - Anonymous, - - /// A session that is associated with a User - User { - /// The User instance - user: U, - }, -} - -impl Session { - /// Create a new session for the given User - pub fn new(user: Option) -> Self { - match user { - Some(user) => Self::User { user }, - None => Self::Anonymous, - } - } - - /// Get the User associated with this session, if any - #[allow(dead_code)] - pub fn get_user(&self) -> Option<&U> { - match self { - Session::Anonymous => None, - Session::User { user, .. } => Some(user), - } - } -} - /// Provide the default Connections implementation #[derive(Default)] pub struct Provide { @@ -137,6 +102,8 @@ impl Provider> for Provide { #[cfg(test)] pub(crate) mod test { + use serde::{Deserialize, Serialize}; + use super::*; #[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq, new)] @@ -144,10 +111,33 @@ pub(crate) mod test { id: String, } + /// A Session tracking details about this particular connection + #[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)] + #[serde(tag = "type")] + enum Session { + /// A session that is not associated with a User + #[default] + Anonymous, + + /// A session that is associated with a User + User(User), + } + + impl Session { + /// Get the User associated with this session, if any + #[allow(dead_code)] + pub fn get_user(&self) -> Option<&User> { + match self { + Session::Anonymous => None, + Session::User(user) => Some(user), + } + } + } + #[tokio::test] async fn test_connection_send_success() -> Result<()> { let (tx, mut rx) = mpsc::unbounded_channel(); - let conn = Connection::new(tx, Session::::Anonymous); + let conn = Connection::new(tx, Session::Anonymous); conn.send(Message::Text("Hello, World!".to_string()))?; @@ -160,11 +150,8 @@ pub(crate) mod test { #[tokio::test] async fn test_connections_get_session_success() -> Result<()> { - let connections = Connections::::default(); - - let expected = Session::::User { - user: User::new(Ulid::new().to_string()), - }; + let connections = Connections::::default(); + let expected = Session::User(User::new(Ulid::new().to_string())); let conn_id = connections .insert(mpsc::unbounded_channel().0, expected.clone()) @@ -179,14 +166,11 @@ pub(crate) mod test { #[tokio::test] async fn test_connections_set_session_success() -> Result<()> { - let connections = Connections::::default(); - - let expected = Session::::User { - user: User::new(Ulid::new().to_string()), - }; + let connections = Connections::::default(); + let expected = Session::User(User::new(Ulid::new().to_string())); let conn_id = connections - .insert(mpsc::unbounded_channel().0, Session::::Anonymous) + .insert(mpsc::unbounded_channel().0, Session::Anonymous) .await; connections.set_session(&conn_id, expected.clone()).await; @@ -200,10 +184,10 @@ pub(crate) mod test { #[tokio::test] async fn test_connections_send_success() -> Result<()> { - let connections = Connections::::default(); + let connections = Connections::::default(); let (tx, mut rx) = mpsc::unbounded_channel(); - let conn_id = connections.insert(tx, Session::::Anonymous).await; + let conn_id = connections.insert(tx, Session::Anonymous).await; connections .send(&conn_id, Message::Text("Hello, World!".to_string())) @@ -218,14 +202,12 @@ pub(crate) mod test { #[tokio::test] async fn test_connections_remove_success() -> Result<()> { - let connections = Connections::::default(); + let connections = Connections::::default(); let conn_id = connections .insert( mpsc::unbounded_channel().0, - Session::::User { - user: User::new(Ulid::new().to_string()), - }, + Session::User(User::new(Ulid::new().to_string())), ) .await; @@ -233,7 +215,7 @@ pub(crate) mod test { let session = connections.get_session(&conn_id).await; - assert_eq!(Session::::Anonymous, session); + assert_eq!(Session::Anonymous, session); Ok(()) } @@ -241,7 +223,7 @@ pub(crate) mod test { #[tokio::test] async fn test_session_get_user_success() -> Result<()> { let user = User::new(Ulid::new().to_string()); - let session = Session::::User { user: user.clone() }; + let session = Session::User(user.clone()); assert_eq!(Some(&user), session.get_user()); diff --git a/nakago_ws/src/controller.rs b/nakago_ws/src/controller.rs index 8ae184c9..c527f384 100644 --- a/nakago_ws/src/controller.rs +++ b/nakago_ws/src/controller.rs @@ -17,42 +17,42 @@ use nakago_derive::Provider; use tokio::sync::mpsc; use tokio_stream::wrappers::UnboundedReceiverStream; -use super::{connections::Session, Connections}; +use super::Connections; /// A Handler handles Websocket messages #[automock] #[async_trait] -pub trait Handler: Send + Sync + Any { +pub trait Handler: Send + Sync + Any { /// Route the given message to the appropriate handler async fn route(&self, conn_id: &str, msg: Message) -> anyhow::Result<()>; /// Get the User from the Subject - async fn get_user(&self, sub: Subject) -> Option; + async fn get_session(&self, sub: Subject) -> Option; } /// WebSocket Controller #[derive(Clone, new)] -pub struct Controller { - connections: Arc>, - handler: Arc>>, +pub struct Controller { + connections: Arc>, + handler: Arc>>, } -impl Controller { +impl Controller { /// Handle requests for new WebSocket connections pub async fn upgrade( self: Arc, sub: Subject, ws: WebSocketUpgrade, ) -> axum::response::Result { - // Retrieve the request User, if username is present - let user = self.handler.get_user(sub).await; + // Retrieve the request Session + let session = self.handler.get_session(sub).await; - Ok(ws.on_upgrade(|socket| async move { self.handle(socket, user).await })) + Ok(ws.on_upgrade(|socket| async move { self.handle(socket, session).await })) } /// Handle `WebSocket` connections by setting up a message handler that deserializes them and /// determines how to handle - async fn handle(&self, socket: WebSocket, user: Option) { + async fn handle(&self, socket: WebSocket, session: Option) { let (mut ws_write, mut ws_read) = socket.split(); let (tx, rx) = mpsc::unbounded_channel(); @@ -69,7 +69,10 @@ impl Controller { } }); - let conn_id = self.connections.insert(tx, Session::new(user)).await; + let conn_id = self + .connections + .insert(tx, session.unwrap_or_default()) + .await; while let Some(result) = ws_read.next().await { let msg = match result { From d0bd2005a2dff95d385bfa4911ab1b23f7184372 Mon Sep 17 00:00:00 2001 From: Brandon Konkle Date: Tue, 3 Sep 2024 18:34:12 -0600 Subject: [PATCH 2/5] Remove workspace version --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d3705077..42540894 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ default-members = [ ] [workspace.package] -version = "0.24.0" license = "MIT" edition = "2021" authors = ["Brandon Konkle "] From af25543d0d3acd1a5e44bbeede4fedeeb6a6d74b Mon Sep 17 00:00:00 2001 From: Brandon Konkle Date: Tue, 3 Sep 2024 18:40:52 -0600 Subject: [PATCH 3/5] More cleanup --- examples/async-graphql/src/events/handler.rs | 13 +++++++------ examples/async-graphql/src/events/session.rs | 8 ++++++++ examples/async-graphql/src/http/router.rs | 8 ++++---- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/examples/async-graphql/src/events/handler.rs b/examples/async-graphql/src/events/handler.rs index f6db35bd..c4fb24eb 100644 --- a/examples/async-graphql/src/events/handler.rs +++ b/examples/async-graphql/src/events/handler.rs @@ -7,7 +7,7 @@ use nakago_axum::auth::Subject; use nakago_derive::Provider; use nakago_ws::connections::Connections; -use crate::domains::users::{self, model::User}; +use crate::domains::users; use super::{ messages::{IncomingMessage, OutgoingMessage}, @@ -22,13 +22,14 @@ pub struct Handler { } #[async_trait] -impl nakago_ws::Handler for Handler { - async fn get_session(&self, sub: Subject) -> Option { +impl nakago_ws::Handler for Handler { + async fn get_session(&self, sub: Subject) -> Option { if let Subject(Some(ref username)) = sub { self.users .get_by_username(username, &true) .await - .unwrap_or(None) + .map(|u| Session::new(u)) + .ok() } else { None } @@ -61,11 +62,11 @@ pub struct Provide {} #[Provider] #[async_trait] -impl Provider>> for Provide { +impl Provider>> for Provide { async fn provide( self: Arc, i: nakago::Inject, - ) -> provider::Result>>> { + ) -> provider::Result>>> { let connections = i.get::>().await?; let users = i.get::>().await?; diff --git a/examples/async-graphql/src/events/session.rs b/examples/async-graphql/src/events/session.rs index ee8bbcb7..a6a88178 100644 --- a/examples/async-graphql/src/events/session.rs +++ b/examples/async-graphql/src/events/session.rs @@ -18,6 +18,14 @@ pub enum Session { } impl Session { + /// Create a new session for the given User + pub fn new(user: Option) -> Self { + match user { + Some(user) => Self::User { user }, + None => Self::Anonymous, + } + } + /// Get the User associated with this session, if any #[allow(dead_code)] pub fn get_user(&self) -> Option<&User> { diff --git a/examples/async-graphql/src/http/router.rs b/examples/async-graphql/src/http/router.rs index 8950d0a8..03cdc6f7 100644 --- a/examples/async-graphql/src/http/router.rs +++ b/examples/async-graphql/src/http/router.rs @@ -3,19 +3,19 @@ use nakago::Inject; use nakago_axum::{init::trace_layer, State}; use nakago_ws::{connections, controller}; -use crate::{domains::users::model::User, events::handler}; +use crate::events::{handler, session::Session}; use super::{events, graphql, health}; /// Provide dependencies needed for the HTTP service pub async fn load(i: &Inject) -> nakago::Result<()> { - i.provide::>(connections::Provide::default()) + i.provide::>(connections::Provide::default()) .await?; - i.provide::>>(handler::Provide::default()) + i.provide::>>(handler::Provide::default()) .await?; - i.provide::>(controller::Provide::default()) + i.provide::>(controller::Provide::default()) .await?; Ok(()) From 3abd689f6e0f56d1a9a4960440e425f23ce30b7b Mon Sep 17 00:00:00 2001 From: Brandon Konkle Date: Tue, 3 Sep 2024 18:44:53 -0600 Subject: [PATCH 4/5] Lint fixes --- examples/async-graphql/src/domains/graphql.rs | 22 +++++++++---------- examples/async-graphql/src/events/handler.rs | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/async-graphql/src/domains/graphql.rs b/examples/async-graphql/src/domains/graphql.rs index 58f71c98..3a9409e6 100644 --- a/examples/async-graphql/src/domains/graphql.rs +++ b/examples/async-graphql/src/domains/graphql.rs @@ -28,11 +28,11 @@ pub type SchemaBuilder = async_graphql::SchemaBuilder nakago::Result<()> { - users::schema::load(&i).await?; - profiles::schema::load(&i).await?; - role_grants::schema::load(&i).await?; - shows::schema::load(&i).await?; - episodes::schema::load(&i).await?; + users::schema::load(i).await?; + profiles::schema::load(i).await?; + role_grants::schema::load(i).await?; + shows::schema::load(i).await?; + episodes::schema::load(i).await?; Ok(()) } @@ -67,14 +67,14 @@ pub async fn init(i: &Inject) -> nakago::Result<()> { i.inject::(builder).await?; - users::schema::init(&i).await?; - profiles::schema::init(&i).await?; - role_grants::schema::init(&i).await?; - shows::schema::init(&i).await?; - episodes::schema::init(&i).await?; + users::schema::init(i).await?; + profiles::schema::init(i).await?; + role_grants::schema::init(i).await?; + shows::schema::init(i).await?; + episodes::schema::init(i).await?; schema::Init::::default() - .init(&i) + .init(i) .await?; Ok(()) diff --git a/examples/async-graphql/src/events/handler.rs b/examples/async-graphql/src/events/handler.rs index c4fb24eb..d567be8d 100644 --- a/examples/async-graphql/src/events/handler.rs +++ b/examples/async-graphql/src/events/handler.rs @@ -28,7 +28,7 @@ impl nakago_ws::Handler for Handler { self.users .get_by_username(username, &true) .await - .map(|u| Session::new(u)) + .map(Session::new) .ok() } else { None From 8b7f4d878305afc427b6e23296783eed83de3ca8 Mon Sep 17 00:00:00 2001 From: Brandon Konkle Date: Tue, 3 Sep 2024 18:50:22 -0600 Subject: [PATCH 5/5] Integration test fixes --- examples/async-graphql/src/http/events.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/async-graphql/src/http/events.rs b/examples/async-graphql/src/http/events.rs index a557a095..85797124 100644 --- a/examples/async-graphql/src/http/events.rs +++ b/examples/async-graphql/src/http/events.rs @@ -1,11 +1,11 @@ use axum::{extract::WebSocketUpgrade, response::IntoResponse}; use nakago_axum::{auth::Subject, Inject}; -use crate::domains::users::model::User; +use crate::events::session::Session; /// Handle WebSocket Events pub async fn handle( - Inject(events_controller): Inject>, + Inject(events_controller): Inject>, sub: Subject, ws: WebSocketUpgrade, ) -> axum::response::Result {