From 579656c6af68146d086a69a844b68e01c5fe6bfb Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Mon, 20 Mar 2023 19:08:19 +0200 Subject: [PATCH] feat(client, server, shared): implement cookie refreshing --- README.md | 9 ---- .../networking/systems/events/receive/mod.rs | 8 ++- server/src/systems/event/message/mod.rs | 50 +++++++++++++++---- shared/src/api/game/all_forming.rs | 15 ++++-- shared/src/api/game/create.rs | 15 ++++-- shared/src/api/game/mygames.rs | 15 ++++-- shared/src/server/channels.rs | 7 +++ shared/src/server/messages/cookierefresh.rs | 22 ++++++++ shared/src/server/messages/mod.rs | 4 ++ 9 files changed, 115 insertions(+), 30 deletions(-) create mode 100644 shared/src/server/messages/cookierefresh.rs diff --git a/README.md b/README.md index 61fefb2..13a172a 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,6 @@ A multiplayer deck building game. ## **Current major issues** -### **Session cookie refreshing** -Currently, the cookie is refreshed on every single action which requires\ -session auth.\ -Okay, that seems pretty normal.\ -So, we just save the new one to the `global.user_to_session_map` hashmap,\ -and just send an event to the client with the new one, so they can update\ -it in the clients presistent storage, right? This can happen automatically\ -in the background. - ### **Quite a few unwraps in use** All should be handled, with sane error responses. diff --git a/client/src/plugins/networking/systems/events/receive/mod.rs b/client/src/plugins/networking/systems/events/receive/mod.rs index e8f88a7..986313a 100644 --- a/client/src/plugins/networking/systems/events/receive/mod.rs +++ b/client/src/plugins/networking/systems/events/receive/mod.rs @@ -8,8 +8,8 @@ use bevy::prelude::*; use laurelin_shared::server::{ - channels::{AfterAuthChannel, DataRequestChannel}, - messages::{AfterAuth, DataRequestResponse, DataRequestType}, + channels::{AfterAuthChannel, CookieRefreshChannel, DataRequestChannel}, + messages::{AfterAuth, CookieRefresh, DataRequestResponse, DataRequestType}, }; use naia_bevy_client::{ events::{ClientTickEvent, ConnectEvent, DisconnectEvent, MessageEvents, RejectEvent}, @@ -77,6 +77,10 @@ pub fn message_events( commands.insert_resource(NextState(Some(MenuState::Menu))); } + for cr_message in events.read::() { + cfg_user.cookie = cr_message.cookie; + } + for response in events.read::() { match DataRequestType::from_u8(&response.r#type) { DataRequestType::GameCreate => { diff --git a/server/src/systems/event/message/mod.rs b/server/src/systems/event/message/mod.rs index 7fd35d9..889044f 100644 --- a/server/src/systems/event/message/mod.rs +++ b/server/src/systems/event/message/mod.rs @@ -6,14 +6,17 @@ * See LICENSE for licensing information. */ -use bevy_ecs::{event::EventReader, system::Res}; +use bevy_ecs::{ + event::EventReader, + system::{Res, ResMut}, +}; use laurelin_shared::{ api::game::{ all_forming, create, my_games, ResponseAllForming, ResponseCreateGame, ResponseMyGames, }, server::{ - channels::DataRequestChannel, - messages::{DataRequest, DataRequestResponse, DataRequestType}, + channels::{CookieRefreshChannel, DataRequestChannel}, + messages::{CookieRefresh, DataRequest, DataRequestResponse, DataRequestType}, }, }; use naia_bevy_server::{events::MessageEvents, Server}; @@ -24,7 +27,7 @@ pub(crate) fn message_events( mut ev: EventReader, mut server: Server, config: Res, - global: Res, + mut global: ResMut, ) { for events in ev.iter() { for (user_key, request) in events.read::() { @@ -32,8 +35,8 @@ pub(crate) fn message_events( DataRequestType::GameCreate => { // TODO: handle let cookie = global.user_to_session_map.get(&user_key).unwrap(); - let response = create(&config.api_address, &cookie); - let json = match response { + let wrapped = create(&config.api_address, &cookie); + let json = match wrapped.response { ResponseCreateGame::Error(err) => serde_json::to_string(&err).unwrap(), // TODO: handle ResponseCreateGame::Valid(result) => { serde_json::to_string(&result).unwrap() // TODO: handle @@ -43,12 +46,21 @@ pub(crate) fn message_events( &user_key, &DataRequestResponse::new(request.r#type, &json), ); + + // update cookie + global + .user_to_session_map + .insert(user_key, wrapped.cookie.clone()); + server.send_message::( + &user_key, + &CookieRefresh::new(&wrapped.cookie), + ); } DataRequestType::GameAllForming => { // TODO: handle let cookie = global.user_to_session_map.get(&user_key).unwrap(); - let response = all_forming(&config.api_address, &cookie); - let json = match response { + let wrapped = all_forming(&config.api_address, &cookie); + let json = match wrapped.response { ResponseAllForming::Error(err) => serde_json::to_string(&err).unwrap(), // TODO: handle ResponseAllForming::Valid(result) => { serde_json::to_string(&result).unwrap() // TODO: handle @@ -58,12 +70,21 @@ pub(crate) fn message_events( &user_key, &DataRequestResponse::new(request.r#type, &json), ); + + // update cookie + global + .user_to_session_map + .insert(user_key, wrapped.cookie.clone()); + server.send_message::( + &user_key, + &CookieRefresh::new(&wrapped.cookie), + ); } DataRequestType::GameMyGames => { // TODO: handle let cookie = global.user_to_session_map.get(&user_key).unwrap(); - let response = my_games(&config.api_address, &cookie); - let json = match response { + let wrapped = my_games(&config.api_address, &cookie); + let json = match wrapped.response { ResponseMyGames::Error(err) => serde_json::to_string(&err).unwrap(), // TODO: handle ResponseMyGames::Valid(result) => { serde_json::to_string(&result).unwrap() // TODO: handle @@ -73,6 +94,15 @@ pub(crate) fn message_events( &user_key, &DataRequestResponse::new(request.r#type, &json), ); + + // update cookie + global + .user_to_session_map + .insert(user_key, wrapped.cookie.clone()); + server.send_message::( + &user_key, + &CookieRefresh::new(&wrapped.cookie), + ); } } } diff --git a/shared/src/api/game/all_forming.rs b/shared/src/api/game/all_forming.rs index b724645..d90c8e7 100644 --- a/shared/src/api/game/all_forming.rs +++ b/shared/src/api/game/all_forming.rs @@ -9,7 +9,7 @@ use reqwest::{self, header::COOKIE}; use serde::{Deserialize, Serialize}; -use crate::{error::api::APIError, types::game::Game}; +use crate::{api::macros::extract_cookie, error::api::APIError, types::game::Game}; pub type ResultAllForming = Vec; @@ -20,7 +20,13 @@ pub enum ResponseAllForming { Valid(ResultAllForming), } -pub fn all_forming(api_address: &String, cookie: &String) -> ResponseAllForming { +#[derive(Deserialize)] +pub struct ResponseAllFormingWrapper { + pub response: ResponseAllForming, + pub cookie: String, +} + +pub fn all_forming(api_address: &String, cookie: &String) -> ResponseAllFormingWrapper { let client = reqwest::blocking::Client::new(); let resp = client @@ -29,5 +35,8 @@ pub fn all_forming(api_address: &String, cookie: &String) -> ResponseAllForming .send() .unwrap(); - resp.json().unwrap() + ResponseAllFormingWrapper { + cookie: extract_cookie!(resp), + response: resp.json().unwrap(), + } } diff --git a/shared/src/api/game/create.rs b/shared/src/api/game/create.rs index 9cec1b6..4ece75f 100644 --- a/shared/src/api/game/create.rs +++ b/shared/src/api/game/create.rs @@ -9,7 +9,7 @@ use reqwest::{self, header::COOKIE}; use serde::{Deserialize, Serialize}; -use crate::{error::api::APIError, types::game::Game}; +use crate::{api::macros::extract_cookie, error::api::APIError, types::game::Game}; #[derive(Serialize, Deserialize)] #[serde(untagged)] @@ -18,7 +18,13 @@ pub enum ResponseCreateGame { Valid(Game), } -pub fn create(api_address: &String, cookie: &String) -> ResponseCreateGame { +#[derive(Deserialize)] +pub struct ResponseCreateGameWrapper { + pub response: ResponseCreateGame, + pub cookie: String, +} + +pub fn create(api_address: &String, cookie: &String) -> ResponseCreateGameWrapper { let client = reqwest::blocking::Client::new(); let resp = client @@ -27,5 +33,8 @@ pub fn create(api_address: &String, cookie: &String) -> ResponseCreateGame { .send() .unwrap(); - resp.json().unwrap() + ResponseCreateGameWrapper { + cookie: extract_cookie!(resp), + response: resp.json().unwrap(), + } } diff --git a/shared/src/api/game/mygames.rs b/shared/src/api/game/mygames.rs index 8ba3a5e..376fa89 100644 --- a/shared/src/api/game/mygames.rs +++ b/shared/src/api/game/mygames.rs @@ -9,7 +9,7 @@ use reqwest::{self, header::COOKIE}; use serde::{Deserialize, Serialize}; -use crate::{error::api::APIError, types::game::Game}; +use crate::{api::macros::extract_cookie, error::api::APIError, types::game::Game}; pub type ResultMyGames = Vec; @@ -20,7 +20,13 @@ pub enum ResponseMyGames { Valid(ResultMyGames), } -pub fn my_games(api_address: &String, cookie: &String) -> ResponseMyGames { +#[derive(Deserialize)] +pub struct ResponseMyGamesWrapper { + pub response: ResponseMyGames, + pub cookie: String, +} + +pub fn my_games(api_address: &String, cookie: &String) -> ResponseMyGamesWrapper { let client = reqwest::blocking::Client::new(); let resp = client @@ -29,5 +35,8 @@ pub fn my_games(api_address: &String, cookie: &String) -> ResponseMyGames { .send() .unwrap(); - resp.json().unwrap() + ResponseMyGamesWrapper { + cookie: extract_cookie!(resp), + response: resp.json().unwrap(), + } } diff --git a/shared/src/server/channels.rs b/shared/src/server/channels.rs index ceb7808..39e6892 100644 --- a/shared/src/server/channels.rs +++ b/shared/src/server/channels.rs @@ -13,6 +13,9 @@ use naia_bevy_shared::{ #[derive(Channel)] pub struct AfterAuthChannel; +#[derive(Channel)] +pub struct CookieRefreshChannel; + #[derive(Channel)] pub struct DataRequestChannel; @@ -25,6 +28,10 @@ impl ProtocolPlugin for ChannelsPlugin { ChannelDirection::ServerToClient, ChannelMode::UnorderedReliable(ReliableSettings::default()), ) + .add_channel::( + ChannelDirection::ServerToClient, + ChannelMode::UnorderedReliable(ReliableSettings::default()), + ) .add_channel::( ChannelDirection::Bidirectional, ChannelMode::OrderedReliable(ReliableSettings::default()), diff --git a/shared/src/server/messages/cookierefresh.rs b/shared/src/server/messages/cookierefresh.rs new file mode 100644 index 0000000..15433e5 --- /dev/null +++ b/shared/src/server/messages/cookierefresh.rs @@ -0,0 +1,22 @@ +/* + * This file is part of laurelin/shared + * Copyright (C) 2023 Jonni Liljamo + * + * Licensed under GPL-3.0-only. + * See LICENSE for licensing information. + */ + +use naia_bevy_shared::Message; + +#[derive(Message)] +pub struct CookieRefresh { + pub cookie: String, +} + +impl CookieRefresh { + pub fn new(cookie: &str) -> Self { + Self { + cookie: cookie.to_string(), + } + } +} diff --git a/shared/src/server/messages/mod.rs b/shared/src/server/messages/mod.rs index ae7e7bb..8bd0729 100644 --- a/shared/src/server/messages/mod.rs +++ b/shared/src/server/messages/mod.rs @@ -11,6 +11,9 @@ use naia_bevy_shared::{Protocol, ProtocolPlugin}; mod auth; pub use auth::{AfterAuth, Auth}; +mod cookierefresh; +pub use cookierefresh::CookieRefresh; + mod datarequest; pub use datarequest::{DataRequest, DataRequestResponse, DataRequestType}; @@ -21,6 +24,7 @@ impl ProtocolPlugin for MessagesPlugin { protocol .add_message::() .add_message::() + .add_message::() .add_message::() .add_message::(); } -- 2.44.1